历史上的今天
返回首页

历史上的今天

今天是:2024年11月25日(星期一)

正在发生

2019年11月25日 | TX2440裸机程序-nand flash

2019-11-25 来源:eefocus

一、开发环境说明


开发板:TX2440A


cpu:s3c2440


nand flash:K9F2G08U0B(256M)


编译软件:ADS1.2


二、nand flash简介


2.1K9F2G08U0B的存储阵列

图 2-1 K9F2G08U0B的存储阵列


由图2-1,我们可以知道:K9F2G08U0B的一页为(2K+64)字节(2K 表示的是 main 区容量,64 表示的是 spare 区容量),它的一块为 64 页,而整个设备包括了2048个块。这样算下来一共有 2112M 位容量,如果只算 main 区容量则有256M 字节(即 256M×8 位)。

要实现用 8 个 IO 口来要访问这么大的容量,如图 2-1 所示:K9F2G08U0A 规定了用 5 个周期来实现。第一个周期访问的地址为 A0-A7;第二个周期访问的地址为A8-A11,它作用在 IO0-IO3 上,而此时 IO4-IO7 必须为低电平;第三个周期访问的地址为 A12-A19;第四个周期访问的地址为 A20-A27;第五个周期访问的地址为 A28,它作用在 IO0上,而此时IO1~IO7 必须为低电平。前两个周期传输的是列地址,后三个周期传输的是行地址。


通过分析可知,


1、块寻址:K9F2G08U0B由2048个block组成,那么块寻址需要11位地址线进行寻址即A18-28(2^(28-18+1)=2048块)。


2、页寻址:一个block由64页组成,那么页寻址需要6位地址线进行寻址即A12-A17(2^6=64)


3、页内字节寻址(即上图中列地址) :页大小为2KB,只需要11位地址线进行寻址A0-10(2^11=2048byte),A11作为页内地址扩展未使用。


由于所有的命令、地址和数据全部从8 位 IO 口传输,所以 Nand flash 定义了一个命令集来完成各种操作。


2.2K9F2G08U0B的命令说明

图2-2 K9F2G08U0B命令表


图2-2是K9F2G08U0B芯片操作读写、擦除等操作的命令表。由于时序都有S3C2440的nand控制器控制。所以,这里的nand驱动。只要好好弄明白K9F2G08U0B这两个要点,就很容易掌握nand驱动。


二、硬件


在S3c2440中可通过NCON0、GPG13-15引脚来设置nand flash控制器所支持nand flash类型

 

图1实际芯片型号K9F2G08U0B 图2引脚配置               


由上图可知


GPG13=3.3V(高电平),GPG14=3.3V(高电平)


GPG15=0.3V(按照图3的ARM芯片直流电气特性定义<0.8V,为低电平),NCON=3.3V(高电平)


根据GPG13-15、NCON引脚配置,配置nand flash存储器(配置表详见下面)

nand flash 存储器配置表


由上配置表可知:nand flash配置成:


1、先进nand(NCON0=1)   


2、页容量2K字节(GPG13=1)  


3、5个地址周期(GPG14=1)  


4、8位宽(GPG15=0)


小结:上面nand flash配置结果与K9F2G08U0B一致。


三、软件


3.1初始化(时序图参数计算)


设置时序,其实是设置NFCONF 配置寄存器。S3C2440内部nand flash控制器时序图

TACLS:表示CLE/ALE的建立时间(setup time)。


TWRPH0:表示写控制信号nWE使能的持续时间。


TWRPH1:表示写控制信号new禁止到 CLE/ALE关闭的时间。


NFCONF配置寄存器

K9F2G08U0B下面的相关时序图

K9F2G08U0B对应时序参数


由上面两个时序图对比可知:TACLS就相当于tCLS或tALS参数,TWRPH0就相当于tWP,而TWRPH1就相当于tCLH或tALH。


其中:HCLK=100MHz(即10ns),TX2440开发板使用电源为3.3V,则tCLS=tALS=12ns(最小值),tWP=12ns(最小值),tCLH=tALH=5ns(最小值)。如果希望nand flash能正常读写操作,时序配置参数必须大于这些最小值。


