首页 > 代码库 > K9F2G08 nandflash 底层读写、控制驱动程序,可随机读写

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 orrandom read operation is in processand 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 \n", i);    if((i==0xecda) || (i==0xadda)) {        have_nandflash = 1;    }    else if(i==0xecf1) {        have_nandflash = 1;    }    else {        have_nandflash = 0;        debugk("unsupported nandflash id \n");    }    if(info)        debugk("Nand flash status = %x\n", 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-2047U32 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!\n");    }    if(buf==NULL){        debugs("RandomWrite :wrong data pointer!\n");    }    //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区域 。//完全同 WritePageU32 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    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!\n");    }    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\n" ,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 errorint 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 \n" ,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!\n");        return 1;    }    if(bufr==NULL){        debugs("RandomRead error : wrong data pointer!\n");        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("\n------------------------------------------------\n");        debugs("nand menu\n");        debugs("input num to select:\n");        debugs("now will operate block %d,its addr is %x\n",AppParaBpageS,AppParaBaseNF);//page num = 34816        debugs("0 sysHardwareReset\n");        debugs("1 nand EraseBlock\n");        debugs("2 nand MY_WritePage caculate ecc\n");        debugs("3 nand ReadPageAll\n");        debugs("4 nand my_cop\n");        debugs("5 nand CheckBadBlk\n");        debugs("6 nand MY_ReadPage check ecc\n");        debugs("------------------------------------------------\n");        ch = mygetc();        switch ( ch - 0 )        {        case 0 :            sysHardwareReset();            break;        case 1 :            ret = EraseBlock(AppParaBpageS );            if(ret&0x1 ==1 ) {                debugs("EraseBlock ok!\n");            } else {                debugs("EraseBlock fail!\n");            }            break;        case 2 :            ret = MY_WritePage(AppParaBpageS,  bufw);            if(ret&0x1 ==1 ) {                debugs("WritePage ok!\n");            } else {                debugs("WritePage fail!\n");            }            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\n" , 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!\n");                } else {                    debugs("WritePage fail!\n");                }                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\n" ,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\n" ,  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 = http://www.mamicode.com/(dat))"color: #0000ff;">#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//funcextern void ReadBlock(U32 addr, U8 buf[64][2048]) ; //pgaddrextern U32  EraseBlock(U32 addr) ;                  //pgaddrextern void WriteBlock(U32 addr, U8 buf[64][2048]); //pgaddrextern void ReadPage(U32 addr, U8 *buf);            //pgaddrextern U32  WritePage(U32 addr, U8 *buf);           //pgaddrextern int getBlockNum(u32 addr ,u32 BlockNum[1]);  //0x_addrextern int getPageNum(u32 addr ,u32 PageNum[1]);    //0x_addrextern U32 ReadChipId(void);extern int CheckNandflash(int info);#endif

 

K9F2G08 nandflash 底层读写、控制驱动程序,可随机读写