zoukankan      html  css  js  c++  java
  • 外设:K9F2G08 nandflash 底层读写、控制驱动程序,可随机读写

    /******************************************************************************
    
      Copyright (C), 2001-2011, DCN Co., Ltd.
    
     ******************************************************************************
      File Name     : nand.c
      Version       : Initial Draft
      Author        : oucaijun
      Created       : 2014/5/9
      Last Modified :
      Description   : K9F2G08 nandflash 底层读写、控制驱动程序
                        当前的程序可以对nand进行随机读写,随机读写的时候数据正确,但没有正确实现ecc算法。
                        当前程序可以实现对nand普通的页读写,并实现ecc算法。
                        因随机读写ecc不正确,因此不能和普通的带ecc的读写方式配套使用。
                        页内地址: 2048 = 2 ^ 11 , 使用A0-A11表示页内地址 见K9F2G08手册
      Function List :
                  CheckBadBlk
                  CheckNandflash
                  EraseBlock
                  getBlockNum
                  getPageNum
                  InitNandCfg
                  MarkBadBlk
                  MY_ReadPage
                  MY_WritePage
                  nandNew
                  NF_Reset
                  RandomRead
                  RandomWrite
                  ReadBlock
                  ReadChipId
                  ReadPage
                  ReadPageAll
                  ReadStatus
                  WaitNFBusy
                  WriteBlock
                  WritePage
      History       :
      1.Date        : 2014/5/9
        Author      : ocj
        Modification: Created file
    
    ******************************************************************************/
    /*----------------------------------------------*
     * routines' implementations                    *
     *----------------------------------------------*/
    #include "Common.h"
    #include <string.h>
    #include "nand.h"
    #include "nfarea.h"
    /*----------------------------------------------*
     * macros                                       *
     *----------------------------------------------*/
    
    /*----------------------------------------------*
     * external routine prototypes                  *
     *----------------------------------------------*/
    
    /*----------------------------------------------*
     * internal routine prototypes                  *
     *----------------------------------------------*/
    
    /*----------------------------------------------*
     * project-wide global variables                *
     *----------------------------------------------*/
    
    /*----------------------------------------------*
     * module-wide global variables                 *
     *----------------------------------------------*/
    
    /*----------------------------------------------*
     *external variables                            *
     *----------------------------------------------*/
    
    /*----------------------------------------------*
     * constants                                    *
     *----------------------------------------------*/
    #define NF_WAIT_RB() {while(!(rNFSTAT &(1<<0)));} //this bit is ReadOnly
    #define NF_CLEAR_RB() {rNFSTAT |=(1<<2);} //清除RnB信号 //this bit is RW
    #define NF_DETECT_RB() {while(!(rNFSTAT &(1<<2))) ;}
    
    
    /*
    R/B: When low, it indicates that a program, erase or
    random read operation is in process
    and returns to high state upon completion.
    */
    void NF_Reset(void)
    {
        NFChipEn();
        NF_CLEAR_RB();
        WrNFCmd(RESET_CMD);
        NF_DETECT_RB();
        NFChipDs();
    }
    /*------------------------------------------------------------/
    函数名称:    InitNandCfg
    功能描述:    配置flash
    传    参:    无
    返 回 值:    无
    -------------------------------------------------------------*/
    static void InitNandCfg(void)
    {
        rNFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4)|(0<<0);//初始化时序参数
        rNFCONT = (0<<13)|(0<<12)|(0<<10)|(0<<9)|(0<<8)|(1<<6)|(1<<5)|(1<<4)|(1<<1)|(1<<0);
        //非锁定,屏蔽nandflash中断,初始化ECC及锁定main区和spare区ECC,使能nandflash片选及控制器
        NF_Reset();
    }
    
    /*------------------------------------------------------------/
    函数名称:    WaitNFBusy
    功能描述:  Read Status Register , I/O = RdNFDat();
                RdNFDat() until(I/O 6 = 1   or  R/B = 1  ) ;
                if(I/O 0 = 0 ) program/erase/ success ;
    传    参:    无
    返 回 值:    I/O bit0 , 表示了命令的执行状况。若为0,表示success
    -------------------------------------------------------------*/
    static U32 WaitNFBusy(void)    //
    {
        U8 stat;
    
        WrNFCmd(QUERYCMD);
        do
        {
            stat = RdNFDat();
        }
        while (!(stat&0x40));
        WrNFCmd(READCMD0);
        return stat&1;    //注意0为操作成功
    }
    
    /*------------------------------------------------------------/
    函数名称:    ReadChipId
    功能描述:    读flash ID
    传    参:    无
    返 回 值:    static U32 id
    -------------------------------------------------------------*/
    U32 ReadChipId(void)
    {
        U8 MID , PID , cyc3,cyc4,cyc5 ;
        NFChipEn();
        WrNFCmd(RdIDCMD);
        WrNFAddr(0);
        while(NFIsBusy());
    
        MID = RdNFDat();
        PID = RdNFDat();
        cyc3 = RdNFDat();
        cyc4 = RdNFDat();
        cyc5 = RdNFDat();
        NFChipDs();
    
        return (MID<<24)|(PID<<16)|(cyc3<<8)|(cyc4);
    }
    
    /*------------------------------------------------------------/
    函数名称:    ReadStatus
    功能描述:    读FLASH状态
    传    参:    无
    返 回 值:    static U16 stat
    -------------------------------------------------------------*/
    static U16 ReadStatus(void)
    {
        U16 stat;
    
        NFChipEn();
        WrNFCmd(QUERYCMD);
        stat = RdNFDat();
        NFChipDs();
    
        return stat;
    
    }
    
    //CheckNandflash(int info) ret =0,没有flash或者不支持的flash。
    int CheckNandflash(int info)
    {
        U32 i;
        int have_nandflash ;
        InitNandCfg();
        i = ReadChipId();
        if(info)
            debugk("NAND ID is 0x%04x 
    ", i);
    
        if((i==0xecda) || (i==0xadda)) {
            have_nandflash = 1;
        }
        else if(i==0xecf1) {
            have_nandflash = 1;
        }
        else {
            have_nandflash = 0;
            debugk("unsupported nandflash id 
    ");
        }
    
        if(info)
            debugk("Nand flash status = %x
    ", ReadStatus());
        return have_nandflash ;
    }
    
    
    /*------------------------------------------------------------/
    函数名称:    EraseBlock
    功能描述:    擦除 FLASH
    传    参:    U32 addr
    返 回 值:    U32 ~stat
    -------------------------------------------------------------*/
    U32 EraseBlock(U32 addr)// if(  stat & 0x1 == 1),erase success
    {
        U8 stat;
        addr &= ~0x3f; // page_addr 的低六位清零
        //addr(page_addr) : row_addr A12-A28   not need cloumn addr A0-A11
        //64*2048(row_addr : one nand 64*2048 pages) * 2048(cloumn_addr : one page 2048 bytes)
        NFChipEn();
        WrNFCmd(ERASECMD0);
        WrNFAddr(addr); //行地址A18~A19
        WrNFAddr(addr>>8);//行地址A20~A27
        WrNFAddr(addr>>16);//行地址A28
        WrNFCmd(ERASECMD1);
        stat = WaitNFBusy();
        NFChipDs();
    
        return ~stat; //最后一位等于0,success
    }
    
    /*------------------------------------------------------------/
    函数名称:    ReadPage
    功能描述:
    传    参:    U32 addr, U8 *buf
    返 回 值:    无
    -------------------------------------------------------------*/
    void ReadPage(U32 addr, U8 *buf)
    {
        U16 i;
    
        NFChipEn();
        WrNFCmd(READCMD0);
        WrNFAddr(0);
        WrNFAddr(0);
        WrNFAddr(addr);
        WrNFAddr(addr>>8);
        WrNFAddr(addr>>16);
        WrNFCmd(READCMD1);
        InitEcc();
        WaitNFBusy();
        for(i=0; i<2048; i++)
            buf[i] = RdNFDat();
        NFChipDs();
    }
    void ReadPageAll(U32 addr, U8 *buf)
    {
        U16 i;
    
        NFChipEn();
        WrNFCmd(READCMD0);
        WrNFAddr(0);
        WrNFAddr(0);
        WrNFAddr(addr);
        WrNFAddr(addr>>8);
        WrNFAddr(addr>>16);
        WrNFCmd(READCMD1);
        InitEcc();
        WaitNFBusy();
        for(i=0; i<2048+64; i++)
            buf[i] = RdNFDat();
        NFChipDs();
    }
    
    /*------------------------------------------------------------/
    函数名称:    WritePage
    功能描述:
    传    参:    U32 addr, U8 *buf
    返 回 值:    ret若为0xff,表示success
    -------------------------------------------------------------*/
    U32 WritePage(U32 addr, U8 *buf)
    {
        U32 i, mecc;
        U8 stat, tmp[7];
    
        NFChipEn();
        WrNFCmd(PROGCMD0);
        WrNFAddr(0);
        WrNFAddr(0);
        WrNFAddr(addr);
        WrNFAddr(addr>>8);
        WrNFAddr(addr>>16);
        InitEcc(); //reset mecc and secc
        MEccUnlock();
        for(i=0; i<2048; i++)
            WrNFDat(buf[i]);
        MEccLock();
    //因为K9F2G08U0A是8位IO口,因此S3C2440共产生4个字节的main区ECC码和2个字节的spare区ECC码
    //在这里我们规定,在每一页的spare区的第0个地址到第3个地址存储main区ECC,第4个地址和第5个地址存储spare区ECC。
    //在下次读取这一页数据的时候,同样我们也计算ECC校验码,然后与spare区中的ECC校验码比较,如果一致则说明读取的数据正确,如果不一致则不正确
    
    //读取rNFMECC0 -- Main的ECC校验码
    //for 8 bit nand flash, only use NFMECC0
        mecc = RdNFMEcc() ;
        tmp[0] = mecc&0xff;
        tmp[1] = (mecc>>8)&0xff;
        tmp[2] = (mecc>>16)&0xff;
        tmp[3] = (mecc>>24)&0xff;
    
        WrNFDat(0xff);//2048,坏块标志
        SEccUnlock();
        WrNFDat(tmp[0]);//ECC校验码
        WrNFDat(tmp[1]);
        WrNFDat(tmp[2]);
        WrNFDat(tmp[3]);
        SEccLock();
    
        WrNFCmd(PROGCMD1);
        stat = WaitNFBusy();//stat若为0,表示success
        NFChipDs();
    
        return ~stat;////ret若为0xff,表示success
    }
    
    // RandomWrite 随机写
    // 不直接改写spare区域
    // addr_in_page 0-2047
    U32 RandomWrite(int page_num, int addr_in_page ,U8 *buf,int len)
    {
        U8 stat ;
        U32 mecc , secc ;
        if( len+addr_in_page>2048 ){
            debugs("RandomWrite :do not allow to write spare_section directly!
    ");
        }
        if(buf==NULL){
            debugs("RandomWrite :wrong data pointer!
    ");
        }
        //cs
        NFChipEn();
        WrNFCmd(PROGCMD0);
        WrNFAddr(0);
        WrNFAddr(0);
        WrNFAddr(page_num&0xff);
        WrNFAddr((page_num>>8) &0xff);
        WrNFAddr((page_num>>16) &0xff);
    
        WrNFCmd(RANDOM_PROGRAMCMD); //85h
        WrNFAddr( (addr_in_page&0xff) );         //页内A0~A7
        WrNFAddr( ((addr_in_page>>8)&0x0f) );    //页内地址A8~A11
        while(len--){
            WrNFDat(*buf++);
        }
        WrNFCmd(PROGCMD1);//10
        stat = WaitNFBusy();
        //ncs
        NFChipDs();
        return ~stat;
    }
    
    //MY_WritePage 写块 ,并将ecc写入spare区域 。
    //完全同 WritePage
    U32 MY_WritePage(U32 addr, U8 *buf)
    {
        U32 mecc ,secc ;
        int i ,ret ;
        U8 stat;
        InitEcc();          //复位ECC
        MEccUnlock();     //解锁main区的ECC
        NFChipEn();          //打开nandflash片选
       // NF_CLEAR_RB();        //清RnB信号 没有用这个判断busy而是直接读的query_nand ,没必要。
    
        WrNFCmd(PROGCMD0);//页写命令周期1
        //写入5个地址周期
        WrNFAddr(0x00);           //列地址A0~A7
        WrNFAddr(0x00);           //列地址A8~A11  列地址就是页内的地址,不能超过2048,要注意传入的值的有效性。
        WrNFAddr((addr) & 0xff);         //行地址A12~A19
        WrNFAddr((addr >> 8) & 0xff);    //行地址A20~A27
        WrNFAddr((addr >> 16) & 0xff);  //行地址A28
        for (i = 0; i < 2048; i++)//写入一页数据
        {
            WrNFDat( buf[i] );
        }
        MEccLock();    //锁定main区的ECC值
    
    //读取main区的ECC校验码
    //for 8 bit nand flash, only use NFMECC0
        mecc = rNFMECC0 ;
        SEccUnlock();//解锁spare区的ECC
        WrNFDat(0xff);//先写入0XFF非坏块标志到2048
        WrNFDat32(mecc);//把main区的ECC值写入到spare区的前2-5字节地址内,即第2049~2052地址
        SEccLock();//锁定spare区的ECC值
    
        secc = rNFSECC ;//读取spare区的ECC校验码
        WrNFDat8(secc & 0xff);//写入secc校验码到spare区第6-7个字节
        WrNFDat8((secc>>8) & 0xff);
    
        WrNFCmd(PROGCMD1);
    
        WrNFCmd(QUERYCMD);
        do {
            stat = RdNFDat();
        } while(!(stat & 0x40));
    
        NFChipDs();
        if (stat & 0x1) {//fail
            debugs("fail to write nand!
    ");
        }
    
        return ~(stat & 0x1); //if ok,ret = 0xff
    }
    
    /*------------------------------------------------------------/
    函数名称:    ReadBlock
    功能描述:
    传    参:    U32 addr, U8 *buf
    返 回 值:    无
    -------------------------------------------------------------*/
    void ReadBlock(U32 addr, U8 buf[N_PAGES_NAND_BLOCK][N_BYTES_NAND_PAGE]) //addr :pages ,64的整数倍
    {
        int i;
        int start ;
        start = addr ;
        for(i=0; i<64; i++) {
            ReadPage( start+i,buf[i] );
        }
    }
    
    /*------------------------------------------------------------/
    函数名称:    WriteBlock
    功能描述:
    传    参:    U32 addr, U8 *buf
    返 回 值:    无
    -------------------------------------------------------------*/
    void WriteBlock(U32 addr, U8 buf[64][2048])
    {
        int i  ;
        int start = addr ;
    
        for(i=0; i<64; i++) {
            WritePage( start+i ,buf[i] );
        }
    
    }
    
    
    int getPageNum(u32 addr ,u32 PageNum[1])
    {
        PageNum[0] = addr/2048 ;
        return  PageNum[0] ;
    }
    
    int getBlockNum(u32 addr ,u32 BlockNum[1])
    {
        BlockNum[0] = addr/2048/64 ;
        return  BlockNum[0] ;
    }
    
    
    ////////////////////////////////////////////
    ////////////////////////////////////////////
    //CheckBadBlk
    //addr : pageaddr{A12--A28}
    //ret == 0 : badblk
    //在该块的第一页 第2048bytes查询是否为non-FFh,是则为badblk 。
    int CheckBadBlk(U32 addr)
    {
        U8 dat;
        addr &= ~0x3f;
        /*
        Samsung makes sure that either the 1st or 2nd page of
        everyinitial invalid block has non-FFh data
        at the column address of 2048.
        */
        NFChipEn();
        WrNFCmd(READCMD0);
        WrNFAddr(0);        //
        WrNFAddr(8);        // A11=1   该地址值为2048
        WrNFAddr(addr & 0xff);
        WrNFAddr((addr>>8) & 0xff);
        WrNFAddr((addr>>16) & 0xff);//in a page [offset == 2048] : read the 2048th bytes of page(addr) .
        WrNFCmd(READCMD1);
        WaitNFBusy();
        dat = RdNFDat();
    
        NFChipDs();
        if(dat!=0xff) {
            debugs("Blk % 4d is NG! page_addr=%d
    " ,addr>>6 , addr );
        }
        return (dat != 0xff);
    }
    
    //MarkBadBlk 标记坏块
    //addr : pageaddr{A12--A28}
    //在该块的第一页 第2048bytes 写入non-FFh。
    void MarkBadBlk(U32 addr)
    {
        addr &= ~0x3f;
        NFChipEn();
        WrNFCmd(PROGCMD0);
    
        //mark offset 2048
        WrNFAddr(0);        //
        WrNFAddr(8);        // A11=1   2048
        WrNFAddr(addr & 0xff);
        WrNFAddr((addr>>8) & 0xff);
        WrNFAddr((addr>>16) & 0xff);//in a page [offset == 2048] : read the 2048th bytes of page(addr) .
    
        WrNFDat(0);            //mark with  0 ==  “badblk”
        WrNFCmd(PROGCMD1);
        WaitNFBusy();        //needn't check return status
    
        NFChipDs();
    }
    
    //MY_ReadPage
    //ret ==0 ok
    //ret ==1 ecc error
    int MY_ReadPage(U32 addr, U8 *buf)
    {
        int i ;
    
        U32 mecc ,secc ;
        char ch;
        InitEcc();
        MEccUnlock();
    
        NFChipEn();
        NF_CLEAR_RB();
    
        WrNFCmd(READCMD0);
        WrNFAddr(0);
        WrNFAddr(0);
        WrNFAddr(addr&0xff);
        WrNFAddr((addr>>8)&0xff);
        WrNFAddr((addr>>16)&0xff);
        WrNFCmd(READCMD1);
    
        NF_DETECT_RB();
    
        for(i=0; i<2048; i++) {
            buf[i] = RdNFDat();
        }
        MEccLock();
    
        SEccUnlock();
        ch = RdNFDat();//跳过0XFF坏块标志 2048
        //PREFERENCE :DATASHEET--ECC MODULE FEATURES
        //读spare区的前4个地址内容,即第 2049 - 2052地址,这4个字节为main区的ECC
        //把读取到的main区的ECC校验码放入NFMECCD0/1的相应位置内
        mecc = RdNFDat32();
        rNFMECCD0 = ((mecc&0xff00)<<8) | (mecc&0xff) ;
        rNFMECCD1 = ((mecc&0xff000000)>>8) | ((mecc&0xff0000)>>16) ;
        SEccLock();//这之前计算的secc仅仅包括bit2048 2049 2050 2051 2052 的计算结果????? 应该是吧
    
        secc = RdNFDat32();
        //继续读spare区的4个地址内容,即第 2052--2055地址
        //把读取到的spare区的ECC校验码放入NFSECCD的相应位置内
        rNFSECCD = ((secc&0xff00)<<8) | (secc&0xff);
        NFChipDs();
    
        if((rNFESTAT0&0xf)==0x0) { //查看ECC状态寄存器
            return 0 ;
        } else {
            debugs("rNFESTAT0 = %0xh 
    " ,rNFESTAT0 );
            return 1 ;
        }
    }
    
    //
    int RandomRead(U32 page_number, U32 addr_in_page , U8 *bufr ,int len )
    {
        if( len+addr_in_page>2048+64 ){
            debugs("RandomRead error : read out of spare_section!
    ");
            return 1;
        }
        if(bufr==NULL){
            debugs("RandomRead error : wrong data pointer!
    ");
            return 1 ;
        }
        NFChipEn();                  //打开Nand Flash片选
        NF_CLEAR_RB();               //清RnB信号
        WrNFCmd(READCMD0);           //页读命令周期1
        //写入5个地址周期
        WrNFAddr(0x00);       //列地址A0~A7
        WrNFAddr(0x00);       //列地址A8~A11
        WrNFAddr((page_number) & 0xff);                //行地址A12~A19
        WrNFAddr((page_number >> 8) & 0xff);           //行地址A20~A27
        WrNFAddr((page_number >> 16) & 0xff);          //行地址A28
        WrNFCmd(READCMD1);          //页读命令周期2
        NF_DETECT_RB();             //等待RnB信号变高,即不忙
        WrNFCmd(RANDOM_READCMD0);   //随意读命令周期1
        //页内地址
        WrNFAddr( addr_in_page&0xff );         //列地址A0~A7
        WrNFAddr( (addr_in_page>>8)&0x0f );    //列地址A8~A11
        WrNFCmd(RANDOM_READCMD1);           //随意读命令周期2
        while(len--){
            *bufr++ = RdNFDat();                   //读取数据
        }
        NFChipDs();
        return 0 ;
    }
    
    
    //http://www.cnblogs.com/idle_man/archive/2010/12/23/1915303.html
    #define getnum(i) {
                mygetstring(string) ;
                i = myatoi(string ) ;
            }
    void nandNew(void)
    {
        int ret , n ,i , j ,k;
        U32 nID;
        U8 MID , PID , cyc3,cyc4,cyc5 ;
        char dat ;
        char ch ;
        U8 uch;
        char string[1000] = {0};
        char bufw[2048] = {1 , 1, 1};
        char bufr[2048+64] = {0};
        memset(bufw , 0xaa , 2048);
    
        while(1) {
    
            debugs("
    ------------------------------------------------
    ");
            debugs("nand menu
    ");
            debugs("input num to select:
    ");
            debugs("now will operate block %d,its addr is %x
    ",AppParaBpageS,AppParaBaseNF);//page num = 34816
            debugs("0 sysHardwareReset
    ");
            debugs("1 nand EraseBlock
    ");
            debugs("2 nand MY_WritePage caculate ecc
    ");
            debugs("3 nand ReadPageAll
    ");
            debugs("4 nand my_cop
    ");
            debugs("5 nand CheckBadBlk
    ");
            debugs("6 nand MY_ReadPage check ecc
    ");
            debugs("------------------------------------------------
    ");
            ch = mygetc();
            switch ( ch - '0' )
            {
            case 0 :
                sysHardwareReset();
                break;
            case 1 :
                ret = EraseBlock(AppParaBpageS );
                if(ret&0x1 ==1 ) {
                    debugs("EraseBlock ok!
    ");
                } else {
                    debugs("EraseBlock fail!
    ");
                }
                break;
            case 2 :
                ret = MY_WritePage(AppParaBpageS,  bufw);
                if(ret&0x1 ==1 ) {
                    debugs("WritePage ok!
    ");
                } else {
                    debugs("WritePage fail!
    ");
                }
                break;
            case 3:
                if(1){
                    int j ;
                    int i = 34816 ;
                    char buf[2047] = {4,5,6,7,8,9,10,11,12};
                    buf[2044] = 11;
                    buf[2045] = 12;
                    buf[2046] = 13;
                    memset(bufr, 0 , sizeof(bufr));
                    ReadPageAll(i , bufr);
                    ret = memcmp(buf , bufr+1 , 2047);
                    debugs("ret of memcmp %x
    " , ret);
                    arryprintfs("ReadPage+0" ,bufr ,2048 );
                    arryprintfs("ReadPage+2048" ,bufr+2048 ,64 );
                }
                break;
            case 4:
                if(1){
                    int time = 0;
                    int nPage = 34816 , nAddr = 1;
                    char rbufw[10] = {1, 2, 3 ,4 ,5 ,6 ,7 ,8 ,9 ,10};
                    ret = RandomWrite(nPage , nAddr, rbufw , 10);
                    if(ret&0x1 ==1 ) {
                        debugs("WritePage ok!
    ");
                    } else {
                        debugs("WritePage fail!
    ");
                    }
    
                    for(time = 0 ; time<10 + 7; time++){
                        ret = 0x11;
                        ret = RandomRead(nPage ,nAddr , bufr , 2048+63);
                        debugs("RamdomRead(page %d, in_page_addr%d ) ,ret = 0x%x
    " ,nPage , nAddr, ret);
                        arryprintfs("RamdomRead bufr" ,bufr ,2048+63 ) ;
                        nAddr++;
                    }
    
                }
                /*
                ----------------prints---------------------------
                WritePage ok!
                RamdomRead(page 34816, in_page_addr1 ) ,uch = 0x1
                RamdomRead(page 34816, in_page_addr2 ) ,uch = 0x2
                RamdomRead(page 34816, in_page_addr3 ) ,uch = 0x3
                RamdomRead(page 34816, in_page_addr4 ) ,uch = 0x4
                RamdomRead(page 34816, in_page_addr5 ) ,uch = 0x5
                RamdomRead(page 34816, in_page_addr6 ) ,uch = 0x6
                RamdomRead(page 34816, in_page_addr7 ) ,uch = 0x7
                RamdomRead(page 34816, in_page_addr8 ) ,uch = 0x8
                RamdomRead(page 34816, in_page_addr9 ) ,uch = 0x9
                RamdomRead(page 34816, in_page_addr10 ) ,uch = 0xa
                ----------------prints---------------------------
                */
                break;
            case 5: //CheckBadBlk from blk0~blk2047
                for(ret=0 ; ret<2047; ret++) {
                    CheckBadBlk(ret<<6); //ret<<6 : page_addr
                }
                break;
            case 6: //
                if(1){
                    memset(bufr, 0 , sizeof(bufr));
                    ret = MY_ReadPage(34816, bufr);
                    debugs("MY_ReadPage ret==%d
    " ,  ret);
                    arryprintfs("ReadPage+0" ,bufr ,2048 );
                }
                break;
    
            case 7: //
                if(1){
                  T_ecc() ;
                }
                break;
            }
        }
    }
    #ifndef _NAND_H_
    #define _NAND_H_
    
    #include "common.h"
    
    #define N_BYTES_NAND_PAGE 2048
    #define N_PAGES_NAND_BLOCK 64
    #define N_BYTES_NAND_BLOCK (N_PAGES_NAND_BLOCK*N_BYTES_NAND_PAGE)
    
    #define    EnNandFlash()    (rNFCONT |= 1)
    #define    DsNandFlash()    (rNFCONT &= ~1)
    #define    NFChipEn()        (rNFCONT &= ~(1<<1))
    #define    NFChipDs()        (rNFCONT |= (1<<1))
    #define    InitEcc()        (rNFCONT |= (1<<4))
    #define    MEccUnlock()    (rNFCONT &= ~(1<<5))
    #define    MEccLock()        (rNFCONT |= (1<<5))
    #define    SEccUnlock()    (rNFCONT &= ~(1<<6))
    #define    SEccLock()        (rNFCONT |= (1<<6))
    
    #define    WrNFDat8(dat)    (rNFDATA8 = (dat))
    #define    WrNFDat32(dat)    (rNFDATA = (dat))
    #define    RdNFDat8()        (rNFDATA8)    //byte access
    #define    RdNFDat32()        (rNFDATA)    //word access
    
    #define    WrNFCmd(cmd)    (rNFCMD = (cmd))
    #define    WrNFAddr(addr)    (rNFADDR = (addr))
    #define    WrNFDat(dat)    WrNFDat8(dat)
    #define    RdNFDat()        RdNFDat8()    //for 8 bit nand flash, use byte access
    
    #define    RdNFMEcc()        (rNFMECC0)    //for 8 bit nand flash, only use NFMECC0
    #define    RdNFSEcc()        (rNFSECC)    //for 8 bit nand flash, only use low 16 bits
    
    #define    RdNFStat()        (rNFSTAT)
    #define    NFIsBusy()        (!(rNFSTAT&1))
    #define    NFIsReady()        (rNFSTAT&1)
    
    #define    READCMD0    0
    #define    READCMD1    0x30
    #define    ERASECMD0    0x60
    #define    ERASECMD1    0xd0
    #define    PROGCMD0    0x80
    #define    PROGCMD1    0x10
    #define    QUERYCMD    0x70
    #define    RdIDCMD        0x90
    
    #define RESET_CMD   0xff
    #define RANDOM_READCMD0 0x05
    #define RANDOM_READCMD1 0xe0
    #define RANDOM_PROGRAMCMD 0x85
    
    #define TACLS        1//7    // 1-clk(0ns)
    #define TWRPH0        4//7    // 3-clk(25ns)
    #define TWRPH1        1//7    // 1-clk(10ns)  //TACLS+TWRPH0+TWRPH1>=50ns
    
    //func
    extern void ReadBlock(U32 addr, U8 buf[64][2048]) ; //pgaddr
    extern U32  EraseBlock(U32 addr) ;                  //pgaddr
    extern void WriteBlock(U32 addr, U8 buf[64][2048]); //pgaddr
    extern void ReadPage(U32 addr, U8 *buf);            //pgaddr
    extern U32  WritePage(U32 addr, U8 *buf);           //pgaddr
    extern int getBlockNum(u32 addr ,u32 BlockNum[1]);  //0x_addr
    extern int getPageNum(u32 addr ,u32 PageNum[1]);    //0x_addr
    extern U32 ReadChipId(void);
    extern int CheckNandflash(int info);
    #endif
  • 相关阅读:
    我深知黑暗,但心向光明(记毕业后第一次在北京求职)
    CF 1200E HASH模板
    CF580D
    CF1433F
    CF1451 E1交互题
    11.23-11.29 训练计划
    11.22 CF总结 #682
    sql问题:备份集中的数据库备份与现有的 '办公系统' 数据库不同
    内容导出成word
    让超链接无法跳转的方法
  • 原文地址:https://www.cnblogs.com/mylinux/p/3994764.html
Copyright © 2011-2022 走看看