📄 ecc.c
字号:
static const unsigned 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
捖捖};
捖捖//捖Creates non-inverted ECC code from line parity
捖捖static void nand_trans_result(unsigned char reg2, unsigned char reg3,unsigned char *ecc_code)
捖捖{
捖捖捖捖unsigned 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;
捖捖}
捖捖//捖Calculate 3 byte ECC code for 256 byte block
捖捖void nand_calculate_ecc (const unsigned char *dat, unsigned char *ecc_code)
捖捖{
捖捖捖捖unsigned 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 ^= (unsigned char) j;
捖捖捖捖捖捖捖捖reg2 ^= ~((unsigned 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;
捖捖}
捖捖//捖Detect and correct a 1 bit error for 256 byte block
捖捖int nand_correct_data (unsigned char *dat, unsigned char *read_ecc, unsigned char *calc_ecc)
捖捖{
捖捖捖捖unsigned 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;
捖捖}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -