新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > arm2440的nandflash相關函數

        arm2440的nandflash相關函數

        作者: 時間:2016-11-21 來源:網絡 收藏
        K9F2G08U0A nand flash 的容量為256M byte,其內部有2048塊,每塊有64頁,每頁有2K+64字節,其中每頁會分為main區(主域)和spare區(備用域),main區一般用來存入主要數據,spare一般用來存放ECC校驗碼。

        本文引用地址:http://www.104case.com/article/201611/319263.htm

        下面幾點是編程時需要注意的:

        1.NAND FLASH芯片手冊里說的column是指頁內地址,row是指頁地址,page也是指頁;

        2.刪除時是以塊為單位的,但是刪除塊時寫的是row地址,自動會刪除row所在的塊;

        3.讀寫方式有頁讀寫,或隨機讀寫,所謂的隨機讀寫就是可以在頁內的任一地方讀寫一個字節;

        4.ECC校驗碼分為main區的ECC和spare區的ECC,它們一般都會存放在64字節的spare區內,下面是翻譯2440手冊的關于ECC編程的內容:

        ECC 編程向導

        1) 在軟件模式, ECC 模塊會為全部讀 / 寫數據產生 ECC 檢驗碼。所以你需要在讀或者寫數據前給 InitECC(NFCONT[4]) 位寫 1 和給 MainECCLock(NFCONT[5]) 位寫 0(Unlock) 來復位 ECC 值。

        MainECCLock(NFCONT[5]) 和 SpareECCLock(NFCONT[6] 控制 ECC 校驗碼是否產生。

        2) 任何時候讀或者寫數據時, ECC 模塊在 NFMECC0/1 上產生 ECC 校驗碼。

        3) 在你完成讀或者寫一個頁后(不包含備用數據域),給 MainECCLock 位置 1(lock) 。 ECC 校驗碼被鎖上, ECC 狀態寄存器的值將不會被改變。

        4) 清 0(Unlock) SpareECCLock(NFCONT[6]) 位來產生備用域的 ECC 校驗碼。

        5) 任何時候讀或者寫數據時,備用域 ECC 模塊在寄存器 NFSECC 上產生 ECC 校驗碼。

        6) 在完成讀或者寫備用域后,給 SpareECCLock 位置 1(lock) 。 ECC 校驗碼被鎖上, ECC 狀態寄存器的值將不會被改變。

        7) 一旦完成你就可以使用這些值來記錄到備用域或者檢測位錯誤。

        接下來是代碼:

        NAND-FLASH.H內容:



        #ifndef __NAND_FLASH_H__ //為了防止重復包含
        #define __NAND_FLASH_H__

        #include "lhg_def.h" //U8,U32相關的宏,也即變量類型

        #define MAX_NAND_BLOCK 2048
        #define NAND_PAGE_SIZE 2048 //2048 blocks,1block has 64pages, each page has 2k+64 bytes
        typedef struct nand_id_info //這樣的結構體變量保存芯片的ID信息
        {
        U8 IDm; //marker code
        U8 IDd; //device code
        U8 ID3rd;
        U8 ID4th;
        U8 ID5th;
        } nand_id_info;


        typedef struct bad_block_info //登記壞塊用的,只記錄數量,沒有記錄壞塊地址
        {
        U8 area[MAX_NAND_BLOCK];//0表示非壞塊,1表示壞塊
        U32 sum;//壞塊的總數
        } bad_block_info;


        //

        //NAND 操作指令,??從哪里來的,我看你怎么用
        #define NAND_CMD_READ_1st 0x00
        #define NAND_CMD_READ_2st 0x30
        #define NAND_CMD_RANDOM_WRITE 0x85
        #define NAND_CMD_RANDOM_READ_1st 0x05
        #define NAND_CMD_RANDOM_READ_2st 0xe0
        #define NAND_CMD_READ_CB_1st 0x00
        #define NAND_CMD_READ_CB_2st 0x35
        #define NAND_CMD_READ_ID 0x90
        #define NAND_CMD_RES 0xff
        #define NAND_CMD_WRITE_PAGE_1st 0x80
        #define NAND_CMD_WRITE_PAGE_2st 0x10
        #define NAND_CMD_BLOCK_ERASE_1st 0x60
        #define NAND_CMD_BLOCK_ERASE_2st 0xd0
        #define NAND_CMD_READ_STATUS 0x70

        //NAND 中斷向量,?這是什么意思
        #define INT_NFCON (24)

        //NFCONF HCLK=100MHZ,nandflash configuration register
        #define S3C2440_NFCONF_TACLS_init (1<<12) //設置cle ale的持續時間,NFCONF[14:12]
        #define S3C2440_NFCONF_TWRPH0_init (4<<8) //TWRPH0持續時間設置,NFCONF[10:8]
        #define S3C2440_NFCONF_TWRPH1_init (0<<4) //TWRPH1持續時間設置,NFCONF[6:4]
        #define S3C2440_NFCONF_BusWidth_init (0) //bus_width for autobooting or general access,0 for1B
        #define S3C2440_NFCONF_init() ( rNFCONF = S3C2440_NFCONF_TACLS_init | /
        S3C2440_NFCONF_TWRPH0_init | /
        S3C2440_NFCONF_TWRPH1_init | /
        S3C2440_NFCONF_BusWidth_init ) //牛逼啊這句話

        //NFCONT,nandflash control register
        #define S3C2440_NFCONT_LockTight_init (0<<13)//disable lock-tight
        #define S3C2440_NFCONT_SoftLock_init (0<<12)//disable lock
        #define S3C2440_NFCONT_EnbIllegalAccINT_init (1<<10)//illegal access interrupt enable
        #define S3C2440_NFCONT_EnbRnBINT_init (0<<9)//RnB ready not busy
        #define S3C2440_NFCONT_RnB_TransMode_init (0<<8)//detect RnB type is rising edge
        #define S3C2440_NFCONT_SpareECCLock_init (1<<6)//1 is to lock sparearea ecc generation
        #define S3C2440_NFCONT_MainECCLock_init (1<<5)//1 is to lock main area ecc generation
        #define S3C2440_NFCONT_InitECC_init (1<<4)//1 is to initialize ecc decoder and encoder
        #define S3C2440_NFCONT_Reg_nCE_init (1<<1)//force nFCE to high,namely disable chip-select
        #define S3C2440_NFCONT_MODE_init (0)//disable nandflash controller
        #define S3C2440_NFCONT_init() ( rNFCONT = S3C2440_NFCONT_LockTight_init | /
        S3C2440_NFCONT_SoftLock_init | /
        S3C2440_NFCONT_EnbIllegalAccINT_init | /
        S3C2440_NFCONT_EnbRnBINT_init | /
        S3C2440_NFCONT_RnB_TransMode_init | /
        S3C2440_NFCONT_SpareECCLock_init | /
        S3C2440_NFCONT_MainECCLock_init | /
        S3C2440_NFCONT_InitECC_init | /
        S3C2440_NFCONT_Reg_nCE_init | /
        S3C2440_NFCONT_MODE_init )

        //NFSTAT
        #define S3C2440_NFSTAT_init() ( rNFSTAT &= 0x3 )//NFSTAT 8 bits, 0x3 means nCE output high,
        //nandflash is ready to operate
        //NFESTAT0
        #define S3C2440_NFESTAT0_init() ( rNFESTAT0 = 0 )//ecc status for io0-io7,k9f1208 only io0-i07

        //NFESTAT1
        #define S3C2440_NFESTAT1_init() ( rNFESTAT1 = 0 )//ecc status for io8-io15

        //
        #define select_nand() ( rNFCONT &= ~(1<<1) )
        #define dis_select_nand() ( rNFCONT |= 1<<1 )片選信號設置不說了啊
        #define controller_enable() ( rNFCONT |= 1 )
        #define controller_disable() ( rNFCONT &= ~1 )nandflash控制器使能與否也不說了

        //
        extern void nand_flash_init(void);//初始化,extern意思是提供給外部上層函數要調用的入口
        extern int nand_block_erase(U32 num);//num要刪除的塊號,一共2048個塊,這么大變量浪費了!
        extern int nand_page_write(U32 addr,U8 *buffer,U32 size);//addr要寫的起始頁地址,buffer要寫的緩存,size要寫的字節大小最大為4G,這里是針對u32說的
        extern int nand_page_read(U32 addr,U8 *buffer,U32 size);//addr開始頁地址,從每頁00地址開始讀
        extern int nand_random_read(U32 paddr,U32 offset,U8 *data); //隨機讀數據 paddr頁地址,offset頁內偏移地址,每次一個字節
        extern int nand_random_write(U32 paddr,U32 offset,U8 data);//隨機寫,paddr頁地址,offset頁內偏移地址
        extern void nand_test_bad_block(void);//測試壞塊函數,并標記在nand_bbi變量里和spare區最后一個地址(如果非0xff則為壞塊??原因是什么)


        #endif

        NAND-FLASH.c內容:



        #include "2440addr.h"
        #include "NAND-FLASH.h"
        #include "uart.h"
        #include "lhg_def.h"
        //#include "iic_lhg.h"

        #define NAND_DEBUG 1
        #define USE_ECC 1

        nand_id_info nand_id;//定義登記芯片ID的全局變量
        bad_block_info nand_bbi;//定義來登記壞用的全局變量

        void init_nand_bbi(void)//初始化變量
        {
        U32 i;
        nand_bbi.sum=0;
        for (i=0;i nand_bbi.area[i]=0;//這里放的是塊數,針對k9f1208是2048塊
        }

        void nand_mask_bad_block(U32 n)//標志壞塊,n是壞塊的塊號
        {
        #ifdef NAND_DEBUG//宏定義的一種,尼瑪也可以寫在這里
        Uart_Printf("NAND found and mask a bad block=%d .",n);
        #endif
        if (nand_bbi.area[n]!=1)//注意這里是對入口參數n操作的
        {
        nand_bbi.area[n]=1;
        nand_bbi.sum++;
        nand_random_write(n*64,2048+64-1,0);//每塊的第一個spare的最后一個字節,標志本塊是否為壞塊,非0xff為壞塊,頁地址計算中要看具體芯片一塊中有多少頁,例如k9f1208是32頁
        }
        }

        int detect_nand_busy(void)//檢測是否忙
        {
        U32 a;
        a=0;
        while(!(rNFSTAT&(1<<2)))//也即RnB狀態,0表示忙
        {
        a++;
        if (a==5000000)//等待超時
        {
        Uart_Printf("/r/n Error: Detect Nand Busy time out!!! /r/n");
        rNFSTAT |= (1<<2);//清忙標志,1表示不忙
        return -1;//錯誤返回-1,這個-1表示的是你他媽的nandflash一直忙,這里是有問題的
        }
        }

        rNFSTAT |= (1<<2);//清忙標志,沒有超時,我給你正常設為清閑,返回值也沒問題
        return 1;
        }

        void nand_reset(void)//復位
        {
        rNFCMD = NAND_CMD_RES;//?從哪里查到的NFCMD命令集合?和韋教材一樣,0xff為復位命令
        detect_nand_busy();//檢測忙,?為什么復位后檢測nandflash忙不忙呢?如果忙說明程序出錯在讀寫
        }

        void control_start(void){ //開啟
        select_nand();
        controller_enable();//也即最后兩位啟用nandflash和選中nandflash
        rNFSTAT |= (1<<2);//清忙標志
        nand_reset();
        }

        void control_end(void) //關閉
        {
        dis_select_nand();//取消片選,關閉nandflash控制器
        controller_disable();
        }

        void ecc_main_init(void)//初始化ECC值
        {
        rNFCONT |= 1<<4;//NFCONT[4]初始化ecc編解碼器


        void ecc_main_start(void)//開始main ECC
        {
        rNFCONT &= ~(1<<5);//unlock NFCONT[5],main area可以產生ecc
        }

        ecc_main_end(void)//結束main ECC
        {
        rNFCONT |= 1<<5;//unlock,main area不可以再產生ecc 了
        }

        void ecc_spare_start(void)//開始spare ECC
        {
        // rNFCONT |= 1<<4; //initEcc
        rNFCONT &= ~(1<<6); //unlock,NFCONT[6]控制spare area的ecc產生
        }

        void ecc_spare_end(void)//結束spare ECC,同樣道理關閉ecc的產生
        {
        rNFCONT |= 1<<6; //unlock
        }

        void __irq nandINT(void) //中斷函數
        {
        //此處寫處理代碼
        #ifdef NAND_DEBUG
        Uart_Printf("/r/n Nand Error... In interrupt now!!!");//只有錯誤才會進入中斷
        #endif
        rSRCPND |= 0x1< rINTPND |= 0x1<}


        void nand_read_id(void)//讀取芯片ID信息
        {
        control_start();//開控制選中nandflash和開啟nandflash控制器
        rNFCMD = NAND_CMD_READ_ID;//讀id命令為0x90,韋教材上有
        rNFADDR = 0;//nandflash address set register,不是發出4個地址序列嗎????
        //讀ID
        nand_id.IDm=(U8)rNFDATA8;//強制轉換為8位的,制造商
        nand_id.IDd=(U8)rNFDATA8; //設備代碼
        nand_id.ID3rd=(U8)rNFDATA8;//保留字節
        nand_id.ID4th=(U8)rNFDATA8;//多層操作代碼
        nand_id.ID5th=(U8)rNFDATA8;//??不知道是什么,反正一共5個信息數據

        #ifdef NAND_DEBUG
        Uart_Printf("/r/n Read NAND Flash ID:");
        Uart_Printf("/r/n NAND Mark code: 0x%x ",nand_id.IDm);//打印ID信息
        Uart_Printf("/r/n NAND Device code: 0x%x ",nand_id.IDd);
        Uart_Printf("/r/n NAND 3rdID code: 0x%x ",nand_id.ID3rd);
        Uart_Printf("/r/n NAND 4thID code: 0x%x ",nand_id.ID4th);
        Uart_Printf("/r/n NAND 5thID code: 0x%x ",nand_id.ID5th);
        #endif

        control_end();//關控制,取消片選和關閉nandflash控制器
        }

        int nand_block_erase(U32 num)//num要擦除的塊號
        {
        num=num*64;//表示要擦除的塊地址,這種nandflash每一個塊有64頁,其他的就不一定了哈哈
        control_start();//開控制
        nand_reset();//復位
        rNFCMD = NAND_CMD_BLOCK_ERASE_1st;//0x60命令
        rNFADDR = num&0xff;//需要發3個地址序列,這里有3個,非常好!!!
        rNFADDR = (num>>8)&0xff;
        rNFADDR = (num>>16)&0xff;
        rNFCMD = NAND_CMD_BLOCK_ERASE_2st;//0xd0命令
        detect_nand_busy();//看看nandflash忙不忙

        rNFCMD =NAND_CMD_READ_STATUS; //讀擦出的結果狀態,命令是0x70
        if (rNFDATA8&1)//如果最高位是1,下面報錯,就是說擦除這個塊沒有成功,這個得記住!
        {
        #ifdef NAND_DEBUG
        Uart_Printf("/r/n Error:nand erase error... block=0x%x",num/64);
        #endif
        control_end();//關控制
        nand_mask_bad_block(num/64);//登記為壞塊
        return -1;//刪除錯誤返回0
        }

        control_end();//關控制
        #ifdef NAND_DEBUG
        Uart_Printf("/r/n NAND block %d erase completed.",num/64);
        #endif
        return 1;
        }

        int nand_page_write(U32 addr,U8 *buffer,U32 size)

        //addr要寫的起始頁地址,buffer要寫的緩存,size要寫的字節大小最大為4G

        //這樣的話addr是有格式要求的比如末尾幾個零,結果這個函數里面沒有加上所謂“對齊判斷”失敗啊!!
        {
        U32 i,n,p,temp,ecc;
        U8 *bu;
        bu=buffer;
        temp=0;
        //我自己加上的對齊判斷,假如每頁是2kbyte的話,也可以再加上串口打印信息

        if(addr & 0xfff) {return -1;}

        //

        n=size/2048+(((size 48)==0)?0:1); //計算出要寫的頁數,小于一頁的部分當作一頁

        for (i=0;i{
        control_start();//開控制,選中nandflash和開啟nandflash控制器
        nand_reset();//復位

        #ifdef USE_ECC
        ecc_main_init();
        ecc_main_start();//可以產生main區ECC
        #endif

        // detect_nand_busy();

        //檢測忙,這里有相當于是復位nandflash后檢測nandflash,復位都不相信了,擦!

        //檢測了更好考慮問題更全面
        rNFCMD = NAND_CMD_WRITE_PAGE_1st;//0x80命令,
        rNFADDR = 0; //從每頁的0地址開始
        rNFADDR = 0; //從每頁的0地址開始
        rNFADDR = (addr)&0xff;//???不是發送四個地址序列嗎?
        rNFADDR = (addr>>8)&0xff;
        rNFADDR = (addr>>16)&0xff;

        for (p=0;p<2048;p++)//寫入一頁
        {
        temp=temp+1;
        if (temp>size)//這個temp并沒有在每一頁中重新置零!!!
        rNFDATA8 = 0xff;//多余的填寫0xff,NFDATA是32位數據
        else
        rNFDATA8 = *(bu+p);
        }
        delay_lhg(100,100);//?草具體的延時函數在哪里
        #ifdef USE_ECC//也即宏定義里面是否啟用了ecc產生記錄
        ecc_main_end();//鎖定main區ecc
        ecc=rNFMECC0;//main ECC值寫入備用區的頭0~4個地址內,NFMECCO是main aera的ecc產生的臨時地方

        ecc_spare_start();//開始spare區ECC
        rNFDATA8 = ecc&0xff;//這樣來看ecc32位數據,
        rNFDATA8 = (ecc>>8)&0xff;
        rNFDATA8 = (ecc>>16)&0xff;
        rNFDATA8 = (ecc>>24)&0xff;//自動完成寫入
        ecc_spare_end();
        delay_lhg(100,100);//
        ecc = rNFSECC;//spare ECC值寫入備用區的5~6兩個地址內,NFSECC是spare area生成ecc的臨時地方
        rNFDATA8 = ecc&0xff;
        rNFDATA8 = (ecc>>8)&0xff;//我靠 spare area的ecc只有16位

        #endif

        bu=bu+2048;//頁增量
        addr++;//起始頁地址為何是++?

        rNFCMD = NAND_CMD_WRITE_PAGE_2st;//這個命令是ox10,意思是啟動寫操作
        detect_nand_busy();//檢測忙
        rNFCMD =NAND_CMD_READ_STATUS; //讀nandflash忙不忙的狀態指令,這個命令是0x70
        if (rNFDATA8&1)//???為什么出來最后一位是1則是有問題啊!!!!
        {
        #ifdef NAND_DEBUG
        Uart_Printf("/r/n nand write page error: page addr=0x%d",addr-1);//寫入失敗
        #endif
        control_end();//關控制,取消選中nandflash然后關閉nandflash控制器
        nand_mask_bad_block((addr-1)/64);//登記為壞塊,我靠整個塊都是壞的!!!
        return -1;//寫入錯誤返回-1
        }
        control_end();//關控制
        }
        return 1;//成功返回1
        }

        int nand_page_read(U32 addr,U8 *buffer,U32 size)//addr開始頁地址,從每頁00地址開始讀
        {
        U32 i,n,p,temp,ecc;
        U8 *bu,no;
        bu=buffer;
        temp=0;

        n=size/2048+(((size 48)==0)?0:1); //計算出要讀的頁數,小于一頁的部分當作一頁

        for (i=0;i++;i {
        control_start();//開控制,選中nandflash并且打開nandflash控制器
        nand_reset();//復位,擦 下邊例行監測nandflash的busy與否
        detect_nand_busy();

        #ifdef USE_ECC
        rNFESTAT0 = 0;//復位錯誤標志位
        ecc_main_init();
        ecc_main_start();//可以產生main區ECC
        #endif

        rNFCMD = NAND_CMD_READ_1st;
        rNFADDR = 0;
        rNFADDR = 0;
        rNFADDR = addr&0xff;
        rNFADDR = (addr>>8)&0xff;
        rNFADDR = (addr>>16)&0xff;//尼瑪地址序列發送的這么混亂!!!
        rNFCMD = NAND_CMD_READ_2st;//這個命令應該是0x50,讀取的是c區的數據
        detect_nand_busy();
        for (p=0;p<2048;p++)
        {
        temp=temp+1;
        if (temp>size)
        no=rNFDATA8;//多余的讀出來扔掉,給了一個無用的臨時變量
        else
        *(bu+p) = rNFDATA8;
        }

        #ifdef USE_ECC
        rNFESTAT0=0;//這個表示io0-io7的ecc狀態
        ecc_main_end();//鎖定main區ECC
        delay_lhg(100,100);//
        ecc_spare_start();//解鎖spare區ecc
        ecc=rNFDATA8;//從flash讀出main區ECC
        no=rNFDATA8;
        ecc |= ((U32)no)<<8;
        no=rNFDATA8;
        ecc |= ((U32)no)<<16;
        no=rNFDATA8;
        ecc |= ((U32)no)<<24;

        //這個是什么意思啊?就是用中間變量no讓ecc存儲了32位的main area的ecc
        rNFMECCD0 = ((ecc&0xff00)<<8)|(ecc&0xff);//硬件檢驗main ECC,一次檢驗16位
        rNFMECCD1 = ((ecc&0xff000000)>>8)|((ecc&0xff0000)>>16);
        ecc_spare_end();//鎖定spare區ecc
        delay_lhg(100,100);//
        ecc=rNFDATA8;//從flash讀出spare區ECC的值
        no=rNFDATA8;
        ecc |= ((U32)no)<<8;

        rNFSECCD = ((ecc&0xff00)<<8)|(ecc&0xff);//硬件檢驗spare ECC
        delay_lhg(100,100);//延時一會

        ecc=rNFESTAT0&0xffffff;//ecc只是臨時用一下錯誤狀態,并非ecc內容

        if (ecc!=0)//有錯誤
        {
        //以后再優化
        #ifdef NAND_DEBUG
        Uart_Printf("/r/n Nand ecc check error... page addr=0x%x,NFESTAT0=0x%x ",addr,ecc);
        #endif
        nand_mask_bad_block((addr+i)/64);//登記為壞塊
        return -1;//
        }
        #endif

        bu=bu+2048;
        addr++;
        control_end();//關控制
        }

        return 1;
        }

        int nand_random_read(U32 paddr,U32 offset,U8 *data) //隨機讀數據 paddr頁地址,offset頁內偏移地址
        {
        control_start();//開控制
        nand_reset();//復位

        rNFCMD = NAND_CMD_READ_1st;
        rNFADDR = 0;
        rNFADDR = 0;
        rNFADDR = paddr&0xff;
        rNFADDR = (paddr>>8)&0xff;
        rNFADDR = (paddr>>16)&0xff;
        rNFCMD = NAND_CMD_READ_2st;

        detect_nand_busy();
        rNFCMD = NAND_CMD_RANDOM_READ_1st;
        rNFADDR = offset&0xff; //寫入頁內偏移地址
        rNFADDR = (offset>>8)&0xff;
        rNFCMD = NAND_CMD_RANDOM_READ_2st;

        *data = rNFDATA8;
        control_end();
        return 1;
        }

        int nand_random_write(U32 paddr,U32 offset,U8 data)//隨機寫,paddr頁地址,offset頁內偏移地址
        {
        control_start();//開控制
        nand_reset();//復位

        rNFCMD = NAND_CMD_WRITE_PAGE_1st;
        rNFADDR = 0;
        rNFADDR = 0;
        rNFADDR = paddr&0xff;
        rNFADDR = (paddr>>8)&0xff;
        rNFADDR = (paddr>>16)&0xff;

        rNFCMD = NAND_CMD_RANDOM_WRITE;
        rNFADDR = offset&0xff; //寫入頁內偏移地址
        rNFADDR = (offset>>8)&0xff;

        rNFDATA8 = data;
        rNFCMD = NAND_CMD_WRITE_PAGE_2st;
        detect_nand_busy();//檢測忙

        rNFCMD =NAND_CMD_READ_STATUS; //讀狀態
        if (rNFDATA8&1)
        {
        #ifdef NAND_DEBUG
        Uart_Printf("/r/n Error:nand random write error... paddr=0x%x,offset=0x%x ",paddr,offset);
        #endif
        return -1;//刪除錯誤返回0
        }

        control_end();
        return 1;//成功返回1
        }


        void nand_test_bad_block(void)//測試壞塊函數,并標記spare區最后一個地址,如果非0xff則為壞塊
        {

        U8 dest[64*2048];//一個塊的main區容量
        U8 src [64*2048];
        U32 i,k;

        #ifdef NAND_DEBUG
        Uart_Printf("/r/n test and mask bad block is begain. /r/n");
        #endif
        //
        //main區檢測
        for (i=0;i<64*2048;i++)
        {
        dest[i]=0xff;//初始化緩沖區
        src [i]=0;
        }
        //刪除所有塊
        for (i=0;i
        {
        nand_block_erase(i);
        }

        for (i=0;i
        {
        nand_page_write(i*64,src,64*2048);
        nand_page_read(i*64,dest,64*2048);//使用了ecc校驗讀出來即可登記壞塊信息
        }

        for (i=0;i<64*2048;i++)
        {
        dest[i]=0;//初始化緩沖區
        src [i]=0xff;
        }
        //刪除所有塊
        for (i=0;i
        {
        nand_block_erase(i);
        }

        for (i=0;i
        {
        nand_page_write(i*64,src,64*2048);
        nand_page_read(i*64,dest,64*2048);//使用了ecc校驗讀出來即可登記壞塊信息
        }

        //
        //spare區檢測
        for (i=0;i<64;i++)
        {
        dest[i]=0xff;//初始化緩沖區
        src [i]=0;
        }
        //刪除所有塊
        for (i=0;i
        {
        nand_block_erase(i);
        }
        for (i=0;i
        {
        if ( nand_bbi.area[i/64] ==1 )//如果是壞塊則跳過
        continue;

        for (k=0;k<64;k++)
        {
        nand_random_write(i,2048+k,src[k]);
        nand_random_read(i,2048+k,&dest[k]);
        if (dest[k]!=src[k])//不相等則登記為壞塊
        {
        nand_mask_bad_block(i/64);
        break;
        }
        }

        }

        for (i=0;i<64;i++)
        {
        dest[i]=0x0;//初始化緩沖區
        src [i]=0xff;
        }
        //刪除所有塊
        for (i=0;i
        {
        nand_block_erase(i);
        }
        for (i=0;i
        {
        if ( nand_bbi.area[i/64] ==1 )//如果是壞塊則跳過
        continue;

        for (k=0;k<64;k++)
        {
        nand_random_write(i,2048+k,src[k]);
        nand_random_read(i,2048+k,&dest[k]);
        if (dest[k]!=src[k])//不相等則登記為壞塊
        {
        nand_mask_bad_block(i/64);
        break;
        }
        }
        }

        #ifdef NAND_DEBUG
        Uart_Printf("/r/n test and mask bad block is over. /r/n");
        #endif
        }

        void nand_flash_init(void)//初始化
        {
        #ifdef NAND_DEBUG
        Uart_Printf("/r/nNAND FLASH init");//
        #endif

        //中斷入口地址
        pISR_NFCON = (U32)nandINT;

        //配置GPIO
        rGPGUP |= 0x7<<13; //GPG13~15關閉上位
        rGPGCON &= ~((U32)0x3f<<26);//GPG13~15為輸入

        //初始化各寄存器
        S3C2440_NFCONF_init();
        S3C2440_NFCONT_init();
        S3C2440_NFSTAT_init();
        S3C2440_NFESTAT0_init();
        S3C2440_NFESTAT1_init();

        //關于中斷
        rINTMSK &= ~(0x1< rINTMOD &= ~(0x1< rSRCPND |= 0x1< rINTPND |= 0x1<
        init_nand_bbi();//初始化全局變量
        nand_read_id();//讀ID

        nand_test_bad_block();//測試并登記壞塊
        }



        關鍵詞: arm2440nandflash函

        評論


        技術專區

        關閉
        主站蜘蛛池模板: 紫金县| 五指山市| 左权县| 九龙城区| 和林格尔县| 汝南县| 开鲁县| 塔城市| 宣城市| 韶山市| 吉林市| 湟中县| 容城县| 宁化县| 丹东市| 漳浦县| 乌兰察布市| 新平| 平泉县| 六枝特区| 东光县| 循化| 化隆| 鹤庆县| 临颍县| 乌拉特中旗| 兖州市| 同心县| 渑池县| 周至县| 中方县| 类乌齐县| 胶南市| 鄯善县| 方正县| 福建省| 公安县| 抚州市| 永州市| 崇阳县| 禹州市|