Nandflash 驱动深度分析(基于S3C2410)

发布者:温馨的家庭最新更新时间:2016-11-25 来源: eefocus关键字:Nandflash  S3C2410 手机看文章 扫描二维码
随时随地手机看文章

NAND Flash在嵌入式系统中的地位与PC机上的硬盘类似,用于保存系统运行所必需的操作系统、应用程序、用户数据、运行过程中产生的各类数据。与内存掉电后数据丢失不同,NAND Flash中的数据在掉电后仍可永久保存。

操作NAND Flash时,先传输命令,然后传输地址,最后读/写数据,期间要检查Flash的状态。对于K9F5608U0D,它的容量为32MB,需要25位地址。发出命令后,后面要紧跟3个地址序列。比如读Flash时,发出读命令和3个地址序列后,后续的读操作就可以得到这个地址及其后续地址的数据。相应的命令字和地址序列如表1和2所示:

表1:K9F5608U0D命令设置表

 

表2:K9F5608U0D寻址周期表

 

K9F5608U0D一页的大小为512字节,分为两部分:前半页,后半页。由于列地址只有8根数据线,所以寻址宽度只有256个字节。而在这512个字节的一页中,当发出读命令为00h时,表示列地址将在前半部分寻址,命令为01h时,表示列地址将在后半部分寻址。A8被读命令00h设置为低电平,而在01时设置成高电平。

S3C2410对NAND Flash操作提供了几个寄存器来简化对NAND Flash的操作。比如要发出读命令时,只需要往NFCMD寄存器中写入0即可,而控制器会自动发出各种控制信号进行操作。以下几个寄存器,为2410专为NAND而设计的:

NFCONF:NAND Flash配置寄存器。

被用来使能/禁止NAND Flash控制器、使能/禁止控制引脚信号nFCE、初始化ECC、设置NAND Flash的时序参数等。

TACLS、TWRPH0、TWRPH1这3个参数控制的是NAND Flash信号线CLE/ALE与写控制信号n/WE的时序关系,如图1所示:

 

 

图1:S3C2410 NAND控制时序图

NFCMD:NAND Flash命令寄存器。

对于不同型号的Flash,操作命令一般不一样。

NFADDR:NAND Flash地址寄存器。

当写这个寄存器时,它将对Flash发出地址信号。

NFDATA:NAND Flash数据寄存器。

只用到低8位,读,写此寄存器将启动对NAND Flash的读数据、写数据操作。

NFSTAT:NAND Flash状态寄存器。

只用到位0,0:busy,1:ready。

在使用NAND Flash之前,需要先对NAND进行初始化:

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

* 名称:             init_nandconf

* 功能:             初始化2410内部nandflash控制寄存器

* 返回:             无         

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

void init_nandcof(void)

{

     rNFCONF=0xf820;//设置NANDFLASH,各位定义如表3所示:

 

表3:NFCONF寄存器

[15]:设置为1,NANDFLASH 控制器开,由datasheet得到,在自动启动后,nandflash控制器会关闭,如果要使用控制器,就要手工开。

[12]:初始化ECC寄存器,设置为1

[11]:外部NAND使能,这里设置为1,先关一下。

[10:8]:TACLS设置,由表4得,ALE和CLE要求保持10ns,而现在的HCLK为100m,所以TACLS为0就可以了。

 

表4:AC TIMING CHARACTERISTICS FOR COMMAND / ADDRESS / DATA INPUT

[6:4]:由表4得,twp在3.3V时需要至少25ns的时间,现在在HCLK为100M的情况下,需要3个周期,所以TWRPH0为2,

[2:0]:由表4得到,tch要求时间为10ns,所以在HCLK为100M的情况下,只要1个周期就行了,所以TWRPH1为0

     rNFCONF &= ~0x800;//NAND使能。CE低电平有效

     rNFCMD=0xff; //重启一下NAND,由表5所示,得到复位的命令

 

表5:NANDFLASH命令表

     while(!(rNFSTAT&0x1));//等待复位完成,由表6得,NFSTAT寄存器定义

      

表6:NFSTAT寄存器

}

对于NANDFLASH操作来说,一般有4种:1、读NAND ID,2、读NAND内容,3、写NANDFLASH,4、擦除NANDFLASH。以下分4个函数说明NANDFLASH的4种操作:

 

