【转帖】花了三四天时间,讲nand flash实验基本看懂了,注释了main程序与大家分享
/**********************按键实验*********************************/// 公司名称 :飞凌嵌入式技术有限公司
// 描 述 :nandflash
// 版 权 :飞凌嵌入式技术有限公司
// 网 址 :www.witech.com.cn
/***************************************************************/
本文转自 飞凌嵌入式ARM技术讨论区 感谢作者的无私奉献!
/*
本实验接口说明
*/
#include "include.h"
/*-----------------------函数声明----------------------------*/
void InitNandFlash(int info);
void cpy_bpage(void);
void add_bpage(unsigned int seq);
extern void Uart_Printf(char *fmt,...);
extern void Uart_Init(int baud);
extern void Uart_Select(int ch);
/*------------------------------------------------------------/
函数名称: 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);
//
}
/*------------------------------------------------------------/
函数名称: WaitNFBusy
功能描述:
传 参: 无
返 回 值: static U32 stat&1
-------------------------------------------------------------*/
static U32 WaitNFBusy(void) // 等待nand flash 的操作结束
{
U8 stat; //因为nansh flash数据通道只有8bit
WrNFCmd(QUERYCMD); //QUERYCMD=0X70,将0x70写入NFCMD
//查看nand flash芯片的资料中的Command Sets
//0x70表示读nand flash的状态
do
{
stat = RdNFDat(); //上面命令是读nandflash的状态,因此RdNFDat获得的是nandflash的状态。
}
while (!(stat&0x40)); // busy:0ready:1
WrNFCmd(READCMD0); //READCMD0=0
return stat&1; //注意0为操作成功.见datasheet34页表。
}
/*------------------------------------------------------------/
函数名称: ReadChipId
功能描述: 读flash ID
传 参: 无
返 回 值: static U32 id
-------------------------------------------------------------*/
// 读ID过程的时序图在K9F1G08U0A的datasheet中,第28和35页//
static U32 ReadChipId(void)
{
U32 id,k;
NFChipEn(); //选中nandflash
WrNFCmd(RdIDCMD);//读ID命令
WrNFAddr(0); //写入00h(根据datasheet)
while(NFIsBusy()); //等待前一步完成
id= RdNFDat()<<8; //define中规定:RdNFDat8(); for 8 bit nand flash,use byt access
for(k=0;k<500;k++); //
id |= RdNFDat(); //从运行结果ID:ecda来看,可能是这边程序有点问题(ID指什么不明确)
NFChipDs();
return id;
}
/*------------------------------------------------------------/
函数名称: ReadStatus
功能描述: 读FLASH状态
传 参: 无
返 回 值: static U16 stat
-------------------------------------------------------------*/
static U16 ReadStatus(void)
{
U16 stat;
NFChipEn();
WrNFCmd(QUERYCMD);
stat = RdNFDat();
NFChipDs();
return stat;
}
/*------------------------------------------------------------/
函数名称: EraseBlock
功能描述: 擦除 FLASH
传 参: U32 addr
返 回 值: U32 ~stat
-------------------------------------------------------------*/
// 地址输入(两个周期) datasheet第27页 //
U32 EraseBlock(U32 addr)
{
U8 stat;
addr &= ~0x3f; //addr=0000 0001 1000 0000
NFChipEn();
WrNFCmd(ERASECMD0); //ERASECMD0=0X60
WrNFAddr(addr); //cycle1:8bit address=1000 0000
WrNFAddr(addr>>8); //cycle2:8bit address=0000 0001
WrNFCmd(ERASECMD1); //ERASE confirm cmd
stat = WaitNFBusy(); //等待擦除完成
NFChipDs();
return ~stat;
}
/*------------------------------------------------------------/
函数名称: ReadPage
功能描述:
传 参: U32 addr, U8 *buf
返 回 值: 无
-------------------------------------------------------------*/
// 读取block6中的page25 参考datasheet30页 //
void ReadPage(U32 addr, U8 *buf)
{
U16 i;
NFChipEn();
WrNFCmd(READCMD0); //READCMD0=0
WrNFAddr(0); //
WrNFAddr(0); //因为读的是一个page,所以col addr=0
WrNFAddr(addr); //
WrNFAddr(addr>>8); //block6,page25的地址
WrNFCmd(READCMD1); //READCMD1=0X30
InitEcc(); //初始化ECC
WaitNFBusy(); //
for(i=0; i<2048; i++)
buf = RdNFDat(); //将2k的内容读出
NFChipDs();
}
/*------------------------------------------------------------/
函数名称: WritePage
功能描述:
传 参: U32 addr, U8 *buf
返 回 值: U32 ~stat
-------------------------------------------------------------*/
/*【Nand Flash中的特殊硬件结构】
1.页寄存器(Page Register):由于Nand Flash读取和编程操作
来说,一般最小单位是页,所以,nand flash在硬件设计时候,就考虑到
这一特性,对于每一片,都有一个对应的区域,专门用于存放,将要写入
到物理存储单元中去的或者刚从存储单元中读取出来的,一页的数据,这
个数据缓存区,本质上就是一个buffer,但是只是名字叫法不同,datasheet
里面叫做data Register,实际理解为页缓存,大小应该是等于1个page
恰当些。而正是因为有些人不了解此内部结构,才容易产生之前遇到的某人
的误解,以为内存里面的数据,通过Nand Flash的FIFO,写入到Nand Flash
里面去,就以为立刻实现了实际数据写入到物理存储单元中了。而实际上,
只是写到了这个页缓存中,只有等你发了对应的编程第二阶段的确认命令0x10
之后,实际的编程动作才开始,才开始把页缓存中的数据,一点点写到物理存
储单元中去。*/
// 参考datasheet的第23页 //
U32 WritePage(U32 addr, U8 *buf)
{
U32 i, mecc;
U8 stat, tmp;
NFChipEn(); //
WrNFCmd(PROGCMD0); //page program 命令
WrNFAddr(0); //
WrNFAddr(0); //
WrNFAddr(addr); //
WrNFAddr(addr>>8); //要写入的page地址
InitEcc(); //reset mecc and secc
MEccUnlock(); //unlock main data area ecc generation
for(i=0; i<512; i++) //具体要写入页的数据写入main data area
WrNFDat(buf); //将数据输入NAND FLASH的data register中
//或者可以理解为写入page的缓冲区
//只有在发送确认命令0x10之后,该内容才被写入物理存储单元。
MEccLock(); //unlock it
mecc = RdNFMEcc(); //mecc赋值等于MAIN DATA AREA ECC0 STATUS ERGISTER的内容
tmp = mecc&0xff; //
tmp = (mecc>>8)&0xff;//
tmp = (mecc>>16)&0xff;//
tmp = (mecc>>24)&0xff;//
tmp = 0xff; //mark good block
//WrNFDat(0xff); //2048,坏块标志//此时主数据区已经lock了。如果不等于0xff就说明是坏块
//sumsung规定在block第一和第二个page的spare area的第一个字节,如果不等于0xff就说明是坏块。
SEccUnlock(); //校验码写入spare data area
WrNFDat(0xff); //改到这里来运行也一样,应该是没做坏块的判断吧?
WrNFDat(tmp);//ECC校验码
WrNFDat(tmp);
WrNFDat(tmp);
WrNFDat(tmp);//同上,也在页缓冲区
SEccLock();
WrNFCmd(PROGCMD1); //确认命令,将以上数据写入物理存储器
stat = WaitNFBusy();
NFChipDs();
return ~stat;
}
/*------------------------------------------------------------/
函数名称: nandMain
功能描述: 入口函数
传 参: 无
返 回 值: 无
-------------------------------------------------------------*/
void nandMain(void)
{
U16 ID,i;
U8 buf;
U32 NFBlockNO=6;
U32 NFPagesNO = 25; //block6,page25
U32 status;
U32 BlockPages;
BlockPages =(NFBlockNO<<6)+NFPagesNO; //BlockPages=000110011001
//左移6位是因为1Block=64Page
//因此block6的起始地址位:6*64=6<<6
Uart_Init(115200);
Uart_Printf("\nthe main is running\n");
InitNandCfg(); //初始化函数
ID=ReadChipId(); //ID=ECf1 ;;ID=ecda
Uart_Printf("\nnand flash`s ID is:%x\n",ID);
if(EraseBlock(BlockPages)&0x1==TRUE)
{
Uart_Printf("\nblock %d is erased\n",NFBlockNO);
ReadPage(BlockPages,buf); //读page中的内容
Uart_Printf("\n/***********************擦除之后flash中的数据****************/\n");
for(i=0; i<512; i++)
Uart_Printf("%4x", buf);
Uart_Printf("\n/***********************应写入数据****************/\n"); 来支持一下楼主,要是把实验平台原理图也发出来就更好了 楼主的努力值得学习和尊敬。谢谢分享。 感谢楼主!!! nice!! 学习,感谢楼主 先mark,再慢慢看 学习了 辛苦楼主了! mark Nand Flash的冰山一角!楼主再接再厉,把copy-back ,two-plane的内容也弄出来 好资料,学习了,谢谢! 先mark 后学习 学习 学习 mark 学习了 呵呵 这个好啊 mark nand flash 回复【楼主位】Ayuflyhigh
-----------------------------------------------------------------------
mark,thanks 学习! hehe 我看着“【Nand Flash中的特殊硬件结构】”那段中文解释,觉得有点熟悉,去查证,果然,是我之前帖子里面的:
【简介】如何编写linux下nand flash驱动
http://blog.chinaunix.net/u3/101630/showart_2004008.html
http://blog.chinaunix.net/u3/101630/showart_2004014.html
感兴趣的,pdf版本的,可以去这下载:
【简介】如何编写linux 下nand flash 驱动version: 1.0 date:20090721
http://blogimg.chinaunix.net/blog/upfile2/091230111752.pdf
麻烦这位哥们引用的话,顺便说一句是从哪里转载的,至少也是对原作者的尊重,谢谢。 回复【9楼】Old_Young
-----------------------------------------------------------------------
我的那个帖子:
【简介】如何编写linux 下nand flash 驱动
里面有关于“copy-back ,two-plane”部分的解释,希望对你有帮助。
如果需要对代码进行解释,可以把代码用邮件发我,也许可以帮你写出必要的注释。 不好意思,看错了,原来lz是转帖的。
帖子原作者,是这里:
http://w126493.s33.mydiscuz.com/thread-1219-1-1.html
所以,上面那番话,引用别人东西要注明,就是对帖子原作者说的了,不是针对lz的,lz见谅哈。 学习 上干货了 好货 mark :D 呵呵,不客气 好久没来论坛了 论坛好火爆,过了个十一,帖子就沉了,还要自己顶。 mark 先mark 后学习 mark mark 这个要mark。 先看看。。。。不错。。 学习一下,谢谢楼主分享! 谢谢分享,Thanks! 回复【楼主位】Ayuflyhigh
-----------------------------------------------------------------------
Thanks mark mark mark mark! mark 回复【40楼】glassheart
学习一下,谢谢楼主分享!
-----------------------------------------------------------------------
不客气,呵呵 mark 先mark
后学习 mark 过来标记下 标记~ mark 回复【22楼】Ayuflyhigh
hehe
-----------------------------------------------------------------------
标记,下载了。很有帮助。
但发现有些错误,如物理地址转为FLAFH格式地址计算错误;硬件ECC的概念不准确等。 mark 学习了,谢谢! mark 回复【楼主位】Ayuflyhigh
-----------------------------------------------------------------------
在ReadChipId()函数中,id = 0xecda表示你的NAND Flash为K9F2G08。
三星公司常见的NAND Flash还有K9F1208、K9F1G08和K9F2G08:
K9F1208的id = 0xec76,容量为64MB,Page Size为512B;
K9F1G08的id = 0xecf1,容量为128MB,Page Size为1024B;
K9F1G08的id = 0xecda,容量为256MB,Page Size为2048B; 回复【59楼】fifihill
-----------------------------------------------------------------------
刚才最后一行写错了,应该是K9F2G08!
K9F2G08的id = 0xecda,容量为256MB,Page Size为2048B; 感谢感谢 不知楼主有没有关于坏块管理的资料 不错啊!!!!!!!!!! mark!! 必须顶,mark 谢谢楼主分享 mark mark mark 谢谢楼主共享!! mark,留着以后需要的时候看 先mark一个 谢谢楼主的分享 有没有这个例子的完整原代码啊? 不错,学习了 ,马渴! mark! 也在学习中~~ 学习了
页:
[1]