From c44092eb0f32b0e1903c99e3f734f3134f01b52c Mon Sep 17 00:00:00 2001 From: barthess Date: Sat, 2 May 2015 20:51:04 +0300 Subject: NAND code changed to use bitmap class --- os/hal/include/nand.h | 31 +++---- os/hal/ports/STM32/LLD/FSMCv1/nand_lld.c | 22 ++--- os/hal/ports/STM32/LLD/FSMCv1/nand_lld.h | 23 +++-- os/hal/src/nand.c | 141 +++++++++++++------------------ 4 files changed, 96 insertions(+), 121 deletions(-) (limited to 'os/hal') diff --git a/os/hal/include/nand.h b/os/hal/include/nand.h index e20add3..350f77b 100644 --- a/os/hal/include/nand.h +++ b/os/hal/include/nand.h @@ -111,31 +111,28 @@ extern "C" { #endif void nandInit(void); void nandObjectInit(NANDDriver *nandp); - void nandStart(NANDDriver *nandp, const NANDConfig *config); + void nandStart(NANDDriver *nandp, const NANDConfig *config, bitmap_t *bb_map); void nandStop(NANDDriver *nandp); - void nandReadPageWhole(NANDDriver *nandp, uint32_t block, - uint32_t page, uint8_t *data, size_t datalen); - uint8_t nandWritePageWhole(NANDDriver *nandp, uint32_t block, - uint32_t page, const uint8_t *data, size_t datalen); - void nandReadPageData(NANDDriver *nandp, uint32_t block, - uint32_t page, uint8_t *data, size_t datalen, uint32_t *ecc); - uint8_t nandWritePageData(NANDDriver *nandp, uint32_t block, - uint32_t page, const uint8_t *data, size_t datalen, uint32_t *ecc); - void nandReadPageSpare(NANDDriver *nandp, uint32_t block, - uint32_t page, uint8_t *spare, size_t sparelen); - uint8_t nandWritePageSpare(NANDDriver *nandp, uint32_t block, - uint32_t page, const uint8_t *spare, size_t sparelen); + void nandReadPageWhole(NANDDriver *nandp, uint32_t block, uint32_t page, + uint8_t *data, size_t datalen); void nandMarkBad(NANDDriver *nandp, uint32_t block); - uint8_t nandReadBadMark(NANDDriver *nandp, - uint32_t block, uint32_t page); + void nandReadPageData(NANDDriver *nandp, uint32_t block, uint32_t page, + uint8_t *data, size_t datalen, uint32_t *ecc); + void nandReadPageSpare(NANDDriver *nandp, uint32_t block, uint32_t page, + uint8_t *spare, size_t sparelen); + uint8_t nandWritePageWhole(NANDDriver *nandp, uint32_t block, uint32_t page, + const uint8_t *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); + 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); bool nandIsBad(NANDDriver *nandp, uint32_t block); - #if NAND_USE_MUTUAL_EXCLUSION void nandAcquireBus(NANDDriver *nandp); void nandReleaseBus(NANDDriver *nandp); #endif /* NAND_USE_MUTUAL_EXCLUSION */ - #ifdef __cplusplus } #endif diff --git a/os/hal/ports/STM32/LLD/FSMCv1/nand_lld.c b/os/hal/ports/STM32/LLD/FSMCv1/nand_lld.c index d187161..cd2f421 100644 --- a/os/hal/ports/STM32/LLD/FSMCv1/nand_lld.c +++ b/os/hal/ports/STM32/LLD/FSMCv1/nand_lld.c @@ -70,7 +70,7 @@ NANDDriver NANDD2; * * @notapi */ -static void wakeup_isr(NANDDriver *nandp){ +static void wakeup_isr(NANDDriver *nandp) { osalDbgCheck(nandp->thread != NULL); osalThreadResumeI(&nandp->thread, MSG_OK); @@ -91,7 +91,7 @@ static void nand_lld_suspend_thread(NANDDriver *nandp) { * * @param[in] nandp pointer to the @p NANDDriver object */ -static uint32_t calc_eccps(NANDDriver *nandp){ +static uint32_t calc_eccps(NANDDriver *nandp) { uint32_t i = 0; uint32_t eccps = nandp->config->page_data_size; @@ -148,7 +148,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(); @@ -252,6 +252,7 @@ void nand_lld_init(void) { 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.bb_map = NULL; #endif /* STM32_NAND_USE_FSMC_NAND1 */ #if STM32_NAND_USE_FSMC_NAND2 @@ -265,6 +266,7 @@ void nand_lld_init(void) { 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.bb_map = NULL; #endif /* STM32_NAND_USE_FSMC_NAND2 */ } @@ -332,8 +334,8 @@ void nand_lld_stop(NANDDriver *nandp) { * * @notapi */ -void nand_lld_read_data(NANDDriver *nandp, uint8_t *data, - size_t datalen, uint8_t *addr, size_t addrlen, uint32_t *ecc){ +void nand_lld_read_data(NANDDriver *nandp, uint8_t *data, size_t datalen, + uint8_t *addr, size_t addrlen, uint32_t *ecc){ nandp->state = NAND_READ; nandp->rxdata = data; @@ -381,7 +383,7 @@ void nand_lld_read_data(NANDDriver *nandp, uint8_t *data, * @notapi */ uint8_t nand_lld_write_data(NANDDriver *nandp, const uint8_t *data, - size_t datalen, uint8_t *addr, size_t addrlen, uint32_t *ecc){ + size_t datalen, uint8_t *addr, size_t addrlen, uint32_t *ecc) { nandp->state = NAND_WRITE; @@ -425,7 +427,7 @@ uint8_t nand_lld_write_data(NANDDriver *nandp, const uint8_t *data, * * @notapi */ -uint8_t nand_lld_erase(NANDDriver *nandp, uint8_t *addr, size_t addrlen){ +uint8_t nand_lld_erase(NANDDriver *nandp, uint8_t *addr, size_t addrlen) { nandp->state = NAND_ERASE; @@ -451,7 +453,7 @@ uint8_t nand_lld_erase(NANDDriver *nandp, uint8_t *addr, size_t addrlen){ * * @notapi */ -void nand_lld_polled_read_data(NANDDriver *nandp, uint8_t *data, size_t len){ +void nand_lld_polled_read_data(NANDDriver *nandp, uint8_t *data, size_t len) { size_t i = 0; for (i=0; imap_cmd[0] = cmd; } diff --git a/os/hal/ports/STM32/LLD/FSMCv1/nand_lld.h b/os/hal/ports/STM32/LLD/FSMCv1/nand_lld.h index f136df4..1d2edef 100644 --- a/os/hal/ports/STM32/LLD/FSMCv1/nand_lld.h +++ b/os/hal/ports/STM32/LLD/FSMCv1/nand_lld.h @@ -26,6 +26,7 @@ #define _NAND_LLD_H_ #include "fsmc.h" +#include "bitmap.h" #if HAL_USE_NAND || defined(__DOXYGEN__) @@ -167,7 +168,7 @@ typedef struct { /** * @brief Pointer to lower level driver. */ - FSMCDriver *fsmcp; + //const FSMCDriver *fsmcp; /** * @brief Number of erase blocks in NAND device. */ @@ -184,13 +185,6 @@ typedef struct { * @brief Number of pages in block. */ uint32_t pages_per_block; -#if NAND_USE_BAD_MAP - /** - * @brief Pointer to bad block map. - * @details One bit per block. Memory for map must be allocated by user. - */ - uint32_t *bb_map; -#endif /* NAND_USE_BAD_MAP */ /** * @brief Number of write cycles for row addressing. */ @@ -287,6 +281,11 @@ struct NANDDriver { * @brief Memory mapping for addresses. */ uint8_t *map_addr; + /** + * @brief Pointer to bad block map. + * @details One bit per block. All memory allocation is user's responsibility. + */ + bitmap_t *bb_map; }; /*===========================================================================*/ @@ -311,14 +310,14 @@ extern "C" { void nand_lld_init(void); void nand_lld_start(NANDDriver *nandp); void nand_lld_stop(NANDDriver *nandp); - uint8_t nand_lld_write_data(NANDDriver *nandp, const uint8_t *data, - size_t datalen, uint8_t *addr, size_t addrlen, uint32_t *ecc); void nand_lld_read_data(NANDDriver *nandp, uint8_t *data, - size_t datalen, uint8_t *addr, size_t addrlen, uint32_t *ecc); + 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); - uint8_t nand_lld_erase(NANDDriver *nandp, uint8_t *addr, size_t addrlen); 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, + size_t datalen, uint8_t *addr, size_t addrlen, uint32_t *ecc); uint8_t nand_lld_read_status(NANDDriver *nandp); #ifdef __cplusplus } diff --git a/os/hal/src/nand.c b/os/hal/src/nand.c index 9135d1a..2b935c3 100644 --- a/os/hal/src/nand.c +++ b/os/hal/src/nand.c @@ -62,7 +62,7 @@ * * @notapi */ -static void pagesize_check(size_t page_data_size){ +static void pagesize_check(size_t page_data_size) { /* Page size out of bounds.*/ osalDbgCheck((page_data_size >= NAND_MIN_PAGE_SIZE) && @@ -85,9 +85,8 @@ static void pagesize_check(size_t page_data_size){ * * @notapi */ -static void calc_addr(const NANDConfig *cfg, - uint32_t block, uint32_t page, uint32_t offset, - uint8_t *addr, size_t addr_len){ +static void calc_addr(const NANDConfig *cfg, uint32_t block, uint32_t page, + uint32_t offset, uint8_t *addr, size_t addr_len) { size_t i = 0; uint32_t row = 0; @@ -121,8 +120,8 @@ static void calc_addr(const NANDConfig *cfg, * * @notapi */ -static void calc_blk_addr(const NANDConfig *cfg, - uint32_t block, uint8_t *addr, size_t addr_len){ +static void calc_blk_addr(const NANDConfig *cfg, uint32_t block, + uint8_t *addr, size_t addr_len) { size_t i = 0; uint32_t row = 0; @@ -139,59 +138,55 @@ static void calc_blk_addr(const NANDConfig *cfg, } } -#if NAND_USE_BAD_MAP /** - * @brief Add new bad block to map. + * @brief Read block badness mark directly from NAND memory array. * * @param[in] nandp pointer to the @p NANDDriver object * @param[in] block block number - * @param[in] map pointer to bad block map + * + * @return block condition + * @retval true if the block is bad. + * @retval false if the block is good. + * + * @notapi */ -static void bad_map_update(NANDDriver *nandp, size_t block) { - - uint32_t *map = nandp->config->bb_map; - const size_t BPMC = sizeof(uint32_t) * 8; /* bits per map claster */ - size_t i; - size_t shift; +static bool read_is_block_bad(NANDDriver *nandp, size_t block) { + uint8_t m0; + uint8_t m1; - /* Nand device overflow.*/ - osalDbgCheck(nandp->config->blocks > block); + m0 = nandReadBadMark(nandp, block, 0); + m1 = nandReadBadMark(nandp, block, 1); - i = block / BPMC; - shift = block % BPMC; - /* This block already mapped.*/ - osalDbgCheck(((map[i] >> shift) & 1) != 1); - map[i] |= (uint32_t)1 << shift; + if ((0xFF != m0) || (0xFF != m1)) + return true; + else + return false; } /** * @brief Scan for bad blocks and fill map with their numbers. * * @param[in] nandp pointer to the @p NANDDriver object + * + * @notapi */ static void scan_bad_blocks(NANDDriver *nandp) { const size_t blocks = nandp->config->blocks; - const size_t maplen = blocks / 32; - size_t b; - uint8_t m0; - uint8_t m1; + + osalDbgCheck(bitmapGetBitsCount(nandp->bb_map) >= blocks); /* clear map just to be safe */ - for (b=0; bconfig->bb_map[b] = 0; + bitmapObjectInit(nandp->bb_map, 0); /* now write numbers of bad block to map */ - for (b=0; bbb_map, b); } } } -#endif /* NAND_USE_BAD_MAP */ /*===========================================================================*/ /* Driver exported functions. */ @@ -235,10 +230,11 @@ void nandObjectInit(NANDDriver *nandp) { * * @param[in] nandp pointer to the @p NANDDriver object * @param[in] config pointer to the @p NANDConfig object + * @param[in] bb_map pointer to the bad block map or @NULL if not need * * @api */ -void nandStart(NANDDriver *nandp, const NANDConfig *config) { +void nandStart(NANDDriver *nandp, const NANDConfig *config, bitmap_t *bb_map) { osalDbgCheck((nandp != NULL) && (config != NULL)); osalDbgAssert((nandp->state == NAND_STOP) || @@ -250,9 +246,10 @@ void nandStart(NANDDriver *nandp, const NANDConfig *config) { nand_lld_start(nandp); nandp->state = NAND_READY; -#if NAND_USE_BAD_MAP - scan_bad_blocks(nandp); -#endif /* NAND_USE_BAD_MAP */ + if (NULL != bb_map) { + nandp->bb_map = bb_map; + scan_bad_blocks(nandp); + } } /** @@ -283,8 +280,8 @@ void nandStop(NANDDriver *nandp) { * * @api */ -void nandReadPageWhole(NANDDriver *nandp, uint32_t block, - uint32_t page, uint8_t *data, size_t datalen) { +void nandReadPageWhole(NANDDriver *nandp, uint32_t block, uint32_t page, + uint8_t *data, size_t datalen) { const NANDConfig *cfg = nandp->config; uint8_t addrbuf[8]; @@ -311,8 +308,8 @@ void nandReadPageWhole(NANDDriver *nandp, uint32_t block, * * @api */ -uint8_t nandWritePageWhole(NANDDriver *nandp, uint32_t block, - uint32_t page, const uint8_t *data, size_t datalen) { +uint8_t nandWritePageWhole(NANDDriver *nandp, uint32_t block, uint32_t page, + const uint8_t *data, size_t datalen) { uint8_t retval; const NANDConfig *cfg = nandp->config; @@ -369,8 +366,8 @@ 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) { +uint8_t nandWritePageData(NANDDriver *nandp, uint32_t block, uint32_t page, + const uint8_t *data, size_t datalen, uint32_t *ecc) { uint8_t retval; const NANDConfig *cfg = nandp->config; @@ -397,8 +394,8 @@ uint8_t nandWritePageData(NANDDriver *nandp, uint32_t block, * * @api */ -void nandReadPageSpare(NANDDriver *nandp, uint32_t block, - uint32_t page, uint8_t *spare, size_t sparelen) { +void nandReadPageSpare(NANDDriver *nandp, uint32_t block, uint32_t page, + uint8_t *spare, size_t sparelen) { const NANDConfig *cfg = nandp->config; uint8_t addr[8]; @@ -425,8 +422,8 @@ void nandReadPageSpare(NANDDriver *nandp, uint32_t block, * * @api */ -uint8_t nandWritePageSpare(NANDDriver *nandp, uint32_t block, - uint32_t page, const uint8_t *spare, size_t sparelen) { +uint8_t nandWritePageSpare(NANDDriver *nandp, uint32_t block, uint32_t page, + const uint8_t *spare, size_t sparelen) { uint8_t retVal; const NANDConfig *cfg = nandp->config; @@ -453,15 +450,12 @@ uint8_t nandWritePageSpare(NANDDriver *nandp, uint32_t block, void nandMarkBad(NANDDriver *nandp, uint32_t block) { uint8_t bb_mark[2] = {0, 0}; - uint8_t op_status; - op_status = nandWritePageSpare(nandp, block, 0, bb_mark, sizeof(bb_mark)); - osalDbgCheck(0 == (op_status & 1)); /* operation failed*/ - op_status = nandWritePageSpare(nandp, block, 1, bb_mark, sizeof(bb_mark)); - osalDbgCheck(0 == (op_status & 1)); /* operation failed*/ - -#if NAND_USE_BAD_MAP - bad_map_update(nandp, block); -#endif + + 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); } /** @@ -475,9 +469,9 @@ void nandMarkBad(NANDDriver *nandp, uint32_t block) { * * @api */ -uint8_t nandReadBadMark(NANDDriver *nandp, - uint32_t block, uint32_t page) { +uint8_t nandReadBadMark(NANDDriver *nandp, uint32_t block, uint32_t page) { uint8_t bb_mark[1]; + nandReadPageSpare(nandp, block, page, bb_mark, sizeof(bb_mark)); return bb_mark[0]; } @@ -492,7 +486,7 @@ uint8_t nandReadBadMark(NANDDriver *nandp, * * @api */ -uint8_t nandErase(NANDDriver *nandp, uint32_t block){ +uint8_t nandErase(NANDDriver *nandp, uint32_t block) { uint8_t retVal; const NANDConfig *cfg = nandp->config; @@ -508,7 +502,7 @@ uint8_t nandErase(NANDDriver *nandp, uint32_t block){ } /** - * @brief Report block badness. + * @brief Check block badness. * * @param[in] nandp pointer to the @p NANDDriver object * @param[in] block block number @@ -519,32 +513,15 @@ uint8_t nandErase(NANDDriver *nandp, uint32_t block){ * * @api */ -bool nandIsBad(NANDDriver *nandp, uint32_t block){ +bool nandIsBad(NANDDriver *nandp, uint32_t block) { osalDbgCheck(nandp != NULL); osalDbgAssert(nandp->state == NAND_READY, "invalid state"); -#if NAND_USE_BAD_MAP - uint32_t *map = nandp->config->bb_map; - const size_t BPMC = sizeof(uint32_t) * 8; /* bits per map claster */ - size_t i; - size_t shift; - - i = block / BPMC; - shift = block % BPMC; - if (((map[i] >> shift) & 1) == 1) - return true; + if (NULL != nandp->bb_map) + return 1 == bitmapGet(nandp->bb_map, block); else - return false; -#else - uint8_t m0, m1; - m0 = nandReadBadMark(nandp, block, 0); - m1 = nandReadBadMark(nandp, block, 1); - if ((0xFF != m0) || (0xFF != m1)) - return true; - else - return false; -#endif /* NAND_USE_BAD_MAP */ + return read_is_block_bad(nandp, block); } #if NAND_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__) -- cgit v1.2.3