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

平臺                        :             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_hwecc\n");
    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%02x\n",
           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...OK\n",
                    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錯誤


發佈了233 篇原創文章 · 獲贊 440 · 訪問量 105萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章