SAMV71 Xplained Ultra Software Package 1.4

smc.c

Go to the documentation of this file.
00001 /* ----------------------------------------------------------------------------
00002  *         ATMEL Microcontroller Software Support
00003  * ----------------------------------------------------------------------------
00004  * Copyright (c) 2010, Atmel Corporation
00005  *
00006  * All rights reserved.
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted provided that the following conditions are met:
00010  *
00011  * - Redistributions of source code must retain the above copyright notice,
00012  * this list of conditions and the disclaimer below.
00013  *
00014  * Atmel's name may not be used to endorse or promote products derived from
00015  * this software without specific prior written permission.
00016  *
00017  * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
00018  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
00019  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
00020  * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
00021  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00022  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
00023  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00024  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00025  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
00026  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00027  * ----------------------------------------------------------------------------
00028  */
00029 /**
00030  *  \file
00031  *
00032  *  Implementation of NFC functions.
00033  */
00034 
00035 /*----------------------------------------------------------------------------
00036  *        Headers
00037  *----------------------------------------------------------------------------*/
00038 
00039 #include "chip.h"
00040 
00041 static SmcStatus smcStatus;
00042 /*----------------------------------------------------------------------------
00043  *        Local functions
00044  *----------------------------------------------------------------------------*/
00045 
00046 /**
00047  * \brief Counts and return the number of bits set to '1' in the given hsiao code .
00048  * \param code  Hsizo code.
00049  */
00050 static unsigned char CountBitsInByte(unsigned char byte)
00051 {
00052     unsigned char count = 0;
00053     while (byte > 0) {
00054         if (byte & 1) {
00055             count++;
00056         }
00057         byte >>= 1;
00058     }
00059 
00060     return count;
00061 }
00062 
00063 /**
00064  * \brief Counts and return the number of bits set to '1' in the given hsiao code.
00065  * \param code  Hsizo code.
00066  */
00067 static unsigned char CountBitsInCode(unsigned char *code)
00068 {
00069     return CountBitsInByte(code[0])
00070         + CountBitsInByte(code[1])
00071         + CountBitsInByte(code[2]);
00072 }
00073 
00074 /**
00075  * \brief Clear the corresponding interrupt flag.
00076  */
00077 static void SMC_Clear_Status (void)
00078 {
00079     smcStatus.BStatus = 0;
00080 }
00081 
00082 /**
00083  * \brief Check the STATUS and set the corresponding interrupt flag.
00084  */
00085 static void SMC_Handler(void)
00086 {
00087     uint32_t status;
00088     status = SMC->SMC_SR;
00089 #if 0
00090     if ((status & SMC_SR_SMCSTS) == SMC_SR_SMCSTS) 
00091         /* NAND Flash Controller is enabled */
00092         smcStatus.bStatus.smcSts = 1; 
00093 #endif
00094     if ((status & SMC_SR_XFRDONE) == SMC_SR_XFRDONE)
00095         /* When set to one, this flag indicates that the NFC has terminated the
00096             Data Transfer. This flag is reset after a status read operation. */
00097         smcStatus.bStatus.xfrDone = 1; 
00098     if ((status & SMC_SR_CMDDONE) == SMC_SR_CMDDONE)
00099         /* When set to one, this flag indicates that the NFC has terminated the
00100             Command. This flag is reset after a status read operation.*/
00101         smcStatus.bStatus.cmdDone = 1; 
00102     if ((status & (1<<24)) == (1<<24)) 
00103         /* If set to one, this flag indicates that an edge has been detected on 
00104             the Ready/Busy Line x. Depending on the EDGE CTRL field located in 
00105             the SMC_CFG register, only rising or falling edge is detected.
00106             This flag is reset after a status read operation. */
00107         smcStatus.bStatus.rbEdge = 1; 
00108     if ((status & SMC_SR_ECCRDY) == SMC_SR_ECCRDY)
00109         /* When set to one, this flag indicates that the Hamming ECC 
00110         computation is completed. This flag is reset after a status read
00111            operation.*/
00112         smcStatus.bStatus.hammingReady = 1; 
00113 }
00114 
00115 /*----------------------------------------------------------------------------
00116  *        Exported functions
00117  *----------------------------------------------------------------------------*/
00118 
00119 /**
00120  * \brief Sets NFC configuration.
00121  * \param cfg  NFC configuration.
00122  */
00123 void SMC_NFC_Configure(uint32_t cfg)
00124 {
00125     SMC->SMC_CFG = cfg;
00126 }
00127 
00128 /**
00129  * \brief Reset NFC controller.
00130  */
00131 void SMC_NFC_Reset(void)
00132 {
00133     /* Disable all the SMC NFC interrupts */
00134     SMC->SMC_IDR = 0xFFFFFFFF;
00135     SMC->SMC_CTRL = 0;
00136 }
00137 
00138 /**
00139  * \brief Enable NFC controller.
00140  */
00141 void SMC_NFC_EnableNfc(void)
00142 {
00143     SMC->SMC_CTRL |= SMC_CTRL_NFCEN;
00144 }
00145 
00146 /**
00147  * \brief Enable NFC controller reads both main and spare area in read mode.
00148  */
00149 void SMC_NFC_EnableSpareRead(void)
00150 {
00151     SMC->SMC_CFG |= SMC_CFG_RSPARE;
00152 }
00153 
00154 /**
00155  * \brief The NFC controller skips spare area in read mode.
00156  */
00157 void SMC_NFC_DisableSpareRead(void)
00158 {
00159     SMC->SMC_CFG &= (~SMC_CFG_RSPARE);
00160 }
00161 
00162 /**
00163  * \brief Enables the NFC controller writes both main and spare area in write
00164  */
00165 void SMC_NFC_EnableSpareWrite(void)
00166 {
00167     SMC->SMC_CFG |= SMC_CFG_WSPARE;
00168 }
00169 
00170 /**
00171  * \brief The NFC controller skips spare area in write mode.
00172  */
00173 void SMC_NFC_DisableSpareWrite(void)
00174 {
00175     SMC->SMC_CFG &= (~SMC_CFG_WSPARE);
00176 }
00177 
00178 /**
00179  * \brief Check if spare area be read in read mode.
00180  *
00181  * \return Returns 1 if NFC controller reads both main and spare area in
00182  *         read mode, otherwise returns 0.
00183  */
00184 uint8_t SMC_NFC_isSpareRead(void)
00185 {
00186     return (((SMC->SMC_CFG) >> 9) & 0x1);
00187 }
00188 
00189 /**
00190  * \brief Check if spare area be written in write mode.
00191  *
00192  * \return Returns 1 if NFC controller writes both main and spare area in
00193  *         write mode, otherwise returns 0.
00194  */
00195 uint8_t SMC_NFC_isSpareWrite(void)
00196 {
00197     return (((SMC->SMC_CFG) >> 8) & 0x1);
00198 }
00199 
00200 /**
00201  * \brief Check if NFC transfer complete.
00202  * \return Returns 1 if NFC controller has terminated the data transmission,
00203  *         otherwise returns 0.
00204  */
00205 uint8_t SMC_NFC_isTransferComplete(void)
00206 {
00207     return ((SMC->SMC_SR & SMC_SR_XFRDONE) == SMC_SR_XFRDONE);
00208 }
00209 
00210 /**
00211  * \brief Check Ready/Busy line.
00212  *
00213  * \return Returns 1 if  edge has been detected on the Ready/Busy line,
00214  *         otherwise returns 0.
00215  */
00216 uint8_t SMC_NFC_isReadyBusy(void)
00217 {
00218     return ((SMC->SMC_SR & SMC_SR_RB_EDGE0) == SMC_SR_RB_EDGE0);
00219 }
00220 
00221 /**
00222  * \brief Check if NFC Controller is busy.
00223  *
00224  * \return Returns 1 if NFC Controller is activated and accesses the memory device,
00225  *         otherwise returns 0.
00226  */
00227 uint8_t SMC_NFC_isNfcBusy(void)
00228 {
00229     return ((SMC->SMC_SR & SMC_SR_NFCBUSY) == SMC_SR_NFCBUSY);
00230 }
00231 
00232 /**
00233  * \brief Get NFC Status.
00234  *
00235  * \return Returns the current status register of SMC NFC Status Register.
00236  *         This resets the internal value of the status register, so further
00237  *         read may yield different values.
00238  */
00239 uint32_t SMC_NFC_GetStatus(void)
00240 {
00241     return SMC->SMC_SR;
00242 }
00243 
00244 /*
00245  * HOST command functions
00246  */
00247 
00248 /**
00249  * \brief Check if the host controller is busy.
00250  * \return Returns 1 if the host controller is busy, otherwise returns 0.
00251  */
00252 static uint8_t SMC_NFC_isHostBusy(void)
00253 {
00254     return (((*((volatile uint32_t *) (NFC_CMD_BASE_ADDR + NFCADDR_CMD_NFCCMD)))
00255         & 0x8000000) == 0x8000000);
00256 }
00257 
00258 /**
00259  * \brief Wait for NFC command has done.
00260  */
00261 void SMC_NFC_Wait_CommandDone(void)
00262 {
00263     while (smcStatus.bStatus.cmdDone == 0)
00264     {
00265         SMC_Handler();
00266     }
00267 }
00268 
00269 /**
00270  * \brief Wait for NFC Data Transfer Terminated.
00271  */
00272 void SMC_NFC_Wait_XfrDone(void)
00273 {
00274     while (smcStatus.bStatus.xfrDone == 0)
00275     {
00276         SMC_Handler();
00277     }
00278 }
00279 
00280 /**
00281  * \brief Wait for NFC Data Transfer Terminated.
00282  */
00283 void SMC_NFC_Wait_HammingReady(void)
00284 {
00285     while (smcStatus.bStatus.hammingReady ==0)
00286     {
00287         SMC_Handler();
00288     }
00289 }
00290 
00291 /**
00292  * \brief Wait for NFC Ready/Busy Line 3 Edge Detected.
00293  */
00294 void SMC_NFC_Wait_RBbusy(void)
00295 {
00296     while (smcStatus.bStatus.rbEdge == 0)
00297     {
00298         SMC_Handler();
00299     }
00300 }
00301 
00302 /**
00303  * \brief Uses the HOST nandflash controller to send a command to the NFC.
00304  * \param cmd  command to send.
00305  * \param addressCycle  address cycle when command access id decoded.
00306  * \param cycle0  address at first cycle.
00307  */
00308 void SMC_NFC_SendCommand(uint32_t cmd, uint32_t addressCycle, uint32_t cycle0)
00309 {
00310     volatile uint32_t *pCommandAddress;
00311     SMC_Clear_Status();
00312     /* Wait until host controller is not busy. */
00313     while(SMC_NFC_isHostBusy());
00314     /* Send the command plus the ADDR_CYCLE */
00315     pCommandAddress = (volatile uint32_t *) (cmd + NFC_CMD_BASE_ADDR);
00316     SMC->SMC_ADDR = cycle0;
00317     *pCommandAddress = addressCycle;
00318     SMC_NFC_Wait_CommandDone();
00319 }
00320 
00321 /* ECC function */
00322 
00323 /**
00324  * \brief Get 24-bit ECC code for 8-bit data path NAND flash.
00325  * 24-bit ECC is generated in order to perform one bit correction
00326  * for 512 byte in page 512/1024/2048/4096 for 8-bit words
00327  *
00328  * \param size  Data size in bytes.
00329  * \param code  Codes buffer.
00330  */
00331 static void _smc_ecc_GetW9BitPer512Ecc(uint32_t pageDataSize, uint8_t *code)
00332 {
00333     uint8_t i;
00334     uint8_t numEcc;
00335     uint32_t eccParity;
00336     uint32_t ecc[16];
00337 
00338     SMC_ECC_GetValue(ecc);
00339     numEcc = pageDataSize / 512;
00340     /*  P2048' P1024' P512' P256' P128'   P64'  P32' P16'  ---  3rd. Ecc Byte to store */
00341     /*  P8'    P4'    P2'   P1'   P2048   P1024 P512 P256  ---  2nd. Ecc Byte to store */
00342     /*  P128   P64    P32   P16   P8      P4    P2   P1    ---  1st. Ecc Byte to store */
00343     for (i = 0; i < numEcc; i++) {
00344         /* Get Parity and NParity value. */
00345         eccParity = ecc[i];
00346         eccParity = ~eccParity;
00347         code[i * 3] = eccParity & 0xff;
00348         code[i * 3 + 1] = (eccParity >> 8) & 0xff;
00349         code[i * 3 + 2] = (eccParity >> 16) & 0xff;
00350     }
00351 }
00352 
00353 /**
00354  * \brief Get 24-bit ECC code for 8-bit data path NAND flash.
00355  * 24-bit ECC is generated in order to perform one bit correction
00356  * for 256 byte in page 512/1024/2048/4096 for 8-bit words
00357  *
00358  * \param size  Data size in bytes.
00359  * \param code  Codes buffer.
00360  */
00361 static void _smc_ecc_GetW8BitPer256Ecc(uint32_t pageDataSize, uint8_t *code)
00362 {
00363     uint8_t i;
00364     uint8_t numEcc;
00365     uint32_t eccParity;
00366     uint32_t ecc[16];
00367 
00368     SMC_ECC_GetValue(ecc);
00369     numEcc = pageDataSize / 256;
00370 
00371     /*  P2048' P1024' P512' P256' P128'   P64'  P32' P16'  ---  3rd. Ecc Byte to store */
00372     /*  P8'    P4'    P2'   P1'   P2048   P1024 P512 P256  ---  2nd. Ecc Byte to store */
00373     /*  P128   P64    P32   P16   P8      P4    P2   P1    ---  1st. Ecc Byte to store */
00374     for (i = 0; i < numEcc; i++) {
00375         /* Get Parity and NParity value. */
00376         eccParity = ecc[i];
00377         eccParity = ~eccParity; 
00378         TRACE_DEBUG("ecc Parity%d is 0x%08x \n\r", (int)i, (uint32_t)eccParity);
00379         code[i * 3] = eccParity & 0xff;
00380         code[i * 3 + 1] = (eccParity >> 8) & 0xff;
00381         code[i * 3 + 2] = (eccParity >> 16) & 0xff;
00382     }
00383 }
00384 
00385 /**
00386  * \breif Get 32-bit ECC code for 16-bit data path NAND flash.
00387  * 32-bit ECC is generated in order to perform one bit correction
00388  * for a page in page 512/1024/2048/4096 for 16-bit words
00389  *
00390  * \param size  Data size in bytes.
00391  * \param code  Codes buffer.
00392  */
00393 static void _smc_ecc_GetW12BitPerPageEcc(uint32_t pageDataSize, uint8_t *code)
00394 {
00395     uint32_t eccParity;
00396     uint32_t eccNparity;
00397     uint32_t ecc[16];
00398 
00399     pageDataSize = pageDataSize; /* stop warning */
00400     /* Get Parity value. */
00401     SMC_ECC_GetValue(ecc);
00402 
00403     /*  ----   P16384'P8192'P4096'P2048'  P1024'P512'P256' ---  4th. Ecc Byte to store */
00404     /*  P128'  P64'   P32'  P16'  P8'     P4'   P2'  P1'   ---  3rd. Ecc Byte to store */
00405     /*  ----   P16384 P8192 P4096 P2048   P1024 P512 P256  ---  2nd. Ecc Byte to store */
00406     /*  P128   P64    P32   P16   P8      P4    P2   P1    ---  1st. Ecc Byte to store */
00407 
00408     /* Invert codes (linux compatibility) */
00409     eccParity = ecc[0];
00410     eccNparity = ecc[1];
00411     code[0] = eccParity & 0xff;
00412     code[1] = (eccParity >> 8 )& 0xff;
00413     code[2] = eccNparity & 0xff;
00414     code[3] = (eccNparity >> 8 )& 0xff;
00415 }
00416 
00417 
00418 /**
00419  * \brief Configures ECC mode.
00420  * \param type  Type of correction.
00421  * \param pageSize  Page size of NAND flash device.
00422  */
00423 void SMC_ECC_Configure(uint32_t type, uint32_t pageSize)
00424 {
00425     /* Software Reset ECC. */
00426     SMC->SMC_ECC_CTRL = (0x1 <<  1) ;
00427     SMC->SMC_ECC_MD = type | pageSize;
00428 }
00429 
00430 /**
00431  * \brief Get ECC correction type.
00432  *
00433  * \return Returns type of ECC correction setting.
00434  */
00435 uint32_t SMC_ECC_GetCorrectoinType(void)
00436 {
00437     return ((SMC->SMC_ECC_MD)& SMC_ECC_MD_TYPCORREC_Msk);
00438 }
00439 
00440 /**
00441  * \brief Get ECC status.
00442  * \param eccNumber  ecc parity number from 0 to 15.
00443  *
00444  * \return Returns ECC status by giving ecc number.
00445  */
00446 uint8_t SMC_ECC_GetStatus(uint8_t eccNumber)
00447 {
00448     uint32_t status;
00449 
00450     if (eccNumber < 8){
00451         status = SMC->SMC_ECC_SR1;
00452     } else {
00453         status = SMC->SMC_ECC_SR2;
00454         eccNumber -=8;
00455     }
00456     return ((status >> (eccNumber * 4)) & 0x07);
00457 }
00458 
00459 /**
00460  * \brief Get all ECC parity and Nparity value.
00461  */
00462 void SMC_ECC_GetValue(uint32_t *ecc)
00463 {
00464     ecc[0] = SMC->SMC_ECC_PR0;
00465     ecc[1] = SMC->SMC_ECC_PR1;
00466     ecc[2] = SMC->SMC_ECC_PR2;
00467     ecc[3] = SMC->SMC_ECC_PR3;
00468     ecc[4] = SMC->SMC_ECC_PR4;
00469     ecc[5] = SMC->SMC_ECC_PR5;
00470     ecc[6] = SMC->SMC_ECC_PR6;
00471     ecc[7] = SMC->SMC_ECC_PR7;
00472     ecc[8] = SMC->SMC_ECC_PR8;
00473     ecc[9] = SMC->SMC_ECC_PR9;
00474     ecc[10] = SMC->SMC_ECC_PR10;
00475     ecc[11] = SMC->SMC_ECC_PR11;
00476     ecc[12] = SMC->SMC_ECC_PR12;
00477     ecc[13] = SMC->SMC_ECC_PR13;
00478     ecc[14] = SMC->SMC_ECC_PR14;
00479     ecc[15] = SMC->SMC_ECC_PR15;
00480 }
00481 
00482 /**
00483  * \brief verifies 4-bytes hsiao codes for a data block whose size is a page Size
00484  * word. Page words block is verified between the given HSIAO code 
00485  * generated by hardware and original HSIAO codes store has been previously stored.
00486  * Returns 0 if the data is correct, Hsiao_ERROR_SINGLEBIT if one or more
00487  * block(s) have had a single bit corrected, or either Hsiao_ERROR_ECC
00488  * or Hsiao_ERROR_MULTIPLEBITS.
00489  * \param data  Data buffer to verify.
00490  * \param originalCode  Original codes.
00491  * \param verifyCode  codes to be verified.
00492  */
00493 static uint8_t _smc_ecc_VerifyW12BitPerPageEcc(
00494         uint8_t *data,
00495         const uint8_t *originalCode,
00496         const uint8_t *verifyCode)
00497 {
00498     uint8_t correctionCode[4];
00499     uint8_t bitCount;
00500     // Xor both codes together
00501     correctionCode[0] = verifyCode[0] ^ originalCode[0];
00502     correctionCode[1] = verifyCode[1] ^ originalCode[1];
00503     correctionCode[2] = verifyCode[2] ^ originalCode[2];
00504     correctionCode[3] = verifyCode[3] ^ originalCode[3];
00505     TRACE_DEBUG("Correction code = %02X %02X %02X %02X\n\r",
00506             correctionCode[0], correctionCode[1], correctionCode[2], correctionCode[3]);
00507     /* If all bytes are 0, there is no error */
00508     if ((correctionCode[0] == 0)
00509             && (correctionCode[1] == 0)
00510             && (correctionCode[2] == 0)
00511             && (correctionCode[3] == 0)) {
00512 
00513         return 0;
00514     }
00515     /* If there is a single bit error, there are 15 bits set to 1 */
00516     bitCount = CountBitsInByte(correctionCode[0]) + 
00517         CountBitsInByte(correctionCode[1]) + 
00518         CountBitsInByte(correctionCode[2]) + 
00519         CountBitsInByte(correctionCode[3]);
00520     if (bitCount == 15) {
00521         /* Get byte and bit indexes */
00522         uint16_t byte = (correctionCode[0] & 0xf0) >> 4;
00523         byte |= (correctionCode[1] & 0xff) << 4;
00524         uint8_t bit = correctionCode[0] & 0x0f;
00525         /* Correct bit */
00526         printf("Correcting byte #%d at bit %d\n\r", byte, bit);
00527         data[byte] ^= (1 << bit);
00528 
00529         return Hsiao_ERROR_SINGLEBIT;
00530     }
00531 
00532     /* Check if ECC has been corrupted */
00533     if (bitCount == 1) {
00534         return Hsiao_ERROR_ECC;
00535     }
00536     /* Otherwise, this is a multi-bit error */
00537     else {
00538         return Hsiao_ERROR_MULTIPLEBITS;
00539     }
00540 }
00541 
00542 /**
00543  * \brief verifies 3-bytes hsiao codes for a data block whose size is a page Size
00544  * word. Page words block is verified between the given HSIAO code 
00545  * generated by hardware and original HSIAO codes store has been previously stored.
00546  * Returns 0 if the data is correct, Hsiao_ERROR_SINGLEBIT if one or more
00547  * block(s) have had a single bit corrected, or either Hsiao_ERROR_ECC
00548  * or Hsiao_ERROR_MULTIPLEBITS.
00549  * \param data  Data buffer to verify.
00550  * \param originalCode  Original codes.
00551  * \param verifyCode  codes to be verified.
00552  */
00553 static uint8_t _smc_ecc_VerifyW8BitPer256Ecc(
00554         uint8_t *data,
00555         uint32_t size,
00556         const uint8_t *originalCode,
00557         const uint8_t *verifyCode)
00558 {
00559     uint8_t correctionCode[3];
00560     uint32_t position = 0;
00561     uint8_t byte;
00562     uint8_t bit;
00563     uint8_t error = 0;
00564 
00565     TRACE_DEBUG("_smc_ecc_VerifyW8BitPer256Ecc()\n\r");
00566     while (position < size) {
00567         /* Xor both codes together */
00568         correctionCode[0] = verifyCode[0] ^ originalCode[0];
00569         correctionCode[1] = verifyCode[1] ^ originalCode[1];
00570         correctionCode[2] = verifyCode[2] ^ originalCode[2];
00571         TRACE_DEBUG("Correction code = %02X %02X %02X\n\r",
00572                 correctionCode[0], correctionCode[1], correctionCode[2]);
00573 
00574         /* If all bytes are 0, there is no error */
00575         if ( correctionCode[0] || correctionCode[1] || correctionCode[2]) {
00576             /* If there is a single bit error, there are 11 bits set to 1 */
00577             if (CountBitsInCode(correctionCode) == 11) {
00578                 /* Get byte and bit indexes */
00579                 byte = (correctionCode[0] & 0xf8) >> 3;
00580                 byte |= (correctionCode[1] & 0x07) << 5;
00581                 bit = correctionCode[0] & 0x07;
00582                 /* Correct bit */
00583                 printf("Correcting byte #%u at bit %u\n\r", (unsigned int)(position + byte),  (unsigned int)bit);
00584                 data[byte] ^= (1 << bit);
00585                 error = Hsiao_ERROR_SINGLEBIT;
00586             }
00587             /* Check if ECC has been corrupted */
00588             else if (CountBitsInCode(correctionCode) == 1) {
00589                 return Hsiao_ERROR_ECC;
00590             } else {
00591                 /* Otherwise, this is a multi-bit error */
00592                 return Hsiao_ERROR_MULTIPLEBITS;
00593             }
00594         }
00595         data += 256;
00596         originalCode += 3;
00597         verifyCode += 3;
00598         position += 256;
00599     }
00600     return error;
00601 }
00602 
00603 /**
00604  * \brief 3-bytes hsiao codes for a data block whose size is multiple of
00605  * 512 bytes. Each 512-bytes block is verified between the given HSIAO code 
00606  * generated by hardware and original HSIAO codes store has been previously stored.
00607  * Returns 0 if the data is correct, Hsiao_ERROR_SINGLEBIT if one or more
00608  * block(s) have had a single bit corrected, or either Hsiao_ERROR_ECC
00609  * or Hsiao_ERROR_MULTIPLEBITS.
00610  * \param data  Data buffer to verify.
00611  * \param originalCode  Original codes.
00612  * \param verifyCode  codes to be verified.
00613  */
00614 static uint8_t _smc_ecc_VerifyW9BitPer512Ecc(
00615         uint8_t *data,
00616         uint32_t size,
00617         const uint8_t *originalCode,
00618         const uint8_t *verifyCode)
00619 {
00620     uint8_t correctionCode[3];
00621     uint32_t position = 0;
00622     uint16_t byte;
00623     uint8_t bit;
00624     uint8_t error = 0;
00625 
00626     TRACE_DEBUG("_smc_ecc_VerifyW9BitPer512Ecc()\n\r");
00627     while (position < size) {
00628         /* Xor both codes together */
00629         correctionCode[0] = verifyCode[0] ^ originalCode[0];
00630         correctionCode[1] = verifyCode[1] ^ originalCode[1];
00631         correctionCode[2] = verifyCode[2] ^ originalCode[2];
00632         TRACE_DEBUG("Correction code = %02X %02X %02X\n\r",
00633                 correctionCode[0], correctionCode[1], correctionCode[2]);
00634 
00635         /* If all bytes are 0, there is no error */
00636         if ( correctionCode[0] || correctionCode[1] || correctionCode[2]) {
00637             // If there is a single bit error, there are 11 bits set to 1
00638             if (CountBitsInCode(correctionCode) == 12) {
00639                 /* Get byte and bit indexes */
00640                 byte = (correctionCode[0] & 0xf8) >> 3;
00641                 byte |= (correctionCode[1] & 0x0f) << 5;
00642                 bit = correctionCode[0] & 0x07;
00643                 /* Correct bit */
00644                 printf("Correcting byte #%u at bit %u\n\r", 
00645                     (unsigned int)(position + byte),  (unsigned int)bit);
00646                 data[byte] ^= (1 << bit);
00647                 error = Hsiao_ERROR_SINGLEBIT;
00648             }
00649             /* Check if ECC has been corrupted */
00650             else if (CountBitsInCode(correctionCode) == 1) {
00651                 return Hsiao_ERROR_ECC;
00652             } else {
00653                 /* Otherwise, this is a multi-bit error */
00654                 return Hsiao_ERROR_MULTIPLEBITS;
00655             }
00656         }
00657         data += 512;
00658         originalCode += 3;
00659         verifyCode += 3;
00660         position += 512;
00661     }
00662     return error;
00663 }
00664 
00665 /**
00666  * Get ECC code for 8bit/16-bit data path NAND flash by giving data path.
00667  * 24-bit or 32-bit ECC is generated in order to perform one bit correction
00668  * for a page in page 512/1024/2048/4096.
00669  *
00670  * \param size  Data size in bytes.
00671  * \param code  Codes buffer.
00672  * \param busWidth 8bit/16bit data path.
00673  */
00674 void SMC_ECC_GetEccParity(uint32_t pageDataSize, uint8_t *code, uint8_t busWidth)
00675 {
00676     uint8_t correctionType;
00677 
00678     correctionType = SMC_ECC_GetCorrectoinType();
00679     /* For 16-bit data path */
00680     if (busWidth == 16 && correctionType == SMC_ECC_MD_TYPCORREC_CPAGE )
00681         _smc_ecc_GetW12BitPerPageEcc(pageDataSize, code);
00682     /* For 8-bit data path */
00683     else {
00684         switch (correctionType){
00685             case SMC_ECC_MD_TYPCORREC_CPAGE:
00686                 _smc_ecc_GetW12BitPerPageEcc(pageDataSize, code);
00687                 break;
00688             case SMC_ECC_MD_TYPCORREC_C256B:
00689                 _smc_ecc_GetW8BitPer256Ecc(pageDataSize, code);
00690                 break;
00691             case SMC_ECC_MD_TYPCORREC_C512B:
00692                 _smc_ecc_GetW9BitPer512Ecc(pageDataSize, code);
00693                 break;
00694         }
00695     }
00696 }
00697 
00698 
00699 /**
00700  *  Verifies hsiao codes for a data block. The block is verified between the given 
00701  *  HSIAO code generated by hardware and original HSIAO codes store has been 
00702  *  previously stored.
00703  *  Returns 0 if the data is correct, Hsiao_ERROR_SINGLEBIT if one or more
00704  *  block(s) have had a single bit corrected, or either Hsiao_ERROR_ECC
00705  *  or Hsiao_ERROR_MULTIPLEBITS.
00706  *  \param data  Data buffer to verify.
00707  *  \param size  Size of the data in words.
00708  *  \param originalCode  Original codes.
00709  *  \param verifyCode  codes to be verified.
00710  *  \param dataPath 8bit/16bit data path.
00711  */
00712 uint8_t SMC_ECC_VerifyHsiao(
00713         uint8_t *data,
00714         uint32_t size,
00715         const uint8_t *originalCode,
00716         const uint8_t *verifyCode,
00717         uint8_t busWidth)
00718 {
00719     uint8_t correctionType;
00720     uint8_t error = 0;
00721     correctionType = SMC_ECC_GetCorrectoinType();
00722     /* For 16-bit data path */
00723     if (busWidth == 16 && (correctionType == SMC_ECC_MD_TYPCORREC_CPAGE) ) {
00724         error = _smc_ecc_VerifyW12BitPerPageEcc((uint8_t*)data, originalCode, verifyCode);
00725     }
00726     /* For 8-bit data path */
00727     else {
00728         switch (correctionType){
00729         case SMC_ECC_MD_TYPCORREC_CPAGE:
00730             error = _smc_ecc_VerifyW12BitPerPageEcc(data, originalCode, verifyCode);
00731             break;
00732         case SMC_ECC_MD_TYPCORREC_C256B:
00733             error = _smc_ecc_VerifyW8BitPer256Ecc(data, size, originalCode, verifyCode);
00734             break;
00735         case SMC_ECC_MD_TYPCORREC_C512B:
00736             error = _smc_ecc_VerifyW9BitPer512Ecc(data, size, originalCode, verifyCode);
00737             break;
00738         }
00739     }
00740     return error;
00741 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines