[STM32 FSMC NAND] Driver variant using dedicated FSMC interrupts finished and tested in hardware.

git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@7176 35acf78f-673a-0410-8e92-d51de3d6d3f4
This commit is contained in:
barthess 2014-08-14 15:29:19 +00:00
parent b7c4aae4e1
commit 00c270af7a
8 changed files with 86 additions and 118 deletions

View File

@ -108,7 +108,7 @@
#define GPIOD_PIN3 3
#define GPIOD_NAND_RE 4
#define GPIOD_NAND_WE 5
#define GPIOD_NAND_RB 6
#define GPIOD_NAND_RB_NWAIT 6
#define GPIOD_NAND_CE 7
#define GPIOD_PIN8 8
#define GPIOD_PIN9 9
@ -536,7 +536,7 @@
PIN_MODE_INPUT(GPIOD_PIN3) | \
PIN_MODE_ALTERNATE(GPIOD_NAND_RE) | \
PIN_MODE_ALTERNATE(GPIOD_NAND_WE) | \
PIN_MODE_INPUT(GPIOD_NAND_RB) | \
PIN_MODE_INPUT(GPIOD_NAND_RB_NWAIT) | \
PIN_MODE_ALTERNATE(GPIOD_NAND_CE) | \
PIN_MODE_INPUT(GPIOD_PIN8) | \
PIN_MODE_INPUT(GPIOD_PIN9) | \
@ -552,7 +552,7 @@
PIN_OTYPE_PUSHPULL(GPIOD_PIN3) | \
PIN_OTYPE_PUSHPULL(GPIOD_NAND_RE) | \
PIN_OTYPE_PUSHPULL(GPIOD_NAND_WE) |\
PIN_OTYPE_PUSHPULL(GPIOD_NAND_RB) | \
PIN_OTYPE_PUSHPULL(GPIOD_NAND_RB_NWAIT) | \
PIN_OTYPE_PUSHPULL(GPIOD_NAND_CE) | \
PIN_OTYPE_PUSHPULL(GPIOD_PIN8) | \
PIN_OTYPE_PUSHPULL(GPIOD_PIN9) | \
@ -568,7 +568,7 @@
PIN_OSPEED_100M(GPIOD_PIN3) | \
PIN_OSPEED_100M(GPIOD_NAND_RE) | \
PIN_OSPEED_100M(GPIOD_NAND_WE) | \
PIN_OSPEED_100M(GPIOD_NAND_RB) | \
PIN_OSPEED_100M(GPIOD_NAND_RB_NWAIT) | \
PIN_OSPEED_100M(GPIOD_NAND_CE) | \
PIN_OSPEED_100M(GPIOD_PIN8) | \
PIN_OSPEED_100M(GPIOD_PIN9) | \
@ -584,7 +584,7 @@
PIN_PUPDR_PULLUP(GPIOD_PIN3) | \
PIN_PUPDR_PULLUP(GPIOD_NAND_RE) | \
PIN_PUPDR_PULLUP(GPIOD_NAND_WE) |\
PIN_PUPDR_PULLUP(GPIOD_NAND_RB) | \
PIN_PUPDR_PULLUP(GPIOD_NAND_RB_NWAIT) | \
PIN_PUPDR_PULLUP(GPIOD_NAND_CE) | \
PIN_PUPDR_PULLUP(GPIOD_PIN8) | \
PIN_PUPDR_PULLUP(GPIOD_PIN9) | \
@ -600,7 +600,7 @@
PIN_ODR_HIGH(GPIOD_PIN3) | \
PIN_ODR_HIGH(GPIOD_NAND_RE) | \
PIN_ODR_HIGH(GPIOD_NAND_WE) | \
PIN_ODR_HIGH(GPIOD_NAND_RB) | \
PIN_ODR_HIGH(GPIOD_NAND_RB_NWAIT) | \
PIN_ODR_HIGH(GPIOD_NAND_CE) | \
PIN_ODR_HIGH(GPIOD_PIN8) | \
PIN_ODR_HIGH(GPIOD_PIN9) | \
@ -616,7 +616,7 @@
PIN_AFIO_AF(GPIOD_PIN3, 0) | \
PIN_AFIO_AF(GPIOD_NAND_RE, 12) | \
PIN_AFIO_AF(GPIOD_NAND_WE, 12) | \
PIN_AFIO_AF(GPIOD_NAND_RB, 0) | \
PIN_AFIO_AF(GPIOD_NAND_RB_NWAIT, 0) | \
PIN_AFIO_AF(GPIOD_NAND_CE, 12))
#define VAL_GPIOD_AFRH (PIN_AFIO_AF(GPIOD_PIN8, 0) | \
PIN_AFIO_AF(GPIOD_PIN9, 0) | \

