加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

在2440的uboot和内核中添加nandflash硬件ECC

发布时间:2020-12-15 18:13:22 所属栏目:百科 来源:网络整理
导读:平台 ? ? ? ? ? ? ? ? ? ? ? ?: ? ? ? ? ? ? tq2440开发板,fl2440开发板 bootload ? ? ? ? ? ? ? ?: ? ? ? ? ? ? u-boot-2010.09 转载声明: http://blog.csdn.net/sonbai/article/details/8737129 借鉴: http://blog.csdn.net/zhaocj/article/details/6
平台 ? ? ? ? ? ? ? ? ? ? ? ?: ? ? ? ? ? ? tq2440开发板,fl2440开发板
bootload ? ? ? ? ? ? ? ?: ? ? ? ? ? ? u-boot-2010.09
转载声明:
http://blog.csdn.net/sonbai/article/details/8737129
借鉴:
http://blog.csdn.net/zhaocj/article/details/6709948
http://blog.chinaunix.net/uid-24063584-id-2642193.html
————————————————————————————————————————
一下是以smdk2410为模板,对代码稍加改造的基础上,添加nandflash硬件ECC的功能如下:


第一步:在include/configs/fl2440.h文件中添加三个宏定义,因为我的nandflash的页大小是512B的所以下面是的
#define CONFIG_S3C2440_NAND_HWECC
#define CONFIG_SYS_NAND_ECCSIZE 512
#define CONFIG_SYS_NAND_ECCBYTES 4

如果你的是2048就改成2048就行
/*-----------------------------------------------------------------------
?* NAND flash settings
?*/
#if defined(CONFIG_CMD_NAND)
#define CONFIG_NAND_S3C2410
#define CONFIG_SYS_MAX_NAND_DEVICE ?1 ? /* Max number of NAND devices ? ? ? */
#define CONFIG_SYS_NAND_BASE 0?
#define SECTORSIZE 512
#define SECTORSIZE_2K 2048
#define NAND_SECTOR_SIZE SECTORSIZE
#define NAND_SECTOR_SIZE_2K SECTORSIZE_2K
#define NAND_BLOCK_MASK 511
#define NAND_BLOCK_MASK_2K 2047
#define NAND_MAX_CHIPS 1
#define CONFIG_MTD_NAND_VERIFY_WRITE?
#define CONFIG_SYS_64BIT_VSPRINTF ? ? ? /* needed for nand_util.c */
#define CONFIG_S3C2440_NAND_HWECC
#define CONFIG_SYS_NAND_ECCSIZE 512
#define CONFIG_SYS_NAND_ECCBYTES 4

#endif ?/* CONFIG_CMD_NAND */


第二步:在drivers/mtd/nand/s3c2410_nand.c文件中对s3c2410_nand_enable_hwecc函数、s3c2410_nand_calculate_ecc函数和s3c2410_nand_correct_data函数进行修改。
1、该函数的任务就是初始化ECC(即复位ECC),并解锁main区ECC。
#ifde CONFIG_s3c2410_NAND_HWECC
? ? ? ?.........
? ? ? ?.........
? ? ? ?.........