验证程序中对nand flash的NFCONF寄存器 时序参数配置是否合适?


在nand flash的NFCONF寄存器中


1、TACLS=NFCONF[13:12]=3,即HCLK*TACLS=30ns >12ns(表中tCLSmin)


2、TWRPH0=NFCONF[10:8]=7 即HCLK*(TWRPH0+1)=80ns >12ns(表中tWPmin)


2、TWRPH1=NFCONF[6:4]=7 即HCLK*(TWRPH1+1)=80ns >5ns(表中tCLHmin),一般TWRPH1设置为0,也满足>5ns条件。


综上所述:设置nand flash寄存器的时序满足K9F2G08U0B要求。


3.2 读取ID


Nand芯片的每一个型号,都有固定的芯片ID和制造商ID。用户通过读取ID,确认是什么类型的nand芯片。


下表是K9F2G08U0B读取ID的代码。过程如下


1、激活芯片片选


2、写入复位命令,芯片复位(记得等待芯片内部操作完成)。复位命令不是必须的。


3、写入读取芯片ID命令(0x90),然后写入地址0x00


4、读取芯片ID(ID信息总共5个信息,每当从NF_RDDATA8读取一个信息后,NF_RDDATA8获取下一个的信息)


5、关掉片


读取ID时序图:


       

源码:


U32 ReadChipId(void)

