ECC算法问题。

请教一下这段读写NANDFLASH的代码中ECC效验是如何实现的??

 

 

 

#include "../inc/def.h"

#include "../inc/config.h"

#include "../inc/utils.h"

#include "../inc/board.h"

#include "2410addr.h"

#ifdef NAND_FLASH_SUPPORT

 

struct NFChipInfo {

U32 id;

U32 size;

}

 

static NandFlashChip[] = {

{0xec73, SIZE_16M},

{0xec75, SIZE_32M},

{0xec76, SIZE_64M},

{0xec79, SIZE_128M},

{0, 0},

};

 

#define BLK_IDXL 8

#define BLK_IDXH 9

#define FMT_TAG 15

 

char format_tags[] = "Formatted For NAND FLASH Driver"; //must be less than 32

/***********************************************************/

//nand ecc utils

typedef unsigned char u_char;

static u_char eccpos[6] = {0, 1, 2, 3, 6, 7};

 

/*

 * Pre-calculated 256-way 1 byte column parity

 */

static const u_char nand_ecc_precalc_table[] = {

0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a, 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00,

0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f, 0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65,

0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c, 0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66,

0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59, 0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03,

0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33, 0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69,

0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56, 0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c,

0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55, 0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f,

0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30, 0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a,

0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30, 0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a,

0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55, 0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f,

0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56, 0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c,

0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33, 0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69,

0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59, 0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03,

0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c, 0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66,

0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f, 0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65,

0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a, 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00

};

 

 

/**

 * nand_trans_result - [GENERIC] create non-inverted ECC

 * @reg2: line parity reg 2

 * @reg3: line parity reg 3

 * @ecc_code: ecc 

 *

 * Creates non-inverted ECC code from line parity

 */

static void nand_trans_result(u_char reg2, u_char reg3,

u_char *ecc_code)

{

u_char a, b, i, tmp1, tmp2;

 

/* Initialize variables */

a = b = 0x80;

tmp1 = tmp2 = 0;

 

/* Calculate first ECC byte */

for (i = 0; i < 4; i++) {

if (reg3 & a) /* LP15,13,11,9 --> ecc_code[0] */

tmp1 |= b;

b >>= 1;

if (reg2 & a) /* LP14,12,10,8 --> ecc_code[0] */

tmp1 |= b;

b >>= 1;

a >>= 1;

}

 

/* Calculate second ECC byte */

b = 0x80;

for (i = 0; i < 4; i++) {

if (reg3 & a) /* LP7,5,3,1 --> ecc_code[1] */

tmp2 |= b;

b >>= 1;

if (reg2 & a) /* LP6,4,2,0 --> ecc_code[1] */

tmp2 |= b;

b >>= 1;

a >>= 1;

}

 

/* Store two of the ECC bytes */

ecc_code[0] = tmp1;

ecc_code[1] = tmp2;

}

 

/**

 * nand_calculate_ecc - [NAND Interface] Calculate 3 byte ECC code for 256 byte block

 * @dat: raw data

 * @ecc_code: buffer for ECC

 */

int nand_calculate_ecc(const u_char *dat, u_char *ecc_code)

{

u_char idx, reg1, reg2, reg3;

int j;

 

/* Initialize variables */

reg1 = reg2 = reg3 = 0;

ecc_code[0] = ecc_code[1] = ecc_code[2] = 0;

 

/* Build up column parity */ 

for(j = 0; j < 256; j++) {

 

/* Get CP0 - CP5 from table */

idx = nand_ecc_precalc_table[dat[j]];

reg1 ^= (idx & 0x3f);

 

/* All bit XOR = 1 ? */

if (idx & 0x40) {

reg3 ^= (u_char) j;

reg2 ^= ~((u_char) j);

}

}

 

/* Create non-inverted ECC code from line parity */

nand_trans_result(reg2, reg3, ecc_code);

 

/* Calculate final ECC code */

ecc_code[0] = ~ecc_code[0];

ecc_code[1] = ~ecc_code[1];

ecc_code[2] = ((~reg1) << 2) | 0x03;

return 0;

}

 

/**

 * nand_correct_data - [NAND Interface] Detect and correct bit error(s)

 * @dat: raw data read from the chip

 * @read_ecc: ECC from the chip

 * @calc_ecc: the ECC calculated from raw data

 *

 * Detect and correct a 1 bit error for 256 byte block

 */

