博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
第一期_Nor Flash
阅读量:4588 次
发布时间:2019-06-09

本文共 7123 字,大约阅读时间需要 23 分钟。

Nor Flash的连接线有地址线,数据线,片选信号读写信号等,Nor Flash的接口属于内存类接口,Nor Flash可以像内存一样读,但是不能像内存一样写,需要做一些特殊的操作才能进行写操作,读只需像内存一样读很简单。

Nor Flash原理图如图:

Flash介绍

常用的Flash类型有Nor Flash和NAND Flash两种。

Nor Flash由Intel公司在1988年发明,以替代当时在市场上占据主要地位的EPROM和E2PROM。NAND Flash由Toshiba公司在1989年发明。两者的主要差别如下表:

  Nor flash Nand flash
XIP(代码可以直接运行) Yes    NO
性能(擦除) 非常慢(5s) 快(3ms)
性能(写)
性能(读)
可靠性 较高,位反转的比例小于NAND Flash的10% 比较低,位反转比较常见,必须有校验措施,比如TNR必须有坏块管理措施
可擦除次数 10000 ~ 100000 100000 ~ 1000000
生命周期 低于NAND Flash的10% 是Nor Flash的10倍以上
接口 与RAM接口相同 I/O接口
易用性 容易 复杂
主要用途 常用于保存代码和关键数 用于保存数据
价格 高  

Nor Flash支持XIP,即代码可以直接在Nor Flash上执行,无需复制到内存中。这是由于NorF lash的接口与RAM完全相同,可以随机访问任意地址的数据。Nor Flash进行读操作的效率非常高,但是擦除和写操作的效率很低,另外,Nor Flash的容量一般比较小。NAND Flash进行擦除和写操作的效率更高,并且容量更大。一般而言,Nor Flash用于存储程序,NAND Flash用于存储数据。基于NAND Flash的设备通常也要搭配Nor Flash以存储程字。

Flash存储器件由擦除单元(也称为块)组成,当要写某个块时,需要确保这个块己经 被擦除。Nor Flash的块大小范围为64kB、128kB:NAND Flash的块大小范围为8kB,64kB,擦/写一个Nor Flash块需4s,而擦/写一个NAND Flash块仅需2ms。Nor Flash的块太大,不仅增加了擦写时间,对于给定的写操作,Nor Flash也需要更多的擦除操作——特别是小文件,比如一个文件只有IkB,但是为了保存它却需要擦除人小为64kB—128kB的Nor Flash块。

Nor Flash的接口与RAM完全相同,可以随意访问任意地址的数据。而NAND Flash的 接口仅仅包含几个I/O引脚,需要串行地访问。NAND Flash一般以512字节为单位进行读写。这使得Nor Flash适合于运行程序,而NAND Flash更适合于存储数据。

容量相同的情况下,NAND Flash的体积更小,对于空间有严格要求的系统,NAND Flash可以节省更多空间。市场上Nor Flash的容量通常为IMB~4MB(也有32MB的Nor Flash),NAND Flash的容量为8MB~512MB。容量的差别也使得Nor Flash多用于存储程序,NAND Flash多用于存储数据。

对于Flash存储器件的可靠性需要考虑3点:位反转、坏块和可擦除次数。所有Flash器件都遭遇位反转的问题:由于Flash固有的电器特性,在读写数据过程中,偶然会产生一位或几位数据错误(这种概率很低),而NAND Flash出现的概率远大于Nor Flash,当位反转发生在关键的代码、数据上时,有可能导致系统崩溃。当仅仅是报告位反转,重新读取即可:如果确实发生了位反转,则必须有相应的错误检测/恢复措施。在NAND Flash上发生位反转的概率史高,推荐使用EDC/ECC进行错误检测和恢复。NAND Flash上面会有坏块随机分布在使用前需要将坏块扫描出来,确保不再使用它们,否则会使产品含有严重的故障。NAND Flash每块的可擦除次数通常在100000次左右,是Nor Flash的10倍。另外,因为NAND Flash的块大小通常是NorF lash的1/8,所以NAND Flash的寿命远远超过Nor Flash。

嵌入式Linux对Nor、NAND Flash的软件支持都很成熟。在Nor Flash上常用jffs2文 件系统,而在NAND Flash常用yaffs文件系统。在更底层,有MTD驱动程序实现对它们的读、写、擦除操仵,它也实现了EDC/ECC校验。

Nor Flash的操作

下面我们使用u-boot来体验Nor Flash的操作(开发板设置Nor启动,进入u-boot)。

1).使用OpenJTAG烧写UBOOT到Nor Flash

那么我们怎么用u-boot来操作呢?

Nor Flash手册里会有一个命令的表格,如图: 

下面简单的举一些例子:

复位(reset):往任何一个地址写入F0。

读ID(ReadSiliconID):很多的Nor Flash可以配置成位宽16bit(Word),位宽8bit(Byte)。对于我们使用的jz2440开发板使用是位宽16bit,怎样读ID呢?

根据前面得图可知,往Nor Flash的555地址写AA,再往2AA的地址写入55,再往555的地址写入90,然后就可以读ADI地址,就可以读到DDI数据了。

实例1

读数据:

在u-boot上执行:md.b0

结果(和我们烧进去的数据完全一样):

00000000:170000ea14f09fe514f09fe514f09fe5................00000010:14f09fe514f09fe514f09fe514f09fe5................ 00000020:6001f833c001f8332002f8337002f833`..3...3..3...3 00000030:e002f8330004f8332004f833efbeadde...3...3..3....

可以得出结论:u-boot可以像读内存一样来读nor flash

实例2

读ID(参考Nor手册)

  • 往地址555H写入AAH(解锁)
  • 往地址2AAH写入55H(解锁)
  • 往地址555H写入90H(命令)
  • 读0地址得到厂家ID(C2H)
  • 读1地址得到设备ID(22DAH或225BH)
  • 退出读ID状态:给任意地址写F0H就可以了。

下图为2440和Nor Flash的简易连接图: 

2440的A1接到Nor的A0所以2440发出的地址是,Nor Flash收到的地址左移一位。比如:2440发出(555H<<1)地址,Nor Flash才能收到555H这个地址。

 下面对在Nor Flash的操作,2440的操作,U-BOOT上的操作进行比较,如下表:

Nor Flash的操作 2440的操作 U-BOOT上的操作
往地址555H写入AAH(解锁) 往地址AAAH写入AAH(解锁) mw.waaaaa
往地址2AAH写入55H(解锁) 往地址554H写入55H(解锁) mw.w 554 55
往地址555H写入90H(命令) 往地址AAAH写入90H(命令) mw.w aaa 90
读0地址得到厂家ID(C2H) 读0地址得到厂家ID(C2H) md.w 0 1 (1:表示都一次)
读1地址得到设备ID(22DAH或225BH) 读2地址得到设备ID(22DAH或225BH md.w 2 1 (1:表示都一次)
退出读ID状态:给任意地址写F0H就可以了 退出读ID状态:给任意地址写F0H就可以了 mw.w 0 f0

 

Nor Flash的两种规范

 通常内核里面要识别一个 Nor Flash 有两种方法:

 一种是 jedec 探测,就是在内核里面事先定义一个数组,该数组里面放有不同厂家各个芯片的一些参数,探测的时候将 flash 的 ID 和数组里面的 ID 一一比较,如果发现相同的,就使用该数组的参数。 jedec 探测的优点就是简单,缺点是如果内核要支持的 flash 种类很多,这个数组就会很庞大。内核里面用 jedec 探测一个芯片时,是先通过发命令来获取 flash 的 ID,然后和数组比较,但是 flash.c 中连 ID 都是自己通过宏配置的。

一种是 CFI(common flash interface)探测,就是直接发各种命令来读取芯片的信息,比如 ID、容量等,芯片本身就包含了电压有多大,容量有有多少等信息。

下面对在Nor Flash上操作,2440上操作,U-BOOT上操作cfi 探测(读取芯片信息)进行比较参考芯片手册

Nor Flash上操作cfi 2440上操作cfi U-BOOT上操作cfi
往55H地址写入98H 往AAH地址写入98H mw.w aa 98
读地址10H得到005 读地址20H得到0051 md.w 20 1
读地址11H得到0052 读地址22H得到0052 md.w 22 1
读地址12H得到0059 读地址24H得到0059 md.w 24 1
读地址27H得到容量 读地址4EH得到容量 md.w 4e 1

Nor Flash写数据

 我们在Nor Flash的10000的地址读数据,

md.w  100000  1

 结果:

00100000:ffff..

 在Nor flash的10000的地址写数据下0x1234,

mw.w 100000   1234

 然后在这个地址读数据

md.w  100000  1

 结果:

00100000:ffff(这个地址上的数据没有被修改,写操作无效)。

 怎样把数据写进Nor Flash进去呢?

写数据之前必须保证,要写的地址是擦除的。

下面是Nor Flash的写操作,如下表:

Nor Flash上操作写操作 2440上操作写操作 U-BOOT上操作写操作
往地址555H写AAH(解锁) 往地址AAAH写AAH(解锁) mw.w aaa aa
往地址2AAH写55H(解锁) 往地址554H写55H(解锁) mw.w 554 55
往地址555H写A0H 往地址AAAH写A0H mw.w aaa a0
往地址PA写PD 往地址0x100000写1234h mw.w 100000 1234

 

1).U-BOOT执行完上述指令后,0x1234,就被写到0x100000地址处,

执行:

md.w1000001

结果(1234被写进去):

00100000:1234   4

从这里可以看出来U-BOOT的操作不是很复杂。

2).我们再次往0x100000地址处,写入0x5678,执行如下命令:

mw.w  aaa  aamw.w  554  55mw.w  aaa  a0mw.w  100000  5678

 

查看0x100000地址处的数据

md.w  100000  1

结果:

00100000:12300.

 0x100000地址处的数据不是0x5678,写操作失败,失败的原因是,原来的数据已经是0x1234不是全0xffff,再次写操作失败,(Nor Flash只有先擦出,才能烧写)。

先擦除(参考Nor Flash芯片手册)

Nor Flash操作      u-boot操作555H AAH      mw.w   aaa    aa2AAH 55H      mw.w   554    55555H 80H      mw.w    aaa   80555H AAH      mw.w   aaa    aa2AAH 55H      mw.w   554    55SA  30H //往扇区地址写入30   mw.w  100000  30

 执行完上述指令后测试

执行:

md.w  100000  1

结果:

00100000:ffff..

已被擦除,这个时候再次烧写就不会有问题了。

再烧写

mw.w  aaa   aamw.w  554   55mw.w  aaa   a0mw.w  100000  5678

测试烧写结果 执行:

md.w  100000  1

结果:

00100000:5678  xV

数据被烧写进去,烧写成功。

总结:我们烧写时,如果上面的数据,不是0ffff,没有被擦除过,我们就要先擦出,擦除完后,才可以烧写,擦除烧写的命令可以从芯片手册里面获得。

Nor Flash编程_识别

 本节实例的目的目的:识别nor flash 发送命令函数 nor_cmd函数代码如下,往NOR Flash某个地址发送指令,

/* offset是基于NOR的角度看到 */18	void nor_cmd(unsigned int offset, unsigned int cmd) 19 { 20 nor_write_word(NOR_FLASH_BASE, offset, cmd); 21 }

nor_read_word函数是从NOR Flash 读取两个字节(本开发板位宽16bit),读取数据的地址,是基于2440,所以读取NOR Flash某个地址上的数据时,需要把NOR Flash对应的地址左移一位(地址乘以2)。

unsigned int nor_read_word(unsigned int base, unsigned int offset) 24 { 25 volatile unsigned short *p = (volatile unsigned short *)(base + (offset << 1)); 26 return *p; 27 }

读取地址中的数据

向nor_dat函数中写入NOR Flash某个地址,返回该NOR Flash地址上的数据。

unsigned int nor_dat(unsigned int offset) 30 { 31 return nor_read_word(NOR_FLASH_BASE, offset); 32 }

进入NOR FLASH的CFI模式,读取各类信息

do_scan_nor_flash函数代码如下,该函数的功能:进入CFI模式读取NOR Flash中的厂家ID,设备ID,容量等信息。

50/* 进入NOR FLASH的CFI模式51 * 读取各类信息52 */53	void do_scan_nor_flash(void) 54 { 55 char str[4]; 56 unsigned int size; 57 int regions, i; 58 int region_info_base; 59 int block_addr, blocks, block_size, j; 60 int cnt; 61 62 int vendor, device; 63 64 /* 打印厂家ID、设备ID */ 65 nor_cmd(0x555, 0xaa); /* 解锁 */ 66 nor_cmd(0x2aa, 0x55); 67 nor_cmd(0x555, 0x90); /* read id */ 68 vendor = nor_dat(0); 69 device = nor_dat(1); 70 nor_cmd(0, 0xf0); /* reset */ 71 72 nor_cmd(0x55, 0x98); /* 进入cfi模式 */ 073 74 str[0] = nor_dat(0x10); 75 str[1] = nor_dat(0x11); 76 str[2] = nor_dat(0x12); 77 str[3] = '\0'; 78 printf("str = %s", str); 79 80 /* 打印容量 */ 81 size = 1<<(nor_dat(0x27)); 82 printf("v=0x%x,d=0x%x,s=0x%x,%dM",vendor,device,size,size/(1024*1024)); 83 84 /* 打印各个扇区的起始地址 */ 85 /* 名词解释: 86 * erase block region : 里面含有1个或多个block, 它们的大小一样 87 * 一个nor flash含有1个或多个region 88 * 一个region含有1个或多个block(扇区) 89 90 * Erase block region information: 91 * 前2字节+1 : 表示该region有多少个block 92 * 后2字节*256 : 表示block的大小 93 */ 94 95 regions = nor_dat(0x2c); 96 region_info_base = 0x2d; 97 block_addr = 0; 98 printf("Block/Sector start Address:"); 99 cnt = 0; 100 for (i = 0; i < regions; i++) 101 {

转载于:https://www.cnblogs.com/yekongdebeijixing/p/10512336.html

你可能感兴趣的文章
深入理解DIP、IoC、DI以及IoC容器
查看>>
赋值文件
查看>>
Vue 数组 字典 template v-for 的使用
查看>>
蓝牙模块选择经验谈
查看>>
java中==和equals
查看>>
CCActionPageTurn3D
查看>>
python random
查看>>
esp32-智能语音-cli(调试交互命令)
查看>>
netty与MQ使用心得
查看>>
MySQL系列教程(一)
查看>>
面向对象设计七大原则
查看>>
React-Redux之connect
查看>>
ubuntu下如何卸载nvidia显卡驱动?
查看>>
tp框架支付宝手机网页支付
查看>>
【栈】【AOJ-558】窃取任务
查看>>
两个被混淆的单词property和attribute
查看>>
apache反向代解决绝对路径可能出现的问题
查看>>
Oracle Metadata
查看>>
jquery 实现3d切割轮播图
查看>>
学习spring cloud 笔记
查看>>