在上一篇关于“支持NandFlash读写”的文章中,我们很好地完成了u-boot对NandFlash的读写,但这个读写进行的是软件ECC,即用软件编程的方法实现ECC。我们知道S3C2440的NandFlash控制器是支持硬件ECC的,因此在这里我们就来讲解如何实现硬件ECC。
NandFlash的每一页分为main区和spare区,S3C2440的NandFlash控制器支持这两个区的硬件ECC,但为了兼容u-boot-2011.06,我们只实现main区的硬件ECC。
为了实现硬件ECC,首先需要在include/configs/zhaocj2440.h文件内定义宏CONFIG_S3C2440_NAND_HWECC,这样在drivers/mtd/nand/s3c2440_nand.c文件内就定义了硬件ECC所需要的三个函数:s3c2440_nand_enable_hwecc函数、s3c2440_nand_calculate_ecc函数和s3c2440_nand_correct_data函数,而且在board_nand_init函数内,又把这三个函数分别赋给了相对应的结构体的三个成员,这样在进行NandFlash读写时,就会调用这三个函数,从而实现了硬件ECC。s3c2440_nand_enable_hwecc函数负责使能硬件ECC,s3c2440_nand_calculate_ecc函数负责计算ECC(当然这种计算是由硬件来完成的),s3c2440_nand_correct_data函数负责进行ECC的校验(同样地,这种校验也是由硬件自动完成的)。
为了理解u-boot是如何进行硬件ECC的,我们先来简要地分析一下相关的函数。NandFlash是以页为最小单位进行读写操作的,支持硬件ECC的读操作最终是由nand_read_page_hwecc函数(在drivers/mtd/nand目录下)来完成的,支持硬件ECC的写操作最终是由nand_write_page_hwecc函数(在drivers/mtd/nand目录下)来完成的。nand_read_page_hwecc函数的流程为先读取main区数据,同时通过调用s3c2440_nand_calculate_ecc函数来得到硬件ECC;再读取spare区数据;然后提取出储存在spare区内的main区ECC;最后通过调用s3c2440_nand_correct_data函数来对刚刚读取的main区数据进行校验。nand_write_page_hwecc函数的流程比较简单,它先写入main区数据,同时通过调用s3c2440_nand_calculate_ecc函数来得到硬件ECC;然后就是把硬件ECC写入到spare区内。
无论是nand_write_page_hwecc函数,还是nand_write_page_hwecc函数,内部都有一个这样的for循环体:
for(i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
…… ……
}
其中三个主要变量的定义为:
eccsize= chip->ecc.size;
eccbytes= chip->ecc.bytes;
eccsteps= chip->ecc.steps;
下面我们就来介绍一下这个循环的作用:不同的CPU的NandFlash控制器一次所能完成的硬件ECC的字节数是不一样的,例如有些CPU一次只能完成512字节的硬件ECC,但如果开发板上的NandFlash每页有2048个字节,那该怎么办呢?这时就要用到一个循环体,