Ayuflyhigh 发表于 2010-6-8 09:21:56

【转帖】花了三四天时间,讲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");

mxy520 发表于 2010-6-8 20:35:53

来支持一下楼主,要是把实验平台原理图也发出来就更好了

tarchen 发表于 2010-6-8 20:40:29

楼主的努力值得学习和尊敬。谢谢分享。

wangxiaoacc 发表于 2010-6-8 21:29:37

感谢楼主!!!

Ayuflyhigh 发表于 2010-6-9 09:57:07

nice!!

skyshow 发表于 2010-6-10 09:52:03

学习,感谢楼主

Fire_cow 发表于 2010-6-10 13:14:38

先mark,再慢慢看

durgy 发表于 2010-6-10 14:51:28

学习了

chinalove 发表于 2010-6-12 06:46:00

辛苦楼主了!

Old_Young 发表于 2010-7-15 15:03:40

mark

hugh512 发表于 2010-7-16 09:41:42

Nand Flash的冰山一角!楼主再接再厉,把copy-back ,two-plane的内容也弄出来

newbud123 发表于 2010-7-17 08:01:33

好资料,学习了,谢谢!

swustlx86 发表于 2010-7-21 10:55:42

先mark 后学习

abu0210 发表于 2010-7-24 16:00:51

学习 学习

wsm80828 发表于 2010-7-24 17:06:37

mark

newbud123 发表于 2010-7-27 15:19:26

学习了

Ayuflyhigh 发表于 2010-8-3 10:47:47

呵呵

prococo 发表于 2010-8-9 07:13:02

这个好啊

chinalove 发表于 2010-8-9 07:15:09

mark

boycn 发表于 2010-8-9 08:54:42

nand flash

wuhaiyun 发表于 2010-8-10 17:26:32

回复【楼主位】Ayuflyhigh
-----------------------------------------------------------------------

mark,thanks

yondyanyu 发表于 2010-8-11 13:57:39

学习!

Ayuflyhigh 发表于 2010-8-16 07:58:13

hehe

crifan 发表于 2010-8-19 15:43:14

我看着“【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

麻烦这位哥们引用的话,顺便说一句是从哪里转载的,至少也是对原作者的尊重,谢谢。

crifan 发表于 2010-8-19 15:45:52

回复【9楼】Old_Young
-----------------------------------------------------------------------
我的那个帖子:
【简介】如何编写linux 下nand flash 驱动
里面有关于“copy-back ,two-plane”部分的解释,希望对你有帮助。
如果需要对代码进行解释,可以把代码用邮件发我,也许可以帮你写出必要的注释。

crifan 发表于 2010-8-19 15:55:00

不好意思,看错了,原来lz是转帖的。
帖子原作者,是这里:
http://w126493.s33.mydiscuz.com/thread-1219-1-1.html
所以,上面那番话,引用别人东西要注明,就是对帖子原作者说的了,不是针对lz的,lz见谅哈。

lghtjpu 发表于 2010-8-19 16:51:38

学习

bj-stm8 发表于 2010-8-19 19:51:09

上干货了 好货

zcronline 发表于 2010-8-21 17:59:27

mark

Ayuflyhigh 发表于 2010-9-21 08:34:23

:D

Ayuflyhigh 发表于 2010-9-26 08:16:35

呵呵,不客气

Ayuflyhigh 发表于 2010-9-28 14:51:21

好久没来论坛了

Ayuflyhigh 发表于 2010-10-9 15:35:22

论坛好火爆,过了个十一,帖子就沉了,还要自己顶。

j491424570 发表于 2010-10-10 20:00:00

mark

pingchangxin 发表于 2010-10-13 08:56:00

先mark 后学习

happywolf999 发表于 2011-1-20 10:55:08

mark

whh217 发表于 2011-1-20 12:41:01

mark

gliet_su 发表于 2011-1-20 12:52:08

这个要mark。

xiaofeierys 发表于 2011-1-20 19:28:07

先看看。。。。不错。。

glassheart 发表于 2011-2-27 21:47:01

学习一下,谢谢楼主分享!

llf021421 发表于 2011-2-28 17:05:32

谢谢分享,Thanks!

minghui2009 发表于 2011-3-3 00:40:38

回复【楼主位】Ayuflyhigh
-----------------------------------------------------------------------

Thanks

kneken 发表于 2011-3-3 07:58:30

mark

wxx116zh 发表于 2011-3-3 08:28:20

mark

banyai 发表于 2011-3-3 08:41:12

mark

jack_yu 发表于 2011-3-3 09:30:50

mark!

lsw0136 发表于 2011-3-3 11:20:29

mark

Ayuflyhigh 发表于 2011-3-26 19:06:49

回复【40楼】glassheart
学习一下,谢谢楼主分享!
-----------------------------------------------------------------------

不客气,呵呵

80162535 发表于 2011-3-28 20:15:01

mark

swustlx86 发表于 2011-4-1 14:31:36

先mark
后学习

ljmdzyx 发表于 2011-4-11 00:41:53

mark

anvy178 发表于 2011-4-11 09:05:38

过来标记下

geniusjia 发表于 2011-4-11 12:17:14

标记~

ap0405209 发表于 2011-4-12 15:26:07

mark

xizi 发表于 2011-4-29 07:21:31

回复【22楼】Ayuflyhigh
hehe
-----------------------------------------------------------------------

标记,下载了。很有帮助。
但发现有些错误,如物理地址转为FLAFH格式地址计算错误;硬件ECC的概念不准确等。

ap0405209 发表于 2011-5-3 17:33:03

mark

maidilong 发表于 2011-5-5 08:40:45

学习了,谢谢!

wajlh 发表于 2011-5-5 09:37:05

mark

fifihill 发表于 2011-5-21 15:20:43

回复【楼主位】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;

fifihill 发表于 2011-5-21 15:22:39

回复【59楼】fifihill
-----------------------------------------------------------------------

刚才最后一行写错了,应该是K9F2G08!
K9F2G08的id = 0xecda,容量为256MB,Page Size为2048B;

shenhao2007 发表于 2011-6-2 13:17:53

感谢感谢 不知楼主有没有关于坏块管理的资料

bingshuihuo888 发表于 2011-6-24 21:19:17

不错啊!!!!!!!!!!

hooddas 发表于 2012-4-1 15:39:54

mark!!

LOVEDOVE 发表于 2012-4-11 16:59:28

必须顶,mark

LOVEDOVE 发表于 2012-4-12 00:23:23

谢谢楼主分享

bluelool 发表于 2012-4-24 22:29:02

mark mark mark

buttonsjj 发表于 2012-4-26 14:14:55

谢谢楼主共享!!

janno0258 发表于 2012-4-26 16:31:27

mark,留着以后需要的时候看

shawnto 发表于 2012-4-26 20:51:24

先mark一个

chenshichao541 发表于 2012-4-27 15:50:08

谢谢楼主的分享

gracialee 发表于 2012-4-30 09:30:14

有没有这个例子的完整原代码啊?

keshipt 发表于 2012-5-4 14:10:33

不错,学习了 ,马渴!

ZL88 发表于 2012-6-11 07:52:16

mark!                  

male123 发表于 2012-6-11 09:41:12

也在学习中~~

eryueniao 发表于 2012-6-12 13:42:15

学习了                           
页: [1]
查看完整版本: 【转帖】花了三四天时间,讲nand flash实验基本看懂了,注释了main程序与大家分享