aboutsummaryrefslogtreecommitdiffstats
path: root/os/hal/ports/STM32/LLD/FSMCv1
diff options
context:
space:
mode:
Diffstat (limited to 'os/hal/ports/STM32/LLD/FSMCv1')
-rw-r--r--os/hal/ports/STM32/LLD/FSMCv1/hal_fsmc.c16
-rw-r--r--os/hal/ports/STM32/LLD/FSMCv1/hal_fsmc.h56
-rw-r--r--os/hal/ports/STM32/LLD/FSMCv1/hal_fsmc_sdram.c8
-rw-r--r--os/hal/ports/STM32/LLD/FSMCv1/hal_fsmc_sdram.h14
-rw-r--r--os/hal/ports/STM32/LLD/FSMCv1/hal_fsmc_sram.c15
-rw-r--r--os/hal/ports/STM32/LLD/FSMCv1/hal_fsmc_sram.h8
-rw-r--r--os/hal/ports/STM32/LLD/FSMCv1/hal_nand_lld.c209
-rw-r--r--os/hal/ports/STM32/LLD/FSMCv1/hal_nand_lld.h62
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_ */
/** @} */