143 lines
3.4 KiB
C
143 lines
3.4 KiB
C
#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;
|
|
}
|