#include "parallel_nand_port_stm32g474ce.h" #include "stm32g4xx_hal.h" /* Пустая плата STM32G474CEU6: PB0..PB7 образуют непрерывную x8 шину. */ #define DATA_MASK 0x00FFU #define CLE_PIN GPIO_PIN_0 #define ALE_PIN GPIO_PIN_1 #define WE_PIN GPIO_PIN_2 #define RE_PIN GPIO_PIN_3 #define CE_PIN GPIO_PIN_4 #define WP_PIN GPIO_PIN_5 #define RB_PIN GPIO_PIN_6 static int data_is_output; static void data_input(void) { if (data_is_output) { GPIOB->MODER &= ~0x0000FFFFUL; data_is_output = 0; } } static void data_output(void) { if (!data_is_output) { GPIOB->MODER = (GPIOB->MODER & ~0x0000FFFFUL) | 0x00005555UL; data_is_output = 1; } } static void short_delay(void) { __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); } static int g474_init(void) { GPIO_InitTypeDef io; __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); io.Pin = DATA_MASK; io.Mode = GPIO_MODE_OUTPUT_PP; io.Pull = GPIO_NOPULL; io.Speed = GPIO_SPEED_FREQ_VERY_HIGH; HAL_GPIO_Init(GPIOB, &io); data_is_output = 1; data_input(); /* Set inactive levels before enabling the pins as outputs. */ GPIOA->BSRR = WE_PIN | RE_PIN | CE_PIN | ((uint32_t)(CLE_PIN | ALE_PIN | WP_PIN) << 16); io.Pin = CLE_PIN | ALE_PIN | WE_PIN | RE_PIN | CE_PIN | WP_PIN; io.Mode = GPIO_MODE_OUTPUT_PP; io.Pull = GPIO_NOPULL; io.Speed = GPIO_SPEED_FREQ_VERY_HIGH; HAL_GPIO_Init(GPIOA, &io); io.Pin = RB_PIN; io.Mode = GPIO_MODE_INPUT; io.Pull = GPIO_NOPULL; HAL_GPIO_Init(GPIOA, &io); return 0; } static void g474_select(void) { GPIOA->BSRR = (uint32_t)CE_PIN << 16; } static void g474_deselect(void) { GPIOA->BSRR = CE_PIN; } static void write_cycle(pnand_octet_t value) { data_output(); GPIOB->BSRR = (uint32_t)DATA_MASK << 16; GPIOB->BSRR = (uint32_t)value & DATA_MASK; short_delay(); GPIOA->BSRR = (uint32_t)WE_PIN << 16; short_delay(); GPIOA->BSRR = WE_PIN; short_delay(); } static void g474_write_command(pnand_octet_t value) { GPIOA->BSRR = CLE_PIN | ((uint32_t)ALE_PIN << 16); write_cycle(value); GPIOA->BSRR = (uint32_t)CLE_PIN << 16; } static void g474_write_address(pnand_octet_t value) { GPIOA->BSRR = ALE_PIN | ((uint32_t)CLE_PIN << 16); write_cycle(value); GPIOA->BSRR = (uint32_t)ALE_PIN << 16; } static void g474_write_data(pnand_octet_t value) { GPIOA->BSRR = ((uint32_t)(CLE_PIN | ALE_PIN) << 16); write_cycle(value); } static pnand_octet_t g474_read_data(void) { pnand_octet_t value; data_input(); GPIOA->BSRR = ((uint32_t)(CLE_PIN | ALE_PIN | RE_PIN) << 16); short_delay(); value = (pnand_octet_t)(GPIOB->IDR & DATA_MASK); GPIOA->BSRR = RE_PIN; short_delay(); return value; } static int g474_is_ready(void) { return (GPIOA->IDR & RB_PIN) != 0U; } static void g474_set_wp(int enabled) { GPIOA->BSRR = enabled ? ((uint32_t)WP_PIN << 16) : WP_PIN; } static void g474_delay_us(unsigned long us) { uint32_t cycles = (SystemCoreClock / 3000000UL) * (uint32_t)us; while (cycles-- != 0U) __NOP(); } static const parallel_nand_port_t g474_port = { g474_init, g474_select, g474_deselect, g474_write_command, g474_write_address, g474_write_data, g474_read_data, g474_is_ready, g474_set_wp, g474_delay_us, 1 }; const parallel_nand_port_t *parallel_nand_port_stm32g474ce(void) { return &g474_port; }