新聞中心

        EEPW首頁 > 嵌入式系統(tǒng) > 設計應用 > TQ2440之nand flash讀寫

        TQ2440之nand flash讀寫

        作者: 時間:2016-11-21 來源:網(wǎng)絡 收藏
        自己寫的一個nand flash讀寫
        #include"2440addr.h"
        #include"def.h"
        #include"Nand.h"
        S8 ECCBuf[6];
        U32 PCLK;
        extern void Port_Init(void);//以下四個函數(shù)在2440lib.c中
        extern void Uart_Select(int ch);
        extern void Uart_Init(int pclk,int baud);
        extern void Uart_Printf(char *fmt,...);
        extern void rNF_Reset();//以下三個函數(shù)在nand.c中
        extern void rNF_Init(void);
        extern char rNF_ReadID();
        void delay(U32 time)
        {
        U32 i,j;
        for(i=0;i
        for(j=0;j<1000;j++)
        ;
        }
        U8 rNF_RamdomRead(U32 page_number, U32 add)
        {
        NF_nFCE_L(); //打開Nand Flash片選
        NF_CLEAR_RB(); //清RnB信號
        NF_CMD(CMD_READ1); //頁讀命令周期1
        //寫入5個地址周期
        NF_ADDR(0x00); //列地址A0~A7
        NF_ADDR(0x00); //列地址A8~A11
        NF_ADDR((page_number) & 0xff); //行地址A12~A19
        NF_ADDR((page_number >> 8) & 0xff); //行地址A20~A27
        NF_ADDR((page_number >> 16) & 0xff); //行地址A28
        NF_CMD(CMD_READ2); //頁讀命令周期2
        NF_DETECT_RB(); //等待RnB信號變高,即不忙
        NF_CMD(CMD_RANDOMREAD1); //隨意讀命令周期1
        //頁內(nèi)地址
        NF_ADDR((char)(add&0xff)); //列地址A0~A7
        NF_ADDR((char)((add>>8)&0x0f)); //列地址A8~A11
        NF_CMD(CMD_RANDOMREAD2); //隨意讀命令周期2
        return NF_RDDATA8(); //讀取數(shù)據(jù)
        }
        U8 rNF_RamdomWrite(U32 page_number, U32 add, U8 dat)
        {
        U8 stat;
        NF_nFCE_L(); //打開Nand Flash片選
        NF_CLEAR_RB(); //清RnB信號
        NF_CMD(CMD_WRITE1); //頁寫命令周期1
        //寫入5個地址周期
        NF_ADDR(0x00); //列地址A0~A7
        NF_ADDR(0x00); //列地址A8~A11
        NF_ADDR((page_number) & 0xff); //行地址A12~A19
        NF_ADDR((page_number >> 8) & 0xff); //行地址A20~A27
        NF_ADDR((page_number >> 16) & 0xff); //行地址A28
        NF_CMD(CMD_RANDOMWRITE); //隨意寫命令
        //頁內(nèi)地址
        NF_ADDR((char)(add&0xff)); //列地址A0~A7
        NF_ADDR((char)((add>>8)&0x0f)); //列地址A8~A11
        NF_WRDATA8(dat); //寫入數(shù)據(jù)
        NF_CMD(CMD_WRITE2); //頁寫命令周期2
        delay(1000); //延時一段時間
        NF_CMD(CMD_STATUS); //讀狀態(tài)命令
        //判斷狀態(tài)值的第6位是否為1,即是否在忙,該語句的作用與NF_DETECT_RB();相同
        do{
        stat = NF_RDDATA8();
        }while(!(stat&0x40));
        NF_nFCE_H(); //關閉Nand Flash片選
        //判斷狀態(tài)值的第0位是否為0,為0則寫操作正確,否則錯誤
        if (stat & 0x1)
        return 0x44; //失敗
        else
        return 0x66; //成功
        }
        U8 rNF_IsBadBlock(U32 block)
        {
        return rNF_RamdomRead(block*64, 2054);
        }
        U8 rNF_MarkBadBlock(U32 block)
        {
        U8 result;
        result = rNF_RamdomWrite(block*64, 2054, 0x33);
        if(result == 0x44)
        return 0x21; //寫壞塊標注失敗
        else
        return 0x60; //寫壞塊標注成功
        }
        U8 rNF_EraseBlock(U32 block_number)
        {
        char stat, temp;
        temp = rNF_IsBadBlock(block_number); //判斷該塊是否為壞塊
        if(temp == 0x33)
        return 0x42; //是壞塊,返回
        NF_nFCE_L(); //打開片選
        NF_CLEAR_RB(); //清RnB信號
        NF_CMD(CMD_ERASE1); //擦除命令周期1
        //寫入3個地址周期,從A18開始寫起
        NF_ADDR((block_number << 6) & 0xff); //行地址A18~A19
        NF_ADDR((block_number >> 2) & 0xff); //行地址A20~A27
        NF_ADDR((block_number >> 10) & 0xff); //行地址A28
        NF_CMD(CMD_ERASE2); //擦除命令周期2
        delay(100); //延時一段時間
        NF_CMD(CMD_STATUS); //讀狀態(tài)命令
        //判斷狀態(tài)值的第6位是否為1,即是否在忙,該語句的作用與NF_DETECT_RB();相同
        NF_DETECT_RB();
        NF_nFCE_H(); //關閉Nand Flash片選
        //判斷狀態(tài)值的第0位是否為0,為0則擦除操作正確,否則錯誤
        if (stat & 0x1)
        {
        temp = rNF_MarkBadBlock(block_number); //標注該塊為壞塊
        if (temp == 0x21)
        return 0x43; //標注壞塊失敗
        else
        return 0x44; //擦除操作失敗
        }
        else
        return 0x66; //擦除操作成功
        }
        U8 rNF_WritePage(U32 page_number,S8 mydata)
        {
        U32 i, mecc0, secc;
        U8 stat, temp;
        temp = rNF_IsBadBlock(page_number>>6); //判斷該塊是否為壞塊
        if(temp == 0x33)
        return 0x42; //是壞塊,返回
        NF_RSTECC(); //復位ECC
        NF_MECC_UnLock(); //解鎖main區(qū)的ECC
        NF_nFCE_L(); //打開nandflash片選
        NF_CLEAR_RB(); //清RnB信號
        NF_CMD(CMD_WRITE1); //頁寫命令周期1
        //寫入5個地址周期
        NF_ADDR(0x00); //列地址A0~A7
        NF_ADDR(0x00); //列地址A8~A11
        NF_ADDR((page_number) & 0xff); //行地址A12~A19
        NF_ADDR((page_number >> 8) & 0xff); //行地址A20~A27
        NF_ADDR((page_number >> 16) & 0xff); //行地址A28
        for (i = 0; i < 2048; i++)//寫入一頁數(shù)據(jù)
        {
        NF_WRDATA8(mydata);
        i += 6;
        Uart_Printf("n test %s",mydata);
        }
        NF_MECC_Lock(); //鎖定main區(qū)的ECC值
        mecc0=rNFMECC0; //讀取main區(qū)的ECC校驗碼
        //把ECC校驗碼由字型轉換為字節(jié)型,并保存到全局變量數(shù)組ECCBuf中
        ECCBuf[0]=(U8)(mecc0&0xff);
        ECCBuf[1]=(U8)((mecc0>>8) & 0xff);
        ECCBuf[2]=(U8)((mecc0>>16) & 0xff);
        ECCBuf[3]=(U8)((mecc0>>24) & 0xff);
        NF_SECC_UnLock(); //解鎖spare區(qū)的ECC
        //把main區(qū)的ECC值寫入到spare區(qū)的前4個字節(jié)地址內(nèi),即第2048~2051地址
        for(i=0;i<4;i++)
        {
        NF_WRDATA8(ECCBuf[i]);
        }
        NF_SECC_Lock(); //鎖定spare區(qū)的ECC值
        secc=rNFSECC; //讀取spare區(qū)的ECC校驗碼
        //把ECC校驗碼保存到全局變量數(shù)組ECCBuf中
        ECCBuf[4]=(U8)(secc&0xff);
        ECCBuf[5]=(U8)((secc>>8) & 0xff);
        //把spare區(qū)的ECC值繼續(xù)寫入到spare區(qū)的第2052~2053地址內(nèi)
        for(i=4;i<6;i++)
        {
        NF_WRDATA8(ECCBuf[i]);
        }
        NF_CMD(CMD_WRITE2); //頁寫命令周期2
        delay(1000); //延時一段時間,以等待寫操作完成
        NF_CMD(CMD_STATUS); //讀狀態(tài)命令
        //判斷狀態(tài)值的第6位是否為1,即是否在忙,該語句的作用與NF_DETECT_RB();相同
        do{
        stat = NF_RDDATA8();
        }while(!(stat&0x40));
        NF_nFCE_H(); //關閉Nand Flash片選
        //判斷狀態(tài)值的第0位是否為0,為0則寫操作正確,否則錯誤
        if (stat & 0x1)
        {
        temp = rNF_MarkBadBlock(page_number>>6);//標注該頁所在的塊為壞塊
        if (temp == 0x21)
        return 0x43; //標注壞塊失敗
        else
        return 0x44; //寫操作失敗
        }
        else
        return 0x66; //寫操作成功
        }
        U8 rNF_ReadPage( U32 page_number)
        {
        U32 i, mecc0, secc;
        S8 buf[2048];
        NF_RSTECC(); //復位ECC
        NF_MECC_UnLock(); //解鎖main區(qū)ECC
        NF_nFCE_L();//使能芯片
        NF_CLEAR_RB();//清除RnB
        NF_CMD(CMD_READ1); //頁讀命令周期1,0x00
        //寫入5個地址周期
        NF_ADDR(0x00); //列地址A0-A7
        NF_ADDR(0x00); //列地址A8-A11
        NF_ADDR((page_number) & 0xff); //行地址A12-A19
        NF_ADDR((page_number >> 8) & 0xff); //行地址A20-A27
        NF_ADDR((page_number >> 16) & 0xff); //行地址A28
        NF_CMD(CMD_READ2); //頁讀命令周期2,0x30
        NF_DETECT_RB(); ////等待RnB信號變高,即不忙
        for (i = 0; i < 2048; i++)
        {
        buf[i] = NF_RDDATA8();//讀取一頁數(shù)據(jù)內(nèi)容
        Uart_Printf("%s",buf[i]);
        }
        NF_MECC_Lock(); //鎖定main區(qū)ECC值
        NF_SECC_UnLock(); //解鎖spare區(qū)ECC
        mecc0=NF_RDDATA(); //讀spare區(qū)的前4個地址內(nèi)容,即第2048~2051地址,這4個字節(jié)為main區(qū)的ECC
        //把讀取到的main區(qū)的ECC校驗碼放入NFMECCD0/1的相應位置內(nèi)
        rNFMECCD0=((mecc0&0xff00)<<8)|(mecc0&0xff);
        rNFMECCD1=((mecc0&0xff000000)>>8)|((mecc0&0xff0000)>>16);
        NF_SECC_Lock(); //鎖定spare區(qū)的ECC值
        secc=NF_RDDATA(); //繼續(xù)讀spare區(qū)的4個地址內(nèi)容,即第2052~2055地址,其中前2個字節(jié)為spare區(qū)的ECC值
        //把讀取到的spare區(qū)的ECC校驗碼放入NFSECCD的相應位置內(nèi)
        rNFSECCD=((secc&0xff00)<<8)|(secc&0xff);
        NF_nFCE_H(); //關閉nandflash片選
        //判斷所讀取到的數(shù)據(jù)是否正確
        if((rNFESTAT0 & 0xf) == 0x0)
        return 0x66; //正確
        else
        return 0x44; //錯誤
        }
        void Main(void)
        {
        S8 myid;
        S8 *str = "BERLIN";
        Port_Init();
        Uart_Select(0);
        Uart_Init(50000000,115200);//初始化串口
        Uart_Printf("nnWelcome to test nand flash!n");
        delay(100);
        Uart_Printf("Now begin to init the nand flashn");
        rNF_Init();//初始化nand flash
        Uart_Printf("Completen");
        delay(100);
        Uart_Printf("Now begin to resetn");
        rNF_Reset();//復位
        Uart_Printf("Completen");
        delay(100);
        Uart_Printf("Now begin to read IDn");
        myid=rNF_ReadID();//讀ID
        Uart_Printf("The ID is %s n",myid);
        delay(100);
        Uart_Printf("Now begin to erase the nand flashn");
        rNF_EraseBlock(0);
        Uart_Printf("Completen");//擦除塊
        delay(100);
        Uart_Printf("Now begin to write data to nand flashn");
        rNF_WritePage(0,*str);
        Uart_Printf("Write Complete!n");//寫頁
        delay(100);
        Uart_Printf("Now begin to read nand flashn");
        rNF_ReadPage(0);
        Uart_Printf("Complete");//讀頁打印在串口
        }



        關鍵詞: TQ2440nandflash讀

        評論


        技術專區(qū)

        關閉
        主站蜘蛛池模板: 抚松县| 遂川县| 凤山县| 特克斯县| 望都县| 资中县| 随州市| 平陆县| 德庆县| 冕宁县| 饶阳县| 双鸭山市| 安福县| 义乌市| 扎鲁特旗| 秀山| 太保市| 镇巴县| 浦县| 东阳市| 通道| 伊川县| 高尔夫| 康马县| 兰考县| 米泉市| 霍山县| 富民县| 江山市| 南溪县| 兴和县| 新邵县| 黄龙县| 民和| 临汾市| 海宁市| 小金县| 尖扎县| 德令哈市| 房产| 乡城县|