diff options
author | Michael Walker <walkerstop@gmail.com> | 2018-05-02 03:37:31 -0700 |
---|---|---|
committer | Michael Walker <walkerstop@gmail.com> | 2018-05-02 03:37:31 -0700 |
commit | cd7559268dcc2da5f2b1f3872e6baa1cff1d5476 (patch) | |
tree | 0cf31de069f9df06a13743eab4e1879f05ce9c12 /os/hal/ports/STM32/LLD/FSMCv1 | |
parent | 4d7ccdd1fce0c95c57129b80c81fab829daf9f99 (diff) | |
parent | 457afa6202fe9f8e6accb65411629172bb32c41b (diff) | |
download | ChibiOS-Contrib-cd7559268dcc2da5f2b1f3872e6baa1cff1d5476.tar.gz ChibiOS-Contrib-cd7559268dcc2da5f2b1f3872e6baa1cff1d5476.tar.bz2 ChibiOS-Contrib-cd7559268dcc2da5f2b1f3872e6baa1cff1d5476.zip |
Merge branch 'master' into mike
Diffstat (limited to 'os/hal/ports/STM32/LLD/FSMCv1')
-rw-r--r-- | os/hal/ports/STM32/LLD/FSMCv1/hal_fsmc.c | 16 | ||||
-rw-r--r-- | os/hal/ports/STM32/LLD/FSMCv1/hal_fsmc.h | 56 | ||||
-rw-r--r-- | os/hal/ports/STM32/LLD/FSMCv1/hal_fsmc_sdram.c | 8 | ||||
-rw-r--r-- | os/hal/ports/STM32/LLD/FSMCv1/hal_fsmc_sdram.h | 14 | ||||
-rw-r--r-- | os/hal/ports/STM32/LLD/FSMCv1/hal_fsmc_sram.c | 15 | ||||
-rw-r--r-- | os/hal/ports/STM32/LLD/FSMCv1/hal_fsmc_sram.h | 8 | ||||
-rw-r--r-- | os/hal/ports/STM32/LLD/FSMCv1/hal_nand_lld.c | 209 | ||||
-rw-r--r-- | os/hal/ports/STM32/LLD/FSMCv1/hal_nand_lld.h | 62 |
8 files changed, 232 insertions, 156 deletions
diff --git a/os/hal/ports/STM32/LLD/FSMCv1/hal_fsmc.c b/os/hal/ports/STM32/LLD/FSMCv1/hal_fsmc.c index 8b1082c..71c6ada 100644 --- a/os/hal/ports/STM32/LLD/FSMCv1/hal_fsmc.c +++ b/os/hal/ports/STM32/LLD/FSMCv1/hal_fsmc.c @@ -15,7 +15,7 @@ */ /** - * @file fsmc.c + * @file hal_fsmc.c * @brief FSMC Driver subsystem low level driver source template. * * @addtogroup FSMC @@ -96,7 +96,11 @@ void fsmc_init(void) { #endif #if (defined(STM32F427xx) || defined(STM32F437xx) || \ - defined(STM32F429xx) || defined(STM32F439xx)) + defined(STM32F429xx) || defined(STM32F439xx) || \ + defined(STM32F745xx) || defined(STM32F746xx) || \ + defined(STM32F756xx) || defined(STM32F767xx) || \ + defined(STM32F769xx) || defined(STM32F777xx) || \ + defined(STM32F779xx)) #if STM32_USE_FSMC_SDRAM FSMCD1.sdram = (FSMC_SDRAM_TypeDef *)FSMC_Bank5_6_R_BASE; #endif @@ -124,7 +128,7 @@ void fsmc_start(FSMCDriver *fsmcp) { rccResetFSMC(); #endif rccEnableFSMC(FALSE); -#if (!STM32_NAND_USE_EXT_INT && HAL_USE_NAND) +#if HAL_USE_NAND nvicEnableVector(STM32_FSMC_NUMBER, STM32_FSMC_FSMC1_IRQ_PRIORITY); #endif } @@ -152,10 +156,10 @@ void fsmc_stop(FSMCDriver *fsmcp) { /* Disables the peripheral.*/ #if STM32_FSMC_USE_FSMC1 if (&FSMCD1 == fsmcp) { -#if (!STM32_NAND_USE_EXT_INT && HAL_USE_NAND) +#if HAL_USE_NAND nvicDisableVector(STM32_FSMC_NUMBER); #endif - rccDisableFSMC(FALSE); + rccDisableFSMC(); } #endif /* STM32_FSMC_USE_FSMC1 */ @@ -163,7 +167,6 @@ void fsmc_stop(FSMCDriver *fsmcp) { } } -#if !STM32_NAND_USE_EXT_INT /** * @brief FSMC shared interrupt handler. * @@ -184,7 +187,6 @@ CH_IRQ_HANDLER(STM32_FSMC_HANDLER) { #endif CH_IRQ_EPILOGUE(); } -#endif /* !STM32_NAND_USE_EXT_INT */ #endif /* HAL_USE_FSMC */ diff --git a/os/hal/ports/STM32/LLD/FSMCv1/hal_fsmc.h b/os/hal/ports/STM32/LLD/FSMCv1/hal_fsmc.h index 7889b01..80c5d26 100644 --- a/os/hal/ports/STM32/LLD/FSMCv1/hal_fsmc.h +++ b/os/hal/ports/STM32/LLD/FSMCv1/hal_fsmc.h @@ -15,15 +15,15 @@ */ /** - * @file fsmc.h + * @file hal_fsmc.h * @brief FSMC Driver subsystem low level driver header. * * @addtogroup FSMC * @{ */ -#ifndef _FSMC_H_ -#define _FSMC_H_ +#ifndef HAL_FSMC_H_ +#define HAL_FSMC_H_ #if (HAL_USE_FSMC == TRUE) || defined(__DOXYGEN__) @@ -35,7 +35,11 @@ * (Re)define if needed base address constants supplied in ST's CMSIS */ #if (defined(STM32F427xx) || defined(STM32F437xx) || \ - defined(STM32F429xx) || defined(STM32F439xx)) + defined(STM32F429xx) || defined(STM32F439xx) || \ + defined(STM32F745xx) || defined(STM32F746xx) || \ + defined(STM32F756xx) || defined(STM32F767xx) || \ + defined(STM32F769xx) || defined(STM32F777xx) || \ + defined(STM32F779xx)) #if !defined(FSMC_Bank1_R_BASE) #define FSMC_Bank1_R_BASE (FMC_R_BASE + 0x0000) #endif @@ -80,7 +84,8 @@ #define FSMC_Bank3_MAP_BASE ((uint32_t) 0x80000000) #define FSMC_Bank4_MAP_BASE ((uint32_t) 0x90000000) #if (defined(STM32F427xx) || defined(STM32F437xx) || \ - defined(STM32F429xx) || defined(STM32F439xx)) + defined(STM32F429xx) || defined(STM32F439xx) || \ + defined(STM32F7)) #define FSMC_Bank5_MAP_BASE ((uint32_t) 0xC0000000) #define FSMC_Bank6_MAP_BASE ((uint32_t) 0xD0000000) #endif @@ -157,7 +162,8 @@ typedef struct { } FSMC_SRAM_NOR_TypeDef; #if (defined(STM32F427xx) || defined(STM32F437xx) || \ - defined(STM32F429xx) || defined(STM32F439xx)) + defined(STM32F429xx) || defined(STM32F439xx) || \ + defined(STM32F7)) typedef struct { __IO uint32_t SDCR1; /**< SDRAM control register (bank 1) */ @@ -174,10 +180,15 @@ typedef struct { /** * @brief PCR register */ -#define FSMC_PCR_PWAITEN ((uint32_t)0x00000002) -#define FSMC_PCR_PBKEN ((uint32_t)0x00000004) -#define FSMC_PCR_PTYP ((uint32_t)0x00000008) -#define FSMC_PCR_ECCEN ((uint32_t)0x00000040) +#define FSMC_PCR_PWAITEN ((uint32_t)1 << 1) +#define FSMC_PCR_PBKEN ((uint32_t)1 << 2) +#define FSMC_PCR_PTYP ((uint32_t)1 << 3) +#define FSMC_PCR_PWID_8 ((uint32_t)0 << 4) +#define FSMC_PCR_PWID_16 ((uint32_t)1 << 4) +#define FSMC_PCR_PWID_RESERVED1 ((uint32_t)2 << 4) +#define FSMC_PCR_PWID_RESERVED2 ((uint32_t)3 << 4) +#define FSMC_PCR_PWID_MASK ((uint32_t)3 << 4) +#define FSMC_PCR_ECCEN ((uint32_t)1 << 6) #define FSMC_PCR_PTYP_PCCARD 0 #define FSMC_PCR_PTYP_NAND FSMC_PCR_PTYP @@ -205,7 +216,8 @@ typedef struct { #define FSMC_BCR_MWID_8 ((uint32_t)0 << 4) #define FSMC_BCR_MWID_16 ((uint32_t)1 << 4) #if (defined(STM32F427xx) || defined(STM32F437xx) || \ - defined(STM32F429xx) || defined(STM32F439xx)) + defined(STM32F429xx) || defined(STM32F439xx) || \ + defined(STM32F7)) #define FSMC_BCR_MWID_32 ((uint32_t)2 << 4) #else #define FSMC_BCR_MWID_RESERVED1 ((uint32_t)2 << 4) @@ -221,6 +233,14 @@ typedef struct { #define FSMC_BCR_EXTMOD ((uint32_t)1 << 14) #define FSMC_BCR_ASYNCWAIT ((uint32_t)1 << 15) #define FSMC_BCR_CBURSTRW ((uint32_t)1 << 19) +#if (defined(STM32F427xx) || defined(STM32F437xx) || \ + defined(STM32F429xx) || defined(STM32F439xx) || \ + defined(STM32F7)) +#define FSMC_BCR_CCLKEN ((uint32_t)1 << 20) +#endif +#if (defined(STM32F7)) +#define FSMC_BCR_WFDIS ((uint32_t)1 << 21) +#endif /*===========================================================================*/ /* Driver pre-compile time settings. */ @@ -238,15 +258,6 @@ typedef struct { #define STM32_FSMC_USE_FSMC1 FALSE #endif -/** - * @brief Internal FSMC interrupt enable switch - * @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_EXT_INT) || defined(__DOXYGEN__) -#define STM32_NAND_USE_EXT_INT FALSE -#endif - /** @} */ /*===========================================================================*/ @@ -303,7 +314,8 @@ struct FSMCDriver { FSMC_NAND_TypeDef *nand2; #endif #if (defined(STM32F427xx) || defined(STM32F437xx) || \ - defined(STM32F429xx) || defined(STM32F439xx)) + defined(STM32F429xx) || defined(STM32F439xx) || \ + defined(STM32F7)) #if STM32_USE_FSMC_SDRAM FSMC_SDRAM_TypeDef *sdram; #endif @@ -334,6 +346,6 @@ extern "C" { #endif /* HAL_USE_FSMC */ -#endif /* _FSMC_H_ */ +#endif /* HAL_FSMC_H_ */ /** @} */ diff --git a/os/hal/ports/STM32/LLD/FSMCv1/hal_fsmc_sdram.c b/os/hal/ports/STM32/LLD/FSMCv1/hal_fsmc_sdram.c index 95f47d5..6d727c8 100644 --- a/os/hal/ports/STM32/LLD/FSMCv1/hal_fsmc_sdram.c +++ b/os/hal/ports/STM32/LLD/FSMCv1/hal_fsmc_sdram.c @@ -18,7 +18,7 @@ */ /** - * @file fsmc_sdram.c + * @file hal_fsmc_sdram.c * @brief SDRAM Driver subsystem low level driver source. * * @addtogroup SDRAM @@ -28,7 +28,11 @@ #include "hal.h" #if (defined(STM32F427xx) || defined(STM32F437xx) || \ - defined(STM32F429xx) || defined(STM32F439xx)) + defined(STM32F429xx) || defined(STM32F439xx) || \ + defined(STM32F745xx) || defined(STM32F746xx) || \ + defined(STM32F756xx) || defined(STM32F767xx) || \ + defined(STM32F769xx) || defined(STM32F777xx) || \ + defined(STM32F779xx)) #if (STM32_USE_FSMC_SDRAM == TRUE) || defined(__DOXYGEN__) diff --git a/os/hal/ports/STM32/LLD/FSMCv1/hal_fsmc_sdram.h b/os/hal/ports/STM32/LLD/FSMCv1/hal_fsmc_sdram.h index cef6772..c9f9de0 100644 --- a/os/hal/ports/STM32/LLD/FSMCv1/hal_fsmc_sdram.h +++ b/os/hal/ports/STM32/LLD/FSMCv1/hal_fsmc_sdram.h @@ -18,18 +18,22 @@ */ /** - * @file fsmc_sdram.h + * @file hal_fsmc_sdram.h * @brief SDRAM Driver subsystem low level driver header. * * @addtogroup SDRAM * @{ */ -#ifndef _FMC_SDRAM_H_ -#define _FMC_SDRAM_H_ +#ifndef HAL_FMC_SDRAM_H_ +#define HAL_FMC_SDRAM_H_ #if (defined(STM32F427xx) || defined(STM32F437xx) || \ - defined(STM32F429xx) || defined(STM32F439xx)) + defined(STM32F429xx) || defined(STM32F439xx) || \ + defined(STM32F745xx) || defined(STM32F746xx) || \ + defined(STM32F756xx) || defined(STM32F767xx) || \ + defined(STM32F769xx) || defined(STM32F777xx) || \ + defined(STM32F779xx)) #include "hal_fsmc.h" @@ -166,6 +170,6 @@ extern "C" { #endif /* STM32F427xx / STM32F429xx / STM32F437xx / STM32F439xx */ -#endif /* _FMC_SDRAM_H_ */ +#endif /* HAL_FMC_SDRAM_H_ */ /** @} */ diff --git a/os/hal/ports/STM32/LLD/FSMCv1/hal_fsmc_sram.c b/os/hal/ports/STM32/LLD/FSMCv1/hal_fsmc_sram.c index 6f710d4..da13ca5 100644 --- a/os/hal/ports/STM32/LLD/FSMCv1/hal_fsmc_sram.c +++ b/os/hal/ports/STM32/LLD/FSMCv1/hal_fsmc_sram.c @@ -15,7 +15,7 @@ */ /** - * @file fsmc_sram.c + * @file hal_fsmc_sram.c * @brief SRAM Driver subsystem low level driver source. * * @addtogroup SRAM @@ -128,9 +128,9 @@ void fsmcSramStart(SRAMDriver *sramp, const SRAMConfig *cfgp) { "invalid state"); if (sramp->state == SRAM_STOP) { - sramp->sram->BCR = cfgp->bcr | FSMC_BCR_MBKEN; sramp->sram->BTR = cfgp->btr; sramp->sram->BWTR = cfgp->bwtr; + sramp->sram->BCR = cfgp->bcr | FSMC_BCR_MBKEN; sramp->state = SRAM_READY; } } @@ -145,7 +145,16 @@ void fsmcSramStart(SRAMDriver *sramp, const SRAMConfig *cfgp) { void fsmcSramStop(SRAMDriver *sramp) { if (sramp->state == SRAM_READY) { - sramp->sram->BCR &= ~FSMC_BCR_MBKEN; + uint32_t mask = FSMC_BCR_MBKEN; +#if (defined(STM32F427xx) || defined(STM32F437xx) || \ + defined(STM32F429xx) || defined(STM32F439xx) || \ + defined(STM32F745xx) || defined(STM32F746xx) || \ + defined(STM32F756xx) || defined(STM32F767xx) || \ + defined(STM32F769xx) || defined(STM32F777xx) || \ + defined(STM32F779xx)) + mask |= FSMC_BCR_CCLKEN; +#endif + sramp->sram->BCR &= ~mask; sramp->state = SRAM_STOP; } } diff --git a/os/hal/ports/STM32/LLD/FSMCv1/hal_fsmc_sram.h b/os/hal/ports/STM32/LLD/FSMCv1/hal_fsmc_sram.h index 529bdc7..5e749a8 100644 --- a/os/hal/ports/STM32/LLD/FSMCv1/hal_fsmc_sram.h +++ b/os/hal/ports/STM32/LLD/FSMCv1/hal_fsmc_sram.h @@ -15,15 +15,15 @@ */ /** - * @file fsmc_sram.h + * @file hal_fsmc_sram.h * @brief SRAM Driver subsystem low level driver header. * * @addtogroup SRAM * @{ */ -#ifndef _FSMC_SRAM_H_ -#define _FSMC_SRAM_H_ +#ifndef HAL_FSMC_SRAM_H_ +#define HAL_FSMC_SRAM_H_ #include "hal_fsmc.h" @@ -167,6 +167,6 @@ extern "C" { #endif /* STM32_USE_FSMC_SRAM */ -#endif /* _FSMC_SRAM_H_ */ +#endif /* HAL_FSMC_SRAM_H_ */ /** @} */ diff --git a/os/hal/ports/STM32/LLD/FSMCv1/hal_nand_lld.c b/os/hal/ports/STM32/LLD/FSMCv1/hal_nand_lld.c index b37c026..5729f92 100644 --- a/os/hal/ports/STM32/LLD/FSMCv1/hal_nand_lld.c +++ b/os/hal/ports/STM32/LLD/FSMCv1/hal_nand_lld.c @@ -15,7 +15,7 @@ */ /** - * @file nand_lld.c + * @file hal_nand_lld.c * @brief NAND Driver subsystem low level driver source. * * @addtogroup NAND @@ -33,6 +33,19 @@ STM32_DMA_GETCHANNEL(STM32_NAND_DMA_STREAM, \ STM32_FSMC_DMA_CHN) +/** + * @brief Bus width of NAND IC. + * @details Must be 8 or 16 + */ +#if ! defined(STM32_NAND_BUS_WIDTH) || defined(__DOXYGEN__) +#define STM32_NAND_BUS_WIDTH 8 +#endif + +/** + * @brief DMA transaction width on AHB bus in bytes + */ +#define AHB_TRANSACTION_WIDTH 2 + /*===========================================================================*/ /* Driver exported variables. */ /*===========================================================================*/ @@ -62,6 +75,47 @@ NANDDriver NANDD2; /*===========================================================================*/ /* Driver local functions. */ /*===========================================================================*/ + +/** + * @brief Helper function. + * + * @notapi + */ +static void align_check(const void *ptr, uint32_t len) { + osalDbgCheck((((uint32_t)ptr % AHB_TRANSACTION_WIDTH) == 0) && + ((len % AHB_TRANSACTION_WIDTH) == 0) && + (len >= AHB_TRANSACTION_WIDTH)); + (void)ptr; + (void)len; +} + +/** + * @brief Work around errata in STM32's FSMC core. + * @details Constant output clock (if enabled) disappears when CLKDIV value + * sets to 1 (FMC_CLK period = 2 × HCLK periods) AND 8-bit async + * transaction generated on AHB. This workaround eliminates 8-bit + * transactions on bus when you use 8-bit memory. It suitable only + * for 8-bit memory (i.e. PWID bits in PCR register must be set + * to 8-bit mode). + * + * @notapi + */ +static void set_16bit_bus(NANDDriver *nandp) { +#if STM32_NAND_BUS_WIDTH + nandp->nand->PCR |= FSMC_PCR_PWID_16; +#else + (void)nandp; +#endif +} + +static void set_8bit_bus(NANDDriver *nandp) { +#if STM32_NAND_BUS_WIDTH + nandp->nand->PCR &= ~FSMC_PCR_PWID_16; +#else + (void)nandp; +#endif +} + /** * @brief Wakes up the waiting thread. * @@ -117,13 +171,10 @@ static uint32_t calc_eccps(NANDDriver *nandp) { * @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); + FSMC_SR_ILEN | FSMC_SR_IFEN); nandp->nand->SR |= FSMC_SR_IREN; -#endif } /** @@ -134,11 +185,8 @@ static void nand_ready_isr_enable(NANDDriver *nandp) { * @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; -#endif } /** @@ -148,31 +196,24 @@ static void nand_ready_isr_disable(NANDDriver *nandp) { * * @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); + dmaStartMemCopy(nandp->dma, nandp->dmamode, nandp->map_data, nandp->rxdata, + nandp->datalen/AHB_TRANSACTION_WIDTH); /* thread will be waked up from DMA ISR */ break; - case NAND_ERASE: - /* NAND reports about erase finish */ - nandp->state = NAND_READY; - wakeup_isr(nandp); - break; - - case NAND_PROGRAM: - /* NAND reports about page programming finish */ + case NAND_ERASE: /* NAND reports about erase finish */ + case NAND_PROGRAM: /* NAND reports about page programming finish */ + case NAND_RESET: /* NAND reports about finished reset recover */ nandp->state = NAND_READY; wakeup_isr(nandp); break; @@ -210,7 +251,7 @@ static void nand_lld_serve_transfer_end_irq(NANDDriver *nandp, uint32_t flags) { case NAND_DMA_TX: nandp->state = NAND_PROGRAM; nandp->map_cmd[0] = NAND_CMD_PAGEPROG; - /* thread will be woken from ready_isr() */ + /* thread will be woken up from ready_isr() */ break; case NAND_DMA_RX: @@ -249,9 +290,9 @@ void nand_lld_init(void) { NANDD1.thread = NULL; NANDD1.dma = STM32_DMA_STREAM(STM32_NAND_DMA_STREAM); NANDD1.nand = FSMCD1.nand1; - NANDD1.map_data = (uint8_t*)FSMC_Bank2_MAP_COMMON_DATA; - NANDD1.map_cmd = (uint8_t*)FSMC_Bank2_MAP_COMMON_CMD; - NANDD1.map_addr = (uint8_t*)FSMC_Bank2_MAP_COMMON_ADDR; + NANDD1.map_data = (void *)FSMC_Bank2_MAP_COMMON_DATA; + NANDD1.map_cmd = (uint16_t *)FSMC_Bank2_MAP_COMMON_CMD; + NANDD1.map_addr = (uint16_t *)FSMC_Bank2_MAP_COMMON_ADDR; NANDD1.bb_map = NULL; #endif /* STM32_NAND_USE_FSMC_NAND1 */ @@ -263,9 +304,9 @@ void nand_lld_init(void) { NANDD2.thread = NULL; NANDD2.dma = STM32_DMA_STREAM(STM32_NAND_DMA_STREAM); NANDD2.nand = FSMCD1.nand2; - NANDD2.map_data = (uint8_t*)FSMC_Bank3_MAP_COMMON_DATA; - NANDD2.map_cmd = (uint8_t*)FSMC_Bank3_MAP_COMMON_CMD; - NANDD2.map_addr = (uint8_t*)FSMC_Bank3_MAP_COMMON_ADDR; + NANDD2.map_data = (void *)FSMC_Bank3_MAP_COMMON_DATA; + NANDD2.map_cmd = (uint16_t *)FSMC_Bank3_MAP_COMMON_CMD; + NANDD2.map_addr = (uint16_t *)FSMC_Bank3_MAP_COMMON_ADDR; NANDD2.bb_map = NULL; #endif /* STM32_NAND_USE_FSMC_NAND2 */ } @@ -280,6 +321,8 @@ void nand_lld_init(void) { void nand_lld_start(NANDDriver *nandp) { bool b; + uint32_t dmasize; + uint32_t pcr_bus_width; if (FSMCD1.state == FSMC_STOP) fsmc_start(&FSMCD1); @@ -290,16 +333,33 @@ void nand_lld_start(NANDDriver *nandp) { (stm32_dmaisr_t)nand_lld_serve_transfer_end_irq, (void *)nandp); osalDbgAssert(!b, "stream already allocated"); + +#if AHB_TRANSACTION_WIDTH == 4 + dmasize = STM32_DMA_CR_PSIZE_WORD | STM32_DMA_CR_MSIZE_WORD; +#elif AHB_TRANSACTION_WIDTH == 2 + dmasize = STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD; +#elif AHB_TRANSACTION_WIDTH == 1 + dmasize = STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE; +#else +#error "Incorrect AHB_TRANSACTION_WIDTH" +#endif + nandp->dmamode = STM32_DMA_CR_CHSEL(NAND_DMA_CHANNEL) | STM32_DMA_CR_PL(STM32_NAND_NAND1_DMA_PRIORITY) | - STM32_DMA_CR_PSIZE_BYTE | - STM32_DMA_CR_MSIZE_BYTE | + dmasize | STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE | STM32_DMA_CR_TCIE; - /* dmaStreamSetFIFO(nandp->dma, - STM32_DMA_FCR_DMDIS | NAND_STM32_DMA_FCR_FTH_LVL); */ - nandp->nand->PCR = calc_eccps(nandp) | FSMC_PCR_PTYP | FSMC_PCR_PBKEN; + +#if STM32_NAND_BUS_WIDTH == 8 + pcr_bus_width = FSMC_PCR_PWID_8; +#elif STM32_NAND_BUS_WIDTH == 16 + pcr_bus_width = FSMC_PCR_PWID_16; +#else +#error "Bus width must be 8 or 16 bits" +#endif + nandp->nand->PCR = pcr_bus_width | calc_eccps(nandp) | + FSMC_PCR_PTYP_NAND | FSMC_PCR_PBKEN; nandp->nand->PMEM = nandp->config->pmem; nandp->nand->PATT = nandp->config->pmem; nandp->isr_handler = nand_isr_handler; @@ -329,24 +389,28 @@ void nand_lld_stop(NANDDriver *nandp) { * * @param[in] nandp pointer to the @p NANDDriver object * @param[out] data pointer to data buffer - * @param[in] datalen size of data buffer + * @param[in] datalen size of data buffer in bytes * @param[in] addr pointer to address buffer * @param[in] addrlen length of address * @param[out] ecc pointer to store computed ECC. Ignored when NULL. * * @notapi */ -void nand_lld_read_data(NANDDriver *nandp, uint8_t *data, size_t datalen, +void nand_lld_read_data(NANDDriver *nandp, uint16_t *data, size_t datalen, uint8_t *addr, size_t addrlen, uint32_t *ecc){ + align_check(data, datalen); + nandp->state = NAND_READ; nandp->rxdata = data; nandp->datalen = datalen; - nand_lld_write_cmd (nandp, NAND_CMD_READ0); + set_16bit_bus(nandp); + nand_lld_write_cmd(nandp, NAND_CMD_READ0); nand_lld_write_addr(nandp, addr, addrlen); osalSysLock(); - nand_lld_write_cmd (nandp, NAND_CMD_READ0_CONFIRM); + nand_lld_write_cmd(nandp, NAND_CMD_READ0_CONFIRM); + set_8bit_bus(nandp); /* Here NAND asserts busy signal and starts transferring from memory array to page buffer. After the end of transmission ready_isr functions @@ -375,7 +439,7 @@ void nand_lld_read_data(NANDDriver *nandp, uint8_t *data, size_t datalen, * * @param[in] nandp pointer to the @p NANDDriver object * @param[in] data buffer with data to be written - * @param[in] datalen size of data buffer + * @param[in] datalen size of data buffer in bytes * @param[in] addr pointer to address buffer * @param[in] addrlen length of address * @param[out] ecc pointer to store computed ECC. Ignored when NULL. @@ -384,14 +448,18 @@ void nand_lld_read_data(NANDDriver *nandp, uint8_t *data, size_t datalen, * * @notapi */ -uint8_t nand_lld_write_data(NANDDriver *nandp, const uint8_t *data, +uint8_t nand_lld_write_data(NANDDriver *nandp, const uint16_t *data, size_t datalen, uint8_t *addr, size_t addrlen, uint32_t *ecc) { + align_check(data, datalen); + nandp->state = NAND_WRITE; - nand_lld_write_cmd (nandp, NAND_CMD_WRITE); + set_16bit_bus(nandp); + nand_lld_write_cmd(nandp, NAND_CMD_WRITE); osalSysLock(); nand_lld_write_addr(nandp, addr, addrlen); + set_8bit_bus(nandp); /* Now start DMA transfer to NAND buffer and put thread in sleep state. Tread will be woken up from ready ISR. */ @@ -403,7 +471,8 @@ uint8_t nand_lld_write_data(NANDDriver *nandp, const uint8_t *data, nandp->nand->PCR |= FSMC_PCR_ECCEN; } - dmaStartMemCopy(nandp->dma, nandp->dmamode, data, nandp->map_data, datalen); + dmaStartMemCopy(nandp->dma, nandp->dmamode, data, nandp->map_data, + datalen/AHB_TRANSACTION_WIDTH); nand_lld_suspend_thread(nandp); osalSysUnlock(); @@ -419,6 +488,26 @@ uint8_t nand_lld_write_data(NANDDriver *nandp, const uint8_t *data, } /** + * @brief Soft reset NAND device. + * + * @param[in] nandp pointer to the @p NANDDriver object + * + * @notapi + */ +void nand_lld_reset(NANDDriver *nandp) { + + nandp->state = NAND_RESET; + + set_16bit_bus(nandp); + nand_lld_write_cmd(nandp, NAND_CMD_RESET); + set_8bit_bus(nandp); + + osalSysLock(); + nand_lld_suspend_thread(nandp); + osalSysUnlock(); +} + +/** * @brief Erase block. * * @param[in] nandp pointer to the @p NANDDriver object @@ -433,10 +522,13 @@ uint8_t nand_lld_erase(NANDDriver *nandp, uint8_t *addr, size_t addrlen) { nandp->state = NAND_ERASE; - nand_lld_write_cmd (nandp, NAND_CMD_ERASE); + set_16bit_bus(nandp); + nand_lld_write_cmd(nandp, NAND_CMD_ERASE); nand_lld_write_addr(nandp, addr, addrlen); osalSysLock(); - nand_lld_write_cmd (nandp, NAND_CMD_ERASE_CONFIRM); + nand_lld_write_cmd(nandp, NAND_CMD_ERASE_CONFIRM); + set_8bit_bus(nandp); + nand_lld_suspend_thread(nandp); osalSysUnlock(); @@ -444,25 +536,6 @@ uint8_t nand_lld_erase(NANDDriver *nandp, uint8_t *addr, size_t addrlen) { } /** - * @brief Read data from NAND using polling approach. - * - * @detatils Use this function to read data when no waiting expected. For - * Example read status word after 0x70 command - * - * @param[in] nandp pointer to the @p NANDDriver object - * @param[out] data pointer to output buffer - * @param[in] len length of data to be read - * - * @notapi - */ -void nand_lld_polled_read_data(NANDDriver *nandp, uint8_t *data, size_t len) { - size_t i = 0; - - for (i=0; i<len; i++) - data[i] = nandp->map_data[i]; -} - -/** * @brief Send addres to NAND. * * @param[in] nandp pointer to the @p NANDDriver object @@ -501,12 +574,14 @@ void nand_lld_write_cmd(NANDDriver *nandp, uint8_t cmd) { */ uint8_t nand_lld_read_status(NANDDriver *nandp) { - uint8_t status[1] = {0x01}; /* presume worse */ + uint16_t status; + set_16bit_bus(nandp); nand_lld_write_cmd(nandp, NAND_CMD_STATUS); - nand_lld_polled_read_data(nandp, status, 1); + set_8bit_bus(nandp); + status = nandp->map_data[0]; - return status[0]; + return status & 0xFF; } #endif /* HAL_USE_NAND */ diff --git a/os/hal/ports/STM32/LLD/FSMCv1/hal_nand_lld.h b/os/hal/ports/STM32/LLD/FSMCv1/hal_nand_lld.h index 8dca42f..5266138 100644 --- a/os/hal/ports/STM32/LLD/FSMCv1/hal_nand_lld.h +++ b/os/hal/ports/STM32/LLD/FSMCv1/hal_nand_lld.h @@ -15,15 +15,15 @@ */ /** - * @file nand_lld.h + * @file hal_nand_lld.h * @brief NAND Driver subsystem low level driver header. * * @addtogroup NAND * @{ */ -#ifndef _NAND_LLD_H_ -#define _NAND_LLD_H_ +#ifndef HAL_NAND_LLD_H_ +#define HAL_NAND_LLD_H_ #include "hal_fsmc.h" #include "bitmap.h" @@ -120,10 +120,6 @@ #error "FSMC not present in the selected device" #endif -#if STM32_NAND_USE_EXT_INT && !HAL_USE_EXT -#error "External interrupt controller must be enabled to use this feature" -#endif - #if !defined(STM32_DMA_REQUIRED) #define STM32_DMA_REQUIRED #endif @@ -133,37 +129,21 @@ /*===========================================================================*/ /** - * @brief NAND driver condition flags type. - */ -typedef uint32_t nandflags_t; - -/** * @brief Type of a structure representing an NAND driver. */ typedef struct NANDDriver NANDDriver; /** - * @brief Type of interrupt handler function + * @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_EXT_INT */ - /** * @brief Driver configuration structure. * @note It could be empty on some architectures. */ typedef struct { /** - * @brief Pointer to lower level driver. - */ - //const FSMCDriver *fsmcp; - /** * @brief Number of erase blocks in NAND device. */ uint32_t blocks; @@ -197,16 +177,6 @@ typedef struct { * from STMicroelectronics. */ uint32_t pmem; -#if STM32_NAND_USE_EXT_INT - /** - * @brief Function enabling interrupts from EXTI - */ - nandisrswitch_t ext_nand_isr_enable; - /** - * @brief Function disabling interrupts from EXTI - */ - nandisrswitch_t ext_nand_isr_disable; -#endif /* STM32_NAND_USE_EXT_INT */ } NANDConfig; /** @@ -236,15 +206,15 @@ struct NANDDriver { #endif /* NAND_USE_MUTUAL_EXCLUSION */ /* End of the mandatory fields.*/ /** - * @brief Function enabling interrupts from FSMC + * @brief Function enabling interrupts from FSMC. */ nandisrhandler_t isr_handler; /** - * @brief Pointer to current transaction buffer + * @brief Pointer to current transaction buffer. */ - uint8_t *rxdata; + void *rxdata; /** - * @brief Current transaction length + * @brief Current transaction length in bytes. */ size_t datalen; /** @@ -266,15 +236,15 @@ struct NANDDriver { /** * @brief Memory mapping for data. */ - uint8_t *map_data; + uint16_t *map_data; /** * @brief Memory mapping for commands. */ - uint8_t *map_cmd; + uint16_t *map_cmd; /** * @brief Memory mapping for addresses. */ - uint8_t *map_addr; + uint16_t *map_addr; /** * @brief Pointer to bad block map. * @details One bit per block. All memory allocation is user's responsibility. @@ -304,21 +274,21 @@ extern "C" { void nand_lld_init(void); void nand_lld_start(NANDDriver *nandp); void nand_lld_stop(NANDDriver *nandp); - void nand_lld_read_data(NANDDriver *nandp, uint8_t *data, + uint8_t nand_lld_erase(NANDDriver *nandp, uint8_t *addr, size_t addrlen); + void nand_lld_read_data(NANDDriver *nandp, uint16_t *data, size_t datalen, uint8_t *addr, size_t addrlen, uint32_t *ecc); - void nand_lld_polled_read_data(NANDDriver *nandp, uint8_t *data, size_t len); void nand_lld_write_addr(NANDDriver *nandp, const uint8_t *addr, size_t len); void nand_lld_write_cmd(NANDDriver *nandp, uint8_t cmd); - uint8_t nand_lld_erase(NANDDriver *nandp, uint8_t *addr, size_t addrlen); - uint8_t nand_lld_write_data(NANDDriver *nandp, const uint8_t *data, + uint8_t nand_lld_write_data(NANDDriver *nandp, const uint16_t *data, size_t datalen, uint8_t *addr, size_t addrlen, uint32_t *ecc); uint8_t nand_lld_read_status(NANDDriver *nandp); + void nand_lld_reset(NANDDriver *nandp); #ifdef __cplusplus } #endif #endif /* HAL_USE_NAND */ -#endif /* _NAND_LLD_H_ */ +#endif /* HAL_NAND_LLD_H_ */ /** @} */ |