From 36aa36843abf43d940094d70f8c72ec0b750d532 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Mon, 18 Nov 2013 09:43:44 -0600 Subject: MTD NAND: Beginning of software ECC logic --- nuttx/ChangeLog | 4 +- nuttx/arch/arm/src/sama5/sam_nand.h | 17 ++ nuttx/drivers/mtd/Kconfig | 30 ++- nuttx/drivers/mtd/Make.defs | 6 +- nuttx/drivers/mtd/hamming.c | 451 ++++++++++++++++++++++++++++++++++++ nuttx/drivers/mtd/mtd_nand.c | 118 ++++++++-- nuttx/drivers/mtd/mtd_nandecc.c | 121 ++++++++++ nuttx/drivers/mtd/mtd_nandmodel.c | 2 +- nuttx/drivers/mtd/mtd_nandraw.c | 115 --------- nuttx/drivers/mtd/mtd_nandscheme.c | 2 +- nuttx/drivers/mtd/mtd_partition.c | 2 +- nuttx/include/nuttx/mtd/hamming.h | 105 +++++++++ nuttx/include/nuttx/mtd/nand_ecc.h | 18 +- nuttx/include/nuttx/mtd/nand_raw.h | 39 ++-- 14 files changed, 860 insertions(+), 170 deletions(-) create mode 100644 nuttx/drivers/mtd/hamming.c create mode 100644 nuttx/drivers/mtd/mtd_nandecc.c delete mode 100755 nuttx/drivers/mtd/mtd_nandraw.c create mode 100644 nuttx/include/nuttx/mtd/hamming.h diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog index 7f9e246ec..aee32e40e 100644 --- a/nuttx/ChangeLog +++ b/nuttx/ChangeLog @@ -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). diff --git a/nuttx/arch/arm/src/sama5/sam_nand.h b/nuttx/arch/arm/src/sama5/sam_nand.h index 2bef90554..fc4812368 100644 --- a/nuttx/arch/arm/src/sama5/sam_nand.h +++ b/nuttx/arch/arm/src/sama5/sam_nand.h @@ -42,12 +42,29 @@ #include +#include + #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__ diff --git a/nuttx/drivers/mtd/Kconfig b/nuttx/drivers/mtd/Kconfig index 687456972..adcb204fc 100644 --- a/nuttx/drivers/mtd/Kconfig +++ b/nuttx/drivers/mtd/Kconfig @@ -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 diff --git a/nuttx/drivers/mtd/Make.defs b/nuttx/drivers/mtd/Make.defs index feabf468f..ee58d3047 100644 --- a/nuttx/drivers/mtd/Make.defs +++ b/nuttx/drivers/mtd/Make.defs @@ -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) diff --git a/nuttx/drivers/mtd/hamming.c b/nuttx/drivers/mtd/hamming.c new file mode 100644 index 000000000..31bd8a3e5 --- /dev/null +++ b/nuttx/drivers/mtd/hamming.c @@ -0,0 +1,451 @@ +/**************************************************************************** + * drivers/mtd/hamming.c + * + * Copyright (C) 2013 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 +#include + +#include +#include +#include + +#include + +/**************************************************************************** + * 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; +} diff --git a/nuttx/drivers/mtd/mtd_nand.c b/nuttx/drivers/mtd/mtd_nand.c index d0f8c8c20..9f5e06ec5 100755 --- a/nuttx/drivers/mtd/mtd_nand.c +++ b/nuttx/drivers/mtd/mtd_nand.c @@ -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; } -#endif - /* Write data with ECC calculation */ +#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. + */ - return nandecc_writepage(nand, block, page, buf, NULL); + else +#endif +#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; diff --git a/nuttx/drivers/mtd/mtd_nandecc.c b/nuttx/drivers/mtd/mtd_nandecc.c new file mode 100644 index 000000000..324723903 --- /dev/null +++ b/nuttx/drivers/mtd/mtd_nandecc.c @@ -0,0 +1,121 @@ +/**************************************************************************** + * drivers/mtd/mtd_nandecc.c + * + * Copyright (C) 2013 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 +#include + +#include +#include +#include +#include + +#include +#include + +/**************************************************************************** + * 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; +} diff --git a/nuttx/drivers/mtd/mtd_nandmodel.c b/nuttx/drivers/mtd/mtd_nandmodel.c index bd7d898c2..48492bbc2 100644 --- a/nuttx/drivers/mtd/mtd_nandmodel.c +++ b/nuttx/drivers/mtd/mtd_nandmodel.c @@ -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 diff --git a/nuttx/drivers/mtd/mtd_nandraw.c b/nuttx/drivers/mtd/mtd_nandraw.c deleted file mode 100755 index 012e470cc..000000000 --- a/nuttx/drivers/mtd/mtd_nandraw.c +++ /dev/null @@ -1,115 +0,0 @@ -/**************************************************************************** - * drivers/mtd/mtd_nandraw.c - * - * Copyright (C) 2013 Gregory Nutt. All rights reserved. - * Author: Gregory Nutt - * - * 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 -#include - -#include -#include -#include - -#include - -/**************************************************************************** - * 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) - * - ****************************************************************************/ - -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); -} diff --git a/nuttx/drivers/mtd/mtd_nandscheme.c b/nuttx/drivers/mtd/mtd_nandscheme.c index 13df5d584..09c98c7b6 100644 --- a/nuttx/drivers/mtd/mtd_nandscheme.c +++ b/nuttx/drivers/mtd/mtd_nandscheme.c @@ -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 diff --git a/nuttx/drivers/mtd/mtd_partition.c b/nuttx/drivers/mtd/mtd_partition.c index 550a775c8..1e788cf36 100644 --- a/nuttx/drivers/mtd/mtd_partition.c +++ b/nuttx/drivers/mtd/mtd_partition.c @@ -1,5 +1,5 @@ /**************************************************************************** - * drivers/child/skeleton.c + * drivers/mtd/mtd_partition.c * * Copyright (C) 2013 Gregory Nutt. All rights reserved. * Author: Gregory Nutt diff --git a/nuttx/include/nuttx/mtd/hamming.h b/nuttx/include/nuttx/mtd/hamming.h new file mode 100644 index 000000000..b7b25033a --- /dev/null +++ b/nuttx/include/nuttx/mtd/hamming.h @@ -0,0 +1,105 @@ +/**************************************************************************** + * include/nuttx/mtd/hamming.h + * + * Copyright (C) 2013 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_HAMMING_H +#define __INCLUDE_NUTTX_HAMMING_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ +/* 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 + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __INCLUDE_NUTTX_HAMMING_H */ diff --git a/nuttx/include/nuttx/mtd/nand_ecc.h b/nuttx/include/nuttx/mtd/nand_ecc.h index a5ce0ca86..0163d4b87 100644 --- a/nuttx/include/nuttx/mtd/nand_ecc.h +++ b/nuttx/include/nuttx/mtd/nand_ecc.h @@ -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 diff --git a/nuttx/include/nuttx/mtd/nand_raw.h b/nuttx/include/nuttx/mtd/nand_raw.h index 193459af7..c30a99e1f 100644 --- a/nuttx/include/nuttx/mtd/nand_raw.h +++ b/nuttx/include/nuttx/mtd/nand_raw.h @@ -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 } -- cgit v1.2.3