在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错误 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |