nandflash时序
- 格式:docx
- 大小:67.40 KB
- 文档页数:5
这篇文章不是介绍nand flash的物理结构和关于nand flash的一些基本知识的。
你需要至少了解你手上的nand flash的物理结构和一些诸如读写命令操作的大概印象,你至少也需要看过s3c2440中关于nand flash控制寄存器的说明。
由于本人也没有专门学过这方面的知识,下面的介绍也是经验之谈。
这里我用的K9F2G08-SCB0 这款nand flash 来介绍时序图的阅读。
不同的芯片操作时序可能不同,读的命令也会有一些差别。
当然其实有时候像nand flash这种s3c2440内部集成了他的控制器的外设。
具体到读写操作的细节时序(比如CLE/ALE的建立时间,写脉冲的宽度。
数据的建立和保持时间等),不明白前期也没有多大的问题。
因为s3c2440内部的nand flash控制器做了大部分的工作,你需要做的基本就是设置几个时间参数而已。
然后nand flash会自动进行这些细节操作。
当然如果处理器上没有集成nand flash的控制器那么久必须要自己来写时序操作了。
所以了解最底层的时序操作总是好的但是上层一点的,比如读写操作的步骤时序(比如读操作,你要片选使能,然后发命令,然后发地址,需要的话还需发一个命令,然后需要等待操作完成,然后再读书数据)。
是必须要明白的。
这都不明白的话,怎么进行器件的操作呢也就是说s3c2440 可以说在你设置很少的几个时间参数后,将每一个步骤中细微的操作都替你做好了。
(比如写命令,你只要写个命令到相应寄存器中,cpu内部就会协各个引脚发出适应的信号来实现写命令的操作)。
而我们所需要做的就是把这些写命令,写地址,等待操作完成。
等步骤组合起来。
从而完成一个读操作就像上面说的,虽然我们不会需要去编写每个步骤中的最细微的时序。
但是了解下。
会让你对每个操作步骤的底层细节更加明了先来看一个命令锁存的时序。
也就是上面说的读nand flash操作中不是有一个写命令步骤吗。
nandflash的原理及运行时序NAND Flash(非与非闪存)是一种主要用于存储数据的闪存类型,广泛应用于各种存储设备中,如固态硬盘(SSD)、USB闪存驱动器(U盘)以及移动设备中的存储卡等。
NAND Flash的原理:NAND Flash中的基本存储单元是晶体管,每个晶体管可以存储一个或多个bit的数据,通过对晶体管的电荷状态进行读取和写入来实现数据的存储和读取。
NAND Flash的存储单元结构主要有两种类型:单栅结构和多栅结构。
单栅结构中每个晶体管只有一个控制栅(Control Gate)和一个栅介电层(Oxide Layer),而多栅结构中每个晶体管有一个控制栅和多个叠加的栅介电层。
NAND Flash的存储单元编址是按行和列进行的。
每一行包含一个选择门(Word Line),每一列包含一个位线(Bit Line)。
数据的读取和写入都是通过对选择门和位线的控制来实现的。
NAND Flash的运行时序:1.写入时序:(1)输入地址:将要写入的存储单元的地址输入到NAND Flash中。
(2)擦除块的选择:选择需要写入数据的块进行擦除。
(3)擦除块的擦除:对选择的块进行擦除操作,将存储单元中的数据清除。
(4)写入数据:将要写入的数据输入到NAND Flash中。
(5)写入选择门:通过选择门将输入的数据写入到相应的存储单元中。
2.读取时序:(1)输入地址:将要读取的存储单元的地址输入到NAND Flash中。
(2)读取选择门:通过选择门将存储单元中的数据读出。
(3)读取数据:将读取的数据输出。
需要注意的是,NAND Flash的擦除操作是以块为单位进行的,而写入操作是以页为单位进行的。
擦除块的大小通常为64KB或128KB,一页的大小通常为2KB或4KB。
此外,NAND Flash还包含了一些管理区域,用于存储元数据和管理信息。
总结:NAND Flash是一种基于晶体管的闪存类型,通过对晶体管的电荷状态进行读取和写入来实现数据的存储和读取。
怎么看时序图--nand flash的读操作详解 2013-11-16 10:25:36分类:嵌入式这篇文章不是介绍 nand flash的物理结构和关于nand flash的一些基本知识的。
你需要至少了解你手上的 nand flash的物理结构和一些诸如读写命令操作的大概印象,你至少也需要看过 s3c2440中关于nand flash控制寄存器的说明。
由于本人也没有专门学过这方面的知识,下面的介绍也是经验之谈。
这里我用的 K9F2G08-SCB0 这款nand flash 来介绍时序图的阅读。
不同的芯片操作时序可能不同,读的命令也会有一些差别。
当然其实有时候像nand flash这种 s3c2440内部集成了他的控制器的外设。
具体到读写操作的细节时序(比如 CLE/ALE的建立时间,写脉冲的宽度。
数据的建立和保持时间等),不明白前期也没有多大的问题。
因为s3c2440内部的nand flash控制器做了大部分的工作,你需要做的基本就是设置几个时间参数而已。
然后nand flash会自动进行这些细节操作。
当然如果处理器上没有集成 nand flash的控制器那么久必须要自己来写时序操作了。
所以了解最底层的时序操作总是好的但是上层一点的,比如读写操作的步骤时序(比如读操作,你要片选使能,然后发命令,然后发地址,需要的话还需发一个命令,然后需要等待操作完成,然后再读书数据)。
是必须要明白的。
这都不明白的话,怎么进行器件的操作呢也就是说 s3c2440 可以说在你设置很少的几个时间参数后,将每一个步骤中细微的操作都替你做好了。
(比如写命令,你只要写个命令到相应寄存器中,cpu内部就会协各个引脚发出适应的信号来实现写命令的操作)。
而我们所需要做的就是把这些写命令,写地址,等待操作完成。
等步骤组合起来。
从而完成一个读操作就像上面说的,虽然我们不会需要去编写每个步骤中的最细微的时序。
但是了解下。
会让你对每个操作步骤的底层细节更加明了先来看一个命令锁存的时序。
NADN FLASH时序详解怎么看时序图--nand flash的读操作详解这篇文章不是介绍 nand flash的物理结构和关于nand flash的一些基本知识的。
你需要至少了解你手上的 nand flash的物理结构和一些诸如读写命令操作的大概印象,你至少也需要看过 s3c2440中关于nand flash控制寄存器的说明。
由于本人也没有专门学过这方面的知识,下面的介绍也是经验之谈。
这里我用的 K9F2G08-SCB0 这款nand flash 来介绍时序图的阅读。
不同的芯片操作时序可能不同,读的命令也会有一些差别。
当然其实有时候像nand flash这种 s3c2440内部集成了他的控制器的外设。
具体到读写操作的细节时序(比如 CLE/ALE的建立时间,写脉冲的宽度。
数据的建立和保持时间等),不明白前期也没有多大的问题。
因为s3c2440内部的nand flash控制器做了大部分的工作,你需要做的基本就是设置几个时间参数而已。
然后nand flash会自动进行这些细节操作。
当然如果处理器上没有集成 nand flash的控制器那么久必须要自己来写时序操作了。
所以了解最底层的时序操作总是好的但是上层一点的,比如读写操作的步骤时序(比如读操作,你要片选使能,然后发命令,然后发地址,需要的话还需发一个命令,然后需要等待操作完成,然后再读书数据)。
是必须要明白的。
这都不明白的话,怎么进行器件的操作呢也就是说 s3c2440 可以说在你设置很少的几个时间参数后,将每一个步骤中细微的操作都替你做好了。
(比如写命令,你只要写个命令到相应寄存器中,cpu内部就会协各个引脚发出适应的信号来实现写命令的操作)。
而我们所需要做的就是把这些写命令,写地址,等待操作完成。
等步骤组合起来。
从而完成一个读操作就像上面说的,虽然我们不会需要去编写每个步骤中的最细微的时序。
但是了解下。
会让你对每个操作步骤的底层细节更加明了先来看一个命令锁存的时序。
Nand flash芯片工作原理------------------------------------Nand flash芯片型号为Samsung K9F1208U0B,数据存储容量为64MB,采用块页式存储管理。
8个I/O引脚充当数据、地址、命令的复用端口。
芯片内部存储布局及存储操作特点:一片Nand flash为一个设备(device), 其数据存储分层为:1 (Device) = 4096 (Blocks)1 (Block) -= 32 (Pages/Rows) 页与行是相同的意思,叫法不一样1 (Page) = 528 (Bytes) = 数据块大小(512Bytes) + OOB 块大小(16Bytes)在每一页中,最后16个字节(又称OOB)用于Nand Flash命令执行完后设置状态用,剩余512个字节又分为前半部分和后半部分。
可以通过Nand Flash命令00h/01h/50h分别对前半部、后半部、OOB进行定位通过Nand Flash内置的指针指向各自的首地址。
存储操作特点:1. 擦除操作的最小单位是块。
2. Nand Flash芯片每一位(bit)只能从1变为0,而不能从0变为1,所以在对其进行写入操作之前要一定将相应块擦除(擦除即是将相应块得位全部变为1).3. OOB部分的第六字节(即517字节)标志是否是坏块,如果不是坏块该值为FF,否则为坏块。
(转载注:应该是每块的第一页的第六个字节。
)4. 除OOB第六字节外,通常至少把OOB的前3个字节存放Nand Flash硬件ECC码NAND FLASH的工作原理- to beginner2007-04-23 23:43NAND FLASH 是一种大容量、高速的存储技术。
其接口较为简单,如果没有专门的nand flash控制器,甚至可以用io口与之对接。
其编程也相对简单,只要了解如下关键概念就可以:1.nand flash内部有管理单元,管理单元负责对nand flash的实际单元的操作。
怎么看时序图--nand flash的读操作详解 2013-11-16 10:25:36分类:嵌入式这篇文章不是介绍 nand flash的物理结构和关于nand flash的一些基本知识的。
你需要至少了解你手上的 nand flash的物理结构和一些诸如读写命令操作的大概印象,你至少也需要看过 s3c2440中关于nand flash控制寄存器的说明。
由于本人也没有专门学过这方面的知识,下面的介绍也是经验之谈。
这里我用的 K9F2G08-SCB0 这款nand flash 来介绍时序图的阅读。
不同的芯片操作时序可能不同,读的命令也会有一些差别。
当然其实有时候像nand flash这种 s3c2440内部集成了他的控制器的外设。
具体到读写操作的细节时序(比如 CLE/ALE的建立时间,写脉冲的宽度。
数据的建立和保持时间等),不明白前期也没有多大的问题。
因为s3c2440内部的nand flash控制器做了大部分的工作,你需要做的基本就是设置几个时间参数而已。
然后nand flash会自动进行这些细节操作。
当然如果处理器上没有集成 nand flash的控制器那么久必须要自己来写时序操作了。
所以了解最底层的时序操作总是好的但是上层一点的,比如读写操作的步骤时序(比如读操作,你要片选使能,然后发命令,然后发地址,需要的话还需发一个命令,然后需要等待操作完成,然后再读书数据)。
是必须要明白的。
这都不明白的话,怎么进行器件的操作呢也就是说 s3c2440 可以说在你设置很少的几个时间参数后,将每一个步骤中细微的操作都替你做好了。
(比如写命令,你只要写个命令到相应寄存器中,cpu内部就会协各个引脚发出适应的信号来实现写命令的操作)。
而我们所需要做的就是把这些写命令,写地址,等待操作完成。
等步骤组合起来。
从而完成一个读操作就像上面说的,虽然我们不会需要去编写每个步骤中的最细微的时序。
但是了解下。
会让你对每个操作步骤的底层细节更加明了先来看一个命令锁存的时序。
NandFlash驱动(实现初始化以及读操作)本节来学习裸机下的Nand Flash驱动,本节学完后,再来学习Linux下如何使⽤Nand Flash驱动Linux中的Nand Flash驱动,链接如下:(只需要初始化Flash以及读Flash)打开2440芯⽚⼿册,K9F2G08U0M芯⽚⼿册(因为2440中Nand Flash是⽤的256MB(2Gb)内存,8个数据引脚)在芯⽚⼿册中得到K9F2G08U0M=2048块Block=128K页Pages=256MB=2Gb1个设备=2048块Block1块Block=64页Pages1页=(2K+64)B (因为每个地址⾥都存放了⼀个字节,所以⽤B表⽰)其中64B是存放ECC的OOB地址,(ECC:存放判断位反转的校验码)Nand Flash 缺点:读数据容易位反转可以通过ECC编码器值来判断读数据是否位反转,若位反转则重新读数据写过程:1)写页数据2)然后⽣成ECC3)将ECC写⼊到OBB页地址⾥(写数据是不会出现位反转)读过程:1)读出页数据,然后⽣成临时ECC(此时ECC可能有错)2)然后读出OOB页地址⾥的ECC3)⽐较两个ECC,判断是否出现位反转读OOB⽅法:读整个Nand Flash时,是读不出页⾥⾯的OBB地址,⽐如读2049这个地址数据时,是读的第⼆页上的第2个地址:只有读某⼀页时,才能读出这个页⾥⾯的OOB地址, ⽐如读第0页的2049这个地址数据时,才是读的第0页OOB的第2个地址:Nand Flash芯⽚硬件引脚图:RnB:就绪(ready)/忙(busy)输出信号,需要采⽤上拉电阻(1:表⽰写⼊数据成功,0:表⽰正在写⼊)CLE:命令(command)锁存(latch)使能,(1:表⽰当前传的是命令值)ALE:地址锁存使能,(1:表⽰当前传的是地址值,当CLE=0和ALE=0,表⽰传的是数据)nCE:芯⽚使能(低电平使能) (n:表⽰低电平有效)nWE:写使能 ,⽐如写命令时,当CLE=1,ALE=0时,当nWE来个上升沿,则会将IO数据写⼊flash中nRE:读使能,和we类似nWP:写保护(protect) (1:不保护,0:只能读不能写),默认接⾼电平.1.编写nand_init()函数1.1设置通信时序图1(nandflash时序表):图2(nandflash时序图):通过图2和图1可以看出:tCS是等待芯⽚使能CE的时间, tCS=20nStCLS和tALS是等待WE(写信号)结束的时间, tCLS=tALS=15nStWP是WE(写信号)维持时间, tWP=15nStALH是等待命令写⼊成功的时间, tALH=5nStCLH是等待地址写⼊成功的时间, tCLH=5nS图3(2440-nandflash时序图):⾸先查看2440芯⽚⼿册⾥nandflash时序图,如上图,可以看出需要设置TACLS,TWRPH0和TWRPH1,这三个参数TACLS:属于等待WE(写信号)就绪的时间,对⽐图2得出TACLS= tCLS- tWP=0nSTWRPH0:属于WE(写信号)的时间, 对⽐图2得出TWRPH0= tWP=15nSTWRPH1:属于等待命令写⼊成功的时间,对⽐图2得出TWRPH1=tALH=tCLH=5nS最后,在NFCONF寄存器中设置这三个参数TACLS[13:12]表⽰Duration(持续时间)=HCLK*TACLS,由于Duration=0nS,所以TACLS=0TWRPH0 [10:8]表⽰Duration(持续时间)=HCLK*( TWRPH0+1),由于Duration=15nS,HCLK=10nS(100Mhz),所以TWRPH0 =1. TWRPH1 [6:4]表⽰Duration(持续时间)= HCLK*( TWRPH1 +1),由于Duration=5nS,HCLK=10nS(100Mhz),所以TWRPH1 =0 1.2然后定义全局变量,并实现nand_init()初始化:/* nand flash 时序 */#define TACLS 0#define TWRPH0 1#define TWRPH1 0/* nand flash 寄存器 */#define NFCONF *((unsigend int *)0X4E000000); //配置寄存器(⽤来设置时序)#define NFCONT *((unsigend int *)0X4E000000); //控制寄存器(⽤来使能nandflash控制器以及ECC编码器,还有控制芯⽚使能CE脚)#define NFCMMD *((unsigend char *)0X4E000000);//发送命令寄存器(命令只有8位)#define NFADDR *((unsigend char *)0X4E000000);//发送地址寄存器(地址只有8位)#define NFDATA *((unsigend int *)0X4E000000);//读/写数据寄存器(数据只有8位)#define NFSTAT *((unsigend int *)0X4E000000);//运⾏状态寄存器(⽤于判断RnB脚)/*因为Nand Flash只有8位I/O脚,所以NFCMMD/ NFADDR/ NFDATA三个寄存器值都是unsigend char型 */1.3 nand_init()函数初始化void nand_init(void){/* 设置时序 */NFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4);/* bit4=1:初始化ECC, bit1=1:禁⽌⽚选 bit0=1:启动nandflash控制器*/NFCONT = (1<<4)|(1<<1)|(1<<0);}2编写nand_read()函数2.1编写nand_read()函数需要以下⼏个⼦函数:2.1.1⽚选使能函数(在读写FLASH之前都要选中⽚选)nand_select() //使能⽚选{int i;NFCONT&=~(1<<1); // NFCONT控制器位1置0for(i=0;i<10;i++); //等待芯⽚使能成功}2.1.2取消⽚选函数(退出读写FLASH时需要取消⽚选)nand_deselect() //取消⽚选{int i;NFCONT&=~(1<<1); // NFCONT控制器位1置0for(i=0;i<10;i++); //等待芯⽚使能成功}2.1.3读命令函数nand_cmd(unsigned char cmd){int i;NFCMMD= cmd; // 向NFCMMD寄存器写⼊命令for(i=0;i<10;i++); //等待写⼊命令成功}2.1.4判断RnB状态函数(在写⼊所有命令后都要判断RnB脚是否为⾼电平就绪)nand_waite_idle(){int i;while(!(NFSTAT&0X01)) // 等待NFSTAT寄存器位0置1for(i=0;i<10;i++);}2.1.5读数据函数nand_read_data(){unsigend char p=NFDATA; //读取NFDATA寄存器return p; //返回}2.1.6 编写写⼊地址函数(分5个周期)⾸先Nand Flash引脚只有8位,然⽽地址共有2048(块)*64(页)*2KB,为了读出多个地址,如下图,所以需要分5个周期来实现发送地址如上图,其中 A10~A0对应页⼤⼩(列),由于nandflash每页2048B,所以只⽤到A10~A0 A28~A11对应页⽬录(⾏),表⽰共有2048块*64(每块有64页)个⽬录例如,4097 地址就是:A10~A0=4097%2048= 1(A0=1,其余为0)A28~A11=4097/2048=2(A13=1,其余为0)所以nand_write_nand()函数如下:void nand_read_addr(unsigned int addr){unsigned int col = addr % 2048;unsigned int page = addr / 2048;volatile int i;NFADDR=(col>>0)&0xff; //A7~A0,第1周期for(i=0;i<10;i++);NFADDR=(col>>8)&0x0f; //A10~A8,第2周期for(i=0;i<10;i++);NFADDR=(page>>0)&0xff; //A18~A11,第3周期for(i=0;i<10;i++);NFADDR=(page>>8)&0xff; //A26~A19,第4周期for(i=0;i<10;i++);NFADDR=(page>>16)&0xff; //A27~A28,第5周期for(i=0;i<10;i++);}2.2Nand Flash命令图:如上图,例如:当要reset复位nand flash时1) 使能⽚选nand_select();2) 发送0XFF复位命令nand_cmd(0xFF);3) 等待RnB状态是否就绪 nand_wait_idle();4) 取消⽚选 nand_deselect();2.3Nand Flash读数据时序图:从上图可以看出nand flash 读数据分为了以下⼏个步骤:(1) 使能⽚选CE,将CLE置1,等待发送命令(2) 将WE置低,将IO置为0X00,然后拉⾼WE,触发⼀次上升沿,则将把0x00写⼊flash中(3) 将CLE置0,表⽰发送地址(分为5个周期)(4) 发送读命令0X30(5) 等待RnB信号为⾼电平(6) 读数据(在同⼀页⾥,数据可以连续读,读下⼀页时,需要重新发送新的地址才⾏例如:读1000地址到2050地址时,1.发出1000地址,到达页0的1000地址上,然后再连续读(2048-1000)次,直到读到页0的2047处.2.再发出2048地址,到达页1的0地址上,然后连续读(2051-2048)次,直到读到2050为⽌)(7) 取消⽚选nCE2.4 所以nand_read()函数如下:void nand_read(unsigned int src,unsigned char *dest,unsigned int len)/* src:源地址,为32位地址,所以⽤unsigend int表⽰*dest:⽬的地址内容,由于这⾥是将数据读出到⽬的地址内容中,所以需要⽤到*指针,因为每个地址⾥存的是⼀个字节,所以⽤unsigend char 型 */ {int col=src%2048; //第⼀次读,可能不是读的页⾸地址,所以需要记录当前页的位置int i=0; //当前读了0次nand_select(); //1使能⽚选nCEwhile(i<len){ nand_cmd(0X00); //2发送读命令0X00nand_write_addr(src); // 3发送yuan地址(分为5个周期)nand_cmd(0X30); //4发送读命令0X30nand_wait_idle(); //5等待RnB信号为⾼电平for(;(col<2048)&&(i<len);col++) //连续读页内数据{dest[i]=nand_read_data(); //6.读数据i++;src++;}col=0;}nand_deselect(); // 取消⽚选nCE }。
三星K9F1G08U0E(128MB,NANDFLASH)STM32平台驱动程序(模拟时序)STM32平台下模拟时序驱动K9F1G08U0E,主要⽬的为了解、学习NAND FLASH的功能特性,没有使⽤STM32的FSMC(⽕龙开发板硬件为模拟时序驱动),纯粹⾃娱⾃乐,如对你有帮助,不胜荣幸,呵呵。
C⽂件内容:1 #include "NAND512W3A2C.h"2/*3作者:毕⼩乐4⽇期:2019.01.245版本:V1.0067驱动代码针对K9F1G08U0E时序⽽写,K9F1G08U0E与NAND512W3A2C,Pin to Pin兼容。
8驱动运⾏平台STM32F103。
9驱动实现功能:101)Page Read112) Page Program123) Block Erase134) Read Status145) Read ID15PE0~PE7 -> DB00~DB0716PD6 -> CL17PD5 -> AL18PD14 -> W19PD15 -> R20PD7 -> CS21PB5 -> R/B22*/23static void NAND512_Delay_uS(int tick)24 {25int i;26while(tick>0)27 {28 tick--;29for(i=0;i<10;i++)30 __nop();31 }32 }33void NAND512_DB_OutPut(void)34 {35 GPIO_InitTypeDef GPIO_InitStructure;3637 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_338 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;39 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;40 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;41 GPIO_Init(GPIOE, &GPIO_InitStructure);42 }43void NAND512_DB_InPut(void)44 {45 GPIO_InitTypeDef GPIO_InitStructure;4647 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_348 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;49 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;50 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;51 GPIO_Init(GPIOE, &GPIO_InitStructure);52 }53char NAND512_DB_Read(void)54 {55char dat;56 NAND512_DB_InPut();57 __nop();58 dat = GPIO_ReadInputData(GPIOE) & 0x00FF;59return dat;60 }61void NAND512_DB_Write(char Data)62 {63 u16 temp;64 NAND512_DB_OutPut();65// __nop();71void NAND512_IO_Init(void)72 {73 GPIO_InitTypeDef GPIO_InitStructure;7475 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOD76 | RCC_APB2Periph_GPIOE, ENABLE);7778/*CL*/79 GPIO_InitStructure.GPIO_Pin = NAND512_CL_PIN;80 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;81 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;82 GPIO_Init(NAND512_CL_PORT, &GPIO_InitStructure);8384/*AL*/85 GPIO_InitStructure.GPIO_Pin = NAND512_AL_PIN;86 GPIO_Init(NAND512_AL_PORT, &GPIO_InitStructure);8788/*W*/89 GPIO_InitStructure.GPIO_Pin = NAND512_W_PIN;90 GPIO_Init(NAND512_W_PORT, &GPIO_InitStructure);9192/*R*/93 GPIO_InitStructure.GPIO_Pin = NAND512_R_PIN;94 GPIO_Init(NAND512_R_PORT, &GPIO_InitStructure);9596/*CE*/97 GPIO_InitStructure.GPIO_Pin = NAND512_CE_PIN;98 GPIO_Init(NAND512_CE_PORT, &GPIO_InitStructure);99100/*R/B*/101 GPIO_InitStructure.GPIO_Pin = NAND512_RB_PIN;102 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;103 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;104 GPIO_Init(NAND512_RB_PORT, &GPIO_InitStructure);105106 NAND512_CL_LOW;107 NAND512_AL_LOW;108 NAND512_R_HIGH;109 NAND512_W_HIGH;110 NAND512_CE_HIGH;111 }112113//读状态寄存器信息114char NAND512_Read_Status(void)115 {116char dat;117118 NAND512_CL_LOW;119 NAND512_W_HIGH;120 NAND512_R_HIGH;121 NAND512_CE_HIGH;122 NOP;123124 NAND512_Delay_uS(5);125 NAND512_CL_HIGH;126 NOP;127 NOP;128 NAND512_CE_LOW;129 NOP;130 NOP;131 NOP;132 NAND512_W_LOW;133 NAND512_DB_Write(0x70);134 NOP;135 NAND512_W_HIGH;136137 NAND512_Delay_uS(5);138 NAND512_CL_LOW;139 NOP;140 NOP;141//CE状态保持不变142143 NAND512_Delay_uS(10);144 NAND512_R_LOW;145 NOP;146 dat = NAND512_DB_Read();147 NAND512_Delay_uS(5);148 NAND512_R_LOW;149 NAND512_Delay_uS(5);155156void NAND512_Read_ID(char* Buf)157 {158char i = 0;159160 NAND512_CL_LOW;161 NAND512_AL_LOW;162 NAND512_R_HIGH;163 NAND512_W_HIGH;164 NAND512_CE_HIGH;165 NAND512_Delay_uS(5);166167 NAND512_CL_HIGH;168 NAND512_W_LOW;169 NAND512_Delay_uS(5);170 NAND512_CE_LOW;171 NAND512_DB_Write(0x90);172 NAND512_Delay_uS(5);173 NAND512_W_HIGH;174 NAND512_Delay_uS(5);175176 NAND512_CL_LOW;177 NAND512_Delay_uS(20);178 NAND512_AL_HIGH;179 NAND512_Delay_uS(20);180 NAND512_W_LOW;181 NAND512_DB_Write(0x00); //写地址0182 NAND512_Delay_uS(5);183 NAND512_W_HIGH;184 NAND512_Delay_uS(10);185 NAND512_AL_LOW;186 NAND512_Delay_uS(20);187188for(i=0;i<5;i++)189 {190 NAND512_R_LOW;191 NAND512_Delay_uS(10);192 Buf[i] = NAND512_DB_Read();193 NAND512_R_HIGH;194 NAND512_Delay_uS(10);195 }196197return ;198 }199200void NAND512_Page_Read(char* Buf,int Len,int Add)201 {202int Bank_Index,Page_Index,Page_Start_Add;203int Add_New,j;204char i;205206 Bank_Index = Add / BANK_SIZE;207 Page_Index = (Add % BANK_SIZE) / PAGE_SIZE;208 Page_Start_Add = Add % PAGE_SIZE;209 Add_New = (((Bank_Index<<6) | Page_Index)<<16) | Page_Start_Add; 210211 NAND512_CL_LOW;212 NAND512_AL_LOW;213 NAND512_W_HIGH;214 NAND512_R_HIGH;215 NAND512_CE_HIGH;216 NAND512_Delay_uS(10);217218 NAND512_CE_LOW;219 NAND512_Delay_uS(5);220 NAND512_CL_HIGH;221 NAND512_W_LOW;222 NAND512_DB_Write(0x00);223 NAND512_Delay_uS(5);224 NAND512_W_HIGH;225 NAND512_Delay_uS(5);226 NAND512_CL_LOW;227 NAND512_Delay_uS(5);228 NAND512_AL_HIGH;229 NAND512_Delay_uS(5);230231//发送地址232for(i=0;i<4;i++)233 {239 NAND512_Delay_uS(10);240 }241 NAND512_AL_LOW;242 NAND512_Delay_uS(5);243 NAND512_CL_HIGH;244 NAND512_Delay_uS(5);245 NAND512_W_LOW;246 NAND512_Delay_uS(5);247 NAND512_DB_Write(0x30);248 NAND512_Delay_uS(5);249 NAND512_W_HIGH;250 NAND512_Delay_uS(5);251 NAND512_CL_LOW;252 NAND512_Delay_uS(5);253254while(NAND512_RB_STATUS == 0);255 NAND512_Delay_uS(5);256257for(j=0;j<Len;j++)258 {259 NAND512_R_LOW;260 NAND512_Delay_uS(5);261 Buf[j] = NAND512_DB_Read();262 NAND512_Delay_uS(5);263 NAND512_R_HIGH;264 NAND512_Delay_uS(10);265 }266267return;268 }269270char NAND512_Page_Write(char* Buf,int Len,int Add)271 {272int Bank_Index,Page_Index,Page_Start_Add;273int Add_New,j;274char i,Status;275276 Bank_Index = Add / BANK_SIZE;277 Page_Index = (Add % BANK_SIZE) / PAGE_SIZE;278 Page_Start_Add = Add % PAGE_SIZE;279 Add_New = (((Bank_Index<<6) | Page_Index)<<16) | Page_Start_Add; 280281 NAND512_CL_LOW;282 NAND512_AL_LOW;283 NAND512_W_HIGH;284 NAND512_R_HIGH;285 NAND512_CE_HIGH;286 NAND512_Delay_uS(10);287288 NAND512_CE_LOW;289 NAND512_Delay_uS(5);290 NAND512_CL_HIGH;291 NAND512_W_LOW;292 NAND512_DB_Write(0x80);293 NAND512_Delay_uS(5);294 NAND512_W_HIGH;295 NAND512_Delay_uS(5);296 NAND512_CL_LOW;297 NAND512_Delay_uS(5);298 NAND512_AL_HIGH;299 NAND512_Delay_uS(5);300301//发送地址302for(i=0;i<4;i++)303 {304 NAND512_W_LOW;305 NAND512_Delay_uS(5);306 NAND512_DB_Write(Add_New>>8*i);307 NAND512_Delay_uS(10);308 NAND512_W_HIGH;309 NAND512_Delay_uS(10);310 }311 NAND512_AL_LOW;312 NAND512_Delay_uS(5);313314for(j=0;j<Len;j++)315 {316 NAND512_W_LOW;317 NAND512_Delay_uS(5);324 NAND512_CL_HIGH;325 NAND512_Delay_uS(5);326 NAND512_W_LOW;327 NAND512_Delay_uS(5);328 NAND512_DB_Write(0x10);329 NAND512_Delay_uS(5);330 NAND512_W_HIGH;331 NAND512_Delay_uS(5);332333while(NAND512_RB_STATUS == 0);334 NAND512_Delay_uS(5);335336 Status = NAND512_Read_Status();337338if((Status & 0x01) == 0)339return1;340else341return0;342 }343344char NAND512_Block_Erase(int Add)345 {346int Bank_Index,Page_Index;347int Add_New;348char i,Status;349350 Bank_Index = Add / BANK_SIZE;351 Page_Index = (Add % BANK_SIZE) / PAGE_SIZE; 352 Add_New = (Bank_Index<<6) | Page_Index;353354 NAND512_CL_LOW;355 NAND512_AL_LOW;356 NAND512_W_HIGH;357 NAND512_R_HIGH;358 NAND512_CE_HIGH;359 NAND512_Delay_uS(10);360361 NAND512_CE_LOW;362 NAND512_Delay_uS(5);363 NAND512_CL_HIGH;364 NAND512_W_LOW;365 NAND512_DB_Write(0x60);366 NAND512_Delay_uS(5);367 NAND512_W_HIGH;368 NAND512_Delay_uS(5);369 NAND512_CL_LOW;370 NAND512_Delay_uS(5);371 NAND512_AL_HIGH;372 NAND512_Delay_uS(5);373374//发送地址375for(i=0;i<2;i++)376 {377 NAND512_W_LOW;378 NAND512_Delay_uS(5);379 NAND512_DB_Write(Add_New>>8*i);380 NAND512_Delay_uS(10);381 NAND512_W_HIGH;382 NAND512_Delay_uS(10);383 }384 NAND512_AL_LOW;385 NAND512_Delay_uS(5);386387 NAND512_CL_HIGH;388 NAND512_Delay_uS(5);389 NAND512_W_LOW;390 NAND512_Delay_uS(5);391 NAND512_DB_Write(0xD0);392 NAND512_Delay_uS(5);393 NAND512_W_HIGH;394 NAND512_Delay_uS(5);395 NAND512_CL_LOW;396 NAND512_Delay_uS(5);397398while(NAND512_RB_STATUS == 0);399 NAND512_Delay_uS(5);400401 Status = NAND512_Read_Status();H⽂件内容:1 #ifndef NAND512W3A2C__H2#define NAND512W3A2C__H34 #include "stm32f10x.h"56#define NAND512_CL_PORT GPIOD7#define NAND512_AL_PORT GPIOD8#define NAND512_W_PORT GPIOD9#define NAND512_R_PORT GPIOD10#define NAND512_CE_PORT GPIOD11#define NAND512_RB_PORT GPIOB12#define NAND512_WP_PORT /*GPIOD*/1314#define NAND512_CL_PIN GPIO_Pin_615#define NAND512_AL_PIN GPIO_Pin_516#define NAND512_W_PIN GPIO_Pin_1417#define NAND512_R_PIN GPIO_Pin_1518#define NAND512_CE_PIN GPIO_Pin_719#define NAND512_RB_PIN GPIO_Pin_520#define NAND512_WP_PIN /*GPIO_Pin_5*/2122#define NAND512_CL_CLK RCC_APB2Periph_GPIOD23#define NAND512_AL_CLK RCC_APB2Periph_GPIOD24#define NAND512_W_CLK RCC_APB2Periph_GPIOD25#define NAND512_R_CLK RCC_APB2Periph_GPIOD26#define NAND512_CE_CLK RCC_APB2Periph_GPIOD27#define NAND512_RB_CLK RCC_APB2Periph_GPIOB28#define NAND512_WP_CLK /*RCC_APB2Periph_GPIOD*/2930#define NAND512_CE_LOW GPIO_ResetBits(NAND512_CE_PORT,NAND512_CE_PIN)31#define NAND512_CE_HIGH GPIO_SetBits(NAND512_CE_PORT,NAND512_CE_PIN)32#define NAND512_CL_LOW GPIO_ResetBits(NAND512_CL_PORT,NAND512_CL_PIN)33#define NAND512_CL_HIGH GPIO_SetBits(NAND512_CL_PORT,NAND512_CL_PIN)34#define NAND512_AL_LOW GPIO_ResetBits(NAND512_AL_PORT,NAND512_AL_PIN)35#define NAND512_AL_HIGH GPIO_SetBits(NAND512_AL_PORT,NAND512_AL_PIN)36#define NAND512_W_LOW GPIO_ResetBits(NAND512_W_PORT,NAND512_W_PIN)37#define NAND512_W_HIGH GPIO_SetBits(NAND512_W_PORT,NAND512_W_PIN)38#define NAND512_R_LOW GPIO_ResetBits(NAND512_R_PORT,NAND512_R_PIN)39#define NAND512_R_HIGH GPIO_SetBits(NAND512_R_PORT,NAND512_R_PIN)4041#define NAND512_RB_STATUS GPIO_ReadInputDataBit(NAND512_RB_PORT,NAND512_RB_PIN) 4243#define NOP __nop()44#define BANK_SIZE 13107245#define PAGE_SIZE 20484647extern void NAND512_IO_Init(void);48extern char NAND512_Read_Status(void);49extern void NAND512_Read_ID(char* Buf);50extern void NAND512_Page_Read(char* Buf,int Len,int Add);51extern char NAND512_Page_Write(char* Buf,int Len,int Add);52extern char NAND512_Block_Erase(int Add);53#endif。
Nandflash启动,norflash启动,SDRAM总结S3C2440的启动时读取的第一条指令是在0x00上,分为成nand flash和nor flash上启动。
nand flash:适合大容量数据存储,类似硬盘;nor flash:适合小容量的程序或数据存储,类似小硬盘;sdram:主要用于程序执行时的程序存储、执行或计算,类似内存。
Nor flash的有自己的地址线和数据线,可以采用类似于memory的随机访问方式,在nor flash上可以直接运行程序,所以nor flash可以直接用来做boot,采用nor flash启动的时候会把地址映射到0x00上。
Nand flash是IO设备,数据、地址、控制线都是共用的,需要软件区控制读取时序,所以不能像nor flash、内存一样随机访问,不能EIP(片上运行),因此不能直接作为boot。
NANDFlash启动: NANDFlash控制器自动把nandflash存储器的前4K载到Steppingstone (内部SRAM缓冲器),并把0x00000000S设置为内部SRAM的起始地址,cpu从内部SRAM的0x00000000开始启动,这个过程不需要程序干涉。
(cpu会自动从NAND flash中读取前4KB的数据放置在片内SRAM里(s3c2440是soc),同时把这段片内SRAM映射到nGCS0片选的空间(即0x00000000)。
cpu是从0x00000000开始执行,也就是NAND flash里的前4KB内容。
因为NAND FLASH连地址线都没有,不能直接把NAND映射到0x00000000,只好使用片内SRAM做一个载体。
通过这个载体把nandflash 中大代码复制到RAM(一般是SDRAM)中去执行)。
程序员要完成的工作是把最核心的代码放在nandflash的前4K中。
4K代码要完成S3C2440的核心配置以及启动代码(U-boot)的剩余部分拷贝到SDRAM中。
Nand Flash 介绍及高通nand flash驱动1. Nand Flash 相关概念1.1 NOR flash与nand flash1) Nor flash 写速度要比Nand flash 慢得多,Nor flash的读速度比Nand flash快得多。
2.)Nor flash 可以挂上CPU 芯片的地址线,不需要额外的sdram 就可直接在Nor flash 中直接运行,而Nand flash 需要代码搬运到Ram中运行,所以需要Boot loader,需要额外的sdram 的开销。
3)Nandflash需要做badblock检测和ecc校验;每个page中需有一块区域标识坏块信息,而 Nor flash 没有badblock 和ecc 校验的概念。
4)Nand flash最小的program单位为page,而Nor flash 可以对bit进行1.2 什么是SLC和MLCSLC,Single Level Cell:单个存储单元,只存储一位数据,表示成1或0.对于数据的表示,单个存储单元中内部所存储电荷的电压,和某个特定的阈值电压Vth,相比,如果大于此Vth值,就是表示1,反之,小于Vth,就表示0.MLC,Multi Level Cell:与SLC相对应,就是单个存储单元,可以存储多个位,比如2位,4位等。
其实现机制,就是,通过控制内部电荷的多少,分成多个阈值,通过控制里面的电荷多少,而达到我们所需要的存储成不同的数据。
比如,假设输入电压是Vin=4V那么,可以设计出2的2次方=4个阈值, 1/4 的Vin=1V,2/4的Vin=2V,3/4的Vin=3V,Vin=4V,分别表示2位数据00,01,10,11。
对于写入数据,就是充电,通过控制内部的电荷的多少,对应表示不同的数据。
另,nand flash:页大小是512+16=528的称为small page页大小是2048+64=2112的称为large page1.3 Nand flash的组成结构图2 Nand flash 物理存储单元的阵列组织结构NAND Flash 的数据是以bit 的方式保存在memory cell,一般来说,一个cell 中只能存储一个bit。
NAND FLASH操作总结目前NAND FLASH主要是SAMSUNG、TOSHIBA两家公司生产。
本文我们主要讨论这两家的产品型号。
另外我们还会讨论Hitachi的AND Flash,为了内容条理起见,我们将分别讨论SAMSUNG、TOSHIBA的Binary Flash,详细说明:1、各个厂家各个型号Flash的操作时序、以及这些操作在“USB-闪存盘控制器”中的影响;2、同一厂家不同型号间的区别、不同厂家之间的区别;然后讨论TOSHIBA的MLC Flash;最后我们要考虑一下AND Flash的情况,并给出一个初步的结论:我们是否需要支持AND Flash。
通过这些比较,给出一个较明确的结论:我们的“USB-闪存盘控制器”需要支持的Flash操作有那些,时序图如何!SAMSUNG:SAMSUNG推出的NAND Flash主要有以下容量:32Mbit、64Mbit、128Mbit、256Mbit、512Mbit、1Gbit、2Gbit、4Gbit通常,我们把其中的1Gbit、2Gbit、4Gbit叫做“大容量”,其余的则不加强调。
32Mbit、64Mbit、128Mbit、256Mbit、512Mbit的Flash 的特性基本相似:∙ Organization- Data Register : (512 + 16) Byte∙ Automatic Program and Erase- Page Program : (512 + 16)Byte- Block Erase : (8K + 256)Byte/(16K + 512)Byte∙ 528-Byte Page Read Operation- Random Access : 10μs(Max.)- Serial Page Access : 50ns(Min.)∙ Fast Write Cycle Time- Program time : 200μs(typ.)- Block Erase time : 2ms(typ.)∙ Flash操作包括基本的七种操作:Read1、Read2、Read ID、Reset、Page Program、Block Erase、Read Status512Mbit的Flash引入了“Plane”和“Copy-Back”的概念,并为此增加了四种新的操作,但却放弃了128Mbit、256Mbit中“Sequential Data Input”操作,这四种操作是:针对“Plane”的Page Program(Dummy)、Multi_Plane Block Erase、Read Multi_Plane Status、针对“Copy-Back”的Copy_Back Program1Gbit、2Gbit、4Gbit(大容量)的操作基本相同,但他们比一般Flash多了Copy-Back、Cache Program的功能:∙ Organization- Data Register : (2K + 64) Byte- Cache Register : (2K + 64) Byte∙ Automatic Program and Erase- Page Program : (2K + 64)Byte- Block Erase : (128K + 4K)Byte∙ Page Read Operation- Random Access : 25μs(Max.)- Serial Page Access : 50ns(Min.)∙ Fast Write Cycle Time- Program time : 300~400μs(typ.)- Block Erase time : 2ms(typ.)∙ 大容量Flash操作包括七种基本操作中的六种:Read、Read ID、Reset、Page Program、Block Erase、Read Status,大容量Flash 的Page不再分为A、B、C区,所以也不再有Read1、Read2的区分。
nand flash 时序参数一、概述NAND Flash 是一种非易失性存储器,具有体积小、容量大、寿命长、工作电压低等优点,因此在嵌入式系统中得到了广泛应用。
在NAND Flash 的应用中,了解和掌握其时序参数是非常重要的。
时序参数是决定 NAND Flash 操作成功与否的关键因素之一,因此必须严格遵守。
二、主要时序参数1. 写时序:包括写启动时间、写操作宽度、写宽高时序、写保持时间等。
这些参数直接关系到数据写入的速度和准确性。
2. 读时序:包括读启动时间、读保持时间、读宽高时序等。
这些参数决定了数据读取的准确性,以及对 NAND Flash 的保护程度。
3. 擦除时序:擦除操作需要保证擦除区域的完全清除,因此时序参数非常重要。
包括擦除宽高时序、擦除保持时间等。
三、影响时序参数的因素1. 芯片类型:不同型号的 NAND Flash 其时序参数可能有所不同,需要根据具体芯片型号进行详细了解和设置。
2. 电压与电流:操作 NAND Flash 时所需的电压和电流也会影响时序参数,需要根据实际情况进行调整。
3. 温度:温度也会影响 NAND Flash 的性能,进而影响时序参数。
因此,在操作过程中需要关注温度变化。
四、注意事项1. 在使用 NAND Flash 时,必须严格遵守其时序参数,否则可能导致数据损坏、芯片损坏等严重后果。
2. 在调试过程中,可以使用示波器等工具来监测时序参数是否符合要求。
3. 在写入数据时,要保证数据的准确性,避免误操作导致数据丢失。
总的来说,NAND Flash 的时序参数是其在嵌入式系统中的应用中不可或缺的一部分。
了解和掌握这些时序参数,对于正确使用 NAND Flash,保护芯片,提高系统性能都具有重要的意义。
Nand Flash中的ONFI,LBA,Unique IDVersion: 2011-6-28Author: crifan目录1名词解释 (3)1.1Non-Volatile Memory非易失性存储器 (3)1.2OTP(One Time Programmable)一次性可编程存储器 (3)1.3NDA(None-Disclosure Agreement) (3)1.4Datasheet数据手册和Specification规范 (3)1.5Nand Flash相关的一些名词解释 (4)1.5.1(Bad) Block Management(坏)块管理 (4)1.5.2Wear-Levelling负载平衡 (4)1.5.3ECC(Error Correction Code)错误校验(代码) (4)2Nand Flash相关规范– ONFI和LBA (6)2.1ONFI是什么 (6)2.1.1ONFI Block Abstracted NAND (8)2.1.2ONFI的好处 (8)2.2LBA规范是什么 (8)2.3为何会有ONFI和LBA (9)2.3.1技术层面的解释 (10)2.3.2现实层面的解释 (10)2.4ONFI和LBA的区别和联系 (10)2.4.1ONFI和LBA的区别 (10)2.4.2ONFI和LBA的联系 (10)3Nand Flash的Unique ID (11)3.1什么是Unique ID唯一性标识 (11)3.2不同Nand Flash厂商的对Unique ID的不同的实现方法 (11)3.2.1Toshiba东芝的Nand的Unique ID (11)3.2.1.1读取Toshiba的Nand的Unique ID (13)3.2.2Samsung三星的Nand的Unique ID (13)3.2.2.1读取Samsung的Nand的Unique ID (14)3.2.3遵循ONFI规范的厂商的Nand的Unique ID (14)3.2.3.1读取遵循ONFI的厂商的Nand的Unique ID (16)4引用文章 (18)图表Figure 1 ONFI中的Nand Flash的命令集合 (7)Figure 2 Toshiba的Unique ID (12)Figure 3 ONFI的参数页数据结构定义 (15)Figure 4 ONFI中Unique ID的结构 (16)Figure 5 ONFI中Read Unique ID命令的时序图 (17)1 名词解释1.1 Non-Volatile Memory非易失性存储器NV (RAM)Memory,断电数据也不会丢失的存储器,比如Nand Flash,Nor Flash,硬盘等等。
三星系列的NAND FLASH芯片容量从8MB到256MB(最近听说有1G容量的了),对于需要大容量数据存储的嵌入式系统是一个很好的选择,尤其是其接近1MB/元的高性价比,更是普通nor flash 无法比拟的。
本文以K9F2808U0C为例,采用AVR芯片连接,进行了初步的读写试验,完成了芯片的ID读出功能。
电路连接如下图:左边是所使用的AVR芯片ATmega16L的局部电路,右边是K9F2808芯片的连接图,数据/地址总线使用ATmega16的PORTB端口连接,其它全部所需信号线使用IO连接,组成了IO模拟方式。
K9F2808芯片的全部命令字如下:其中,Read1读取的是普通数据存储区域的数据,Read2读取的是每页存储器附加的16Bytes区域的数据;Page Program可以编程一页最大528Bytes的数据,Block Erase擦除指定页面数据,Read Status可以读取芯片状态。
芯片的整个读写时序可以分解为4个基本步骤,即1、命令写入,2、数据写入,3、数据读出,4、地址写入。
1、命令写入时序如下:对应函数为:void WriteCmd(unsigned char cmd) {nandPortD = 0xFF;ClsLine(nandSPortO,nandALE); ClsLine(nandSPortO,nandnCE); SetLine(nandSPortO,nandCLE); ClsLine(nandSPortO,nandnWE); nandPortO = cmd;SetLine(nandSPortO,nandnWE); ClsLine(nandSPortO,nandCLE); SetLine(nandSPortO,nandALE);}2、数据写入时序如下:对应函数为:void WriteByte(unsigned char Wdata){nandPortD = 0xFF;SetLine(nandSPortO,nandnWE);ClsLine(nandSPortO,nandCLE);ClsLine(nandSPortO,nandnCE);ClsLine(nandSPortO,nandALE);ClsLine(nandSPortO,nandnWE);while((nandSPortI & nandRnB) != nandRnB); // wait busy end nandPortO = Wdata;while((nandSPortI & nandRnB) != nandRnB); // wait busy end SetLine(nandSPortO,nandnWE);}3、数据读出时序如下:对应函数为:unsigned char ReadByte(void){unsigned char Rdata;nandPortD = 0x00;SetLine(nandSPortO,nandnWE);ClsLine(nandSPortO,nandCLE);ClsLine(nandSPortO,nandALE);ClsLine(nandSPortO,nandnCE);ClsLine(nandSPortO,nandnRE);while((nandSPortI & nandRnB) != nandRnB); // wait busy end Rdata = nandPortI;while((nandSPortI & nandRnB) != nandRnB); // wait busy end SetLine(nandSPortO,nandnRE);return Rdata;}4、地址写入时序如下:对应函数为:void WriteByteAdd(unsigned char Add){nandPortD = 0xFF;SetLine(nandSPortO,nandnWE);ClsLine(nandSPortO,nandnCE);ClsLine(nandSPortO,nandCLE);SetLine(nandSPortO,nandALE);ClsLine(nandSPortO,nandnWE);nandPortO = Add;SetLine(nandSPortO,nandnWE);while((nandSPortI & nandRnB) != nandRnB); // wait busy endClsLine(nandSPortO,nandALE);}其余操作方式均从这四种基本操作组合变化而来,适当调用或者重新编写其中的某些语句就能完成全部的K9F2808芯片读写操作。
nand flash 裸板驱动,介绍的比较精辟/u3/96362/showart_211 3221.htmlNAND Flash的驱动程序设计:/html/99/n-599.html1. 硬件特性:【Flash的硬件实现机制】Flash全名叫做Flash Memory,属于非易失性存储设备(Non-volatile Memory Device),与此相对应的是易失性存储设备(Volatile Memory Device)。
关于什么是非易失性/易失性,从名字中就可以看出,非易失性就是不容易丢失,数据存储在这类设备中,即使断电了,也不会丢失,这类设备,除了Flash,还有其他比较常见的入硬盘,ROM等,与此相对的,易失性就是断电了,数据就丢失了,比如大家常用的内存,不论是以前的SDRAM,DDR SDRAM,还是现在的DDR2,DDR3等,都是断电后,数据就没了。
Flash的内部存储是MOSFET,里面有个悬浮门(Floating Gate),是真正存储数据的单元。
在Flash之前,紫外线可擦除(uv-erasable)的EPROM,就已经采用用Floating Gate存储数据这一技术了。
数据在Flash内存单元中是以电荷(electrical charge)形式存储的。
存储电荷的多少,取决于图中的外部门(external gate)所被施加的电压,其控制了是向存储单元中冲入电荷还是使其释放电荷。
而数据的表示,以所存储的电荷的电压是否超过一个特定的阈值Vth来表示。
【SLC和MLC的实现机制】Nand Flash按照内部存储数据单元的电压的不同层次,也就是单个内存单元中,是存储1位数据,还是多位数据,可以分为SLC和MLC:1. SLC,Single Level Cell:单个存储单元,只存储一位数据,表示成1或0.就是上面介绍的,对于数据的表示,单个存储单元中内部所存储电荷的电压,和某个特定的阈值电压Vth,相比,如果大于此Vth值,就是表示1,反之,小于Vth,就表示0.对于nand Flash的数据的写入1,就是控制External Gate去充电,使得存储的电荷够多,超过阈值Vth,就表示1了。
三星系列的NAND FLASH芯片容量从8MB到256MB(最近听说有1G容量的了),对于需要大容量数据存储的嵌入式系统是一个很好的选择,尤其是其接近1MB/元的高性价比,更是普通nor flash 无法比拟的。
本文以K9F2808U0C为例,采用AVR芯片连接,进行了初步的读写试验,完成了芯片的ID读出功能。
电路连接如下图:
左边是所使用的AVR芯片ATmega16L的局部电路,右边是K9F2808芯片的连接图,数据/地址总线使用ATmega16的PORTB端口连接,其它全部所需信号线使用IO连接,组成了IO模拟方式。
K9F2808芯片的全部命令字如下:
其中,Read1读取的是普通数据存储区域的数据,Read2读取的是每页存储器附加的16Bytes区域的数据;Page Program可以编程一页最大528Bytes的数据,Block Erase擦除指定页面数据,Read Status可以读取芯片状态。
芯片的整个读写时序可以分解为4个基本步骤,即1、命令写入,2、数据写入,3、数据读出,4、地址写入。
1、命令写入时序如下:
对应函数为:
void WriteCmd(unsigned char cmd) {
nandPortD = 0xFF;
ClsLine(nandSPortO,nandALE); ClsLine(nandSPortO,nandnCE); SetLine(nandSPortO,nandCLE); ClsLine(nandSPortO,nandnWE); nandPortO = cmd;
SetLine(nandSPortO,nandnWE); ClsLine(nandSPortO,nandCLE); SetLine(nandSPortO,nandALE);
}
2、数据写入时序如下:
对应函数为:
void WriteByte(unsigned char Wdata)
{
nandPortD = 0xFF;
SetLine(nandSPortO,nandnWE);
ClsLine(nandSPortO,nandCLE);
ClsLine(nandSPortO,nandnCE);
ClsLine(nandSPortO,nandALE);
ClsLine(nandSPortO,nandnWE);
while((nandSPortI & nandRnB) != nandRnB); // wait busy end nandPortO = Wdata;
while((nandSPortI & nandRnB) != nandRnB); // wait busy end SetLine(nandSPortO,nandnWE);
}
3、数据读出时序如下:
对应函数为:
unsigned char ReadByte(void)
{
unsigned char Rdata;
nandPortD = 0x00;
SetLine(nandSPortO,nandnWE);
ClsLine(nandSPortO,nandCLE);
ClsLine(nandSPortO,nandALE);
ClsLine(nandSPortO,nandnCE);
ClsLine(nandSPortO,nandnRE);
while((nandSPortI & nandRnB) != nandRnB); // wait busy end Rdata = nandPortI;
while((nandSPortI & nandRnB) != nandRnB); // wait busy end SetLine(nandSPortO,nandnRE);
return Rdata;
}
4、地址写入时序如下:
对应函数为:
void WriteByteAdd(unsigned char Add)
{
nandPortD = 0xFF;
SetLine(nandSPortO,nandnWE);
ClsLine(nandSPortO,nandnCE);
ClsLine(nandSPortO,nandCLE);
SetLine(nandSPortO,nandALE);
ClsLine(nandSPortO,nandnWE);
nandPortO = Add;
SetLine(nandSPortO,nandnWE);
while((nandSPortI & nandRnB) != nandRnB); // wait busy end
ClsLine(nandSPortO,nandALE);
}
其余操作方式均从这四种基本操作组合变化而来,适当调用或者重新编写其中的某些语句就能完成全部的K9F2808芯片读写操作。
下面以读K9F2808芯片ID为例调用以上函数完成。
读芯片ID的时序如下图:
实现函数编写为:
void ReadId(unsigned char *ptr)
{
WriteCmd(0x90);
WriteByteAdd(0x00);
*ptr++ = ReadByte();
*ptr = ReadByte();
SetLine(nandSPortO,nandnCE);
}
函数调用后,*ptr的值为0xEC,即厂家代码;*(ptr+1)的值为0x73,即设备代码。
实际在芯片的读写操作中,还要注意对坏扇区进行检错,并将检错结果存入芯片的第一个块中,以确保数据的读写地址均为有效地址。