电子说
本文主要是关于NOR Flash的相关介绍,并着重对NOR Flash的读写及其应用原理进行了详尽的阐述。
它是现在市场上两种主要的非易失闪存技术之一。Intel于1988年首先开发出NOR Flash 技术,彻底改变了原先由EPROM(Erasable Programmable Read-Only-Memory电可编程序只读存储器)和EEPROM(电可擦只读存储器Electrically Erasable Programmable Read - Only Memory)一统天下的局面。紧接着,1989年,东芝公司发表了NAND Flash 结构,强调降低每比特的成本,有更高的性能,并且像磁盘一样可以通过接口轻松升级。NOR Flash 的特点是芯片内执行(XIP ,eXecute In Place),这样应用程序可以直接在Flash闪存内运行,不必再把代码读到系统RAM中。NOR 的传输效率很高,在1~4MB的小容量时具有很高的成本效益,但是很低的写入和擦除速度大大影响到它的性能。NAND的结构能提供极高的单元密度,可以达到高存储密度,并且写入和擦除的速度也很快。应用NAND的困难在于Flash的管理需要特殊的系统接口。通常读取NOR的速度比NAND稍快一些,而NAND的写入速度比NOR快很多,在设计中应该考虑这些情况。——《ARM嵌入式Linux系统开发从入门到精通》 李亚峰 欧文盛 等编著 清华大学出版社 P52 注释 API Key。
性能比较
flash闪存是非易失存储器,可以对称为块的存储器单元块进行擦写和再编程。任何flash器件的写入操作只能在空或已擦除的单元内进行,所以大多数情况下,在进行写入操作之前必须先执行擦除。NAND器件执行擦除操作是十分简单的,而NOR则要求在进行擦除前先要将目标块内所有的位都写为0。
由于擦除NOR器件时是以64~128KB的块进行的,执行一个写入/擦除操作的时间为5s,与此相反,擦除NAND器件是以8~32KB的块进行的,执行相同的操作最多只需要4ms。
执行擦除时块尺寸的不同进一步拉大了NOR和NAND之间的性能差距,统计表明,对于给定的一套写入操作(尤其是更新小文件时),更多的擦除操作必须在基于NOR的单元中进行。这样,当选择存储解决方案时,设计师必须权衡以下的各项因素。
l 、NOR的读速度比NAND稍快一些。
2、 NAND的写入速度比NOR快很多。
3 、NAND的4ms擦除速度远比NOR的5s快。
4 、大多数写入操作需要先进行擦除操作。
5 、NAND的擦除单元更小,相应的擦除威廉希尔官方网站 更少。
此外,NAND的实际应用方式要比NOR复杂的多。NOR可以直接使用,并可在上面直接运行代码;而NAND需要I/O接口,因此使用时需要驱动程序。不过当今流行的操作系统对NAND结构的Flash都有支持。此外,Linux内核也提供了对NAND结构的Flash的支持。
详解
NOR和NAND是现在市场上两种主要的非易失闪存技术。Intel于1988年首先开发出NOR flash技术,彻底改变了原先由EPROM和EEPROM一统天下的局面。紧接着,1989年,东芝公司发表了NAND flash结构,强调降低每比特的成本,更高的性能,并且象磁盘一样可以通过接口轻松升级。但是经过了十多年之后,仍然有相当多的硬件工程师分不清NOR和NAND闪存。
像“flash存储器”经常可以与相“NOR存储器”互换使用。许多业内人士也搞不清楚NAND闪存技术相对于NOR技术的优越之处,因为大多数情况下闪存只是用来存储少量的代码,这时NOR闪存更适合一些。而NAND则是高数据存储密度的理想解决方案。
NOR的特点是芯片内执行(XIP, eXecute In Place),这样应用程序可以直接在flash闪存内运行,不必再把代码读到系统RAM中。NOR的传输效率很高,在1~4MB的小容量时具有很高的成本效益,但是很低的写入和擦除速度大大影响了它的性能。
NAND结构能提供极高的单元密度,可以达到高存储密度,并且写入和擦除的速度也很快。应用NAND的困难在于flash的管理需要特殊的系统接口。
以下内容,如无特别说明,处理器指的是 ARM 处理器,FLASH 指的都是 NOR FLASH.另外,BYTE指的是8-BIT的数据单元,HALF-WORD代表的是16-BIT的数据单元,而WORD 则代表了32-BIT的数据单元。
2.1 处理器寻址
ARM 可以说是目前最流行的32位嵌进式处理器。在这里只提一下ARM处理器的寻址,为后面做个展垫。从处理器的角度来看,系统中每个地址对应的是一个BYTE的数据单元。这和很多别的处理器都是一样的。
2.2 处理器和NOR FLASH的硬件连接
从前面的先容,我们知道从处理器的角度来看,每个地址对应的是一个 BYTE 的数据单元。而,NOR FLASH 的每个地址有可能对应的是一个BYTE的数据单元,也有可能对应的是一个HALF-WORD的数据单元。所以在硬件设计中,连接ARM处理器和 NOR FLASH时,必须根据实际情况对地址信号做特别的处理。
假如ARM处理器外部扩展的是8-BIT的NOR FLASH, 数据线和地址线的连接应该如图1所示。 从图中我们可以看到,处理器的数据信号D0-D7和 FLASH的数据信号D0-D7是逐一对应连接的,处理器的地址信号A0-An和NOR FLASH的地址信号A0-An 也是逐一对应连接的。
假如ARM处理器外部扩展的是16-BIT的NOR FLASH, 地址线必须要错位连接。 图2给了一个ARM处理器和16-BIT NOR FLASH的连接示意图。如图2所示,ARM处理器的数据信号D0-D15和FLASH 的数据信号D0-D15是逐一对应的。而ARM处理器的地址信号和NOR FLASH 的地址信号是错位连接的,ARM的A0悬空,ARM 的A1 连接FLASH 的A0,ARM 的A2连接FLASH的A1,依次类推。需要错位连接的原因是:ARM处理器的每个地址对应的是一个BYTE 的数据单元,而 16-BIT 的 FLASH 的每个地址对应的是一个HALF-WORD(16-BIT)的数据单元。为了保持匹配,所以必须错位连接。这样,从ARM处理器发送出来的地址信号的最低位A0对16-BIT FLASH来说就被屏蔽掉了。
补充说明:
一般来说,ARM处理器内部要设置相应的寄存器,告诉处理器外部扩展的FLASH的位宽(8-BIT/16-BIT/32-BIT) 。这样,处理器才知道在访问的时候如何从FLASH正确的读取数据;
有些ARM处理器内部可以设置地址的错位。对于支持软件选择地址错位的处理器,在连接16-BIT FLASH的时候,硬件上可以不需要把地址线错位。读者设计的时候,请参考MCU的数据手册,以手册为准,以免造成不必要的麻烦;
假如处理器支持内部设置地址错位,在实际访问的时候,送出的地址实际上是在MCU内部做了错位处理,其作用是等效于硬件连接上的错位的。
上面的描述可能比较抽象,下面让我们来看2个ARM处理器访问16-BIT FLASH的例子:
例子 1:ARM处理器需要从地址0x0读取一个BYTE
ARM处理器在地址线An-A0上送出信号0x0;
16-BIT FLASH在自己的地址信号An-A0上看到的地址是0x0,然后将地址0x0对应的16-BIT数据单元输出到D15-D0上;
ARM处理器知道访问的是16-BIT的FLASH,从D7-D0上读取所需要的一个BYTE的数据。
例子 2:ARM处理器需要从地址0x1读取一个BYTE
ARM处理器在地址线An-A0上送出信号0x1;
16-BIT FLASH在自己的地址信号An-A0上看到的地址依然是0x0, 然后将地址0x0对应的16-BIT数据单元输出到D15-D0上;
ARM处理器知道访问的是16-BIT的FLASH,从D15-D8 上读取所需要的一个BYTE 的数据。
2.3 从软件角度来看 ARM 处理器和 NOR FLASH 的连接
从软件的角度来理解ARM处理器和 FLASH的连接。对于8-BIT的FLASH的连接,很好理解,由于ARM处理器和8-BIT FLASH的每个地址对应的都是一个 BYTE 的数据单元。所以地址连接毫无疑问是逐一对应的。假如 ARM 处理器连接的是 16-BIT 的处理器,由于 ARM 处理器的每个地址对应的是一个 BYTE 的数据单元,而 16-BIT FLASH 的每个地址对应的是一个 HALF-WORD 的16-BIT的数据单元。所以,也毫无疑问,ARM处理器访问16-BIT处理器的时候,地址肯定是要错开一位的。在写FLASH驱动的时候,我们不需要知道地址错位是由硬件实现的,还是是通过设置ARM处理器内部的寄存器来实现的,只需要记住2点:
ARM处理器访问8-BIT FLASH的时候,地址是逐一对应的;
ARM处理器访问16-BIT FLASH的时候,地址肯定是错位的。
2.4 8-BIT FLASH 烧写驱动实例 - HY29F040
HY29F040是现代公司的一款8-BIT的NOR FLASH.在这个小节里,我们以这个芯片为例子,讲述如何对8-BIT NOR FLASH进行操作。
HY29F040的容量为512K-BYTE,总共包括8 个SECTOR,每个SECTOR 的容量是64K-BYTE.该芯片支持SECTOR擦除,整片擦除和以BYTE 为基本单位的写操纵.HY29F040的命令定义如表-1所示。
下面,我们来看看如何实现基本的擦除和编程操作。在本节后面的描述中,我们使用了下面的2 个定义:
U32 sysbase; //该变量用来表示 FLASH 的起始地址
#define SysAddr8(sysbase, offset) ((volatile U8*)(sysbase)+(offset)) //用来方便对指定的 FALSH 地址进行操作
宏SysAddr8定义了一个 BYTE(8-BIT)指针,其地址为(sysbase + offset)。假设FLASH的起始地址为0x10000000,假如要将0xAB写到FLASH的第一个BYTE中往,可以用下面的代码:
*SysAddr8(0x10000000, 0x1) = 0xAB;
注意:
在本节后面的描述中,sysbase代表的是FLASH的起始地址,而SysAddr8中的offset则代表了相对于FLASH起始地址的BYTE偏移量.offset也是8-BIT FLASH在自己的地址信号An-A0上看到的地址。
a. 整片擦除操作
整片擦除操纵共需要6个周期的总线写操作:
将 0xAA写到 FLASH 地址 0x5555;
将 0x55 写到 FLASH 地址 0x2AAA;
将 0x80 写到 FLASH 地址 0x5555;
将 0xAA写到 FLASH 地址 0x5555;
将 0x55 写到 FLASH 地址 0x2AAA;
将 0x10 写到 FLASH 地址 0x5555.
对应的代码:
*SysAddr8(sysbase, 0x5555) = 0xAA; //将值 0xAA写到 FLASH 地址 0x5555
*SysAddr8(sysbase, 0x2AAA) = 0x55; //将值 0x55 写到 FLASH 地址 0x2AAA
*SysAddr8(sysbase, 0x5555) = 0x80; //将值 0x80 写到 FLASH 地址 0x5555
*SysAddr8(sysbase, 0x5555) = 0xAA; //将值 0xAA写到 FLASH 地址 0x5555
*SysAddr8(sysbase, 0x2AAA) = 0x55; //将值 0x55 写到 FLASH 地址 0x2AAA
*SysAddr8(sysbase, 0x5555) = 0x10; //将值 0x10 写到 FLASH 地址 0x5555
b. SECTOR擦除操作
SECTOR的擦除操纵共需要6个周期的总线写操作:
将 0xAA写到 FLASH 地址 0x5555;
将 0x55 写到 FLASH 地址 0x2AAA;
将 0x80 写到 FLASH 地址 0x5555;
将 0xAA写到 FLASH 地址 0x5555;
将 0x55 写到 FLASH 地址 0x2AAA;
将 0x30 写到要擦除的 SECTOR 对应的地址。
对应的代码:
*SysAddr8(sysbase, 0x5555) = 0xAA; //将值 0xAA写到 FLASH 地址 0x5555
*SysAddr8(sysbase, 0x2AAA) = 0x55; //将值 0x55 写到 FLASH 地址 0x2AAA
*SysAddr8(sysbase, 0x5555) = 0x80; //将值 0x80 写到 FLASH 地址 0x5555
*SysAddr8(sysbase, 0x5555) = 0xAA; //将值 0xAA写到 FLASH 地址 0x5555
*SysAddr8(sysbase, 0x2AAA) = 0x55; //将值 0x55 写到 FLASH 地址 0x2AAA
*SysAddr8(sysbase, addr) = 0x30; //将值 0x30 写到要擦除的 SECTOR 对应的地址
c. BYTE擦除操作
写一个BYTE 的数据到FLASH中往,需要 4个周期的总线写操作:
将 0xAA写到 FLASH 地址 0x5555;
将 0x55 写到 FLASH 地址 0x2AAA;
将 0xA0 写到 FLASH 地址 0x5555;
将编程数据(BYTE)写到对应的编程地址上。
对应的代码:
*SysAddr8(sysbase, 0x5555) = 0xAA; //将值 0xAA写到 FLASH 地址 0x5555
*SysAddr8(sysbase, 0x2AAA) = 0x55; //将值 0x55 写到 FLASH 地址 0x2AAA
*SysAddr8(sysbase, 0x5555) = 0xA0; //将值 0xA0 写到 FLASH 地址 0x5555
*SysAddr8(sysbase, addr) = data; //将一个 BYTE的数据写到期看的地址
2.5 16-BIT FLASH 烧写驱动实例 - SST39VF160
SST39VF160是SST公司的一款16-BIT的NOR FLASH. 在这个小节里, 我们以SST39VF160为例子, 讲述如何对16-BIT NOR FLASH进行操作。对8-BIT FLASH的操作很好理解,但对16-BIT FLASH的操作理解起来要晦涩很多。我尽力描述得清楚些。
SST39VF160的容量为2M-BYTE , 总共包括512个SECTOR, 每个SECTOR 的容量是4K-BYTE. 该芯片支持SECTOR擦除,整片擦除和以 HALF-WORD 为基本单位的写操纵.SST39VF160 的命令定义如表-2 所示。在表 2 中,由于所有命令都是从FLASH的角度来定义的。 所以, 所有的地址都是HALF-WORD地址, 指的是16-BIT FLASH在自己的地址信号An-A0上看到的地址。
在本节后面的描述中,我们使用了下面的2个定义:
U32 sysbase; //该变量用来表示 FLASH 的起始地址
#define SysAddr16(sysbase, offset) ((volatile U16*)(sysbase)+(offset)) //用来方便对指定的 FALSH 地址进行操作
SysAddr16(sysbase, offset)首先定义了一个16-BIT HALF-WORD的指针,指针的地址为sysbase,然后根据offset做个偏移操纵。 由于HALF-WORD指针的地址是2个BYTE对齐的, 所以每个偏移操纵会使得地址加2. 终极, SysAddr16 (sysbase, offset)相当于定义了一个HALF-WORD的指针,其终极地址为(sysbase + 2offset) 。在使用SysAddr16的时候,将sysbase设置成 FLASH 的起始地址,offset 则可以理解为相对于 FLASH 起始地址的HALF-WORD 偏移量或是偏移地址。假设FLASH 的起始地址为 0x10000000,SysAddr16(0x10000000, 0)指向 16-BIT FLASH 的第 0 个HALF-WORD, SysAddr16(0x10000000, 1指向16-BIT FLASH的第1个HALF-WORD.依次类推。假如要将0xABCD分别写到FLASH 的第0个和第 1个HALF-WORD 中往,可以用下面的代码:
*SysAddr16(0x10000000, 0x0) = 0xABCD;
*SysAddr16(0x10000000, 0x1) = 0xABCD;
接下来,我们分别从ARM处理器的角度和FLASH的角度来具体分析一下。
从 ARM 的角度来看:
假设 FLASH 的起始地址为 0x10000000,由于 ARM 处理器知道 FLASH 的地址空间为 0x10000000 ~ (0x10000000 +FLASH容量 – 1),所以在对这个地址空间进行访问的时候,会设置好FLASH的片选信号,并将低位的地址输出到 地址信号上。以*SysAddr16(0x10000000, 0x1) = 0xABCD 为例。从ARM 处理器的角度来看,该操纵是把0xABCD写到地址0x10000002上往。所以ARM处理器终极会在它的地址信号An-A0输出地址0x2,同时会在D15-D0 上输出0xABCD.
从 FLASH 的角度来看:
还是以 *SysAddr16(0x10000000, 0x1) = 0xABCD 为例,FLASH看到的地址是多少呢?接着分析.ARM 处理器在执行操纵的时候,会设置好相应的FLASH片选使能信号,并在ARM的地址信号An-A0上输出 0x2.由于 ARM和 16-BIT FLASH的地址信号的连接是错开一位的, 所以, FLASH终极在自己的地址An-A0上看到的信号是0x1, 相当于将ARM处理器输出的地址往右做了一个移位操纵,恰好对应的是FLASH的第1 个HALF-WORD.同时,FLASH会在自己的D15-D0上看到数据0xABCD.
通过上面的分析,我们知道 SysAddr16 中指定的 offset 的值就是 16-BIT FLASH 在自己的地址 An-A0 上看到的值。所以,我们可以很方便的通过 SysAddr16(sysbase, offset) 对 FLASH 进行操纵,其中 sysbase 代表 FLASH 起始地址,offset 则代表了FLASH 的第几个HALF-WORD(HALF-WORD偏移量或偏移地址)
注意:
在本节后面的描述中,SysAddr16中的 SYSBASE代表的是FLASH的起始地址,而SysAddr16中的 OFFSET则代表了相对于FLASH起始地址的 HALF-WORD 偏移量或偏移地址.OFFSET 的值也是16-BIT FLASH在自己的地址信号An-A0上看到的值;
在SST39VF160的命令定义中,所有的地址都是针对FLASH的HALF-WORD地址,指的是在FLASH自己的地址信号An-A0上看到的地址。
整片擦除操作
整片擦除操纵共需要6个周期的总线写操作:
将 0x00AA写到 FLASH HALF-WORD 地址 0x5555;
将 0x0055 写到 FLASH HALF-WORD地址 0x2AAA;
将 0x0080 写到 FLASH HALF-WORD地址 0x5555;
将 0x00AA写到 FLASH HALF-WORD 地址 0x5555;
将 0x0055 写到 FLASH HALF-WORD地址 0x2AAA;
将 0x0010 写到 FLASH HALF-WORD地址 0x5555.
对应的代码:
*SysAddr16(sysbase, 0x5555) = 0x00AA; //将值 0x00AA 写到 FLASH HALF-WORD地址 0x5555
*SysAddr16(sysbase, 0x2AAA) = 0x0055; //将值 0x0055 写到 FLASH HALF-WORD地址 0x2AAA
*SysAddr16(sysbase, 0x5555) = 0x0080; //将值 0x0080 写到 FLASH HALF-WORD地址 0x5555
*SysAddr16(sysbase, 0x5555) = 0x00AA; //将值 0x00AA 写到 FLASH HALF-WORD地址 0x5555
*SysAddr16(sysbase, 0x2AAA) = 0x0055; //将值 0x0055 写到 FLASH HALF-WORD地址 0x2AAA
*SysAddr16(sysbase, 0x5555) = 0x0010; //将值 0x0010 写到 FLASH HALF-WORD地址 0x5555
SECTOR擦除操作
SECTOR的擦除操纵共需要6个周期的总线写操作:
将 0x00AA写到 FLASH HALF-WORD 地址 0x5555;
将 0x0055 写到 FLASH HALF-WORD地址 0x2AAA;
将 0x0080 写到 FLASH HALF-WORD地址 0x5555;
将 0x00AA写到 FLASH HALF-WORD 地址 0x5555;
将 0x0055 写到 FLASH HALF-WORD地址 0x2AAA;
将 0x0030 写到要擦除的 SECTOR 对应的 HALF-WORD地址。
对应的代码:
*SysAddr16(sysbase, 0x5555) = 0x00AA; //将值 0x00AA 写到 FLASH HALF-WORD地址 0x5555
*SysAddr16(sysbase, 0x2AAA) = 0x0055; //将值 0x0055 写到 FLASH HALF-WORD地址 0x2AAA
*SysAddr16(sysbase, 0x5555) = 0x0080; //将值 0x0080 写到 FLASH HALF-WORD地址 0x5555
*SysAddr16(sysbase, 0x5555) = 0x00AA; //将值 0x00AA 写到 FLASH HALF-WORD地址 0x5555
*SysAddr16(sysbase, 0x2AAA) = 0x0055; //将值 0x0055 写到 FLASH HALF-WORD地址 0x2AAA
*SysAddr16(sysbase, addr 》》 1) = 0x0030; //将值 0x0030 写到要擦除的 SECTOR 对应的HALF-WORD地址
注意:
上面的代码中第6个操纵周期中的ADDR 是从ARM处理器的角度来看的BYTE地址,由于在擦除的时候,用户希看指定的是从 ARM 的角度看到的地址,这样更方便和更直观。而在 SysAddr16 的宏定义中,OFFSET 表示的是相对于FLASH起始地址的 HALF-WORD 偏移量,或是FLASH在自己的地址信号An-A0上看到的地址。所以需要执行一个右移操作,把ADDR转换成 HALF-WORD 地址。
举例说明,SST39VF160 每个 SECTOR 的大小是 4K-BYTE.从 ARM 处器的角度和用户的角度来看,SECTOR-0 相对于FLASH起始地址的BYTE地址是0x0;从FLASH来看SECTOR-0 的HALF-WORD地址是0x0.从ARM处理器的角度和用户的角度来看, FLASH SECTOR-1相对于FLASH起始地址的BYTE地址0x1000; 从FLASH来看, SECTOR-1的HALF-WORD地址应该是(0x1000 》》 1) = 0x800.
假如要擦除SECTOR-0,上面代码的第6条指令应该是:
*SysAddr16(sysbase, 0x0 》》 1) = 0x0030;
假如要擦除SECTOR-1,上面代码的第6条指令应该是:
*SysAddr16(sysbase, 0x1000 》》 1) = 0x0030;
HALF-WORD 编程操作
写一个HALF-WORD的数据到FLASH中往,需要4个周期的总线写操作:
将 0x00AA写到 FLASH HALF-WORD 地址 0x5555;
将 0x0055 写到 FLASH HALF-WORD地址 0x2AAA;
将 0x00A0 写到 FLASH HALF-WORD 地址 0x5555;
将编程数据(HALF-WORD)写到对应的 HALF-WORD地址。
对应的代码:
*SysAddr16(sysbase, 0x5555) = 0x00AA; //将值 0x00AA 写到 FLASH 地址 0x5555
*SysAddr16(sysbase, 0x2AAA) = 0x0055; //将值 0x0055 写到 FLASH 地址 0x2AAA
*SysAddr16(sysbase, 0x5555) = 0x00A0; //将值 0x00A0 写到 FLASH 地址 0x5555
*SysAddr16(sysbase, addr 》》 1) = data; //将数据写到对应的 HALF-WORD 地址
注意:
上面的代码中第4个操作周期中的ADDR是从ARM处理器的角度来看的BYTE地址, 由于在执行写操作的时候,用户希看指定的是从 ARM 的角度看到的地址,这样会更方便和更直观。而在 SysAddr16 的宏定义中,OFFSET表示的是相对于FLASH起始地址的HALF-WORD偏移量。 所以需要执行一个右移操纵, 把它转换成HALF-WORD地址。
例如要将数据 0x0123 写到地址 0x0处,对应的是 FLASH 的第 0 个 HAFL-WORD,对应的 HALF-WORD 地址应该是0x0,上面代码的第4条指令应该是:
*SysAddr16(sysbase, 0x0 》》 1) = 0x0123;
又如要将数据0x4567写到地址0x2处, 对应的是FLASH的第1个 HALF-WORD, 对应的HALF-WORD地址应该是0x1, 上面代码的第4条指令应该是:
*SysAddr16(sysbase, 0x2 》》 1) = 0x4567;
再如要将数据0x89AB写到地址0x4处, 对应的是FLASH的第2个HALF-WORD, 对应的HALF-WORD地址应该是0x2,上面代码的第4条指令应该是:
*SysAddr16(sysbase, 0x4 》》 1) = 0x89AB;
还如要将数据0xCDEF 写到地址 0x6处,对应的是 FLASH 的第 3 个 HALF-WORD,对应的 HALF-WORD 地址应该是0x3,上面代码的第4条指令应该是:
*SysAddr16(sysbase, 0x6 》》 1) = 0xCDEF;
NorFlash简单来说与sdram与Nand的中间品,它能像sdram一样直接读,但是又得像nand一样编程擦写。因此程序可以直接在nor里跑,速度要比sdram慢一些,往nor里写数据必须先擦除,因为nor的每一位只能由1变为0。Nor可读不可直接写的特性可以被用来判断是Nor启动还是nand启动,因为nand启动的话前4K是可写的,我们写入数据再读取出来应该是没有问题的,而nor启动的话,读出的数据必然是错误的。
NorFlash的硬件接线:
首先,如果做过sdram实验的朋友应该知道,NorFlash与sdram很相似,只不过sdram位宽为32,NOR为16。在硬件连接上,Nor的地址线与cpu的地址线错开1位,sdram错开2位。简单分析一下:
32位的CPU地址线为32位,每一个地址对应1个byte,地址的步长为1byte
0x0000 0000 对应第1个地址空间 大小为1bytes
0x0000 0001 对应 2 大小为1bytes
依次类推。..
可以理解为cpu的地址类型 为 u8 * addraddr+1 移动1个字节
32位的sdram,每一个地址对应于4个byte,地址步长为4byte
0x0000 0000 对应第1个地址空间 大小为4bytes
0x0000 0001 对应 2 大小为4bytes
依次类推。..
可以理解为sdram的地址类型 为 u32 * addraddr+1 移动4个字节
16位的nor,每一个地址对应于2个byte,地址步长为2byte
0x0000 0000 对应第1个地址空间 大小为2bytes
0x0000 0001 对应 2 大小为2bytes
依次类推。..
可以理解为nor的地址类型 为 u16 * addraddr+1 移动2个字节
因此,CPU的地址与它们的地址是错位的。
CPU的4个连续地址 如 0 1 2 3 均对应于sdram的 0地址
CPU的2个连续地址 如 0 1 均对应于nor 的 0地址
假如我想取sdram 0地址的 第二个byte 地址如何写?对于sdram和nor具体的每一个byte是无法寻址的呀,但是arm有一个叫存储管理器的东西,它大概会帮我们实现单字节的读。
关于Nor Flash的相关介绍就到这了,如有不足之处欢迎指正。
全部0条评论
快来发表一下你的评论吧 !