From 88c55f1aaa3875184f43cb345831b2c776ae7d76 Mon Sep 17 00:00:00 2001 From: barthess Date: Fri, 13 Jan 2017 16:43:57 +0300 Subject: FSMC NAND improvements. 1) Implemented 16 bit bus width support 2) Added workaround errata in STM32 --- os/hal/include/hal_nand.h | 18 +-- os/hal/ports/STM32/LLD/FSMCv1/hal_fsmc.h | 13 ++- os/hal/ports/STM32/LLD/FSMCv1/hal_nand_lld.c | 169 +++++++++++++++++++-------- os/hal/ports/STM32/LLD/FSMCv1/hal_nand_lld.h | 23 ++-- os/hal/src/hal_nand.c | 97 +++++++-------- 5 files changed, 198 insertions(+), 122 deletions(-) (limited to 'os') diff --git a/os/hal/include/hal_nand.h b/os/hal/include/hal_nand.h index 7897187..f907152 100644 --- a/os/hal/include/hal_nand.h +++ b/os/hal/include/hal_nand.h @@ -107,21 +107,21 @@ extern "C" { void nandObjectInit(NANDDriver *nandp); void nandStart(NANDDriver *nandp, const NANDConfig *config, bitmap_t *bb_map); void nandStop(NANDDriver *nandp); + uint8_t nandErase(NANDDriver *nandp, uint32_t block); void nandReadPageWhole(NANDDriver *nandp, uint32_t block, uint32_t page, - uint8_t *data, size_t datalen); - void nandMarkBad(NANDDriver *nandp, uint32_t block); + void *data, size_t datalen); void nandReadPageData(NANDDriver *nandp, uint32_t block, uint32_t page, - uint8_t *data, size_t datalen, uint32_t *ecc); + void *data, size_t datalen, uint32_t *ecc); void nandReadPageSpare(NANDDriver *nandp, uint32_t block, uint32_t page, - uint8_t *spare, size_t sparelen); + void *spare, size_t sparelen); uint8_t nandWritePageWhole(NANDDriver *nandp, uint32_t block, uint32_t page, - const uint8_t *data, size_t datalen); + const void *data, size_t datalen); uint8_t nandWritePageData(NANDDriver *nandp, uint32_t block, uint32_t page, - const uint8_t *data, size_t datalen, uint32_t *ecc); + const void *data, size_t datalen, uint32_t *ecc); uint8_t nandWritePageSpare(NANDDriver *nandp, uint32_t block, uint32_t page, - const uint8_t *spare, size_t sparelen); - uint8_t nandReadBadMark(NANDDriver *nandp, uint32_t block, uint32_t page); - uint8_t nandErase(NANDDriver *nandp, uint32_t block); + const void *spare, size_t sparelen); + uint16_t nandReadBadMark(NANDDriver *nandp, uint32_t block, uint32_t page); + void nandMarkBad(NANDDriver *nandp, uint32_t block); bool nandIsBad(NANDDriver *nandp, uint32_t block); #if NAND_USE_MUTUAL_EXCLUSION void nandAcquireBus(NANDDriver *nandp); diff --git a/os/hal/ports/STM32/LLD/FSMCv1/hal_fsmc.h b/os/hal/ports/STM32/LLD/FSMCv1/hal_fsmc.h index f4837f5..51b9428 100644 --- a/os/hal/ports/STM32/LLD/FSMCv1/hal_fsmc.h +++ b/os/hal/ports/STM32/LLD/FSMCv1/hal_fsmc.h @@ -177,10 +177,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 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 5ba1b29..3e2db55 100644 --- a/os/hal/ports/STM32/LLD/FSMCv1/hal_nand_lld.c +++ b/os/hal/ports/STM32/LLD/FSMCv1/hal_nand_lld.c @@ -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. * @@ -142,7 +196,7 @@ static void nand_ready_isr_disable(NANDDriver *nandp) { * * @notapi */ -static void nand_isr_handler (NANDDriver *nandp) { +static void nand_isr_handler(NANDDriver *nandp) { osalSysLockFromISR(); @@ -152,8 +206,8 @@ static void nand_isr_handler (NANDDriver *nandp) { 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; @@ -197,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: @@ -236,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 */ @@ -250,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 */ } @@ -267,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); @@ -277,16 +333,34 @@ 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; @@ -316,24 +390,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 @@ -362,7 +440,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. @@ -371,14 +449,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. */ @@ -390,7 +472,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(); @@ -416,7 +499,10 @@ void nand_lld_reset(NANDDriver *nandp) { nandp->state = NAND_RESET; - nand_lld_write_cmd (nandp, NAND_CMD_RESET); + set_16bit_bus(nandp); + nand_lld_write_cmd(nandp, NAND_CMD_RESET); + set_8bit_bus(nandp); + osalSysLock(); nand_lld_suspend_thread(nandp); osalSysUnlock(); @@ -437,35 +523,19 @@ 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(); return nand_lld_read_status(nandp); } -/** - * @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; imap_data[i]; -} - /** * @brief Send addres to NAND. * @@ -505,13 +575,14 @@ void nand_lld_write_cmd(NANDDriver *nandp, uint8_t cmd) { */ uint8_t nand_lld_read_status(NANDDriver *nandp) { - uint8_t status; - status = 1; /* 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; + 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 ead1a4e..5266138 100644 --- a/os/hal/ports/STM32/LLD/FSMCv1/hal_nand_lld.h +++ b/os/hal/ports/STM32/LLD/FSMCv1/hal_nand_lld.h @@ -134,7 +134,7 @@ typedef struct NANDDriver NANDDriver; /** - * @brief Type of interrupt handler function + * @brief Type of interrupt handler function. */ typedef void (*nandisrhandler_t)(NANDDriver *nandp); @@ -206,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; /** @@ -236,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. @@ -274,13 +274,12 @@ 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); diff --git a/os/hal/src/hal_nand.c b/os/hal/src/hal_nand.c index 2e5c505..a2101d6 100644 --- a/os/hal/src/hal_nand.c +++ b/os/hal/src/hal_nand.c @@ -139,12 +139,13 @@ static void calc_blk_addr(const NANDConfig *cfg, uint32_t block, */ static bool read_is_block_bad(NANDDriver *nandp, size_t block) { - if (0xFF != nandReadBadMark(nandp, block, 0)) - return true; - if (0xFF != nandReadBadMark(nandp, block, 1)) - return true; + uint16_t badmark0 = nandReadBadMark(nandp, block, 0); + uint16_t badmark1 = nandReadBadMark(nandp, block, 1); - return false; + if ((0xFFFF != badmark0) || (0xFFFF != badmark1)) + return true; + else + return false; } /** @@ -260,24 +261,24 @@ void nandStop(NANDDriver *nandp) { * @param[in] nandp pointer to the @p NANDDriver object * @param[in] block block number * @param[in] page page number related to begin of block - * @param[out] data buffer to store data - * @param[in] datalen length of data buffer + * @param[out] data buffer to store data, half word aligned + * @param[in] datalen length of data buffer in bytes, half word aligned * * @api */ void nandReadPageWhole(NANDDriver *nandp, uint32_t block, uint32_t page, - uint8_t *data, size_t datalen) { + void *data, size_t datalen) { const NANDConfig *cfg = nandp->config; - uint8_t addrbuf[8]; - size_t addrlen = cfg->rowcycles + cfg->colcycles; + const size_t addrlen = cfg->rowcycles + cfg->colcycles; + uint8_t addr[addrlen]; osalDbgCheck((nandp != NULL) && (data != NULL)); osalDbgCheck((datalen <= (cfg->page_data_size + cfg->page_spare_size))); osalDbgAssert(nandp->state == NAND_READY, "invalid state"); - calc_addr(cfg, block, page, 0, addrbuf, addrlen); - nand_lld_read_data(nandp, data, datalen, addrbuf, addrlen, NULL); + calc_addr(cfg, block, page, 0, addr, addrlen); + nand_lld_read_data(nandp, data, datalen, addr, addrlen, NULL); } /** @@ -286,20 +287,20 @@ void nandReadPageWhole(NANDDriver *nandp, uint32_t block, uint32_t page, * @param[in] nandp pointer to the @p NANDDriver object * @param[in] block block number * @param[in] page page number related to begin of block - * @param[in] data buffer with data to be written - * @param[in] datalen length of data buffer + * @param[in] data buffer with data to be written, half word aligned + * @param[in] datalen length of data buffer in bytes, half word aligned * * @return The operation status reported by NAND IC (0x70 command). * * @api */ uint8_t nandWritePageWhole(NANDDriver *nandp, uint32_t block, uint32_t page, - const uint8_t *data, size_t datalen) { + const void *data, size_t datalen) { uint8_t retval; const NANDConfig *cfg = nandp->config; - uint8_t addr[8]; - size_t addrlen = cfg->rowcycles + cfg->colcycles; + const size_t addrlen = cfg->rowcycles + cfg->colcycles; + uint8_t addr[addrlen]; osalDbgCheck((nandp != NULL) && (data != NULL)); osalDbgCheck((datalen <= (cfg->page_data_size + cfg->page_spare_size))); @@ -316,25 +317,25 @@ uint8_t nandWritePageWhole(NANDDriver *nandp, uint32_t block, uint32_t page, * @param[in] nandp pointer to the @p NANDDriver object * @param[in] block block number * @param[in] page page number related to begin of block - * @param[out] data buffer to store data - * @param[in] datalen length of data buffer + * @param[out] data buffer to store data, half word aligned + * @param[in] datalen length of data buffer in bytes, half word aligned * @param[out] ecc pointer to calculated ECC. Ignored when NULL. * * @api */ void nandReadPageData(NANDDriver *nandp, uint32_t block, uint32_t page, - uint8_t *data, size_t datalen, uint32_t *ecc) { + void *data, size_t datalen, uint32_t *ecc) { const NANDConfig *cfg = nandp->config; - uint8_t addrbuf[8]; - size_t addrlen = cfg->rowcycles + cfg->colcycles; + const size_t addrlen = cfg->rowcycles + cfg->colcycles; + uint8_t addr[addrlen]; osalDbgCheck((nandp != NULL) && (data != NULL)); osalDbgCheck((datalen <= cfg->page_data_size)); osalDbgAssert(nandp->state == NAND_READY, "invalid state"); - calc_addr(cfg, block, page, 0, addrbuf, addrlen); - nand_lld_read_data(nandp, data, datalen, addrbuf, addrlen, ecc); + calc_addr(cfg, block, page, 0, addr, addrlen); + nand_lld_read_data(nandp, data, datalen, addr, addrlen, ecc); } /** @@ -343,8 +344,8 @@ void nandReadPageData(NANDDriver *nandp, uint32_t block, uint32_t page, * @param[in] nandp pointer to the @p NANDDriver object * @param[in] block block number * @param[in] page page number related to begin of block - * @param[in] data buffer with data to be written - * @param[in] datalen length of data buffer + * @param[in] data buffer with data to be written, half word aligned + * @param[in] datalen length of data buffer in bytes, half word aligned * @param[out] ecc pointer to calculated ECC. Ignored when NULL. * * @return The operation status reported by NAND IC (0x70 command). @@ -352,12 +353,12 @@ void nandReadPageData(NANDDriver *nandp, uint32_t block, uint32_t page, * @api */ uint8_t nandWritePageData(NANDDriver *nandp, uint32_t block, uint32_t page, - const uint8_t *data, size_t datalen, uint32_t *ecc) { + const void *data, size_t datalen, uint32_t *ecc) { uint8_t retval; const NANDConfig *cfg = nandp->config; - uint8_t addr[8]; - size_t addrlen = cfg->rowcycles + cfg->colcycles; + const size_t addrlen = cfg->rowcycles + cfg->colcycles; + uint8_t addr[addrlen]; osalDbgCheck((nandp != NULL) && (data != NULL)); osalDbgCheck((datalen <= cfg->page_data_size)); @@ -374,17 +375,17 @@ uint8_t nandWritePageData(NANDDriver *nandp, uint32_t block, uint32_t page, * @param[in] nandp pointer to the @p NANDDriver object * @param[in] block block number * @param[in] page page number related to begin of block - * @param[out] spare buffer to store data - * @param[in] sparelen length of data buffer + * @param[out] spare buffer to store data, half word aligned + * @param[in] sparelen length of data buffer in bytes, half word aligned * * @api */ void nandReadPageSpare(NANDDriver *nandp, uint32_t block, uint32_t page, - uint8_t *spare, size_t sparelen) { + void *spare, size_t sparelen) { const NANDConfig *cfg = nandp->config; - uint8_t addr[8]; - size_t addrlen = cfg->rowcycles + cfg->colcycles; + const size_t addrlen = cfg->rowcycles + cfg->colcycles; + uint8_t addr[addrlen]; osalDbgCheck((NULL != spare) && (nandp != NULL)); osalDbgCheck(sparelen <= cfg->page_spare_size); @@ -400,19 +401,19 @@ void nandReadPageSpare(NANDDriver *nandp, uint32_t block, uint32_t page, * @param[in] nandp pointer to the @p NANDDriver object * @param[in] block block number * @param[in] page page number related to begin of block - * @param[in] spare buffer with spare data to be written - * @param[in] sparelen length of data buffer + * @param[in] spare buffer with spare data to be written, half word aligned + * @param[in] sparelen length of data buffer in bytes, half word aligned * * @return The operation status reported by NAND IC (0x70 command). * * @api */ uint8_t nandWritePageSpare(NANDDriver *nandp, uint32_t block, uint32_t page, - const uint8_t *spare, size_t sparelen) { + const void *spare, size_t sparelen) { const NANDConfig *cfg = nandp->config; - uint8_t addr[8]; - size_t addrlen = cfg->rowcycles + cfg->colcycles; + const size_t addrlen = cfg->rowcycles + cfg->colcycles; + uint8_t addr[addrlen]; osalDbgCheck((NULL != spare) && (nandp != NULL)); osalDbgCheck(sparelen <= cfg->page_spare_size); @@ -432,10 +433,10 @@ uint8_t nandWritePageSpare(NANDDriver *nandp, uint32_t block, uint32_t page, */ void nandMarkBad(NANDDriver *nandp, uint32_t block) { - uint8_t bb_mark[2] = {0, 0}; + uint16_t bb_mark = 0; - nandWritePageSpare(nandp, block, 0, bb_mark, sizeof(bb_mark)); - nandWritePageSpare(nandp, block, 1, bb_mark, sizeof(bb_mark)); + nandWritePageSpare(nandp, block, 0, &bb_mark, sizeof(bb_mark)); + nandWritePageSpare(nandp, block, 1, &bb_mark, sizeof(bb_mark)); if (NULL != nandp->bb_map) bitmapSet(nandp->bb_map, block); @@ -452,11 +453,11 @@ void nandMarkBad(NANDDriver *nandp, uint32_t block) { * * @api */ -uint8_t nandReadBadMark(NANDDriver *nandp, uint32_t block, uint32_t page) { - uint8_t bb_mark[1]; +uint16_t nandReadBadMark(NANDDriver *nandp, uint32_t block, uint32_t page) { + uint16_t bb_mark; - nandReadPageSpare(nandp, block, page, bb_mark, sizeof(bb_mark)); - return bb_mark[0]; + nandReadPageSpare(nandp, block, page, &bb_mark, sizeof(bb_mark)); + return bb_mark; } /** @@ -472,8 +473,8 @@ uint8_t nandReadBadMark(NANDDriver *nandp, uint32_t block, uint32_t page) { uint8_t nandErase(NANDDriver *nandp, uint32_t block) { const NANDConfig *cfg = nandp->config; - uint8_t addr[4]; - size_t addrlen = cfg->rowcycles; + const size_t addrlen = cfg->rowcycles; + uint8_t addr[addrlen]; osalDbgCheck(nandp != NULL); osalDbgAssert(nandp->state == NAND_READY, "invalid state"); -- cgit v1.2.3