diff options
Diffstat (limited to 'os/hal')
| -rw-r--r-- | os/hal/include/nand.h | 31 | ||||
| -rw-r--r-- | os/hal/ports/STM32/LLD/FSMCv1/nand_lld.c | 22 | ||||
| -rw-r--r-- | os/hal/ports/STM32/LLD/FSMCv1/nand_lld.h | 23 | ||||
| -rw-r--r-- | os/hal/src/nand.c | 141 | 
4 files changed, 96 insertions, 121 deletions
| 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; i<len; i++) @@ -467,7 +469,7 @@ void nand_lld_polled_read_data(NANDDriver *nandp, uint8_t *data, size_t len){   *   * @notapi   */ -void nand_lld_write_addr(NANDDriver *nandp, const uint8_t *addr, size_t len){ +void nand_lld_write_addr(NANDDriver *nandp, const uint8_t *addr, size_t len) {    size_t i = 0;    for (i=0; i<len; i++) @@ -482,7 +484,7 @@ void nand_lld_write_addr(NANDDriver *nandp, const uint8_t *addr, size_t len){   *   * @notapi   */ -void nand_lld_write_cmd(NANDDriver *nandp, uint8_t cmd){ +void nand_lld_write_cmd(NANDDriver *nandp, uint8_t cmd) {    nandp->map_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; b<maplen; b++) -    nandp->config->bb_map[b] = 0; +  bitmapObjectInit(nandp->bb_map, 0);    /* now write numbers of bad block to map */ -  for (b=0; b<blocks; b++){ -    m0 = nandReadBadMark(nandp, b, 0); -    m1 = nandReadBadMark(nandp, b, 1); -    if ((0xFF != m0) || (0xFF != m1)){ -      bad_map_update(nandp, b); +  for (b=0; b<blocks; b++) { +    if (read_is_block_bad(nandp, b)) { +      bitmapSet(nandp->bb_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__) | 