View File

@ -106,9 +106,9 @@ void fsmc_start(FSMCDriver *fsmcp) {
if (&FSMCD1 == fsmcp) {
rccResetFSMC();
rccEnableFSMC(FALSE);
#if STM32_NAND_USE_FSMC_INT
nvicEnableVector(FSMC_IRQn, STM32_FSMC_FSMC1_IRQ_PRIORITY);
#endif
#if !STM32_NAND_USE_EXT_INT
nvicEnableVector(STM32_FSMC_NUMBER, STM32_FSMC_FSMC1_IRQ_PRIORITY);
#endif
}
#endif /* STM32_FSMC_USE_FSMC1 */
@ -132,50 +132,39 @@ void fsmc_stop(FSMCDriver *fsmcp) {
/* Disables the peripheral.*/
#if STM32_FSMC_USE_FSMC1
if (&FSMCD1 == fsmcp) {
#if STM32_NAND_USE_FSMC_INT
nvicDisableVector(FSMC_IRQn);
#endif
#if !STM32_NAND_USE_EXT_INT
nvicDisableVector(STM32_FSMC_NUMBER);
#endif
rccDisableFSMC(FALSE);
}
#endif /* PLATFORM_STM32_USE_FSMC1 */
#endif /* STM32_FSMC_USE_FSMC1 */
fsmcp->state = FSMC_STOP;
}
}
#if STM32_NAND_USE_FSMC_INT
/**
* @brief Serve common interrupt.
*
* @notapi
*/
void fsmc_serve_interrupt(void) {
osalSysHalt("Unrealized");
}
#if !STM32_NAND_USE_EXT_INT
/**
* @brief FSMC shared interrupt handler.
*
* @notapi
*/
CH_IRQ_HANDLER(FSMC_IRQHandler) {
osalSysHalt("This functionality untested");
CH_IRQ_HANDLER(STM32_FSMC_HANDLER) {
CH_IRQ_PROLOGUE();
#if STM32_NAND_USE_FSMC_NAND1
if (FSMCD1.nand1->SR & FSMC_SR_ISR_MASK){
NANDD1.isr_handler(&NANDD1, FSMCD1.nand1->SR);
NANDD1.isr_handler(&NANDD1);
}
#endif
#if STM32_NAND_USE_FSMC_NAND2
if (FSMCD1.nand2->SR & FSMC_SR_ISR_MASK){
NANDD2.isr_handler(&NANDD2, FSMCD1.nand2->SR);
NANDD2.isr_handler(&NANDD2);
}
#endif
CH_IRQ_EPILOGUE();
}
#endif /* STM32_FSMC_USE_INT */
#endif /* !STM32_NAND_USE_EXT_INT */
#endif /* HAL_USE_FSMC */

View File

@ -158,8 +158,8 @@ typedef struct {
* @details MCUs in 100-pin package has no dedicated interrupt pin for FSMC.
* You have to use EXTI module instead to workaround this issue.
*/
#if !defined(STM32_NAND_USE_FSMC_INT) || defined(__DOXYGEN__)
#define STM32_NAND_USE_FSMC_INT FALSE
#if !defined(STM32_NAND_USE_EXT_INT) || defined(__DOXYGEN__)
#define STM32_NAND_USE_EXT_INT FALSE
#endif
/** @} */

View File

@ -87,7 +87,6 @@ static void wakeup_isr(NANDDriver *nandp){
*/
static void nand_lld_suspend_thread(NANDDriver *nandp) {
//nandp->thread = chThdGetSelfX();
osalThreadSuspendS(&nandp->thread);
}
@ -114,86 +113,60 @@ static uint32_t calc_eccps(NANDDriver *nandp){
/* Driver interrupt handlers. */
/*===========================================================================*/
#if STM32_NAND_USE_FSMC_INT
/**
* @brief Enable interrupts from FSMC
* @brief Enable interrupts from NAND
*
* @param[in] nandp pointer to the @p NANDDriver object
*
* @notapi
*/
static void nand_ready_isr_enable(NANDDriver *nandp) {
#if STM32_NAND_USE_EXT_INT
nandp->config->ext_nand_isr_enable();
#else
nandp->nand->SR &= ~(FSMC_SR_IRS | FSMC_SR_ILS | FSMC_SR_IFS |
FSMC_SR_ILEN | FSMC_SR_IFEN);
nandp->nand->SR |= FSMC_SR_IREN;
osalSysHalt("Function untested");
#endif
}
/**
* @brief Disable interrupts from FSMC
* @brief Disable interrupts from NAND
*
* @param[in] nandp pointer to the @p NANDDriver object
*
* @notapi
*/
static void nand_ready_isr_disable(NANDDriver *nandp) {
#if STM32_NAND_USE_EXT_INT
nandp->config->ext_nand_isr_disable();
#else
nandp->nand->SR &= ~FSMC_SR_IREN;
osalSysHalt("Function untested");
#endif
}
/**
* @brief Ready interrupt handler
*
* @param[in] nandp pointer to the @p NANDDriver object
* @param[in] flags flags passed from FSMC intrrupt handler
*
* @notapi
*/
static void nand_isr_handler (NANDDriver *nandp,
nandflags_t flags){
(void)nandp;
(void)flags;
osalSysHalt("Unrealized");
}
#else /* STM32_NAND_USE_FSMC_INT */
/**
* @brief Disable interrupts from EXTI
*
* @param[in] nandp pointer to the @p NANDDriver object
*
* @notapi
*/
static void nand_ready_isr_enable(NANDDriver *nandp) {
nandp->config->ext_isr_enable();
}
/**
* @brief Enable interrupts from EXTI
*
* @param[in] nandp pointer to the @p NANDDriver object
*
* @notapi
*/
static void nand_ready_isr_disable(NANDDriver *nandp) {
nandp->config->ext_isr_disable();
}
/**
* @brief Ready pin interrupt handler.
*
* @param[in] nandp pointer to the @p NANDDriver object
*
* @notapi
*/
static void nand_isr_handler(NANDDriver *nandp){
static void nand_isr_handler (NANDDriver *nandp){
osalSysLockFromISR();
#if !STM32_NAND_USE_EXT_INT
osalDbgCheck(nandp->nand->SR & FSMC_SR_IRS); /* spurious interrupt happened */
nandp->nand->SR &= ~FSMC_SR_IRS;
#endif
switch (nandp->state){
case NAND_READ:
nandp->state = NAND_DMA_RX;
dmaStartMemCopy(nandp->dma, nandp->dmamode,
nandp->map_data, nandp->rxdata, nandp->datalen);
/* thread will be woked up from DMA ISR */
/* thread will be waked up from DMA ISR */
break;
case NAND_ERASE:
@ -212,10 +185,8 @@ static void nand_isr_handler(NANDDriver *nandp){
osalSysHalt("Unhandled case");
break;
}
osalSysUnlockFromISR();
}
#endif /* STM32_NAND_USE_FSMC_INT */
/**
* @brief DMA RX end IRQ handler.
@ -225,8 +196,7 @@ static void nand_isr_handler(NANDDriver *nandp){
*
* @notapi
*/
static void nand_lld_serve_transfer_end_irq(NANDDriver *nandp,
uint32_t flags) {
static void nand_lld_serve_transfer_end_irq(NANDDriver *nandp, uint32_t flags) {
/* DMA errors handling.*/
#if defined(STM32_NAND_DMA_ERROR_HOOK)
if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) {

View File

@ -128,7 +128,7 @@
#error "FSMC not present in the selected device"
#endif
#if !STM32_NAND_USE_FSMC_INT && !HAL_USE_EXT
#if STM32_NAND_USE_EXT_INT && !HAL_USE_EXT
#error "External interrupt controller must be enabled to use this feature"
#endif
@ -156,23 +156,17 @@ typedef uint32_t nandflags_t;
*/
typedef struct NANDDriver NANDDriver;
#if STM32_NAND_USE_FSMC_INT
/**
* @brief Type of interrupt handler function
*/
typedef void (*nandisrhandler_t)
(NANDDriver *nandp, nandflags_t flags);
#else
/**
* @brief Type of interrupt handler function
*/
typedef void (*nandisrhandler_t)(NANDDriver *nandp);
#if STM32_NAND_USE_EXT_INT
/**
* @brief Type of function switching external interrupts on and off.
*/
typedef void (*nandisrswitch_t)(void);
#endif /* STM32_NAND_USE_FSMC_INT */
#endif /* STM32_NAND_USE_EXT_INT */
/**
* @brief Driver configuration structure.
@ -224,16 +218,16 @@ typedef struct {
* from STMicroelectronics.
*/
uint32_t pmem;
#if !STM32_NAND_USE_FSMC_INT
#if STM32_NAND_USE_EXT_INT
/**
* @brief Function enabling interrupts from EXTI
*/
nandisrswitch_t ext_isr_enable;
nandisrswitch_t ext_nand_isr_enable;
/**
* @brief Function disabling interrupts from EXTI
*/
nandisrswitch_t ext_isr_disable;
#endif /* !STM32_NAND_USE_FSMC_INT */
nandisrswitch_t ext_nand_isr_disable;
#endif /* STM32_NAND_USE_EXT_INT */
} NANDConfig;
/**

View File

@ -147,6 +147,13 @@
*/
#define ETH_IRQHandler Vector134
/*
* FSMC
*/
#define STM32_FSMC_HANDLER Vector100
#define STM32_FSMC_NUMBER 48
/** @} */
/*===========================================================================*/

View File

@ -73,13 +73,21 @@
#define NAND_ROW_WRITE_CYCLES 3
#define NAND_COL_WRITE_CYCLES 2
#define NANF_TEST_START_BLOCK 1100
#define NAND_TEST_END_BLOCK 1150
#define NANF_TEST_START_BLOCK 1200
#define NAND_TEST_END_BLOCK 1220
#if USE_KILL_BLOCK_TEST
#define NAND_TEST_KILL_BLOCK 8000
#endif
#if STM32_NAND_USE_FSMC_NAND1
#define NAND NANDD1
#elif STM32_NAND_USE_FSMC_NAND2
#define NAND NANDD2
#else
#error "You should enable at least one NAND interface"
#endif
/*
******************************************************************************
* EXTERNS
@ -91,7 +99,7 @@
* PROTOTYPES
******************************************************************************
*/
#if !STM32_NAND_USE_FSMC_INT
#if STM32_NAND_USE_EXT_INT
static void ready_isr_enable(void);
static void ready_isr_disable(void);
static void nand_ready_cb(EXTDriver *extp, expchannel_t channel);
@ -138,7 +146,7 @@ static const NANDConfig nandcfg = {
/* stm32 specific fields */
((FSMCNAND_TIME_HIZ << 24) | (FSMCNAND_TIME_HOLD << 16) | \
(FSMCNAND_TIME_WAIT << 8) | FSMCNAND_TIME_SET),
#if !STM32_NAND_USE_FSMC_INT
#if STM32_NAND_USE_EXT_INT
ready_isr_enable,
ready_isr_disable
#endif
@ -147,7 +155,7 @@ static const NANDConfig nandcfg = {
/**
*
*/
#if !STM32_NAND_USE_FSMC_INT
#if STM32_NAND_USE_EXT_INT
static const EXTConfig extcfg = {
{
{EXT_CH_MODE_DISABLED, NULL}, //0
@ -175,7 +183,7 @@ static const EXTConfig extcfg = {
{EXT_CH_MODE_DISABLED, NULL},
}
};
#endif /* !STM32_NAND_USE_FSMC_INT */
#endif /* STM32_NAND_USE_EXT_INT */
static uint32_t BackgroundThdCnt = 0;
@ -191,7 +199,7 @@ static uint32_t KillCycle = 0;
******************************************************************************
*/
#if !STM32_NAND_USE_FSMC_INT
#if STM32_NAND_USE_EXT_INT
static void nand_ready_cb(EXTDriver *extp, expchannel_t channel){
(void)extp;
(void)channel;
@ -200,13 +208,13 @@ static void nand_ready_cb(EXTDriver *extp, expchannel_t channel){
}
static void ready_isr_enable(void) {
extChannelEnable(&EXTD1, GPIOD_NAND_RB);
extChannelEnable(&EXTD1, GPIOD_NAND_RB_NWAIT);
}
static void ready_isr_disable(void) {
extChannelDisable(&EXTD1, GPIOD_NAND_RB);
extChannelDisable(&EXTD1, GPIOD_NAND_RB_NWAIT);
}
#endif /* STM32_NAND_USE_FSMC_INT */
#endif /* STM32_NAND_USE_EXT_INT */
/**
*
@ -228,9 +236,9 @@ static bool is_erased(NANDDriver *dp, size_t block){
uint32_t page = 0;
size_t i = 0;
for (page=0; page<NANDD1.config->pages_per_block; page++){
nandReadPageData(dp, block, page, nand_buf, NANDD1.config->page_data_size, NULL);
nandReadPageSpare(dp, block, page, &nand_buf[2048], NANDD1.config->page_spare_size);
for (page=0; page<NAND.config->pages_per_block; page++){
nandReadPageData(dp, block, page, nand_buf, NAND.config->page_data_size, NULL);
nandReadPageSpare(dp, block, page, &nand_buf[2048], NAND.config->page_spare_size);
for (i=0; i<sizeof(nand_buf); i++) {
if (nand_buf[i] != 0xFF)
return false;
@ -276,7 +284,7 @@ static void kill_block(NANDDriver *nandp, uint32_t block){
osalDbgCheck(!nandIsBad(nandp, block));
while(true){
op_status = nandErase(&NANDD1, block);
op_status = nandErase(&NAND, block);
if (0 != (op_status & 1)){
if(!is_erased(nandp, block))
osalSysHalt("Block successfully killed");
@ -378,7 +386,7 @@ static void ecc_test(NANDDriver *nandp, uint32_t block){
/* This test requires good block.*/
osalDbgCheck(!nandIsBad(nandp, block));
if (!is_erased(nandp, block))
nandErase(&NANDD1, block);
nandErase(&NAND, block);
pattern_fill();
@ -440,7 +448,7 @@ static void ecc_test(NANDDriver *nandp, uint32_t block){
osalDbgCheck(ECC_UNCORRECTABLE_ERROR == ecc_result); /* This error must be NOT correctable */
/*** make clean ***/
nandErase(&NANDD1, block);
nandErase(&NAND, block);
}
/*
@ -557,10 +565,10 @@ int main(void) {
halInit();
chSysInit();
#if !STM32_NAND_USE_FSMC_INT
#if STM32_NAND_USE_EXT_INT
extStart(&EXTD1, &extcfg);
#endif
nandStart(&NANDD1, &nandcfg);
nandStart(&NAND, &nandcfg);
chThdSleepMilliseconds(4000);
@ -579,7 +587,7 @@ int main(void) {
dma_storm_uart_start();
dma_storm_spi_start();
T = chVTGetSystemTimeX();
general_test(&NANDD1, NANF_TEST_START_BLOCK, NAND_TEST_END_BLOCK, 1);
general_test(&NAND, NANF_TEST_START_BLOCK, NAND_TEST_END_BLOCK, 1);
T = chVTGetSystemTimeX() - T;
adc_ints = dma_storm_adc_stop();
uart_ints = dma_storm_uart_stop();
@ -611,10 +619,10 @@ int main(void) {
/*
* perform ECC calculation test
*/
ecc_test(&NANDD1, NAND_TEST_END_BLOCK);
ecc_test(&NAND, NAND_TEST_END_BLOCK);
#if USE_KILL_BLOCK_TEST
kill_block(&NANDD1, NAND_TEST_KILL_BLOCK);
kill_block(&NAND, NAND_TEST_KILL_BLOCK);
#endif
nand_wp_assert();

View File

@ -310,7 +310,7 @@
#define STM32_FSMC_FSMC1_IRQ_PRIORITY 10
#define STM32_NAND_USE_FSMC_NAND1 TRUE
#define STM32_NAND_USE_FSMC_INT FALSE
#define STM32_NAND_USE_EXT_INT TRUE
#define STM32_NAND_DMA_STREAM STM32_DMA_STREAM_ID(2, 7)
#define STM32_NAND_DMA_PRIORITY 0
#define STM32_NAND_DMA_ERROR_HOOK(nandp) osalSysHalt("DMA failure")