1、读NANDFLASH的ID

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

* 名称:             nand_read_id

* 功能:             读取nandflash的ID

* 输入:             无

* 返回:             id          

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

 

static int nand_read_id(void)

{

    int i,id;//i用于记录当前的,id用于记录读取的ID

 

    /* NAND使能 */

    rNFCONF &= ~0x800;使能//NANDFLASH

    for(i=0; i<10; i++);//等待10个周期,等待Nand准备就绪

 

图2:NAND读时序图

以下部分按照图2时序图而写

rNFCMD=0x90;

for(i=0;i<5;i++);//由于FCLK为200MHz,这里5个周期为25ns

查器件手册得tAR最小需要10ns,最大没有上限

id=rNFDATA;//读出NAND的制做商编号:这里三星为0xEC

id=(id<<8)+rNFDATA

    //关芯片使能,防止误操作对NAND中的数据修改

    rNFCONF |= 0x800;

    return id;//返回读取的ID

}

2、读NAND内容

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

* 名称:             nand_read

* 功能:             读取nandflash上一块内容到指定的地址中

* 输入:             unsigned char *buf:              要写入数据的首地址

                   unsigned long start_addr: 要读取的数据在Nand上的首地址

                   int size:                                  读取长度

* 返回:             0           

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

 

static int nand_read(unsigned char *buf, unsigned long start_addr, int size)

{

    int i, j;//i用于记录当前的,j记录每一页中的byte地址

 

    /* NAND使能 */

    rNFCONF &= ~0x800;//使能NANDFLASH

    for(i=0; i<10; i++);//等待10个周期

 

图3:NAND读时序图

以下部分按照图3时序图而写

    for(i=start_addr; i < (start_addr + size);)

    {

      /* READ0 */

      rNFCMD = 0;//由表3-4-5所示,读数据区的命令为0x0或者0x1,而对于512bytes来说,0x0是从第0个字节开始读起,而0x1是从第256个字节读起。当使用NFCMD寄存器时,控制NAND的ALE会置0,CLE会置1,数据写入时,WE也会由低变高,而当WE由低变高的过程后,命令将锁存在了NAND中的命令寄存器中,而这些都是自动的

 

      /* Write Address */

      //nand的写入方法见时序图,由于向2410的NAND的NFADDR寄存器写数据,此时ALE至1,CLE至0,数据写入时,WE也会由低变高,而当WE由低变高的过程后,地址数据将锁存在了NAND中的地址寄存器中,这些全是自动的,而又因为32M的NAND只需要3个周期寻址,所以这里只向地址寄存器发3个周期的命令就可以了

      rNFADDR = i & 0xff;

      rNFADDR = (i >> 9) & 0xff;//(左移9位,不是8位)

      rNFADDR = (i >> 17) & 0xff; //(左移17位,不是16位)

表3-4-2列出了在地址操作的3个步骤对应的NAND内部地址线,没有A8(它由读命令设置,当读命令为0时,A8=0;当读命令为1时,A8=1),所以在第二,第三次向rNFADDR寄存器发送地址时,需要再多移一位,而不是原来的8和16。

      wait_idle();//由时序图得到,当输入地址完成后,NANDFLASH会进入忙状态,我个人认为是NAND内部对输入的地址进行解释。

 

     for(j=0; j < 512; j++, i++)

      {

            *buf = (rNFDATA & 0xff);//读取NAND中的数据,将数据写入到指定的数据写入位置,当使用NFDATA寄存器时,控制NAND的CLE和ALE都会自动1。而buf指针是外面传进来的地址,在下面的函数调用会用到,每读取一次NFDATA寄存器,控制NAND的OE都会由高电平到低电平转变。而NANDFLASH的数据每读取一次,都会指向下一个内部的地址,而一个数据区由512bytes组成,当继续读下去的时候,将读到16bytes的ECC区,所以每对完512个字节后,要对nand的地址重新定位。

            buf++;//写入地址位置+1

      }

    }

 

    //关芯片使能,防止误操作对NAND中的数据修改

    rNFCONF |= 0x800;

    return 0;//返回0,表示读取成功

}

3、写NAND内容

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

