加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

九ARM9(2440)对nandflash…

发布时间:2020-12-15 17:37:41 所属栏目:百科 来源:网络整理
导读:原文地址: 九? ? ARM9(2440)对nand? flash的读写操作——程序实例分析 作者: 骨Zi里德骄傲 我相信上一篇文章已经对nand flash的操作有了一定的了解,下面一起看一下程序实例: #include "include.h" extern void Uart_Printf(char *fmt,...); extern void
原文地址:九??ARM9(2440)对nand?flash的读写操作——程序实例分析 作者:骨Zi里德骄傲

我相信上一篇文章已经对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,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
???? //???? 0????????? 1?????? 0???,???? 0????????? 1??????? 0?????????? 0????,?????? 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

以上就是一个完整的工程

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读