#elif defined(CONFIG_S3C2440_NAND_HWECC)
void s3c2440_nand_enable_hwecc(struct mtd_info *mtd,int mode)
{
? ? printf("nand_enable_hweccn");
? ? struct s3c2410_nand *nand = s3c2410_get_base_nand();
? ? debugX(1,"s3c2410_nand_enable_hwecc(%p,%d)n",mtd,mode);
? ? writel(readl(&nand->NFCONT) | S3C2410_NFCONT_INITECC & ~S3C2410_NFCONT_MAINECCLOCK,&nand->NFCONT);
}
2、该函数首先锁定main区ECC,然后读取寄存器NFMECC0,该寄存器存放着由硬件生成的main区ECC,最后把4个1字节的ECC存放到ecc_code数组内。
static int s3c2410_nand_calculate_ecc(struct mtd_info *mtd,const u_char *dat,
? ? ? ? ? ? ? ? ? ? ? u_char *ecc_code)
{
? ? struct s3c2410_nand *nand = s3c2410_get_base_nand();


? ? writel(read(&nand->NFCONT)|S3C2410_NFCONT_MAINECLLOCK,&nand->NFCONT)


? ? ecc_code[0] = readb(&nand->NFECC);
? ? ecc_code[1] = readb(&nand->NFECC + 1);
? ? ecc_code[2] = readb(&nand->NFECC + 2);
? ? ecc_code[3] = readb(&nand->NFECC + 3);
? ? debugX(1,"s3c2410_nand_calculate_hwecc(%p,): 0x%02x 0x%02x 0x%02x 0x%02xn",
? ? ? ? ? ?mtd,ecc_code[0],ecc_code[1],ecc_code[2] ecc_code[3]);


? ? return 0;
}
3、该函数首先把read_ecc数组内的ECC存入寄存器NFMECCD0和寄存器NFMECCD1中,这样系统就会自动校验数据,并把状态放入寄存器NFESTAT0中,然后读取该寄存器的后4位,当为0时表示校验正确;当为1时表示发生了1位错误(该类错误可以校正),我们把它校正过来;当为2和3时表示发生其他类型的错误,这类错误是无法校正的。
static int s3c2440_nand_correct_data(struct mtd_info *mtd,u_char *dat,
? ? ? ? u_char *read_ecc,u_char *calc_ecc)
{
? ? struct s3c2410_nand *nand = s3c2410_get_base_nand();


? ? u32 estat0,err_byte_addr;
? ? int ret = -1;
? ? u8 repaired;


? ? writel((read_ecc[1] << 16) | read_ecc[0],&nand->NFMECCD0);
? ? writel((read_ecc[3] << 16) | read_ecc[2],&nand->NFMECCD1);


? ? /* Read ecc status */
? ? estat0= readl(&nand->NFSTAT);


? ? 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%ld. "
? ? ? ? ? ? ? ? ? ? "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


4、下面是将s3c2440_nand_enable_hwecc函数、s3c2440_nand_calculate_ecc函数和s3c2440_nand_correct_data函数,这三个函数放到
?一个结构体中:
#ifdef CONFIG_S3C2410_NAND_HWECC
? ? nand->ecc.hwctl = s3c2410_nand_enable_hwecc;
? ? nand->ecc.calculate = s3c2410_nand_calculate_ecc;
? ? nand->ecc.correct = s3c2410_nand_correct_data;
? ? nand->ecc.mode = NAND_ECC_HW;
? ? nand->ecc.size = CONFIG_SYS_NAND_ECCSIZE;
? ? nand->ecc.bytes = CONFIG_SYS_NAND_ECCBYTES;
#elif defined(CONFIG_S3C2440_NAND_HWECC)
? ? nand->ecc.hwctl = s3c2440_nand_enable_hwecc;
? ? nand->ecc.calculate = s3c2440_nand_calculate_ecc;
? ? nand->ecc.correct = s3c2440_nand_correct_data;
? ? nand->ecc.mode = NAND_ECC_HW;
? ? nand->ecc.size = CONFIG_SYS_NAND_ECCSIZE;
? ? nand->ecc.bytes = CONFIG_SYS_NAND_ECCBYTES;
#else

? ? nand->ecc.mode = NAND_ECC_SOFT;
#endif


这样我们重新make一下就行了。

内核的ECC配置我上个图片吧告诉你路径,你选上就行:



后话:

在内核中我添加了支持硬件ECC后发现了有错误,如图:


上面是进入如linux登陆界面之前打印的信息,下面是我查看nand挂载在mnt/目录下的错误:


我的mnt目录下有个xxx文件上面是ECC error

我擦了一下uboot后面的nandflash后,问题就好了,你可以看下:


这就没有打印ECC错误

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读