历史上的今天
今天是:2024年12月25日(星期三)
2020年12月25日 | S3C6410使用---21yaffs2的ECC
2020-12-25 来源:eefocus
一. ECC校验
ECC: error Checking and correct,既能检查错误也能纠正错误.
优点是: 速度奇快
缺点是: 只能检查2bit的错误,只能纠正1bit的错误
如果想验证这儿需要打开 param . no_tags_ecc=0,默认 param . no_tags_ecc=1不进行tags校验.
同时,mkyaffs2image中也要把ECC校验信息加进去,这样才能从nand_flash中读出ECC进行比较.
nandmtd2_read_chunk_tags
--> yaffs_unpack_tags2
void yaffs_unpack_tags2(struct yaffs_ext_tags *t, struct yaffs_packed_tags2 *pt, int tags_ecc)
{
enum yaffs_ecc_result ecc_result = YAFFS_ECC_RESULT_NO_ERROR;
if (pt->t.seq_number != 0xffffffff && tags_ecc) {
struct yaffs_ecc_other ecc;
int result;
yaffs_ecc_calc_other((unsigned char *)&pt->t, sizeof(struct yaffs_packed_tags2_tags_only), &ecc);
result = yaffs_ecc_correct_other((unsigned char *)&pt->t,
sizeof(struct yaffs_packed_tags2_tags_only), &pt->ecc, &ecc);
switch (result) {
case 0:
ecc_result = YAFFS_ECC_RESULT_NO_ERROR;
break;
case 1:
ecc_result = YAFFS_ECC_RESULT_FIXED;
break;
case -1:
ecc_result = YAFFS_ECC_RESULT_UNFIXED;
break;
default:
ecc_result = YAFFS_ECC_RESULT_UNKNOWN;
}
}
yaffs_unpack_tags2_tags_only(t, &pt->t);
t->ecc_result = ecc_result; //保存校验后的结果, 调用它的函数是要检查的
yaffs_dump_packed_tags2(pt); //打印而己,不关心
yaffs_dump_tags2(t); //打印而己,不关心
}
这部分主要是校验yaffs_packed_tags2* pt中的结果, sizeof(yaffs_packed_tags2)=4*7=28
struct yaffs_packed_tags2_tags_only {
unsigned seq_number;
unsigned obj_id;
unsigned chunk_id;
unsigned n_bytes;
};
struct yaffs_ecc_other {
unsigned char col_parity;
unsigned line_parity;
unsigned line_parity_prime;
};
struct yaffs_packed_tags2 {
struct yaffs_packed_tags2_tags_only t;
struct yaffs_ecc_other ecc;
};
注意: 这个校验只被 nandmtd2_read_chunk_tags所调用,因为 pt中的数据是存在nand flash的OOB区的,data区的数据在读取时己经被检验过了.
yaffs把OOB区前28个字节也拿来当数据使用了,所以这部分也需要校验.但是nand_flash只会对data区的数据进行校验,所以需要自己写代码来校验这OOB的28个字节
二.校验算法
2. 生成column_parity_table表
#include #include unsigned char entry(unsigned char x) { unsigned char b0, b1, b2, b3, b4, b5, b6, b7; unsigned char p4, p2, p1, p4p, p2p, p1p; unsigned char linep; unsigned char result; b0 = (x & 0x01) ? 1 : 0; b1 = (x & 0x02) ? 1 : 0; b2 = (x & 0x04) ? 1 : 0; b3 = (x & 0x08) ? 1 : 0; b4 = (x & 0x10) ? 1 : 0; b5 = (x & 0x20) ? 1 : 0; b6 = (x & 0x40) ? 1 : 0; b7 = (x & 0x80) ? 1 : 0; p4 = b7 ^ b6 ^ b5 ^ b4; p4p = b3 ^ b2 ^ b1 ^ b0; p2 = b7 ^ b6 ^ b3 ^ b2; p2p = b5 ^ b4 ^ b1 ^ b0; p1 = b7 ^ b5 ^ b3 ^ b1; p1p = b6 ^ b4 ^ b2 ^ b0; linep = p1 ^ p1p; result = 0; if(p4) result |= 0x80; if(p4p) result |= 0x40; if(p2) result |= 0x20; if(p2p) result |= 0x10; if(p1) result |= 0x08; if(p1p) result |= 0x04; if(linep) result |= 0x01; //result >>= 2; //if(linep) result |= 0x40; return result; } int main(int argc, char *argv[]) { unsigned i; printf("const unsigned char column_parity_table[] = {"); for(i = 0; i < 256; i++) { if((i & 0xf) == 0) printf("n"); printf("0x%02x, ",entry((unsigned char) i)); } printf("n};n"); } 2.1校验步骤 a. 通过yaffs_ecc_calc_other生成ECC, 称为new_ecc b. new_ecc与old_ecc进行异或,如果不一样,则说明出错 c. 类似于二叉树,找到出错位,并进行校正 void yaffs_ecc_calc_other(const unsigned char *data, unsigned n_bytes, struct yaffs_ecc_other *ecc_other) //生成新的ECC { unsigned int i; unsigned char col_parity = 0; unsigned line_parity = 0; unsigned line_parity_prime = 0; unsigned char b; for (i = 0; i < n_bytes; i++) { b = column_parity_table[*data++]; col_parity ^= b; if (b & 0x01) { /* odd number of bits in the byte */ line_parity ^= i; line_parity_prime ^= ~i; } } ecc_other->col_parity = (col_parity >> 2) & 0x3f; ecc_other->line_parity = line_parity; ecc_other->line_parity_prime = line_parity_prime; } 3. int yaffs_ecc_correct_other(unsigned char *data, unsigned n_bytes, struct yaffs_ecc_other *read_ecc, const struct yaffs_ecc_other *test_ecc) { //与test_ecc比较如果不同则进行校正 unsigned char delta_col; /* column parity delta */ unsigned delta_line; /* line parity delta */ unsigned delta_line_prime; /* line parity delta */ unsigned bit; delta_col = read_ecc->col_parity ^ test_ecc->col_parity; delta_line = read_ecc->line_parity ^ test_ecc->line_parity; delta_line_prime = read_ecc->line_parity_prime ^ test_ecc->line_parity_prime; if ((delta_col | delta_line | delta_line_prime) == 0) return 0; /* no error */ if (delta_line == ~delta_line_prime && (((delta_col ^ (delta_col >> 1)) & 0x15) == 0x15)) { bit = 0; //bit <0-7>,代表哪一位出错 if (delta_col & 0x20) bit |= 0x04; if (delta_col & 0x08) bit |= 0x02; if (delta_col & 0x02) bit |= 0x01; if (delta_line >= n_bytes) return -1; data[delta_line] ^= (1 << bit); //找到出错的位了,把它反转 return 1; /* corrected */ } if ((hweight32(delta_line) + hweight32(delta_line_prime) + hweight8(delta_col)) == 1) { /* Reccoverable error in ecc */ *read_ecc = *test_ecc; return 1; /* corrected */ } /* Unrecoverable error */ return -1; }
所以每一个result都是:![]()
史海拾趣
|
module decoder1(c,y,clk);output[6:0] c;input[6:0] y;input clk;reg[2:0] s;reg[6:0] e,c;always @(posedge clk) begins[0] = y[0] ^ y[3] ^ y[5] ^ y[6];s[1] = y[1] ^ y[3] ^ y[4] ^ y[5];s[2] = y[2] ^ y[4] ^ y[5] ^ y[6]; //s[0]~ s[2]为伴 ...… 查看全部问答> |
|
一般控制步进电机的程序里都有一个“转动表格”之类的东西,比如{0xf1,0xe9,0xe5,0xe3}等等。本来我一直以为步进电机是一次接收一个数字所代表的信号,从第一个接收到第四个就是走一步,周而复始。 现在我编写了这样一个程序: void main() { & ...… 查看全部问答> |
|
vxworks NAT的问题 .只要回复都给分...分不够再加... 版上的各位大侠,有人在vxworks5.4下做过NAT的东西没,能给小弟一点提示吗,现在这个东西已径把我折磨的半死了。 也可以把资料发到我的email中。zhouxiongjun@hotmail.com 谢谢啦。 … 查看全部问答> |
|
请教大虾们如何实现如下功能: 平台:wince6.0 假如现在已经有一个应用程序myap.exe运行了。当我插入sd卡时(sk卡上有新版的myap.exe),点击更新程序按钮时,把sd卡新版本的myap.exe程序拷贝到旧版本的myap.exe处(把旧版的覆盖掉),然后自动运 ...… 查看全部问答> |
|
用的是linux的内核,ARM的CPU 我用make zImage编译好2.6.13的内核文件后,把/arch/arm/boot/zImage 文件烧进板子后,linux解压出错.错误信息如下: VIVI version 0.1.4 (root@localhost.localdomain) (gcc version 2.95.2 20000516 (re ...… 查看全部问答> |
|
最近在用MSP430F149做一个谐波检测的功能,听说FFT能够实现,但是无从下手,希望高手们能够指教,或给出FFT程序,或给出学习的方法均可,谢谢大家能帮忙了~~~… 查看全部问答> |




