From 03d210895f393b6eba617ac945a729f70c7101a4 Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Fri, 1 Jul 2011 13:05:06 +0000 Subject: 2011-07-01 Stephan Hoffmann Sebastian Huber * misc/nand-mlc-erase-block-safe.c: New file * Makefile.am: Reflect change from above. * misc/nand-mlc-write-blocks.c: Use lpc32xx_mlc_erase_block_safe_3(). * include/nand-mlc.h: Bad block handling. --- c/src/lib/libbsp/arm/lpc32xx/ChangeLog | 8 ++ c/src/lib/libbsp/arm/lpc32xx/Makefile.am | 1 + c/src/lib/libbsp/arm/lpc32xx/include/nand-mlc.h | 66 +++++++++++++-- .../arm/lpc32xx/misc/nand-mlc-erase-block-safe.c | 94 ++++++++++++++++++++++ .../arm/lpc32xx/misc/nand-mlc-write-blocks.c | 78 +++--------------- 5 files changed, 174 insertions(+), 73 deletions(-) create mode 100644 c/src/lib/libbsp/arm/lpc32xx/misc/nand-mlc-erase-block-safe.c (limited to 'c/src') diff --git a/c/src/lib/libbsp/arm/lpc32xx/ChangeLog b/c/src/lib/libbsp/arm/lpc32xx/ChangeLog index 5e3582d11d..df256ec869 100644 --- a/c/src/lib/libbsp/arm/lpc32xx/ChangeLog +++ b/c/src/lib/libbsp/arm/lpc32xx/ChangeLog @@ -1,3 +1,11 @@ +2011-07-01 Stephan Hoffmann + Sebastian Huber + + * misc/nand-mlc-erase-block-safe.c: New file + * Makefile.am: Reflect change from above. + * misc/nand-mlc-write-blocks.c: Use lpc32xx_mlc_erase_block_safe_3(). + * include/nand-mlc.h: Bad block handling. + 2011-06-19 Ralf Corsépius * Makefile.am: Fix broken path to cache_.h. diff --git a/c/src/lib/libbsp/arm/lpc32xx/Makefile.am b/c/src/lib/libbsp/arm/lpc32xx/Makefile.am index 4b03978eec..afb268de67 100644 --- a/c/src/lib/libbsp/arm/lpc32xx/Makefile.am +++ b/c/src/lib/libbsp/arm/lpc32xx/Makefile.am @@ -125,6 +125,7 @@ libbsp_a_SOURCES += misc/timer.c \ misc/nand-mlc.c \ misc/nand-mlc-read-blocks.c \ misc/nand-mlc-write-blocks.c \ + misc/nand-mlc-erase-block-safe.c \ misc/restart.c \ misc/boot.c \ misc/emc.c \ diff --git a/c/src/lib/libbsp/arm/lpc32xx/include/nand-mlc.h b/c/src/lib/libbsp/arm/lpc32xx/include/nand-mlc.h index 4e70345716..29ad8d04b4 100644 --- a/c/src/lib/libbsp/arm/lpc32xx/include/nand-mlc.h +++ b/c/src/lib/libbsp/arm/lpc32xx/include/nand-mlc.h @@ -7,12 +7,15 @@ */ /* - * Copyright (c) 2010 - * embedded brains GmbH - * Obere Lagerstr. 30 - * D-82178 Puchheim - * Germany - * + * Copyright (c) 2010-2011 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * + * + * Copyright (c) 2011 Stephan Hoffmann * * The license and distribution terms for this file may be * found in the file LICENSE in this distribution or at @@ -165,6 +168,19 @@ extern "C" { #define MLC_BAD_BLOCK_MASK ((uint32_t) 0xff00) +/** + * @brief Bad block mark. + * + * We define our own bad block mark to be able to recognize the blocks that + * have been marked bad during operation later. + */ +#define MLC_BAD_BLOCK_MARK ((uint32_t) 0xbadb) + +/** + * @brief The bytes 4 and 5 are reserved for bad block handling. + */ +#define MLC_RESERVED ((uint32_t) 0xffff) + /** * @name NAND Status Register * @@ -252,6 +268,32 @@ rtems_status_code lpc32xx_mlc_read_page( */ rtems_status_code lpc32xx_mlc_erase_block(uint32_t block_index); +/** + * @brief Erases the block with index @a block_index. + * + * In case of an erase error all pages and the spare areas of this block are + * programmed with zero values. This will mark the first and second page as + * bad. + * + * @retval RTEMS_SUCCESSFUL Successful operation. + * @retval RTEMS_INCORRECT_STATE The first or second page of this block is bad. + * @retval RTEMS_INVALID_ID Invalid @a block_index value. + * @retval RTEMS_IO_ERROR Erase error. + */ +rtems_status_code lpc32xx_mlc_erase_block_safe(uint32_t block_index); + +/** + * @brief Erases the block with index @a block_index. + * + * Variant of lpc32xx_mlc_erase_block_safe() with more parameters for + * efficiency reasons. + */ +rtems_status_code lpc32xx_mlc_erase_block_safe_3( + uint32_t block_index, + uint32_t first_page_of_block, + uint32_t pages_per_block +); + /** * @brief Writes the page with index @a page_index. * @@ -278,7 +320,7 @@ rtems_status_code lpc32xx_mlc_write_page_with_ecc( * * @retval RTEMS_SUCCESSFUL Successful operation. * @retval RTEMS_INVALID_ID Invalid @a block_begin or @a block_end value. - * @retval RTEMS_IO_ERROR To many bad blocks or source area to big. + * @retval RTEMS_IO_ERROR Too many bad blocks or source area too big. */ rtems_status_code lpc32xx_mlc_write_blocks( uint32_t block_begin, @@ -328,6 +370,16 @@ static inline bool lpc32xx_mlc_is_bad_page(const uint32_t *spare) return (spare [1] & MLC_BAD_BLOCK_MASK) != MLC_BAD_BLOCK_MASK; } +static inline void lpc32xx_mlc_set_bad_page(uint32_t *spare) +{ + spare [1] = MLC_BAD_BLOCK_MARK; +} + +static inline void lpc32xx_mlc_set_reserved(uint32_t *spare) +{ + spare [1] = MLC_RESERVED; +} + /** @} */ #ifdef __cplusplus diff --git a/c/src/lib/libbsp/arm/lpc32xx/misc/nand-mlc-erase-block-safe.c b/c/src/lib/libbsp/arm/lpc32xx/misc/nand-mlc-erase-block-safe.c new file mode 100644 index 0000000000..e7b49f58e7 --- /dev/null +++ b/c/src/lib/libbsp/arm/lpc32xx/misc/nand-mlc-erase-block-safe.c @@ -0,0 +1,94 @@ +/** + * @file + * + * @ingroup lpc32xx_nand_mlc + * + * @brief lpc32xx_mlc_erase_block_safe() and lpc32xx_mlc_erase_block_safe_3() + * implementation. + */ + +/* + * Copyright (c) 2011 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + */ + +#include + +#include + +#include + +static void zero_block(uint32_t first_page_of_block, uint32_t pages_per_block) +{ + uint32_t page = 0; + + for (page = 0; page < pages_per_block; ++page) { + lpc32xx_mlc_write_page_with_ecc( + first_page_of_block + page, + lpc32xx_magic_zero_begin, + lpc32xx_magic_zero_begin + ); + } +} + +static bool is_bad_page( + uint32_t first_page_of_block, + uint32_t page +) +{ + uint32_t spare [MLC_LARGE_SPARE_WORD_COUNT]; + + memset(spare, 0, MLC_LARGE_SPARE_SIZE); + lpc32xx_mlc_read_page( + first_page_of_block + page, + lpc32xx_magic_zero_begin, + spare + ); + return lpc32xx_mlc_is_bad_page(spare); +} + +rtems_status_code lpc32xx_mlc_erase_block_safe_3( + uint32_t block_index, + uint32_t first_page_of_block, + uint32_t pages_per_block +) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + + if (is_bad_page(first_page_of_block, 0)) { + return RTEMS_INCORRECT_STATE; + } + + if (is_bad_page(first_page_of_block, 1)) { + return RTEMS_INCORRECT_STATE; + } + + sc = lpc32xx_mlc_erase_block(block_index); + if (sc != RTEMS_SUCCESSFUL) { + zero_block(first_page_of_block, pages_per_block); + + return RTEMS_IO_ERROR; + } + + return RTEMS_SUCCESSFUL; +} + +rtems_status_code lpc32xx_mlc_erase_block_safe(uint32_t block_index) +{ + uint32_t pages_per_block = lpc32xx_mlc_pages_per_block(); + + return lpc32xx_mlc_erase_block_safe_3( + block_index, + block_index * pages_per_block, + pages_per_block + ); +} diff --git a/c/src/lib/libbsp/arm/lpc32xx/misc/nand-mlc-write-blocks.c b/c/src/lib/libbsp/arm/lpc32xx/misc/nand-mlc-write-blocks.c index 8b9c438602..b95c9e1399 100644 --- a/c/src/lib/libbsp/arm/lpc32xx/misc/nand-mlc-write-blocks.c +++ b/c/src/lib/libbsp/arm/lpc32xx/misc/nand-mlc-write-blocks.c @@ -7,12 +7,13 @@ */ /* - * Copyright (c) 2010 - * embedded brains GmbH - * Obere Lagerstr. 30 - * D-82178 Puchheim - * Germany - * + * Copyright (c) 2010-2011 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * * * The license and distribution terms for this file may be * found in the file LICENSE in this distribution or at @@ -21,10 +22,6 @@ #include -#include - -#include - static const uint32_t ones_spare [MLC_LARGE_SPARE_WORD_COUNT] = { 0xffffffff, 0xffffffff, @@ -44,61 +41,6 @@ static const uint32_t ones_spare [MLC_LARGE_SPARE_WORD_COUNT] = { 0xffffffff }; -static void zero_block(uint32_t first_page_of_block, uint32_t pages_per_block) -{ - uint32_t page = 0; - - for (page = 0; page < pages_per_block; ++page) { - lpc32xx_mlc_write_page_with_ecc( - first_page_of_block + page, - lpc32xx_magic_zero_begin, - lpc32xx_magic_zero_begin - ); - } -} - -static bool is_bad_page( - uint32_t first_page_of_block, - uint32_t page -) -{ - uint32_t spare [MLC_LARGE_SPARE_WORD_COUNT]; - - memset(spare, 0, MLC_LARGE_SPARE_SIZE); - lpc32xx_mlc_read_page( - first_page_of_block + page, - lpc32xx_magic_zero_begin, - spare - ); - return lpc32xx_mlc_is_bad_page(spare); -} - -static rtems_status_code erase_block( - uint32_t block, - uint32_t first_page_of_block, - uint32_t pages_per_block -) -{ - rtems_status_code sc = RTEMS_SUCCESSFUL; - - if (is_bad_page(first_page_of_block, 0)) { - return RTEMS_IO_ERROR; - } - - if (is_bad_page(first_page_of_block, 1)) { - return RTEMS_IO_ERROR; - } - - sc = lpc32xx_mlc_erase_block(block); - if (sc != RTEMS_SUCCESSFUL) { - zero_block(first_page_of_block, pages_per_block); - - return RTEMS_IO_ERROR; - } - - return RTEMS_SUCCESSFUL; -} - rtems_status_code lpc32xx_mlc_write_blocks( uint32_t block_begin, uint32_t block_end, @@ -124,7 +66,11 @@ rtems_status_code lpc32xx_mlc_write_blocks( uint32_t first_page_of_block = block * pages_per_block; uint32_t page = 0; - sc = erase_block(block, first_page_of_block, pages_per_block); + sc = lpc32xx_mlc_erase_block_safe_3( + block, + first_page_of_block, + pages_per_block + ); if (sc != RTEMS_SUCCESSFUL) { continue; } -- cgit v1.2.3