* 名称:             nand_write

* 功能:             将内存中的一块内容写到nandflash上

* 输入:             unsigned char *buf:              要读取数据的首地址

                   unsigned long start_addr: 要写入的数据在Nand上的首地址

                   int size:                                  写入长度

* 返回:             写入状态           

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

 

static int nand_write(unsigned char *buf, unsigned long start_addr, int size)

{

    int i, j;//i用于记录当前的,j记录每一页中的byte地址

 

    /* NAND使能 */

    rNFCONF &= ~0x800;使能//NANDFLASH

    for(i=0; i<10; i++);//等待10个周期

 

图4:NAND编程时序图

以下部分按照图4时序图而写

    for(i=start_addr; i < (start_addr + size);)

    {

      /* READ0 */

rNFCMD = 0;//由图3-4-5所示,写数据区前先确认写入哪个区,命令为0x0或者0x1。而对于512bytes来说,0x0是从第0个字节开始读起,而0x1是从第256个字节读起。当使用NFCMD寄存器时,控制NAND的ALE会置0,CLE会置1,数据写入时,WE也会由低变高,而当WE由低变高的过程后,命令将锁存在了NAND中的命令寄存器中,而这些都是自动的。

 

图5:NAND写入位置图

      /* Write Address */

      //nand的写入方法见时序图,由于向2410的NAND的NFADDR寄存器写数据,此时ALE至1,CLE至0,数据写入时,WE也会由低变高,而当WE由低变高的过程后,地址数据将锁存在了NAND中的地址寄存器中,这些全是自动的,而又因为32M的NAND只需要3个周期寻址,所以这里只向地址寄存器发3个周期的命令就可以了。

      rNFADDR = i & 0xff;

      rNFADDR = (i >> 9) & 0xff;//(左移9位,不是8位)

      rNFADDR = (i >> 17) & 0xff; //(左移17位,不是16位)

表3-4-2列出了在地址操作的3个步骤对应的NAND内部地址线,没有A8(它由读命令设置,当读命令为0时,A8=0;当读命令为1时,A8=1),所以在第二,第三次向rNFADDR寄存器发送地址时,需要再多移一位,而不是原来的8和16。

 

     for(j=0; j < 512; j++, i++)

      {

            rNFDATA =(*buf )& 0xff;//向NAND写入数据,将数据写入到指定的数据写入位置,当使用NFDATA寄存器时,控制NAND的CLE和ALE都会自动1。而buf指针是外面传进来的地址,在下面的函数调用会用到,每写一次NFDATA寄存器,控制NAND的WE都会由低电平向高电平转变。而NANDFLASH的数据每写一次,都会指向下一个内部的地址,而一个数据区由512bytes组成,当继续写下去的时候,将写到16bytes的ECC区,所以每对完512个字节后,要对nand的地址重新定位。

            buf++;//写入地址位置+1

      }

            rNFCMD(0x10);//写入确认命令,由表3-4-5所得,在512个字节写完后,需要确认。这种设计可以防止误操作而影响了内部数据区

wait_idle();//由时序图得到,等待512字节输入完成。

rNFCMD(0x70);//读取NAND状态寄存器的内容

if(rNFDATA&0x1==0x1)

return 1;//读取状态寄存器,判读写入是否成功,由图3-4-4所得,读出的数据0位为1时,写入失败。

    }

 

    //关芯片使能,防止误操作对NAND中的数据修改

    rNFCONF |= 0x800;

    return 0;//返回0,表示写入成功

}

4、擦NAND内容

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

* 名称:             nand_erase

* 功能:             擦除nandflash上一块内容到指定

* 输入:             unsigned long start_addr: 要擦除的数据在Nand上的首地址

                      int size:              擦除长度

* 返回:             0           

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

 

static int nand_ erase (unsigned long start_addr, int size)