{

U32 id;

unsigned char Makercode,Devcode,ID3rd,ID4rd,ID5rd;

NF_ChipEn(); //片选使能

NF_CMD(RdIDCMD); //写读nand flash IDC命令0x90 

NF_ADDR(0);//写地址0x00

while(NFIsBusy());//判断nand flash是否busy?若busy,则继续等待。

Makercode = NF_RDDATA8();

Devcode   = NF_RDDATA8();

ID3rd     = NF_RDDATA8();

ID4rd     = NF_RDDATA8();

ID5rd     = NF_RDDATA8();

NF_ChipDs();//禁止片选使能

if((Makercode == 0xec)  && (Devcode=0xda) && (ID3rd == 0x10) &&

(ID3rd == 0x10) && (ID4rd == 0x95) && (ID5rd == 0x44))

Uart_Printf("nK9F2G08U0Bn");

Uart_Printf("Makercode=%x,Devcode=%x,ID3rd=%x,ID4rd=%x,ID5rd=%xn",Makercode,Devcode,ID3rd,ID4rd,ID5rd);

 

运行结果:

由上图可知读取ID信息与K9F2G08U0B中ID信息一致。


3.3块擦除


nandflash擦除操作以块为单位,对任何Flash闪存存储器进行写操作之前,都必须先进行擦除,然后写入。读写操作是页为单位


快擦除操作步骤(参考下面时序图):


1、nand falsh芯片使能


2、写擦除命令 0x60


3、写 需要擦除的块地址(块地址只需要行地址[28:13])


4、写擦除命令 0xD0


5、nand flash 忙检测,若处于busy,则等待至不忙ready。


6、写读取状态命令0x70


8、操作成功判断,首先通过IO[6]做忙状态检测,然后IO[0]位进行判断是否成功(为什么是IO0位,请参考下面读取70h状态的返回值定义)。


9、关闭芯片使能


块擦除时序图

读取70h状态后,返回值说明(由K9F2G08U0B的datasheet提供)

块擦除源码 


/*********************************************************

**函数名称:U8 EraseBlock_2G08(U32 block_number) 

**函数功能:nand flash的块擦除

**入口参数:block---块号

**出口参数:无

**返回值     : 擦除成功标志位   

1、Earse_ok表示擦除成功

2、Earse_fail表示擦除失败

3、Markbad_fail表示标注失败

************************************************************/

U8 EraseBlock_2G08(U32 block)

{

     char stat, temp;

temp = IsBadBlock_2G08( block);     //判断该块是否为坏块  ,这些语句测试通过

     if(temp == Isbad_ok){ return Isbad_ok;}           //是坏块,返回

     NF_ChipEn();            //打开片选

     NF_CLEAR_RB();        //清RnB信号

/*擦除命令0x60*/

    NF_CMD(ERASECMD0);         //擦除命令周期1

   //写入块地址的3个地址周期,从A18开始写起

NF_ADDR((block << 6) & 0xff);         //行地址A18~A19

NF_ADDR((block >> 2) & 0xff);         //行地址A20~A27

NF_ADDR((block >> 10) & 0xff);        //行地址A28

/*擦除命令0xD0*/

    NF_CMD(ERASECMD1);         //擦除命令周期2

    NF_DETECT_RB_my();//nand flahs的busy状态检测

    /*读取状态0x70*/

NF_CMD(QUERYCMD);          //读状态命令

    //判断状态值的第6位是否为1,即是否在忙,该语句的作用与NF_DETECT_RB();相同

do{

      stat = NF_RDDATA8();

}while(!(stat&0x40));

NF_ChipDs();            //关闭nandflash片选

//判断状态值的第0位是否为0,为0则擦除操作正确,否则错误

 

if (stat & 0x1)

{

     temp = MarkBadBlock_2G08(block);         //标注该块为坏块

      if (temp == Markbad_fail)

             return Markbad_fail;         //标注坏块失败

      else

  return Earse_fail;          //擦除操作失败

}

else 

return  Earse_ok;                  //擦除操作成功

}



建议:在读取状态70h返回值时,加入忙状态检测(通过IO[6]位)


3.4 写入数据


nand falsh支持以页为单位写入、随机写入两种数据方式。


3.4.1 页写入


时序图

源码


/*********************************************************

**函数名称:static int WritePage_2G08(U32 block,U32 page,U8 *buffer)

**函数功能:在nand flash芯片中页读功能

**入口参数:

1、block----  块号

2、page-----页号

3、*buffer----------存放读取整页的数据缓冲区

**出口参数:无

**返回值  : 写成功标志位   

1、Write_ok表示写入成功

2、Write_fail表示写入失败

************************************************************/

static int WritePage_2G08(U32 block,U32 page,U8 *buffer)

{

    int i;

    U32 blockpage, Mecc, Secc;

    U8 *bufPt=buffer,temp;

    blockpage=(block<<6)+page;

temp = IsBadBlock_2G08(block);   //判断该块是否为坏块

    if(temp == Isbad_ok){return Isbad_ok ; }          //是坏块,返回

    NF_RSTECC();    // Initialize ECC

    NF_MECC_UnLock();

NF_ChipEn(); 

NF_CMD(PROGCMD0);   // Write 1st command

NF_ADDR(0);    //Column (A[7:0]) = 0

NF_ADDR(0);    // A[11:8]

NF_ADDR((blockpage)&0xff); // A[19:12]

NF_ADDR((blockpage>>8)&0xff); // A[27:20]

NF_ADDR((blockpage>>16)&0xff);  //A[28]

for(i=0;i<2048;i++)

{

NF_WRDATA8(*bufPt++); // Write one page data from buffer

      }

 

  NF_CLEAR_RB();

NF_CMD(PROGCMD1); // Write 2nd command

NF_DETECT_RB();

NF_CMD(QUERYCMD);   // Read status command   

   //判断状态值的第6位是否为1,即是否在忙,该语句的作用与NF_DETECT_RB();相同

do{

 

        temp = NF_RDDATA8();

 

}while(!(temp&0x40));

   //判断状态值的第0位是否为0,为0则写操作正确,否则错误 

    if (temp&0x1)  

{

   NF_ChipDs();

Uart_Printf("[PROGRAM_ERROR:block#=%d]n",block);

MarkBadBlock_2G08(block);

return Write_fail;

    } 

else

{

    NF_ChipDs();

  return Write_ok;

}

 


3.4.2随机写入


时序图

源码:


/*********************************************************

**函数名称:RamdomWrite_2G08(U32 blockpage, U32 page_add, U8 data) 

**函数功能:在nand flash芯片中随机写

**入口参数:

1、blockpage--页号(由块和页信息组成),blockpage=(block<<6)+page;

2、page_add-----页内地址

3、data----------写入的数据

**出口参数:无

**返回值     : 写成功标志位   

1、Write_ok表示写入成功

2、Write_fail表示写入失败

************************************************************/

U8 RamdomWrite_2G08(U32 blockpage, U32 page_add, U8 data) 

{

    U8 temp,stat;

    NF_ChipEn();                    //打开nandflash片选

    NF_CLEAR_RB();               //清RnB信号 

//随机写命令80h

    NF_CMD(PROGCMD0);          

    //写入5个地址周期

NF_ADDR(0x00);                      //列地址A0~A7

NF_ADDR(0x00);   //列地址A8~A11

                                        

NF_ADDR((blockpage) & 0xff);           //行地址A12~A19

NF_ADDR((blockpage >> 8) & 0xff);    //行地址A20~A27

NF_ADDR((blockpage >> 16) & 0xff);  //行地址A28

 

//随机写命令85h

    NF_CMD(PROGCMD2);                 

    //页内地址

NF_ADDR((U8)(page_add&0xff));                   //列地址A0~A7

NF_ADDR((U8)((page_add>>8)&0x0f));          //列地址A8~A11

    NF_WRDATA8(data);                          //写入数据

       

//写第二写命令10h

    NF_CMD(PROGCMD1);                //页写命令周期2

NF_DETECT_RB_my(); //busy检测 

    NF_CMD(QUERYCMD);               //读状态命令

//判断状态值的第6位是否为1,即是否在忙,该语句的作用与NF_DETECT_RB();相同

do{

        stat = NF_RDDATA8();

  }while(!(stat&0x40));

NF_ChipDs();                  //关闭nandflash片选

//判断状态值的第0位是否为0,为0则写操作正确,否则错误

if (stat & 0x1){return Write_fail; } //失败

else {return Write_ok;  }         //成功

}


3.5读取数据


3.5.1页读取


时序图

源码


/*********************************************************

**函数名称:static int ReadPage_2G08(U32 block,U32 page,U8 *buffer)

**函数功能:在nand flash芯片中页读功能

**入口参数:

1、block----  块号

2、page-----页号

**出口参数:*buffer----------存放读取整页的数据缓冲区

推荐阅读

史海拾趣

全鹏(CHAMPION)公司的发展小趣事

为了提升国际市场竞争力,全鹏公司一直致力于提高产品质量和管理水平。在2014年,全鹏电子科技有限公司成立,并成功通过了ISO9001国际质量管理体系、ISO14001环境管理体系认证和汽车与医疗器材体系IATF/16949认证。这些认证不仅证明了全鹏公司在质量管理方面的实力,也为其在国际市场上赢得了更多的信任和机会。

Eurohm Resistors公司的发展小趣事

随着环保意识的不断提高,Eurohm Resistors公司积极响应绿色发展的号召。公司投入大量资源研发环保型电阻器产品,采用可再生材料和绿色生产工艺,降低产品对环境的影响。同时,公司还积极参与各种环保活动,推动行业的绿色发展。

DAPAudio公司的发展小趣事

DAPAudio公司自成立以来,一直将技术创新作为公司发展的核心动力。在音频处理领域,DAPAudio率先推出了基于先进算法的数字音频处理器,其独特的音质优化技术迅速赢得了市场的认可。随着技术的不断迭代和更新,DAPAudio的产品逐渐在高端音频市场占据了一席之地。

GWP Group公司的发展小趣事

DAPAudio公司自成立以来,一直将技术创新作为公司发展的核心动力。在音频处理领域,DAPAudio率先推出了基于先进算法的数字音频处理器,其独特的音质优化技术迅速赢得了市场的认可。随着技术的不断迭代和更新,DAPAudio的产品逐渐在高端音频市场占据了一席之地。

Cicoil公司的发展小趣事

Cicoil公司的创立可以追溯到电子行业的快速发展时期。创始人看到了扁平电缆在电子设备中的巨大潜力,于是决定专注于这一领域的研究和开发。他们投入大量资源,研发出具有独特技术的柔性扁平电缆,为电子设备提供了更为灵活和可靠的连接方案。这一创新产品在市场上引起了轰动,为Cicoil公司赢得了良好的声誉和市场份额。

Ava Electronics Corp公司的发展小趣事

随着产品线的不断丰富和技术的不断进步,AVA电子开始将目光投向更广阔的市场。公司积极参加各类行业展会和论坛,与国内外客户建立了广泛的联系。同时,AVA电子还加大了品牌建设的力度,通过广告宣传、品牌推广等方式提高了品牌的知名度和美誉度。这些举措不仅有效提升了公司的市场份额,也为公司的长远发展奠定了坚实的基础。

问答坊 | AI 解惑

浅谈手机发射功率(转帖)

笔者从事手机测试校准系统集成有段时间,感觉到手机发射功率在不同的系统、不同的协议下有很多的不同。笔者对此深感有意思,故把PHS、GSM、cdma2000 1x、wcdma下对手机发射功率的规定罗列于此,希望能给同行起到抛砖引玉的作用,斧正我的错误 ...…

查看全部问答>

谁能帮我分析下下面这段代码干嘛的!(BCD相关)

-- a:dial[3:0] library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; ENTITY bcd IS    PORT (       clk          ...…

查看全部问答>

串口通讯-RS-232-C祥解

串口通讯-RS-232-C祥解…

查看全部问答>

100分求助开发板字体显示问题

我用程序下面的程序使我输入的字变大并且变为了红色,但字体变大了编辑框中的光标并没有变大,举个例子,我在编辑框框中输入8,框内只能显示8的上半部分,下半部分显示不出来,而且即使把框拉大后数字还是无法显示完全,请问是程序的问题还是其他问 ...…

查看全部问答>

C8051F120+CP2200 我使用例子程序UDP来实现接收数据相关问题

C8051F120+CP2200 我基于例子程序UDP来实现接收数据相关问题,往板子里传数据,但是传了不到2秒就断开了,就算是使用其例子程序与PC机交互,数据传了一段时间也会停止传输,传输时间时长时短,我想问问有没使用过该网卡CP2200的大侠,一般使用该网卡 ...…

查看全部问答>

如何设计微指令系统实现除法运算,请高手提供思路,谢谢了。

    现在课程设计要求自己设计一个微指令系统,我打算实现除法运算,但是目前遇到困难,不知道该如何实现。我的思路是利用加法和乘法的思路,比如要实现 M / N 的话,则是对1/N实现M次累加。。。可是不知道如何得到1/N。     ...…

查看全部问答>

一个伤脑筋的问题

一般说来, 手机在没有插SIM卡的情况下, 开机会出现提示\"无SIM卡\"的对话框, 如果不做任何操作, 这个对话框不会关闭. 但是在横屏模式下, 这个对话框在开机时闪一下就自动关闭了.我做了很多测试, 它与AP无关, 但我又找不出其他原因. 或许只是哪个 ...…

查看全部问答>

switch()问题

#include #include main() {  SCON=0x50;   TMOD|=0x20;   TH1=0xf3;   TR1=1;   TI=1;      switch(1)   {     case 1: printf(\"%d\\n\" ...…

查看全部问答>

KEILFOR51

UV4-IDE 你懂的…

查看全部问答>

易电源试用报告3:LMZ12001的负输出电压应用与LMZ12010模块试用

送的套装里有两个赠送的芯片 LMZ12001和LMZ12010  前者与DEMO板上的LMZ12002是同样的封装不同的最大电流值,LMZ12010是个大块头,最大10A输出。昨天参考应用手册AN-2027做了个LMZ12001的负输出电压应用的板子,和一个12010的板子,参考手 ...…

查看全部问答>