新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > 九 ARM9(2440)對nand flash的讀寫操作-程序實例分析

        九 ARM9(2440)對nand flash的讀寫操作-程序實例分析

        作者: 時間:2016-11-27 來源:網絡 收藏
        我相信上一篇文章已經對nand flash的操作有了一定的了解,下面一起看一下程序實例:


        #include "include.h"

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


        extern void Uart_Printf(char *fmt,...);
        extern void Uart_Init(int baud);
        //extern void Uart_Select(int ch);


        static void InitNandCfg(void)
        {
        rGPACON = (rGPACON &~(0x3f<<17)) | (0x3f<<17);//配置芯片引腳,因為GPACON復位后各位的值為1,所以此步也可沒有


        //TACLS為1個HCLK,TWRPH0為5個HCLK,TWRPH1為2個HCLK,數據寬度8位
        rNFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4)|(0<<0);
        //禁止緊鎖,軟件禁止上鎖,禁止非法訪問中斷,禁止RnB 中斷,RnB檢測上升沿,鎖定備份ECC,鎖定主數據區域ECC生成,初始化ECC 編碼器/譯碼器,
        //強制nFCE 為高(禁止片選),NAND Flash 控制器使能
        rNFCONT = (0<<13)|(0<<12)|(0<<10)|(0<<9)|(0<<8)|(1<<6)|(1<<5)|(1<<4)|(1<<1)|(1<<0);
        }


        static U32 WaitNFBusy(void)// R/B 未接好?
        {
        U8 stat;

        WrNFCmd(QUERYCMD);//0x70,讀狀態命令
        do
        {
        stat = RdNFDat();//讀取NFDATA
        }
        while (!(stat&0x40));//,第6位,判斷是否在忙
        WrNFCmd(READCMD0);//寫頁讀命令周期0
        return stat&1;//注意0為操作成功
        }


        static U32 ReadChipId(void)
        {
        U32 id,k;

        NFChipEn();//使能片選
        WrNFCmd(RdIDCMD);//讀ID命令
        WrNFAddr(0);//寫入地址0
        while(NFIsBusy());//等待不忙
        id= RdNFDat()<<8;//應該是只讀的廠商ID
        for(k=0;k<500;k++);//延時
        id |= RdNFDat();//低8位為設備ID
        NFChipDs();//關閉片選

        return id;//返回ID值
        }


        static U16 ReadStatus(void)
        {
        U16 stat;

        NFChipEn();//片選使能
        WrNFCmd(QUERYCMD);//讀狀態命令
        stat = RdNFDat();//讀取狀態值
        NFChipDs();//關閉片選

        return stat;
        }


        U32 EraseBlock(U32 addr)//輸入參數是具體的頁數,擦除的是頁數所在的塊
        {
        U8 stat;

        addr &= ~0x3f;//為了將地址賦給A18~A19

        NFChipEn();//片選使能
        WrNFCmd(ERASECMD0);//擦除命令周期0
        WrNFAddr(addr);//寫地址寫3個行周期A18~A19
        WrNFAddr(addr>>8);//A20~A27
        WrNFAddr(addr>>16);//A28
        WrNFCmd(ERASECMD1);//擦除命令周期1
        stat = WaitNFBusy();//等待不忙
        NFChipDs();//關閉片選

        return ~stat;//返回1則操作成功
        }


        void ReadPage(U32 addr, U8 *buf)//并沒有使用ECC校驗
        {
        U16 i;

        NFChipEn();//片選使能
        WrNFCmd(READCMD0);//讀命令周期0
        WrNFAddr(0);//寫列地址A0~A7
        WrNFAddr(0);//寫列地址A8~A11
        WrNFAddr(addr);//行地址A12~A19
        WrNFAddr(addr>>8);//行地址A20~A27
        WrNFAddr(addr>>16);//行地址A28
        WrNFCmd(READCMD1);//讀命令周期1
        InitEcc();//復位ECC
        WaitNFBusy();
        for(i=0; i<2048; i++)
        buf[i] = RdNFDat();//讀取數據存入buf中
        NFChipDs();//關閉片選
        }


        U32 WritePage(U32 addr, U8 *buf)
        {
        U32 i, mecc;
        U8 stat, tmp[7];


        NFChipEn();
        WrNFCmd(PROGCMD0);//頁寫命令周期1
        WrNFAddr(0);
        WrNFAddr(0);
        WrNFAddr(addr);
        WrNFAddr(addr>>8);
        WrNFAddr(addr>>16);
        InitEcc();//reset mecc and secc
        MEccUnlock();//ECC解鎖
        for(i=0; i<2048; i++)
        WrNFDat(buf[i]);//寫數據
        MEccLock();//鎖定ECC值

        mecc =RdNFMEcc();//讀取ECC碼
        //把ECC碼轉化為字節型
        tmp[0] = mecc&0xff;
        tmp[1] = (mecc>>8)&0xff;
        tmp[2] = (mecc>>16)&0xff;
        tmp[3] = (mecc>>24)&0xff;
        tmp[5] = 0xff;//mark good block



        WrNFDat(0xff);//2048,壞塊標志
        SEccUnlock();//解鎖spare區ECC
        WrNFDat(tmp[0]);//把main區的ECC寫入spare區的前4個字節
        WrNFDat(tmp[1]);
        WrNFDat(tmp[2]);
        WrNFDat(tmp[3]);
        SEccLock();//鎖定spare區ECC


        WrNFCmd(PROGCMD1);//頁寫命令周期1
        stat = WaitNFBusy();
        NFChipDs();

        return ~stat;


        }


        void nandMain(void)
        {
        U16 ID,i;
        U8buf[2048];
        U32 NFBlockNO=6;
        U32 NFPagesNO = 25; //第6塊第25頁
        U32 status;
        U32 BlockPages;

        BlockPages =(NFBlockNO<<6)+NFPagesNO; //轉化為總頁數

        Uart_Init(115200);
        Uart_Printf("nthe main is runningn");

        InitNandCfg();//初始化函數
        ID=ReadChipId();//ID 我的是現代的FLash,ID為:adda
        Uart_Printf("nnand flash`s ID is:%xn",ID);

        if(EraseBlock(BlockPages)&0x1==TRUE)//因為EraseBlock()的輸入參數是頁數,所以輸入的是BlockPages
        {
        Uart_Printf("nblock %d is erasedn",NFBlockNO);//打印擦除的是那一塊

        ReadPage(BlockPages,buf);//讀取擦除后的數據

        Uart_Printf("nn");
        for(i=0; i<2048; i++)
        Uart_Printf("%4x", buf[i]); //將讀出的數據進行打印

        Uart_Printf("nn");
        for(i=0; i<2048; i++)
        {
        buf[i] = i;
        Uart_Printf("%4x", buf[i]);
        }

        Uart_Printf("nWrite data[%d block, %d page].n", NFBlockNO,NFPagesNO);
        status = WritePage(BlockPages,buf);//寫入數據

        if(status&0x1==TRUE )//返回成功值
        Uart_Printf("nWrite OK.n");
        else
        Uart_Printf("nWrite Error.n");

        for(i=0; i<2048; i++)
        buf[i] = 1;//為驗證后邊數組中的數據是來自flash,實際上相當于是在數組中擦除了flash的數據,因為如果flash擦除時內容就全為1


        ReadPage(BlockPages,buf); //將讀取的數據存入buf中
        Uart_Printf("nRead data[%d block, %d page].n", NFBlockNO,NFPagesNO);//輸出塊號和頁號

        Uart_Printf("nn");
        for(i=0; i<2048; i++)
        Uart_Printf("%4x", buf[i]);//打印所讀取的數據
        }

        else
        Uart_Printf("nblock %4x erased is badn",NFBlockNO); //否則是壞塊,并打印信息

        while(1);
        }


        上一頁 1 2 下一頁

        評論


        技術專區

        關閉
        主站蜘蛛池模板: 怀安县| 同江市| 新巴尔虎左旗| 岳普湖县| 灵台县| 仙桃市| 连山| 新巴尔虎右旗| 隆子县| 秦安县| 红桥区| 深州市| 平顺县| 北辰区| 萨嘎县| 斗六市| 武定县| 巩义市| 上饶市| 靖远县| 平塘县| 明水县| 静宁县| 嘉兴市| 那曲县| 稷山县| 西畴县| 吕梁市| 龙游县| 巴林左旗| 万安县| 化州市| 遵义市| 岐山县| 满城县| 枣强县| 军事| 府谷县| 玉门市| 南岸区| 汤阴县|