int nand_correct_data(u_char *dat, u_char *read_ecc, u_char *calc_ecc)

{

u_char a, b, c, d1, d2, d3, add, bit, i;

 

/* Do error detection */ 

d1 = calc_ecc[0] ^ read_ecc[0];

d2 = calc_ecc[1] ^ read_ecc[1];

d3 = calc_ecc[2] ^ read_ecc[2];

 

if ((d1 | d2 | d3) == 0) {

/* No errors */

return 0;

}

else {

a = (d1 ^ (d1 >> 1)) & 0x55;

b = (d2 ^ (d2 >> 1)) & 0x55;

c = (d3 ^ (d3 >> 1)) & 0x54;

 

/* Found and will correct single bit error in the data */

if ((a == 0x55) && (b == 0x55) && (c == 0x54)) {

c = 0x80;

add = 0;

a = 0x80;

for (i=0; i<4; i++) {

if (d1 & c)

add |= a;

c >>= 2;

a >>= 1;

}

c = 0x80;

for (i=0; i<4; i++) {

if (d2 & c)

add |= a;

c >>= 2;

a >>= 1;

}

bit = 0;

b = 0x04;

c = 0x80;

for (i=0; i<3; i++) {

if (d3 & c)

bit |= b;

c >>= 2;

b >>= 1;

}

b = 0x01;

a = dat[add];

a ^= (b << bit);

dat[add] = a;

return 1;

}

else {

i = 0;

while (d1) {

if (d1 & 0x01)

++i;

d1 >>= 1;

}

while (d2) {

if (d2 & 0x01)

++i;

d2 >>= 1;

}

while (d3) {

if (d3 & 0x01)

++i;

d3 >>= 1;

}

if (i == 1) {

/* ECC Code Error Correction */

read_ecc[0] = calc_ecc[0];

read_ecc[1] = calc_ecc[1];

read_ecc[2] = calc_ecc[2];

return 2;

}

else {

/* Uncorrectable Error */

return -1;

}

}

}

 

/* Should never happen */

return -1;

}

 

/**********************************************************/

 

 

static U32 NFWritePage(U32 addr, U8 *buf, U16 blk_idx)

{

U16 i, stat;

// U8 tmp[3];

U8 ecc_code[3];

U8 oob_info[16];

 

for(i=0; i<sizeof(oob_info); i++)

oob_info[i] = 0xff;

 

nand_calculate_ecc(buf, ecc_code);

oob_info[eccpos[0]] = ecc_code[0];

oob_info[eccpos[1]] = ecc_code[1];

oob_info[eccpos[2]] = ecc_code[2];

nand_calculate_ecc(buf+256, ecc_code);

oob_info[eccpos[3]] = ecc_code[0];

oob_info[eccpos[4]] = ecc_code[1];

oob_info[eccpos[5]] = ecc_code[2];

oob_info[BLK_IDXL]  = blk_idx;

oob_info[BLK_IDXH]  = blk_idx>>8;

oob_info[FMT_TAG]   = format_tags[addr&0x1f];

 

NFChipEn();

NFWrCmd(PROGCMD0);

NFWrAddr(0);

NFWrAddr(addr);

NFWrAddr(addr>>8);

if(NandAddr)

NFWrAddr(addr>>16);

// InitEcc();

for(i=0; i<512; i++)

NFWrDat(buf[i]);

 

if(!addr) {

NFWrDat('b');

NFWrDat('o');

NFWrDat('o');

NFWrDat('t');

} else {

for(i=0; i<sizeof(oob_info); i++)

NFWrDat(oob_info[i]);

}

 

NFWrCmd(PROGCMD1);

stat = NFWaitBusy();

NFChipDs();

 

#ifdef WR_BAD_BLK_TEST

if((addr&0xff)==0x17) stat = 1; //just for test bad block

#endif

 

if(stat)

printf("Write nand flash 0x%x fail/n", addr);

else {

U8 RdDat[512];

 

NFReadPage(addr, RdDat);

for(i=0; i<512; i++)

if(RdDat[i]!=buf[i]) {

printf("Check data at page 0x%x, offset 0x%x fail/n", addr, i);

stat = 1;

break;

}

}

 

return stat;

}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值