forked from Imagelibrary/rtems
2011-07-01 Stephan Hoffmann <sho@reLinux.de>
Sebastian Huber <sebastian.huber@embedded-brains.de> * 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.
This commit is contained in:
@@ -1,3 +1,11 @@
|
|||||||
|
2011-07-01 Stephan Hoffmann <sho@reLinux.de>
|
||||||
|
Sebastian Huber <sebastian.huber@embedded-brains.de>
|
||||||
|
|
||||||
|
* 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 <ralf.corsepius@rtems.org>
|
2011-06-19 Ralf Corsépius <ralf.corsepius@rtems.org>
|
||||||
|
|
||||||
* Makefile.am: Fix broken path to cache_.h.
|
* Makefile.am: Fix broken path to cache_.h.
|
||||||
|
|||||||
@@ -125,6 +125,7 @@ libbsp_a_SOURCES += misc/timer.c \
|
|||||||
misc/nand-mlc.c \
|
misc/nand-mlc.c \
|
||||||
misc/nand-mlc-read-blocks.c \
|
misc/nand-mlc-read-blocks.c \
|
||||||
misc/nand-mlc-write-blocks.c \
|
misc/nand-mlc-write-blocks.c \
|
||||||
|
misc/nand-mlc-erase-block-safe.c \
|
||||||
misc/restart.c \
|
misc/restart.c \
|
||||||
misc/boot.c \
|
misc/boot.c \
|
||||||
misc/emc.c \
|
misc/emc.c \
|
||||||
|
|||||||
@@ -7,12 +7,15 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2010
|
* Copyright (c) 2010-2011 embedded brains GmbH. All rights reserved.
|
||||||
* embedded brains GmbH
|
*
|
||||||
* Obere Lagerstr. 30
|
* embedded brains GmbH
|
||||||
* D-82178 Puchheim
|
* Obere Lagerstr. 30
|
||||||
* Germany
|
* 82178 Puchheim
|
||||||
* <rtems@embedded-brains.de>
|
* Germany
|
||||||
|
* <rtems@embedded-brains.de>
|
||||||
|
*
|
||||||
|
* Copyright (c) 2011 Stephan Hoffmann <sho@reLinux.de>
|
||||||
*
|
*
|
||||||
* The license and distribution terms for this file may be
|
* The license and distribution terms for this file may be
|
||||||
* found in the file LICENSE in this distribution or at
|
* found in the file LICENSE in this distribution or at
|
||||||
@@ -165,6 +168,19 @@ extern "C" {
|
|||||||
|
|
||||||
#define MLC_BAD_BLOCK_MASK ((uint32_t) 0xff00)
|
#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
|
* @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);
|
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.
|
* @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_SUCCESSFUL Successful operation.
|
||||||
* @retval RTEMS_INVALID_ID Invalid @a block_begin or @a block_end value.
|
* @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(
|
rtems_status_code lpc32xx_mlc_write_blocks(
|
||||||
uint32_t block_begin,
|
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;
|
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
|
#ifdef __cplusplus
|
||||||
|
|||||||
@@ -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
|
||||||
|
* <rtems@embedded-brains.de>
|
||||||
|
*
|
||||||
|
* 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 <bsp/nand-mlc.h>
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <bsp.h>
|
||||||
|
|
||||||
|
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
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -7,12 +7,13 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2010
|
* Copyright (c) 2010-2011 embedded brains GmbH. All rights reserved.
|
||||||
* embedded brains GmbH
|
*
|
||||||
* Obere Lagerstr. 30
|
* embedded brains GmbH
|
||||||
* D-82178 Puchheim
|
* Obere Lagerstr. 30
|
||||||
* Germany
|
* 82178 Puchheim
|
||||||
* <rtems@embedded-brains.de>
|
* Germany
|
||||||
|
* <rtems@embedded-brains.de>
|
||||||
*
|
*
|
||||||
* The license and distribution terms for this file may be
|
* The license and distribution terms for this file may be
|
||||||
* found in the file LICENSE in this distribution or at
|
* found in the file LICENSE in this distribution or at
|
||||||
@@ -21,10 +22,6 @@
|
|||||||
|
|
||||||
#include <bsp/nand-mlc.h>
|
#include <bsp/nand-mlc.h>
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include <bsp.h>
|
|
||||||
|
|
||||||
static const uint32_t ones_spare [MLC_LARGE_SPARE_WORD_COUNT] = {
|
static const uint32_t ones_spare [MLC_LARGE_SPARE_WORD_COUNT] = {
|
||||||
0xffffffff,
|
0xffffffff,
|
||||||
0xffffffff,
|
0xffffffff,
|
||||||
@@ -44,61 +41,6 @@ static const uint32_t ones_spare [MLC_LARGE_SPARE_WORD_COUNT] = {
|
|||||||
0xffffffff
|
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(
|
rtems_status_code lpc32xx_mlc_write_blocks(
|
||||||
uint32_t block_begin,
|
uint32_t block_begin,
|
||||||
uint32_t block_end,
|
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 first_page_of_block = block * pages_per_block;
|
||||||
uint32_t page = 0;
|
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) {
|
if (sc != RTEMS_SUCCESSFUL) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user