{

    int i, j;//i用于记录当前的,j记录每一页中的byte地址

 

    /* NAND使能 */

    rNFCONF &= ~0x800;使能//NANDFLASH

    for(i=0; i<10; i++);//等待10个周期

 

图6:NAND擦除时序图

以下部分按照图6时序图而写

    for(i=start_addr; i < (start_addr + size);)

    {

            rNFCMD=0x60;//擦除命令

rNFADDR = (i >> 9) & 0xff;//(左移9位,不是8位)

      rNFADDR = (i >> 17) & 0xff; //(左移17位,不是16位)

            NFCMD=0xD0;//确认擦除命令

            i+=512*32;//擦除一块的长度为512字节的页,此种页32页组成一块

       wait_idle();//由时序图得到,等待1块内容被擦除完成。

rNFCMD(0x70);//读取NAND状态寄存器的内容

if(rNFDATA&0x1==0x1)

returen 1;//如果失败,则返回1

 

}

//关芯片使能,防止误操作对NAND中的数据修改

    rNFCONF |= 0x800;

    return 0;//返回0,表示擦除成功

}

以上4次情况可以基本完成对NAND的操作,但是这里要注意的是,在linux写入和读出时,必须是出NAND中的每一页的第0个字节读取,而不能随便从其中间的位置读取,而这一部分是MTD中有明确的方法,这里不作进一步分析了。


关键字:Nandflash  S3C2410 引用地址:Nandflash 驱动深度分析(基于S3C2410)

上一篇:S3C2410 TFT LCD显示原理分析
下一篇:Linux-2.6.12移植到斯道s3c2410

推荐阅读最新更新时间:2024-03-16 15:22

零死角玩转2440下NandFlash拷贝并跳转到SDRAM的(启动过程)
先上张图: 第一步:当S3C2440被配置成从Nand Flash启动时, S3C2440的Nand Flash控制器会在 S3C2440上电时自动把NandFlash上的前4K代码搬移到Boot Internal SRAM,然后系统从起始地址是0x0000_0000的Boot Internal SRAM启动,在这4K代码中我们必须完成CPU的核心配置,把NandFlash上的代码全部拷贝到SDRAM中去,然后跳转到SDRAM中去执行剩余的代码(进入操作系统等等); 第1步: 这一步主要完成的是把NandFlash上的代码拷贝到SDRAM的过程: (1)先判断是从nor启动还是从nand启动 ldr
[单片机]
零死角玩转2440下<font color='red'>NandFlash</font>拷贝并跳转到SDRAM的(启动过程)
基于S3C2410嵌入式设备的U-Boo移植及自启动的实现
  S3C2410是三星公司针对嵌入式系统推出的高性价比 微处理器 ,它是基于ARM9TDMI内核的16/32位RISC处理器,工作主频为200M Hz 。由于现有的Linux系统引入了设备文件的概念,读写串口可以像读写普通文件一样进行操作,非常方便。   一、Linux系统的安装   安装过程首先出现欢迎对话框,如上图所示。Red Hat先后会询问用户使用何种语言、用户使用的键盘类型(默认选项为美式键盘)以及安装软件的位置(选择本地CD -ROM)等许多需用户选择的问题。   使用Disk Druid建立Linux文件系统然后通过PC机对开发板进行设置,并执行以下命令,从而对开发板进行内核及文件系统的烧写工作:
[单片机]
基于<font color='red'>S3C2410</font>嵌入式设备的U-Boo移植及自启动的实现
基于S3C2410的IP电话设计
  IP电话的发展已经历了三代。第三代IP电话是Internet普及的产物,目前,以太网接口直接入户已经越来越普遍,有必要开发一种带有RJ-45以太网接口、直接连入Internet、使用更加方便的IP电话。用户在打电话时,可以直接拨叫远端的电话号码,通过网闸把所拨的电话号码转换成远端IP电话的IP地址,从而建立起通话连接。与第二代IP电话终端不同的是,第三代IP电话终端直接把输入语音信号数字化,并按照一定的语音压缩编码标准算法(如G.728,G.729等)完成对输入语音信号的实时压缩,使带宽从64kbps降低到8kbps甚至8kbps以下,大大提高了信道的利用率,IP电话终端遵循SIP(或者H.323)协议。第三代IP电话系统通过网
