u-boot移植3:支持 nandflash 的硬件 ECC
发布时间:2020-12-15 20:04:50 所属栏目:百科 来源:网络整理
导读:u-boot 版本:2016.03 用的交叉编译工具:arm-none-linux-gnueabi- 操作的文件:drivers/mtd/nand/s3c2440_nand.c 1. 程序分析: 要知道的几点 : 从s3c2440_nand.c 中知道,要想开启 硬件的ECC ,需要定义一个 CONFIG_S3C2440_NAND_HWECC 的宏,可以放在板
u-boot 版本:2016.03
用的交叉编译工具:arm-none-linux-gnueabi-
操作的文件:drivers/mtd/nand/s3c2440_nand.c 1. 程序分析:要知道的几点:
1.1 当定义了 CONFIG_S3C2440_NAND_HWECC 后,在s3c2440_nand.c 中就定义了3个函数:
1.2 在?board_nand_init 函数中关联上 nand_chip 结构体中相应的函数指针:
#ifdef CONFIG_S3C2440_NAND_HWECC nand->ecc.hwctl = s3c24x0_nand_enable_hwecc; nand->ecc.calculate = s3c24x0_nand_calculate_ecc; nand->ecc.correct = s3c24x0_nand_correct_data; nand->ecc.mode = NAND_ECC_HW; nand->ecc.size = CONFIG_SYS_NAND_ECCSIZE; nand->ecc.bytes = CONFIG_SYS_NAND_ECCBYTES; nand->ecc.strength = 1; #else nand->ecc.mode = NAND_ECC_SOFT; #endif 1.3 在?drivers/mtd/nand/nand_base.c?中的函数中进行使用:
比如?
nand_read_page_hwecc 函数中的:
for (i = 0; eccsteps; eccsteps--,i += eccbytes,p += eccsize) { chip->ecc.hwctl(mtd,NAND_ECC_READ); chip->read_buf(mtd,p,eccsize); chip->ecc.calculate(mtd,&ecc_calc[i]); }
在这些函数中关键的 for 循环中所用的参数是我们需要修改的:
for(i = 0; eccsteps; eccsteps--,p += eccsize) {
…… ?……?
}
for循环的作用是适应不同 cpu 的nandflash 控制器一次所能完成的硬件ECC的字节数不同
举例:
? ? ? ? 如果:
需要分4次来计算ecc,还要注意的是每次ecc产生的结果字节数也有所不同,有的3字节,有的4字节。
eccsize= chip->ecc.size;
eccbytes= chip->ecc.bytes;?
eccsteps= chip->ecc.steps;
我们需要查看的是前两个参数,后边的一个参数是程序中自己计算的
我们的s3c2440:
nand->ecc.size = 2048;
nand->ecc.bytes = 4;
2. 程序修改:2.1 修改配置文件:include/configs/lip2440.h?
? ??
---?a/include/configs/lip2440.h
+++?b/include/configs/lip2440.h
@@?-147,7?+147,7?@@
?#define?CONFIG_SYS_FLASH_BANKS_LIST?????{?CONFIG_SYS_FLASH_BASE?}
?#define?CONFIG_SYS_MAX_FLASH_SECT??????(35)
-#define?CONFIG_ENV_ADDR????????????????????????(CONFIG_SYS_FLASH_BASE?+?0x070000)
+#define?CONFIG_ENV_ADDR????????????????????????(CONFIG_SYS_FLASH_BASE?+?0x100000)
?#define?CONFIG_ENV_IS_IN_FLASH
?#define?CONFIG_ENV_SIZE????????????????????????0x10000
?/*?allow?to?overwrite?serial?and?ethaddr?*/
@@?-168,8?+168,11?@@
?#ifdef?CONFIG_CMD_NAND
?#define?CONFIG_NAND_S3C2440
?#define?CONFIG_SYS_S3C2440_NAND_HWECC
+#define?CONFIG_S3C2440_NAND_HWECC
?#define?CONFIG_SYS_MAX_NAND_DEVICE?????1
?#define?CONFIG_SYS_NAND_BASE???????????0x4E000000
+#define?CONFIG_SYS_NAND_ECCSIZE?2048
+#define?CONFIG_SYS_NAND_ECCBYTES?4
?#endif
2.2 更改 s3c2440 的寄存器的:arch/arm/include/asm/arch-s3c24x0/s3c24x0.h
@@?-145,16?+145,16?@@?struct?s3c24x0_nand?{
????????u32?????nfaddr;
????????u32?????nfdata;
?#ifndef?CONFIG_S3C2410
-???????u32?????nfeccd0;
-???????u32?????nfeccd1;
-???????u32?????nfeccd;
+???????u32?????nfmeccd0;
+???????u32?????nfmeccd1;
+???????u32?????nfseccd;
?#endif
????????u32?????nfstat;
?#ifdef?CONFIG_S3C2410
????????u32?????nfecc;
?#else
-???????u32?????nfstat0;
-???????u32?????nfstat1;
+???????u32?????nfestat0;
+???????u32?????nfestat1;
????????u32?????nfmecc0;
????????u32?????nfmecc1;
????????u32?????nfsecc;
2.3 修改关键的3函数:drivers/mtd/nand/s3c2440_nand.c
@@?-82,32?+82,75?@@?void?s3c24x0_nand_enable_hwecc(struct?mtd_info?*mtd,?int?mode)
?{
????????struct?s3c24x0_nand?*nand?=?s3c24x0_get_base_nand();
????????debug("s3c24x0_nand_enable_hwecc(%p,?%d)n",?mtd,?mode);
-???????writel(readl(&nand->nfconf)?|?S3C2440_NFCONF_INITECC,?&nand->nfconf);
+???????writel((readl(&nand->nfcont)?|?S3C2440_NFCONT_INITECC)?&?~S3C2440_NFCONT_MECCL,?&nand->nfcont);
?}
?static?int?s3c24x0_nand_calculate_ecc(struct?mtd_info?*mtd,?const?u_char?*dat,
??????????????????????????????????????u_char?*ecc_code)
?{
????????struct?s3c24x0_nand?*nand?=?s3c24x0_get_base_nand();
-???????ecc_code[0]?=?readb(&nand->nfecc);
-???????ecc_code[1]?=?readb(&nand->nfecc?+?1);
-???????ecc_code[2]?=?readb(&nand->nfecc?+?2);
-???????debug("s3c24x0_nand_calculate_hwecc(%p,):?0x%02x?0x%02x?0x%02xn",
-?????????????mtd?,?ecc_code[0],?ecc_code[1],?ecc_code[2]);
+????u_int32_t?mecc0;
+????writel(readl(&nand->nfcont)|?S3C2440_NFCONT_MECCL,&nand->nfcont);
+????mecc0?=?readl(&nand->nfmecc0);
+???????ecc_code[0]?=?mecc0?&?0xff;
+???????ecc_code[1]?=?(mecc0?>>?8)?&?0xff;
+???????ecc_code[2]?=?(mecc0?>>?16)?&?0xff;
+???????ecc_code[3]?=?(mecc0?>>?24)?&?0xff;
+???????debug("s3c24x0_nand_calculate_hwecc(%p,):?0x%02x?0x%02x?0x%02x?0x%02xn",
+?????????????mtd?,?ecc_code[2],?ecc_code[3]);
????????return?0;
?}
?static?int?s3c24x0_nand_correct_data(struct?mtd_info?*mtd,?u_char?*dat,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? u_char?*read_ecc,?u_char?*calc_ecc)
?{
-???????if?(read_ecc[0]?==?calc_ecc[0]?&&
-???????????read_ecc[1]?==?calc_ecc[1]?&&
-???????????read_ecc[2]?==?calc_ecc[2])
-???????????????return?0;
-???????printf("s3c24x0_nand_correct_data:?not?implementedn");
-???????return?-1;
+????struct??s3c24x0_nand?*nand?=?s3c24x0_get_base_nand();
+????u_int32_t??meccdata0,?meccdata1,?estat0,?err_byte_addr;
+????int??ret?=?-1;
+????u_int8_t??repaired;
+
+????meccdata0=?(read_ecc[1]?<<?16)?|?read_ecc[0];
+????meccdata1=?(read_ecc[3]?<<?16)?|?read_ecc[2];
+
+????writel(meccdata0,&nand->nfmeccd0);
+????writel(meccdata1,&nand->nfmeccd1);
+
+????/*?Read?ecc?status?*/
+
+????estat0=?readl(&nand->nfestat0);??
+
+????switch(estat0?&?0x3)?{
+????case??0:?/*?No?error?*/
+????????ret=?0;
+????????break;
+????case??1:
+????????/*
+?????????*?1?bit?error?(Correctable)
+?????????*?(nfestat0?>>?7)?&?0x7ff????:error?byte?number
+?????????*?(nfestat0?>>?4)?&?0x7??????:error?bit?number
+?????????*/
+
+????????err_byte_addr=?(estat0?>>?7)?&?0x7ff;
+????????repaired=?dat[err_byte_addr]?^?(1?<<?((estat0?>>?4)?&?0x7));
+
+????????printf("S3C?NAND:?1?bit?error?detected?at?byte%d.?"
+????????????????"Correcting?from?0x%02x?to0x%02x...OKn",
+????????????????err_byte_addr,?dat[err_byte_addr],repaired);
+
+????????dat[err_byte_addr]=?repaired;
+????????ret=?1;
+????????break;
+????case??2:?/*?Multiple?error?*/
+????case??3:?/*?ECC?area?error?*/
+????????printf("S3C?NAND:?ECC?uncorrectable?errordetected.?"
+????????????????"Not?correctable.n");
+????????ret=?-1;
+????????break;
+????}
+
+????return???ret;
?}
?#endif
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |