⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 2410.c

📁 NAND FLASH通用的读写
💻 C
字号:
//2410寄存器
#define NF_CMD(cmd)     {rNFCMD=cmd;}
#define NF_ADDR(addr)   {rNFADDR=addr;}
#define NF_nFCE_L()     {rNFCONF&=~(1<<11);}
#define NF_nFCE_H()     {rNFCONF|=(1<<11);}
#define NF_RSTECC()     {rNFCONF|=(1<<12);}
#define NF_RDDATA()     (rNFDATA)
#define NF_WRDATA(data) {rNFDATA=data;}
#define NF_WAITRB()     {while(!(rNFSTAT&(1<<0)));}


//NAND 设备命令
#define NAND_CMD_READ0     0x00
#define NAND_CMD_READ1     0x01
#define NAND_CMD_PAGEPROG  0x10
#define NAND_CMD_READOOB   0x50
#define NAND_CMD_ERASE1    0x60
#define NAND_CMD_STATUS    0x70
#define NAND_CMD_SEQIN     0x80
#define NAND_CMD_READID    0x90
#define NAND_CMD_READID1   0x91
#define NAND_CMD_ERASE2    0xd0
#define NAND_CMD_RESET     0xff


//NAND 设备初始化代码如下

void NF_Init(void)
{
       int i;
       rNFCONF=(1<<15)|                                /*使能2410的NAND接口*/
               (1<<14)|                                /*Page大小: 512Bytes*/
               (1<<13)|                                /*地址周期为4*/
               (1<<12)|                                /*初始化ECC*/
               (1<<11)|                                /*nFCE=HIGH*/
               (TACLS<<8)|(TWRPH0<<4)|(TWRPH1<<0);     //设置时间参数
/*Reset NAND*/
       NF_nFCE_L();
       NF_CMD(NAND_CMD_RESET);
       NF_WAITRB();
       NF_nFCE_H();
}

//NAND 设备测试代码如下

int NF_Test(void)
{
       unsigned char buffer[1000];
       NF_Init();
       printk("testing Smart Media Card...\n\r");
       printk("ID1=%x(using command 0x90)\n\r",NF_CheckId(NAND_CMD_READID));
       printk("ID2=%x(using command 0x91)\n\r",NF_CheckId(NAND_CMD_READID1));
       NF_ReadPage(1,0,buffer);                        //读取第1个block的第0个page的内容
       for(i=0;i<528;i++)
       {
            printk("%2x",buffer[i]);
            if(i%16==15)
            printk("\n\r");
       }
       printk("\n\r"); 
}

//NF_ReadPage函数的代码如下

int NF_ReadPage(unsigned block,unsigned page,unsigned char *buffer)
{
       register unsigned char * bufPt=buffer;
       unsigned int blockPage,i;
       U8 ecc0,ecc1,ecc2,ecc3,ecc4,ecc5;
       U8 se[16];
       blockPage=(block<<5)+page;                      //一个block包含32page
       NF_RSTECC();                                    /*初始化ECC*/
       
       NF_nFCE_L();
       NF_CMD(NAND_CMD_READ0);                         //发出Read命令
       
//发送4个地址周期

       NF_ADDR(0);                                     /*页内起始地址设为0*/
       NF_ADDR(blockPage & 0xff);                           
       NF_ADDR((blockPage>>8) & 0xff);
       NF_ADDR((blockPage>>16) & 0xff);
       NF_WAITRB();
       for(i=0;i<256;i++)
            bufPt[i]=NF_RDDATA();                      //读出页内前256字节
//记录前256字节的ECC校验和
       ecc0=rNFECC0;
       ecc1=rNFECC1;
       ecc2=rNFECC2;
       NF_RSTECC();
       for(i=256;i<512;i++)
            bufPt[i]=NF_RDDATA();                      //读出页内后256字节
//记录后256字节的ECC校验和
       ecc3=rNFECC0;
       ecc4=rNFECC1;
       ecc5=rNFECC2;
       for(i=0;i<16;i++)
            bufPt[i+512]=se[i]=NF_RDDATA();            //读出页内冗余的16字节
       NF_nFCE_H();
//比较ECC校验码和事先存在页内的校验和是否一致
//se[5]应该为0xff,否则表示该block为bad block
       if(ecc0==se[13] && ecc1==se[14] && ecc2==se[15] && se[5]=0xff)
            printk("[first 256 bytes ECC OK:%x,%x,%x]\n\r",se[13],se[14],se[15]);
       else{
            printk("[ECC ERROR(RD):read:%x,%x,%x,reg:%x,%x,%x]\n\r",se[13],se[14],se[15],ecc0,ecc1,ecc2);
            return 0;
       }
       
       if(ecc3==se[8] && ecc4==se[9] && ecc5==se[10] && se[5]==0xff)
       printk("[last 256 bytes ECC OK:%x,%x,%x]\n\r",se[8],se[9],se[10]);
       else{
            printk("[ECC ERROR(RD):read:%x,%x,%x,reg:%x,%x,%x]\n\r",se[8],se[9].se[10],ecc3,ecc4,ecc5);
            return 0;
           }
           return 1;
}

//NAND 设备擦除和写函数的代码如下
int NF_EraseBlock(unsigned block)
{
       unsigned blockPage;
       unsigned char data;
       
       blockPage=(block<<5);
       NF_nFCE_L();
       NF_CMD(NAND_CMD_ERASE1);                        //发出擦除命令
       NF_ADDR(blockPage&0xff);
       NF_ADDR((blockPage>>8)&0xff);
       NF_ADDR((blockPage>>16) & 0xff);
       NF_CMD(NAND_CMD_ERASE2);                        //确认并开始擦除
       NF_WAITRB();                                    //等待状态查询命令
       
       NF_CMD(NAND_CMD_STATUS);                        //发出状态查询命令
       data=NF_RDDATA();
       NF_nFCE_H();
       return !(data & 1);                             //data=0:擦除成功 data=1:擦除失败 
}
int NF_WritePage(unsigned block,unsigned page,unsigned char *buffer)
{
       register unsigned char *bufPt=buffer;
       unsigned int blockPage,i;
       unsigned char se[16],data;
       blockPage=(block<<5)+page;
       NF_CMD(NAND_CMD_SEQIN);                         //发出送数据的命令
       NF_ADDR(0);                                     //从页内地址为0的地方开始写数据
       NF_ADDR(blockPage & 0xff);
       NF_ADDR((blockPage>>8) & 0xff);
       NF_ADDR((blockPage>>16) & 0xff); 
       for(i=0;i<256;i++)NF_WRDATA(*bufPt++);
       se[13]=rNFECC0;se[14]=rNFECC1;se[15]=rNFECC2|3;
       NF_RSTECC();                                    //复位ECC
       for(i=0;i<256;i++)NF_WRDATA(*buftPt++);
       se[8]=rNFECC0;se[9]=rNFECC1;se[10]=rNFECC2|3;
       for(i=0;i<16;i++)NF_WRDATA(se[i]);              //写入16个的冗余字节spare array
       NF_CMD(NAND_CMD_PAGEPROG);                      //开始编程
       NF_WAITRB();                                    //等待R/B#信号有效
       NF_CMD(NAND_CMD_STATUS);                        //发出状态查询命令
       data=NF_RDDATA();
       NF_nFCE_H();
       return !(data & 1);                             //data=0;编程成功 data=1:编程失败
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -