#include "parallel_nand_port_stm32f103rc.h" #include "stm32f1xx_hal.h" /* STM32F103RCT6 LQFP64: FSMC is unavailable, so use GPIO bit-bang. */ #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->CRL = 0x44444444UL; /* PB0..PB7: floating input. */ data_is_output = 0; } } static void data_output(void) { if (!data_is_output) { GPIOB->CRL = 0x33333333UL; /* PB0..PB7: 50 MHz push-pull. */ data_is_output = 1; } } static void short_delay(void) { __NOP(); __NOP(); __NOP(); __NOP(); } static int f103rc_init(void) { GPIO_InitTypeDef io; __HAL_RCC_AFIO_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); __HAL_RCC_GPIOC_CLK_ENABLE(); /* Latch inactive control levels while pins are still inputs. */ GPIOC->BSRR = WE_PIN | RE_PIN | CE_PIN | ((uint32_t)(CLE_PIN | ALE_PIN | WP_PIN) << 16); /* PB3/PB4 carry I/O3/I/O4. Keep SWD, release only the JTAG pins. */ __HAL_AFIO_REMAP_SWJ_NOJTAG(); GPIOB->BSRR = DATA_MASK; GPIOB->CRL = 0x33333333UL; data_is_output = 1; data_input(); 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_HIGH; HAL_GPIO_Init(GPIOC, &io); io.Pin = RB_PIN; io.Mode = GPIO_MODE_INPUT; io.Pull = GPIO_NOPULL; HAL_GPIO_Init(GPIOC, &io); return 0; } static void f103rc_select(void) { GPIOC->BRR = CE_PIN; } static void f103rc_deselect(void) { GPIOC->BSRR = CE_PIN; } static void write_cycle(pnand_octet_t value) { data_output(); GPIOB->BRR = DATA_MASK; GPIOB->BSRR = (uint32_t)value & DATA_MASK; short_delay(); GPIOC->BRR = WE_PIN; short_delay(); GPIOC->BSRR = WE_PIN; short_delay(); } static void f103rc_write_command(pnand_octet_t value) { GPIOC->BSRR = CLE_PIN; GPIOC->BRR = ALE_PIN; write_cycle(value); GPIOC->BRR = CLE_PIN; } static void f103rc_write_address(pnand_octet_t value) { GPIOC->BSRR = ALE_PIN; GPIOC->BRR = CLE_PIN; write_cycle(value); GPIOC->BRR = ALE_PIN; } static void f103rc_write_data(pnand_octet_t value) { GPIOC->BRR = CLE_PIN | ALE_PIN; write_cycle(value); } static pnand_octet_t f103rc_read_data(void) { pnand_octet_t value; data_input(); GPIOC->BRR = CLE_PIN | ALE_PIN | RE_PIN; short_delay(); value = (pnand_octet_t)(GPIOB->IDR & DATA_MASK); GPIOC->BSRR = RE_PIN; short_delay(); return value; } static int f103rc_is_ready(void) { return (GPIOC->IDR & RB_PIN) != 0U; } static void f103rc_set_wp(int enabled) { if (enabled) GPIOC->BRR = WP_PIN; else GPIOC->BSRR = WP_PIN; } static void f103rc_delay_us(unsigned long us) { uint32_t cycles = (SystemCoreClock / 3000000UL) * (uint32_t)us; while (cycles-- != 0U) __NOP(); } static const parallel_nand_port_t f103rc_port = { f103rc_init, f103rc_select, f103rc_deselect, f103rc_write_command, f103rc_write_address, f103rc_write_data, f103rc_read_data, f103rc_is_ready, f103rc_set_wp, f103rc_delay_us }; const parallel_nand_port_t *parallel_nand_port_stm32f103rc(void) { return &f103rc_port; }