九  ARM9(2440)对nand flash…

我相信上一篇文章已经对nand flash的操作有了一定的了解,下面一起看一下程序实例:


#include "include.h"


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;
 U8  buf[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);
}

本工程中用到的其他文件:

include.h:

#define rNFCONF (*(volatile unsigned *)0x4E000000)

#define rNFCONT (*(volatile unsigned *)0x4E000004)

#define rNFCMD  (*(volatile unsigned *)0x4E000008)

#define rNFADDR  (*(volatile unsigned *)0x4E00000C)

#define rNFCMMD  (*(volatile unsigned *)0x4E000008)

#define rNFDATA  (*(volatile unsigned *)0x4E000010)

#define rNFDATA8  (*(volatile unsigned char *)0x4E000010)

#define rNFMECC0  (*(volatile unsigned *)0x4E00002c)

#define rNFSTAT  (*(volatile unsigned *)0x4E000020)

#define rNFESTAT0  (*(volatile unsigned *)0x4E000024)

#define rGPACON   (*(volatile unsigned *)0x56000000)


#define rUTRSTAT0   (*(volatile unsigned *)0x50000010) //UART 0 Tx/Rx status
#define rULCON0     (*(volatile unsigned *)0x50000000) //UART 0 Line control
#define rUCON0      (*(volatile unsigned *)0x50000004) //UART 0 Control
#define rUFCON0     (*(volatile unsigned *)0x50000008) //UART 0 FIFO control
#define rUBRDIV0    (*(volatile unsigned *)0x50000028) //UART 0 Baud rate divisor
#define WrUTXH0(ch) (*(volatile unsigned char *)0x50000020)=(unsigned char)(ch)

#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 TACLS  1//7 // 1-clk(0ns)
#define TWRPH0  4//7 // 3-clk(25ns)
#define TWRPH1  1//7 // 1-clk(10ns)  //TACLS+TWRPH0+TWRPH1>=50ns

#define U32 unsigned int
#define U16 unsigned short
#define S32 int
#define S16 short int
#define U8  unsigned char
#define S8  char

#define TRUE 1
#define FALSE 0

#define OK 1
#define FAIL 0

///////////////////////////////////////////////////////////////////////////////////////////////
uart.c

#include "include.h"
#include <stdarg.h>


void Uart_Init(int baud)
{
    int i;
    rUFCON0 = 0x0;   //UART channel 0 FIFO control register, FIFO disable
 
 
//UART0
    rULCON0 = 0x3;   //Line control register : Normal,No parity,1 stop,8 bits
     //    [10]       [9]     [8]        [7]        [6]      [5]         [4]           [3:2]        [1:0]
     // Clock Sel,  Tx Int,  Rx Int, Rx Time Out, Rx err, Loop-back, Send break,  Transmit Mode, Receive Mode
     //                                                      01          01
     //   PCLK       Level    Pulse    Disable    Generate  Normal      Normal        Interrupt or Polling
    rUCON0  = 0x805;   // Control register
    rUBRDIV0=( (int)(50000000/16./baud+0.5) -1 );   //Baud rate divisior register 0
//UART1

    for(i=0;i<100;i++);
}


   
//=====================================================================
void Uart_SendByte(int data)
{
  
        if(data=='n')
        {
            while(!(rUTRSTAT0 & 0x2));
           // Delay(1);                 //because the slow response of hyper_terminal
            WrUTXH0('r');
        }
        while(!(rUTRSTAT0 & 0x2));   //Wait until THR is empty.
      //  Delay(1);
        WrUTXH0(data);
 
  
             

//====================================================================
void Uart_SendString(S8 *pt)
{
    while(*pt)
        Uart_SendByte(*pt++);
}

//=====================================================================
//If you don't use vsprintf(), the code size is reduced very much.
void Uart_Printf(S8 *fmt,...)
{
    va_list ap;
    S8 str[255];

    va_start(ap,fmt);
    vsprintf(str,fmt,ap);
    Uart_SendString(str);
    va_end(ap);
}

另外还要加上初始化文件以跳转到nandMain

以上就是一个完整的工程

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值