十八、flash 适配(四)

18.9 硬件 ecc 适配

18.9.1 配置修改

根据前面的内容,修改配置:

查看代码,还需要配置几个选项,在 Kconfig 中没有添加,所以需要添加进去。

先看下 size、bytes 是做什么用的:

  • CONFIG_SYS_NAND_ECCSIZE:定义了数据的长度,即每多少字节进行 1 次 ECC 校验
  • CONFIG_SYS_NAND_ECCBYTES:生成的 ECC 的字节个数,对于 512 字节可以生成 3 个字节,2048 字节可以生成 4 个字节

确定一下 nandflash 的每一页的大小:

 可以看到每一页是 2 x 1024 字节,那么CONFIG_SYS_NAND_ECCSIZE 设置成2048, CONFIG_SYS_NAND_ECCBYTES 设置成 4 个字节

先添加 drivers/mtd/nand/Kconfig 中的代码:

修改配置:

 18.9.2 代码修改

硬件 ECC 主要由 nand 控制器进行控制,所以我们只需要操作寄存器即可。先修改一下硬件控制 ECC 的宏:

 1     /** ecc 初始化, 一个是硬件 ECC 校验,一个是软件 ECC 校验 */
 2 #ifdef CONFIG_NAND_HW_ECC
 3     nand->ecc.hwctl = s3c24x0_nand_enable_hwecc;
 4     nand->ecc.calculate = s3c24x0_nand_calculate_ecc;
 5     nand->ecc.correct = s3c24x0_nand_correct_data;
 6     nand->ecc.mode = NAND_ECC_HW;
 7     nand->ecc.size = CONFIG_SYS_NAND_ECCSIZE;
 8     nand->ecc.bytes = CONFIG_SYS_NAND_ECCBYTES;
 9     nand->ecc.strength = 1;
10 #else
11     nand->ecc.mode = NAND_ECC_SOFT;
12 #endif

接下来来看看芯片手册给我们提供的硬件 ECC 的操作步骤:

 在步骤 1 中很明确的说明需要对 MainECCCLock 开锁,我们放在硬件初始化函数中进行:

之后就是计算 s3c24x0_nand_calculate_ecc :

 对 ECC 进行校验:

 1 /** 该函数首先把 read_ecc 数组内的 ECC 存入寄存器 NFMECCD0 和寄存器 NFMECCD1 中,这样系统就会自动校验数据,
 2  *  并把状态放入寄存器 NFESTAT0 中,然后读取该寄存器的后 4 位,当为 0 时表示校验正确;
 3  *  当为 1 时表示发生了 1 位错误(该类错误可以校正),
 4  *  我们把它校正过来;当为 2 和 3 时表示发生其他类型的错误,这类错误是无法校正的。
 5  */
 6 static int s3c24x0_nand_correct_data(struct mtd_info *mtd, u_char *dat,
 7                      u_char *read_ecc, u_char *calc_ecc)
 8 {
 9 #if CONFIG_S3C2440_NAND_HWECC
10     struct s3c24x0_nand *nand = s3c24x0_get_base_nand();
11 
12     uint  meccdata0, meccdata1, estat0, err_byte_addr;
13     uchar repaired;
14     int ret = -1;
15 
16     meccdata0 = (read_ecc[1] << 16) | read_ecc[0];
17     meccdata1 = (read_ecc[3] << 16) | read_ecc[2];
18 
19     writel(meccdata0, &nand->nfeccd0);
20     writel(meccdata1, &nand->nfeccd1);
21 
22     /** 读取 ecc 得状态 */
23     estat0 = readl(&nand->nfstat0);
24     switch (estat0 & 0x3)
25     {
26         case 0: /*no error*/
27             ret = 0;
28             break;
29         case 1:
30             /* 
31              *1bit error(correctable)
32              *(nfestat0 >> 7) & 0x7ff    error byte number
33              *(nfestat0 >> 4) & 0x7      error bit number
34             */
35             err_byte_addr = (estat0 >>7 ) & 0x7ff;
36             repaired = dat[err_byte_addr] ^ (1 << ((estat0 >> 4) & 0x7));
37             printf("S3C NAND: 1 bit error detected at byte %u. Correcting from 0x%02x to0x%02x...OK\n",
38                err_byte_addr, dat[err_byte_addr], repaired);
39             dat[err_byte_addr] = repaired;
40             ret = 1;
41             break;
42         case 2:  /* Multiple error */
43         case 3:  /* ECC area error */
44             printf("S3C NAND: ECC uncorrectable errordetected. Not correctable.\n");
45             ret= -1;
46             break;
47     }
48 
49     return ret;
50 #else
51     if (read_ecc[0] == calc_ecc[0] &&
52         read_ecc[1] == calc_ecc[1] &&
53         read_ecc[2] == calc_ecc[2])
54         return 0;
55 
56     printf("s3c24x0_nand_correct_data: not implemented\n");
57     return -EBADMSG;
58 #endif
59 }

18.9.3 编译测试

烧写进去后,读写都是 OK 的,但是在擦除的时候报了错,如下:

追踪代码发现是 BBT,即进行擦除的过程中,会进行坏块检查,会去读取每一页的数据,然后进行 ecc 校验,开 debug 进行测试,测试结果如下:

加入打印测试:

nandflash 中有坏块,所以这个问题是非问题。

猜你喜欢

转载自www.cnblogs.com/kele-dad/p/13179385.html