MTD NAND: Beginning of software ECC logic

This commit is contained in:
Gregory Nutt 2013-11-18 09:43:44 -06:00
parent 22d4eb9cca
commit 3faa880ef1
13 changed files with 806 additions and 116 deletions

View file

@ -6081,4 +6081,6 @@
NAND support (2013-11-17).
* drivers/mtd/mtd_nandscheme.c: More NAND support (2013-11-17).
* include/nuttx/mtd/nand_ecc.h: More NAND (2013-11-17).
* drivers/mtd/hamming.c and mtd_nandecc.c and
include/nuttx/mtd/hamming.h: Beginning of NAND software ECC
calculations. (2013-11-18).

View file

@ -42,12 +42,29 @@
#include <nuttx/config.h>
#include <nuttx/mtd/nand_raw.h>
#include "chip.h"
#include "chip/sam_hsmc.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Hardware ECC types. These are extensions to the NANDECC_HWECC value
* defined in include/nuttx/mtd/nand_raw.h.
*
* NANDECC_CHIPECC ECC is performed internal to chip
* NANDECC_PMECC Programmable Multibit Error Correcting Code (PMECC)
* NANDECC_HSIAO HSIAO ECC
*/
#define NANDECC_CHIPECC (NANDECC_HWECC + 0)
#define NANDECC_PMECC (NANDECC_HWECC + 1)
#define NANDECC_HSIAO (NANDECC_HWECC + 2)
/****************************************************************************
* Public Data
****************************************************************************/
#ifndef __ASSEMBLY__

View file

@ -87,12 +87,6 @@ config ARCH_NAND_HWECC
if MTD_NAND
config MTD_NAND_BLOCKCHECK
bool "Block check"
default y
---help---
Enable support for bad block checking.
config MTD_NAND_MAXNUMBLOCKS
int "Max blocks"
default 1024
@ -123,6 +117,28 @@ config MTD_NAND_MAXSPAREECCBYTES
---help---
Maximum number of ECC bytes stored in the spare for one single page.
config MTD_NAND_BLOCKCHECK
bool "Block check"
default y
---help---
Enable support for ECC and bad block checking.
if MTD_NAND_BLOCKCHECK
config MTD_NAND_SWECC
bool "Sofware ECC support"
default n if ARCH_NAND_HWECC
default y if !ARCH_NAND_HWECC
---help---
Build in logic to support software calculation of ECC.
config MTD_NAND_HWECC
bool "Hardware ECC support"
default n
depends on ARCH_NAND_HWECC
---help---
Build in logic to support hardware calculation of ECC.
config MTD_NAND_MAXSPAREEXTRABYTES
int "Max extra free bytes"
default 206
@ -132,7 +148,7 @@ config MTD_NAND_MAXSPAREEXTRABYTES
config MTD_NAND_MAX_HWECCSIZE
int "Max H/W ECC size"
default 200
depends on ARCH_NAND_HWECC
depends on MTD_NAND_HWECC
---help---
Maximum HW ECC size

View file

@ -46,8 +46,10 @@ CSRCS += mtd_partition.c
endif
ifeq ($(CONFIG_MTD_NAND),y)
CSRCS += mtd_nand.c mtd_onfi.c mtd_nandscheme.c mtd_nandraw.c
CSRCS += mtd_nandmodel.c mtd_modeltab.c
CSRCS += mtd_nand.c mtd_onfi.c mtd_nandscheme.c mtd_nandmodel.c mtd_modeltab.c
ifeq ($(CONFIG_MTD_NAND_BLOCKCHECK),y)
CSRCS += mtd_nandecc.c hamming.c
endif
endif
ifeq ($(CONFIG_RAMMTD),y)

451
drivers/mtd/hamming.c Normal file
View file

@ -0,0 +1,451 @@
/****************************************************************************
* drivers/mtd/hamming.c
*
* Copyright (C) 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* This logic was taken directly from Atmel sample code with only
* modifications for better integration with NuttX. The Atmel sample
* code has a BSD compatibile license that requires this copyright notice:
*
* Copyright (c) 2011, Atmel Corporation
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the names NuttX nor Atmel nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <nuttx/mtd/nand_config.h>
#include <stdint.h>
#include <assert.h>
#include <debug.h>
#include <nuttx/mtd/hamming.h>
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: bitsinbyte
*
* Description:
* Counts the number of bits set to '1' in the given byte.
*
* Input Parameters:
* bytes - The byte to use.
*
* Returned Values:
* Returns the number of bits set to '1' in the given byte.
*
****************************************************************************/
static unsigned int bitsinbyte(uint8_t byte)
{
unsigned int count = 0;
while (byte != 0)
{
if ((byte & 1) != 0)
{
count++;
}
byte >>= 1;
}
return count;
}
/****************************************************************************
* Name: bitsincode256
*
* Description:
* Counts the number of bits set to '1' in the given hamming code.
*
* Input Parameters:
* code - Hamming code
*
* Returned Values:
* Returns the number of bits set to '1' in the given hamming code.
*
****************************************************************************/
static uint8_t bitsincode256(FAR uint8_t *code)
{
return bitsinbyte(code[0]) + bitsinbyte(code[1]) + bitsinbyte(code[2]);
}
/****************************************************************************
* Name: compute256
*
* Description:
* Calculates the 22-bit hamming code for a 256-bytes block of data.
*
* Input Parameters:
* data - Data buffer to calculate code
* code - Pointer to a buffer where the code should be stored
*
* Returned Values:
* None
*
****************************************************************************/
static void compute256(FAR const uint8_t *data, FAR uint8_t *code)
{
uint8_t colsum = 0;
uint8_t evenline = 0;
uint8_t oddline = 0;
uint8_t evencol = 0;
uint8_t oddcol = 0;
int i;
/* Xor all bytes together to get the column sum;
* At the same time, calculate the even and odd line codes
*/
for (i = 0; i < 256; i++)
{
colsum ^= data[i];
/* If the xor sum of the byte is 0, then this byte has no incidence on
* the computed code; so check if the sum is 1.
*/
if ((bitsinbyte(data[i]) & 1) == 1)
{
/* Parity groups are formed by forcing a particular index bit to 0
* (even) or 1 (odd).
* Example on one byte:
*
* bits (dec) 7 6 5 4 3 2 1 0
* (bin) 111 110 101 100 011 010 001 000
* '---'---'---'----------.
* |
* groups P4' ooooooooooooooo eeeeeeeeeeeeeee P4 |
* P2' ooooooo eeeeeee ooooooo eeeeeee P2 |
* P1' ooo eee ooo eee ooo eee ooo eee P1 |
* |
* We can see that: |
* - P4 -> bit 2 of index is 0 --------------------'
* - P4' -> bit 2 of index is 1.
* - P2 -> bit 1 of index if 0.
* - etc...
* We deduce that a bit position has an impact on all even Px if
* the log2(x)nth bit of its index is 0
* ex: log2(4) = 2, bit2 of the index must be 0 (-> 0 1 2 3)
* and on all odd Px' if the log2(x)nth bit of its index is 1
* ex: log2(2) = 1, bit1 of the index must be 1 (-> 0 1 4 5)
*
* As such, we calculate all the possible Px and Px' values at the
* same time in two variables, evenline and oddline, such as
* evenline bits: P128 P64 P32 P16 P8 P4 P2 P1
* oddline bits: P128' P64' P32' P16' P8' P4' P2' P1'
*/
evenline ^= (255 - i);
oddline ^= i;
}
}
/* At this point, we have the line parities, and the column sum. First, We
* must caculate the parity group values on the column sum.
*/
for (i = 0; i < 8; i++)
{
if (colsum & 1)
{
evencol ^= (7 - i);
oddcol ^= i;
}
colsum >>= 1;
}
/* Now, we must interleave the parity values, to obtain the following layout:
* Code[0] = Line1
* Code[1] = Line2
* Code[2] = Column
* Line = Px' Px P(x-1)- P(x-1) ...
* Column = P4' P4 P2' P2 P1' P1 PadBit PadBit
*/
code[0] = 0;
code[1] = 0;
code[2] = 0;
for (i = 0; i < 4; i++)
{
code[0] <<= 2;
code[1] <<= 2;
code[2] <<= 2;
/* Line 1 */
if ((oddline & 0x80) != 0)
{
code[0] |= 2;
}
if ((evenline & 0x80) != 0)
{
code[0] |= 1;
}
/* Line 2 */
if ((oddline & 0x08) != 0)
{
code[1] |= 2;
}
if ((evenline & 0x08) != 0)
{
code[1] |= 1;
}
/* Column */
if ((oddcol & 0x04) != 0)
{
code[2] |= 2;
}
if ((evencol & 0x04) != 0)
{
code[2] |= 1;
}
oddline <<= 1;
evenline <<= 1;
oddcol <<= 1;
evencol <<= 1;
}
/* Invert codes (linux compatibility) */
code[0] = (~(uint32_t)code[0]);
code[1] = (~(uint32_t)code[1]);
code[2] = (~(uint32_t)code[2]);
fvdbg("Computed code = %02X %02X %02X\n", code[0], code[1], code[2]);
}
/****************************************************************************
* Name: verify256
*
* Description:
* Verifies and corrects a 256-bytes block of data using the given 22-bits
* hamming code.
*
* Input Parameters:
* data - Data buffer to check
* original - Hamming code to use for verifying the data
*
* Returned Values:
* Zero on success, otherwise returns a HAMMING_ERROR_ code.
*
****************************************************************************/
static int verify256(FAR uint8_t *data, FAR const uint8_t *original)
{
/* Calculate new code */
uint8_t computed[3];
uint8_t correction[3];
compute256(data, computed);
/* Xor both codes together */
correction[0] = computed[0] ^ original[0];
correction[1] = computed[1] ^ original[1];
correction[2] = computed[2] ^ original[2];
fvdbg("Correction code: %02x %02x %02x\n",
correction[0], correction[1], correction[2]);
/* If all bytes are 0, there is no error */
if ((correction[0] == 0) && (correction[1] == 0) && (correction[2] == 0))
{
return 0;
}
/* If there is a single bit error, there are 11 bits set to 1 */
if (bitsincode256(correction) == 11)
{
uint8_t byte;
uint8_t bit;
/* Get byte and bit indexes */
byte = correction[0] & 0x80;
byte |= (correction[0] << 1) & 0x40;
byte |= (correction[0] << 2) & 0x20;
byte |= (correction[0] << 3) & 0x10;
byte |= (correction[1] >> 4) & 0x08;
byte |= (correction[1] >> 3) & 0x04;
byte |= (correction[1] >> 2) & 0x02;
byte |= (correction[1] >> 1) & 0x01;
bit = (correction[2] >> 5) & 0x04;
bit |= (correction[2] >> 4) & 0x02;
bit |= (correction[2] >> 3) & 0x01;
/* Correct bit */
fdbg("Correcting byte %d at bit %d\n", byte, bit);
data[byte] ^= (1 << bit);
return HAMMING_ERROR_SINGLEBIT;
}
/* Check if ECC has been corrupted */
if (bitsincode256(correction) == 1)
{
return HAMMING_ERROR_ECC;
}
/* Otherwise, this is a multi-bit error */
else
{
return HAMMING_ERROR_MULTIPLEBITS;
}
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: hamming_compute256x
*
* Description:
* Computes 3-bytes hamming codes for a data block whose size is multiple
* of 256 bytes. Each 256 bytes block gets its own code.
*
* Input Parameters:
* data - Data to compute code for
* size - Data size in bytes
* code - Codes buffer
*
* Returned Values:
* None
*
****************************************************************************/
void hamming_compute256x(FAR const uint8_t *data, size_t size, uint8_t *code)
{
ssize_t remaining = (ssize_t)size;
DEBUGASSERT((size & 0xff) == 0);
/* Loop, computing the Hamming code on each 256 byte chunk of data */
while (remaining > 0)
{
compute256(data, code);
/* Setup for the next 256 byte chunk */
data += 256;
code += 3;
remaining -= 256;
}
}
/****************************************************************************
* Name: hamming_verify256x
*
* Description:
* Verifies 3-bytes hamming codes for a data block whose size is multiple
* of 256 bytes. Each 256-bytes block is verified with its own code.
*
* Input Parameters:
* data - Data buffer to verify
* size - Size of the data in bytes
* code - Original codes
*
* Returned Values:
* Return 0 if the data is correct, HAMMING_ERROR_SINGLEBIT if one or more
* block(s) have had a single bit corrected, or either HAMMING_ERROR_ECC
* or HAMMING_ERROR_MULTIPLEBITS.
*
****************************************************************************/
int hamming_verify256x(uint8_t *data, size_t size, const uint8_t *code)
{
ssize_t remaining = (ssize_t)size;
int result = HAMMING_SUCCESS;
int ret;
DEBUGASSERT((size & 0xff) == 0);
/* Loop, verifying each 256 byte chunk of data */
while (remaining > 0)
{
result = verify256(data, code);
if (result != HAMMING_SUCCESS)
{
/* Check for the case of a single bit error that was corrected */
if (result == HAMMING_ERROR_SINGLEBIT)
{
/* Report the error, but continue verifying */
ret = HAMMING_ERROR_SINGLEBIT;
}
else
{
/* A bad error occurred, abort the verification and return the
* error code
*/
return result;
}
}
/* Setup for the next 256 byte chunk */
data += 256;
code += 3;
remaining -= 256;
}
return ret;
}

View file

@ -88,7 +88,7 @@
static int nand_lock(FAR struct nand_dev_s *nand);
#define nand_unlock(n) sem_post(&(n)->exclsem)
/* Sparing logic */
/* Bad block checking */
#ifdef CONFIG_MTD_NAND_BLOCKCHECK
static int nand_checkblock(FAR struct nand_dev_s *nand, off_t block);
@ -98,8 +98,15 @@ static int nand_devscan(FAR struct nand_dev_s *nand);
# define nand_devscan(n)
#endif
/* Misc. NAND helpers */
static uint32_t nand_chipid(struct nand_raw_s *raw);
static int nand_eraseblock(FAR struct nand_dev_s *nand,
off_t block, bool scrub);
static int nand_readpage(FAR struct nand_dev_s *nand, off_t block,
unsigned int page, FAR uint8_t *buf);
static int nand_writepage(FAR struct nand_dev_s *nand, off_t block,
unsigned int page, FAR const void *buf);
/* MTD driver methods */
@ -283,6 +290,44 @@ static int nand_devscan(FAR struct nand_dev_s *nand)
}
#endif /* CONFIG_MTD_NAND_BLOCKCHECK */
/****************************************************************************
* Name: nand_chipid
*
* Description:
* Reads and returns the identifiers of a NAND FLASH chip
*
* Input Parameters:
* raw - Pointer to a struct nand_raw_s instance.
*
* Returned Value:
* id1|(id2<<8)|(id3<<16)|(id4<<24)
*
****************************************************************************/
static uint32_t nand_chipid(struct nand_raw_s *raw)
{
uint8_t id[5];
DEBUGASSERT(raw);
WRITE_COMMAND8(raw, COMMAND_READID);
WRITE_ADDRESS8(raw, 0);
id[0] = READ_DATA8(raw);
id[1] = READ_DATA8(raw);
id[2] = READ_DATA8(raw);
id[3] = READ_DATA8(raw);
id[4] = READ_DATA8(raw);
fvdbg("Chip ID: %02x %02x %02x %02x %02x\n",
id[0], id[1], id[2], id[3], id[4]);
return (uint32_t)id[0] |
((uint32_t)id[1] << 8) |
((uint32_t)id[2] << 16) |
((uint32_t)id[3] << 24);
}
/****************************************************************************
* Name: nand_eraseblock
*
@ -383,12 +428,27 @@ static int nand_readpage(FAR struct nand_dev_s *nand, off_t block,
return -EAGAIN;
}
/* Read data with ECC verification */
#ifdef CONFIG_MTD_NAND_SWECC
/* nandecc_readpage will handle the software ECC case */
return nandecc_readpage(nand, block, page, buf, NULL);
#else
return NAND_READPAGE(nand->raw, block, page, buf, NULL);
DEBUGASSERT(nand && nand->raw);
if (nand->raw->ecc == NANDECC_SWECC)
{
/* Read data with software ECC verification */
return nandecc_readpage(nand, block, page, buf, NULL);
}
/* The lower half will handle the No ECC and all hardware assisted
* ECC calculations.
*/
else
#endif
#endif
{
return NAND_READPAGE(nand->raw, block, page, buf, NULL);
}
}
/****************************************************************************
@ -420,11 +480,28 @@ static int nand_writepage(FAR struct nand_dev_s *nand, off_t block,
fdbg("ERROR: Block is BAD\n");
return -EAGAIN;
}
#ifdef CONFIG_MTD_NAND_SWECC
/* nandecc_writepage will handle the software ECC case */
DEBUGASSERT(nand && nand->raw);
if (nand->raw->ecc == NANDECC_SWECC)
{
/* Write data with software ECC calculation */
return nandecc_writepage(nand, block, page, buf, NULL);
}
/* The lower half will handle the No ECC and all hardware assisted
* ECC calculations.
*/
else
#endif
/* Write data with ECC calculation */
return nandecc_writepage(nand, block, page, buf, NULL);
#endif
{
return NAND_WRITEPAGE(nand->raw, block, page, buf, NULL);
}
}
/****************************************************************************
@ -614,7 +691,7 @@ static ssize_t nand_bwrite(struct mtd_dev_s *dev, off_t startpage,
ret = nand_writepage(nand, block, page, buf);
if (ret < 0)
{
fdbg("ERROR: nand_readpage failed block=%ld page=%d: %d\n",
fdbg("ERROR: nand_writepage failed block=%ld page=%d: %d\n",
(long)block, page, ret);
goto errout_with_lock;
}
@ -656,8 +733,14 @@ errout_with_lock:
static int nand_ioctl(struct mtd_dev_s *dev, int cmd, unsigned long arg)
{
FAR struct nand_dev_s *nand = (FAR struct nand_dev_s *)dev;
FAR struct nand_raw_s *raw;
FAR struct nand_model_s *model;
int ret = -EINVAL; /* Assume good command with bad parameters */
DEBUGASSERT(nand && nand->raw);
raw = nand->raw;
model = &raw->model;
switch (cmd)
{
case MTDIOC_GEOMETRY:
@ -666,17 +749,16 @@ static int nand_ioctl(struct mtd_dev_s *dev, int cmd, unsigned long arg)
if (geo)
{
/* Populate the geometry structure with information needed to know
* the capacity and how to access the device.
* the capacity and how to access the device. Returns:
*
* NOTE: that the device is treated as though it where just an array
* of fixed size blocks. That is most likely not true, but the client
* will expect the device logic to do whatever is necessary to make it
* appear so.
* blocksize Size of one read/write block in bytes
* erasesize Size of one erase block in bytes
* neraseblocks The number of erase blocks in the device
*/
geo->blocksize = 512; /* Size of one read/write block */
geo->erasesize = 4096; /* Size of one erase block */
geo->neraseblocks = 1024; /* Number of erase blocks */
geo->blocksize = model->pagesize;
geo->erasesize = nandmodel_getbyteblocksize(model);
geo->neraseblocks = nandmodel_getdevblocks(model);
ret = OK;
}
}
@ -686,7 +768,7 @@ static int nand_ioctl(struct mtd_dev_s *dev, int cmd, unsigned long arg)
{
/* Erase the entire device */
ret = OK;
ret = nand_erase(dev, 0, nandmodel_getdevblocks(model));
}
break;