[单片机]
基于<font color='red'>S3C2410</font>的IP电话设计
S3C2410与指纹传感器MBF200的SPI通信
  引 言   随着网络技术和通信技术的发展,传统的身份认证技术对于信息安全表现得越来越有些力不从心了。由于人的身体特征具有唯一性和稳定性,人们开始把目光转向了生物识别技术,如指纹、虹膜、DNA、掌形识别等。在众多的特征识别中,指纹采集设备由于具有体积小、功耗低、稳定性好、误判概率低等优点,而受到人们的青睐。指纹传感器是指纹采集设备中的核心器件,在此选用富士通公司的MBF200。它是一款先进的固态指纹传感器芯片,具有性能高、功耗低、成本低、接口方便等特点。这使得在嵌入式系统中实现数据的传输更加方便。S3C2410是三星公司推出的ARM920T核微处理器,主要面向手持设备以及高性价比、低功耗的应用,且在片上集成了丰富的组件,有利于其扩
[单片机]
<font color='red'>S3C2410</font>与指纹传感器MBF200的SPI通信
LCD深度剖析
LCD背景知识: TFT(Thin Film Transistor)即薄膜场效应晶体管 1. LCD工作的硬件需求: 要使一块LCD正常的显示文字或图像,不仅需要LCD驱动器,而且还需要相应的LCD控制器。在通常情况下,生产厂商把LCD驱动器会以COF/COG的形式与LCD玻璃基板制作在一起,而LCD控制器则是由外部的电路来实现,现在很多的MCU内部都集成了LCD控制器,如S3C2410/2440等。通过LCD控制器就可以产生LCD驱动器所需要的控制信号来控制STN/TFT屏了。也就说,LCD控制驱动器一般都是由厂家做好的,我们只需要商家提供我们VBPD,VFPD,VSPW,HBPD,HFPD,HSPW,这些参数即可。
[单片机]
LCD深度剖析
S3C2410中文芯片手册-11.串口
S3C2410x 提供3个独立的异步串行I/O接口,每一个都可以工作在中断或是 DMA 模式。UART 最高可以支持230. 4K bps波特率,通过使用系统时钟。如果有外部设备给 UART 提供 UCLK, 那么 UART 可以达到更高的速度。每个 UART 通道包含2个16个字节的 FIFO 用于接收和发送数据。 S3C2410 的 UART 包括 可编程波特率,infra-red 发送/接收, 1~2个停止位, 5~8位数据位和奇偶校验。 每个 UART 由波特率发生器、发送器、接收器和控制单元组成,如图11-1所示。波特率发生器可以由 PCLK 或是 UCLK 提供时钟。数据发送器和接收器包含16字节的 FIF
[单片机]
<font color='red'>S3C2410</font>中文芯片手册-11.串口
嵌入式Linux视频采集系统的设计与实现
  1 引言   多媒体通信技术的发展为信息的获取和传输提供了丰富的手段,视频采集是其中不可缺少的重要组成部分。视频采集的手段多种多样,随着人们对降低系统成本和提高可靠性的迫切需求,基于嵌入式的视频采集系统成为新的研发热点。本方案以S3C2410 微控制器作为硬件平台,通过移植具有实现硬件功能的Linux 操作系统,实现了对视频数据的实时采集和存储。   2 系统构成   系统平台采用三星公司的处理器S3C2410,该处理器内部集成了ARM920T 处理器核,为32 位微控制器,带独立的16KB 指令Cache 和16KB 数据Cache,LCD 控制器,RAM 控制器,NAND Flash 控制器,并行I/O 口,8 路1
[单片机]
嵌入式Linux视频采集系统的设计与实现
基于ARM与电力线载波技术的广场照明系统设计
O 引言 目前大空间的广场或教室等场所的照明系统绝大部分都采用完全照明的方式,即使只有某个部分区域有人活动也会开放全部的照明设备,从而造成了巨大的电能浪费。因此设计了基于ARM9和电力线载波通信技术相结合的控制系统,能够实时检测大空间中各区域人员活动情况,并根据控制指令以及事先设好的算法控制相应区域的照明设备点亮及照明时间,并能够对控制信息、照明情况进行记录,便于管理与查询。这样在人员较少的时候,大空间中只有局部区域照明设备点亮,从而实现大幅度节约电能。 1 硬件组成及原理 为了更好地实现控制与节能,将广场照明系统分为若干个区域,每个区域都由一个单片机从机系统负责单独控制。广场分区照明系统总体结构如图1所示,整个系
[单片机]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
随便看看
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved