加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

NOR FLASH

发布时间:2020-12-15 17:28:47 所属栏目:百科 来源:网络整理
导读:相对于硬件工程师和嵌进式软件工程师一般在完成设计之后经常需要验证FLASH是否在工作.在应用当中,也有很多时候需要对FLASH进行写操纵.该文章简单先容了基于ARM芯片的NOR FLASH烧写,并提供了2个具体的实例和源代码,希看对有需要的朋友有点帮助.在开始之前,先
相对于硬件工程师和嵌进式软件工程师一般在完成设计之后经常需要验证FLASH是否在工作.在应用当中,也有很多时候需要对FLASH进行写操纵.该文章简单先容了基于ARM芯片的NOR FLASH烧写,并提供了2个具体的实例和源代码,希看对有需要的朋友有点帮助.在开始之前,先声明一下,这篇文章只是先容了如何写 NOR FLASH 的烧写驱动,和H-JTAG/H-FLASHER没有直接的联系.

??? 在后面的先容里,如无特别说明,处理器指的是 ARM 处理器,FLASH 指的都是 NOR FLASH.另外,BYTE 指的是8-BIT的数据单元,HALF-WORD代表的是16-BIT的数据单元,而WORD 则代表了32-BIT的数据单元.

??? 1. NOR FLASH 的简单介绍

??? NOR FLASH 是很常见的一种存储芯片,数据掉电不会丢失.NOR FLASH支持Execute ON Chip,即程序可以直接在FLASH片内执行.这点和NAND FLASH不一样.因此,在嵌进是系统中,NOR FLASH很适合作为启动程序的存储介质.

??? NOR FLASH的读取和RAM很类似,但不可以直接进行写操纵.对NOR FLASH的写操纵需要遵循特定的命令序列,终极由芯片内部的控制单元完成写操纵.从支持的最小访问单元来看,NOR FLASH一般分为 8 位的和16位的(当然,也有很多NOR FLASH芯片同时支持8位模式和是16 位模式,具体的工作模式通过特定的管脚进行选择) . 对8位的 NOR FLASH芯片,或是工作在8-BIT模式的芯片来说,一个地址对应一个BYTE(8-BIT)的数据.例如一块8-BIT的NOR FLASH,假设容量为4个 BYTE.那芯片应该有8个数据信号D7-D0 和2个地址信号,A1-A0.地址0x0对应第0个 BYTE,地址0x1对应于第1BYTE,地址0x2对应于第2个 BYTE,而地址0x3则对应于第3 个BYTE对16位的 NOR FLASH芯片,或是工作在16-BIT模式的芯片来说,一个地址对应于一个HALF-WORD(16-BIT)的数据.例如,一块16-BIT的 NOR FLASH,假设其容量为4个BYTE.那芯片应该有16 个数据信号线D15-D0 和1个地址信号A0.地址 0x0对应于芯片内部的第0个 HALF-WORD,地址0x1对应于芯片内部的第1个 HALF-WORD. FLASH一般都分为很多个SECTOR,每个SECTOR包括一定数目的存储单元.对有些大容量的FLASH,还分为不同的BANK,每个BANK包括一定数目的SECTOR.FLASH的擦除操纵一般都是以SECTOR,BANK或是整片FLASH为单位的.

??? 在对FLASH进行写操纵的时候,每个BIT可以通过编程由1变为0,但不可以有0修改为1.为了保证写操纵的正确性,在执行写操纵前,都要执行擦除操纵.擦除操纵会把FLASH的一个SECTOR,一个BANK或是整片FLASH 的值全修改为0xFF.这样,写操纵就可以正确完成了.

??? 2. ARM 处理器的寻址

??? ARM 可以说是目前最流行的32位嵌进式处理器.在这里只提一下 ARM 处理器的寻址,为后面做个展垫.从处理器的角度来看,系统中每个地址对应的是一个BYTE的数据单元.这和很多别的处理器都是一样的.

??? 3.? 处理器和 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-BITNOR? 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来说就被屏蔽掉了.

??? 补充说明:

??? 1.? 一般来说,ARM处理器内部要设置相应的寄存器,告诉处理器外部扩展的FLASH的位宽(8-BIT/16-BIT/32-BIT) .这样,处理器才知道在访问的时候如何从FLASH正确的读取数据.

??? 2.? 有些ARM处理器内部可以设置地址的错位.对于支持软件选择地址错位的处理器,在连接16-BIT FLASH的时候,硬件上可以不需要把地址线错位.读者设计的时候,请参考MCU的数据手册,以手册为准,以免造成不必要的麻烦.

??? 3.? 假如处理器支持内部设置地址错位,在实际访问的时候,送出的地址实际上是在MCU内部做了错位处理,其作用是等效于硬件连接上的错位的.

??? 上面的描述可能比较抽象,下面让我们来看2个 ARM处理器访问16-BIT FLASH的例子:

??? 例子 1:ARM处理器需要从地址 0x0 读取一个 BYTE

??? 1 - ARM处理器在地址线An-A0上送出信号0x0;

??? 2 – 16-BIT FLASH在自己的地址信号An-A0上看到的地址是0x0,然后将地址0x0对应的16-BIT数据单元输出到D15-D0上;

??? 3 – ARM处理器知道访问的是16-BIT的FLASH,从D7-D0上读取所需要的一个BYTE的数据;

??? 例子 2:ARM处理器需要从地址 0x1 读取一个 BYTE

??? 1 - ARM处理器在地址线An-A0上送出信号0x1;

??? 2 – 16-BIT FLASH在自己的地址信号An-A0上看到的地址依然是0x0,u5b8bu4f53; font-size:16px; text-indent:2em"> ??? 3 –ARM处理器知道访问的是16-BIT的FLASH,从D15-D8 上读取所需要的一个BYTE 的数据;

??? 4.? 从软件角度来看 ARM 处理器和 NOR FLASH 的连接

??? 在上一个小节里,我们简单了解了 ARM 处理器和 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点:

??? 1 – ARM处理器访问8-BIT FLASH的时候,地址是逐一对应的;

??? 2 – ARM处理器访问16-BIT FLASH的时候,地址肯定是错位的.这一点对理解后面的例子会很有帮助.

??? 5. 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上看到的地址.

??? 整片擦除操纵

??? 整片擦除操纵共需要6个周期的总线写操纵

??? 1 – 将 0xAA写到 FLASH 地址 0x5555

??? 2 – 将 0x55 写到 FLASH 地址 0x2AAA

??? 3 – 将 0x80 写到 FLASH 地址 0x5555

??? 4 – 将 0xAA写到 FLASH 地址 0x5555

??? 5 – 将 0x55 写到 FLASH 地址 0x2AAA

??? 6 – 将 0x10 写到 FLASH 地址 0x5555

??? 对应的代码:

??? *SysAddr8(sysbase,0x5555) = 0xAA;??? //将值 0xAA写到 FLASH 地址 0x5555

??? SECTOR 擦除操纵

??? SECTOR的擦除操纵共需要6个周期的总线写操纵

??? 6 – 将 0x30 写到要擦除的 SECTOR 对应的地址

??? BYTE 编程操纵

??? 写一个BYTE 的数据到FLASH中往,需要 4个周期的总线写操纵

??? 3 – 将 0xA0 写到 FLASH 地址 0x5555

??? 4 – 将编程数据(BYTE)写到对应的编程地址上往

??? 6. 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上看到的地址.

??? #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,1指向16-BIT FLASH的第1 个HALF-WORD.依次类推.假如要将0xABCD分别写到FLASH 的第0个和第 1个HALF-WORD 中往,u5b8bu4f53; font-size:16px; text-indent:2em"> ??? *SysAddr16(0x10000000,0x0) = 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偏移量或偏移地址) .

??? 1. 在本节后面的描述中,SysAddr16中的 SYSBASE代表的是FLASH的起始地址,而SysAddr16中的 OFFSET则代表了相对于FLASH起始地址的 HALF-WORD 偏移量或偏移地址.OFFSET 的值也是16-BIT FLASH在自己的地址信号An-A0上看到的值.

??? 2.在SST39VF160的命令定义中,所有的地址都是针对FLASH的HALF-WORD地址,指的是在FLASH自己的地址信号An-A0上看到的地址.

??? 1 – 将 0x00AA写到 FLASH HALF-WORD 地址 0x5555

??? 2 – 将 0x0055 写到 FLASH HALF-WORD地址 0x2AAA

??? 3 – 将 0x0080 写到 FLASH HALF-WORD地址 0x5555

??? 4 – 将 0x00AA写到 FLASH HALF-WORD 地址 0x5555

??? 5 – 将 0x0055 写到 FLASH HALF-WORD地址 0x2AAA

??? 6 – 将 0x0010 写到 FLASH HALF-WORD地址 0x5555

??? *SysAddr16(sysbase,0x5555) = 0x00AA;??? //将值 0x00AA 写到 FLASH HALF-WORD地址 0x5555

??? 6 – 将 0x0030 写到要擦除的 SECTOR 对应的 HALF-WORD地址

??? 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条指令应该是:

??? 假如要擦除SECTOR-1,0x1000 >> 1) = 0x0030;

??? HALF-WORD 编程操纵

??? 写一个HALF-WORD的数据到FLASH中往,需要4个周期的总线写操纵

??? 3 – 将 0x00A0 写到 FLASH HALF-WORD 地址 0x5555

??? 4 – 将编程数据(HALF-WORD)写到对应的 HALF-WORD地址

??? 上面的代码中第4个操纵周期中的ADDR是从ARM处理器的角度来看的BYTE地址,由于在执行写操纵的时候,这样会更方便和更直观.而在 SysAddr16 的宏定义中,OFFSET表示的是相对于FLASH起始地址的HALF-WORD偏移量. 所以需要执行一个右移操纵,把它转换成HALF-WORD

??? 地址.

??? 假如要数据0x4567写到地址0x2往,对应的是FLASH的第1个 HALF-WORD,对应的HALF-WORD地址应该是0x1,0x2 >> 1) = 0x4567;

??? 假如要数据0x89AB写到地址0x4往,对应的是FLASH的第2个HALF-WORD,对应的HALF-WORD地址应该是0x2,0x4 >> 1) = 0x89AB;

??? 假如要数据 0xCDEF 写到地址 0x6 往,对应的是 FLASH 的第 3 个 HALF-WORD,对应的 HALF-WORD 地址应该是0x3,0x6 >> 1) = 0xCDEF;

??? 7. ADS 版源代码下载

??? 假如用户有需要,可以往下载在前面讨论的 2 个实例的 ADS 版的完整源代码和 FLASH 数据手册.提供给用户的程序都是在实际使用过程中经过测试的.源代码只供用户参考,并不一定能直接使用在用户的开发板上.用户需要根据自己实际使用的芯片进行相应的修改.

??? 源代码下载链接:Http://www.hjtag.com/forum/forumdisplay.php?fid=3

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读