121
drivers/mtd/mtd_nandecc.c Normal file
View file

@ -0,0 +1,121 @@
/****************************************************************************
* drivers/mtd/mtd_nandecc.c
*
* Copyright (C) 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* This logic was based largely on Atmel sample code with modifications for
* better integration with NuttX. The Atmel sample code has a BSD
* compatibile license that requires this copyright notice:
*
* Copyright (c) 2011, 2012, Atmel Corporation
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the names NuttX nor Atmel nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <nuttx/mtd/nand_config.h>
#include <sys/types.h>
#include <stdint.h>
#include <errno.h>
#include <debug.h>
#include <nuttx/mtd/nand.h>
#include <nuttx/mtd/nand_ecc.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: nandecc_readpage
*
* Description:
* Reads the data and/or spare areas of a page of a NAND FLASH chip and
* verifies that the data is valid using the ECC information contained in
* the spare area. If a buffer pointer is NULL, then the corresponding area
* is not saved.
*
* Input parameters:
* nand - Upper-half, NAND FLASH interface
* block - Number of the block where the page to read resides.
* page - Number of the page to read inside the given block.
* data - Buffer where the data area will be stored.
* spare - Buffer where the spare area will be stored.
*
* Returned value.
* OK is returned in success; a negated errno value is returned on failure.
*
****************************************************************************/
int nandecc_readpage(FAR struct nand_dev_s *nand, off_t block,
unsigned int page, FAR void *data, FAR void *spare)
{
#warning Missing logic
return -ENOSYS;
}
/****************************************************************************
* Name: nandecc_writepage
*
* Description:
* Writes the data and/or spare area of a NAND FLASH page after
* calculating an ECC for the data area and storing it in the spare. If no
* data buffer is provided, the ECC is read from the existing page spare.
* If no spare buffer is provided, the spare area is still written with the
* ECC information calculated on the data buffer.
*
* Input parameters:
* nand - Upper-half, NAND FLASH interface
* block - Number of the block where the page to write resides.
* page - Number of the page to write inside the given block.
* data - Buffer containing the data to be writting
* spare - Buffer containing the spare data to be written.
*
* Returned value.
* OK is returned in success; a negated errno value is returned on failure.
*
****************************************************************************/
int nandecc_writepage(FAR struct nand_dev_s *nand, off_t block,
unsigned int page, FAR const void *data,
FAR void *spare)
{
#warning Missing logic
return -ENOSYS;
}

View file

@ -1,5 +1,5 @@
/****************************************************************************
* drivers/mtd/mtd_nand.c
* drivers/mtd/mtd_nandmodel.c
*
* Copyright (C) 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>

View file

@ -1,5 +1,5 @@
/****************************************************************************
* include/nuttx/mtd/nand_scheme.c
* include/nuttx/mtd/mtd_nandscheme.c
*
* Copyright (C) 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>

View file

@ -1,5 +1,5 @@
/****************************************************************************
* drivers/child/skeleton.c
* drivers/mtd/mtd_partition.c
*
* Copyright (C) 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>

110
drivers/mtd/mtd_nandraw.c → include/nuttx/mtd/hamming.h Executable file → Normal file
View file

@ -1,14 +1,14 @@
/****************************************************************************
* drivers/mtd/mtd_nandraw.c
* include/nuttx/mtd/hamming.h
*
* Copyright (C) 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* This logic was based largely on Atmel sample code with modifications for
* better integration with NuttX. The Atmel sample code has a BSD
* compatibile license that requires this copyright notice:
* This logic was taken directly from Atmel sample code with only
* modifications for better integration with NuttX. The Atmel sample
* code has a BSD compatibile license that requires this copyright notice:
*
* Copyright (c) 2011, 2012, Atmel Corporation
* Copyright (c) 2011, Atmel Corporation
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@ -39,77 +39,67 @@
*
****************************************************************************/
#ifndef __INCLUDE_NUTTX_HAMMING_H
#define __INCLUDE_NUTTX_HAMMING_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <nuttx/mtd/nand_config.h>
#include <stdint.h>
#include <assert.h>
#include <debug.h>
#include <stdbool.h>
#include <semaphore.h>
#include <nuttx/mtd/mtd.h>
#include <nuttx/mtd/nand_raw.h>
/****************************************************************************
* Pre-processor Definitions
* Pre-Processor Definitions
****************************************************************************/
/****************************************************************************
* Private Types
****************************************************************************/
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
/****************************************************************************
* Private Data
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: nand_chipid
*
* Description:
* Reads and returns the identifiers of a NAND FLASH chip
*
* Input Parameters:
* raw - Pointer to a struct nand_raw_s instance.
*
* Returned Value:
* id1|(id2<<8)|(id3<<16)|(id4<<24)
/* These are the possible errors when trying to verify a block of data
* encoded using a Hamming code:
*
* HAMMING_SUCCESS - Block verified without errors
* HAMMING_ERROR_SINGLEBIT - A single bit was incorrect but has been
* recovered
* HAMMING_ERROR_ECC - The original code has been corrupted
* HAMMING_ERROR_MULTIPLEBITS - Multiple bits are incorrect in the data
* and they cannot be corrected
*/
#define HAMMING_SUCCESS 0
#define HAMMING_ERROR_SINGLEBIT 1
#define HAMMING_ERROR_ECC 2
#define HAMMING_ERROR_MULTIPLEBITS 3
/****************************************************************************
* Public Types
****************************************************************************/
uint32_t nand_chipid(struct nand_raw_s *raw)
/****************************************************************************
* Public Data
****************************************************************************/
#ifndef __ASSEMBLY__
#ifdef __cplusplus
#define EXTERN extern "C"
extern "C"
{
uint8_t id[5];
#else
#define EXTERN extern
#endif
DEBUGASSERT(raw);
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
WRITE_COMMAND8(raw, COMMAND_READID);
WRITE_ADDRESS8(raw, 0);
id[0] = READ_DATA8(raw);
id[1] = READ_DATA8(raw);
id[2] = READ_DATA8(raw);
id[3] = READ_DATA8(raw);
id[4] = READ_DATA8(raw);
fvdbg("Chip ID: %02x %02x %02x %02x %02x\n",
id[0], id[1], id[2], id[3], id[4]);
return (uint32_t)id[0] |
((uint32_t)id[1] << 8) |
((uint32_t)id[2] << 16) |
((uint32_t)id[3] << 24);
#undef EXTERN
#ifdef __cplusplus
}
#endif
#endif /* __ASSEMBLY__ */
#endif /* __INCLUDE_NUTTX_HAMMING_H */

View file

@ -81,8 +81,10 @@ extern "C"
* Name: nandecc_readpage
*
* Description:
* Reads the data and/or the spare areas of a page of a NAND FLASH into the
* provided buffers.
* Reads the data and/or spare areas of a page of a NAND FLASH chip and
* verifies that the data is valid using the ECC information contained in
* the spare area. If a buffer pointer is NULL, then the corresponding area
* is not saved.
*
* Input parameters:
* nand - Upper-half, NAND FLASH interface
@ -103,14 +105,18 @@ int nandecc_readpage(FAR struct nand_dev_s *nand, off_t block,
* Name: nandecc_writepage
*
* Description:
* Writes the data and/or the spare area of a page on a NAND FLASH chip.
* Writes the data and/or spare area of a NAND FLASH page after
* calculating an ECC for the data area and storing it in the spare. If no
* data buffer is provided, the ECC is read from the existing page spare.
* If no spare buffer is provided, the spare area is still written with the
* ECC information calculated on the data buffer.
*
* Input parameters:
* nand - Upper-half, NAND FLASH interface
* block - Number of the block where the page to write resides.
* page - Number of the page to write inside the given block.
* data - Buffer containing the data to be writting
* spare - Buffer conatining the spare data to be written.
* spare - Buffer containing the spare data to be written.
*
* Returned value.
* OK is returned in success; a negated errno value is returned on failure.
@ -118,8 +124,8 @@ int nandecc_readpage(FAR struct nand_dev_s *nand, off_t block,
****************************************************************************/
int nandecc_writepage(FAR struct nand_dev_s *nand, off_t block,
unsigned int page, FAR const void *data,
FAR const void *spare);
unsigned int page, FAR const void *data,
FAR void *spare);
#undef EXTERN
#ifdef __cplusplus

View file

@ -81,6 +81,19 @@
#define COMMAND_READ_A 0x00
#define COMMAND_READ_C 0x50
/* Type of ECC to be performed (must be enabled in the configuration)
* NANDECC_NONE No ECC, only raw NAND FLASH accesses
* NANDECC_SWECC Software ECC. Handled by the common MTD logic.
* NANDECC_HWECC Values >= 2 are various hardware ECC implementations
* all handled by the lower-half, raw NAND FLASH driver.
* These hardware ECC types may be extended beginning
* with the value NANDECC_HWECC.
*/
#define NANDECC_NONE 0
#define NANDECC_SWECC 1
#define NANDECC_HWECC 2
/* NAND access macros */
#define WRITE_COMMAND8(raw, command) \
@ -151,7 +164,7 @@
* block - Number of the block where the page to write resides.
* page - Number of the page to write inside the given block.
* data - Buffer containing the data to be writting
* spare - Buffer conatining the spare data to be written.
* spare - Buffer containing the spare data to be written.
*
* Returned value.
* OK is returned in succes; a negated errno value is returned on failure.
@ -171,13 +184,19 @@
struct nand_raw_s
{
/* NAND data */
/* NAND data description */
struct nand_model_s model; /* The NAND model storage */
uintptr_t cmdaddr; /* NAND command address base */
uintptr_t addraddr; /* NAND address address base */
uintptr_t dataaddr; /* NAND data address */
#ifdef CONFIG_MTD_NAND_BLOCKCHECK
/* ECC */
uint8_t ecc; /* See enum nand_ecc_e */
#endif
/* NAND operations */
CODE int (*eraseblock)(FAR struct nand_raw_s *raw, off_t block);
@ -206,22 +225,6 @@ extern "C"
* Public Function Prototypes
****************************************************************************/
/****************************************************************************
* Name: nand_chipid
*
* Description:
* Reads and returns the identifiers of a NAND FLASH chip
*
* Input Parameters:
* raw - Pointer to a struct nand_raw_s instance.
*
* Returned Value:
* id1|(id2<<8)|(id3<<16)|(id4<<24)
*
****************************************************************************/
uint32_t nand_chipid(FAR struct nand_raw_s *raw);
#undef EXTERN
#ifdef __cplusplus
}