“第015课 Nor Flash”的版本间的差异
Baiwen root(讨论 | 贡献) |
Baiwen root(讨论 | 贡献) |
||
第46行: | 第46行: | ||
嵌入式Linux对Nor、NAND Flash的软件支持都很成熟。在Nor Flash上常用jffs2文 | 嵌入式Linux对Nor、NAND Flash的软件支持都很成熟。在Nor Flash上常用jffs2文 | ||
件系统,而在NAND Flash常用yaffs文件系统。在更底层,有MTD驱动程序实现对它们的读、写、擦除操仵,它也实现了EDC/ECC校验。 | 件系统,而在NAND Flash常用yaffs文件系统。在更底层,有MTD驱动程序实现对它们的读、写、擦除操仵,它也实现了EDC/ECC校验。 | ||
+ | |||
+ | == Nor Flash的操作 == | ||
+ | 下面我们使用u-boot来体验Nor Flash的操作(开发板设置Nor启动,进入u-boot)。 | ||
+ | 1),使用OpenJTAG烧写UBOOT到Nor Flash | ||
+ | 那么我们怎么用u-boot来操作呢? | ||
+ | Nor Flash手册里会有一个命令的表格,如图: | ||
+ | [[File:chapter15_lesson1_002.png|800px]] | ||
+ | 下面简单的举一些例子: | ||
+ | 复位(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 | ||
+ | 结果(和我们烧进去的数据完全一样): | ||
+ | <syntaxhighlight lang="c" > | ||
+ | 00000000:170000ea14f09fe514f09fe514f09fe5................ | ||
+ | 00000010:14f09fe514f09fe514f09fe514f09fe5................ | ||
+ | 00000020:6001f833c001f8332002f8338002f833`..3...3..3...3 | ||
+ | 00000030:e002f8330004f8332004f833efbeadde...3...3..3.... | ||
+ | </syntaxhighlight> | ||
+ | 可以得出结论: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的简易连接图: | ||
+ | [[File:chapter15_lesson1_003.jpg|800px]] | ||
+ | 2440的A1接到Nor的A0所以2440发出的地址是,Nor Flash收到的地址左移一位。比如:2440发出(555H<<1)地址,Nor Flash才能收到555H这个地址。 | ||
+ | 下面对在Nor Flash的操作,2440的操作,U-BOOT上的操作进行比较,如下表: | ||
+ | {| class="wikitable" | ||
+ | |- | ||
+ | ! 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 | ||
+ | |} | ||
+ | |||
+ | 1),当执行过md.w 0 1 | ||
+ | 结果(输出厂家ID): | ||
+ | 00000000:00c2..(00c2就是厂家ID) | ||
+ | 2),当执行过md.w 2 1 | ||
+ | 结果(输出设备ID): | ||
+ | 00000002:2249I"(2249就是设备ID) | ||
+ | |||
+ | 3),当执行mw.w 0 f0,就退出读ID的状态, | ||
+ | 执行:md.b0 | ||
+ | 结果: | ||
+ | 00000000:17.(读到的就是Nor Flash地址·0的数据) | ||
+ | |||
+ | == Nor Flash的两种规范 == | ||
+ | 通常内核里面要识别一个 Nor Flash 有两种方法: | ||
+ | 一种是 jedec 探测,就是在内核里面事先定义一个数组,该数组里面放有不同厂家各个芯片的一些参数,探测的时候将 flash 的 ID 和数组里面的 ID 一一比较,如果发现相同的,就使用该数组的参数。jedec 探测的优点就是简单,缺点是如果内核要支持的 flash 种类很多,这个数组就会很庞大。内核里面用 jedec 探测一个芯片时,是先通过发命令来获取 flash 的 ID,然后和数组比较,但是 flash.c 中连 ID 都是自己通过宏配置的。 | ||
+ | 一种是 CFI(commonoflashinterface)探测,就是直接发各种命令来读取芯片的信息,比如 ID、容量等,芯片本身就包含了电压有多大,容量有有多少等信息。 | ||
+ | 下面对在Nor Flash上操作,2440上操作,U-BOOT上操作cfi 探测(读取芯片信息)进行比较参考芯片手册。 | ||
+ | {| class="wikitable" | ||
+ | |- | ||
+ | ! Nor Flash上操作cfi !! 2440上操作cfi !! U-BOOT上操作cfi | ||
+ | |- | ||
+ | | 往55H地址写入98H || 往AAH地址写入98H || mw.w aa 98 | ||
+ | |- | ||
+ | | 读地址10H得到0051 || 读地址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.. | ||
+ | 在noroflash的10000的地址写数据下0x1234, | ||
+ | mw.w 100000 1234 | ||
+ | 然后在这个地址读数据, | ||
+ | md.w 100000 1 | ||
+ | 结果: | ||
+ | 00100000:ffff(这个地址上的数据没有被修改,写操作无效)。 | ||
+ | |||
+ | 怎样把数据写进Nor Flash进去呢?参考图1-3,写数据之前必须保证,要写的地址是擦除的。下面是Nor Flash的写操作,如下表: | ||
+ | {| class="wikitable" | ||
+ | |- | ||
+ | ! 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 aa | ||
+ | mw.w 554 55 | ||
+ | mw.w aaa a0 | ||
+ | mw.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 aa | ||
+ | 2AAH 55H mw.w 554 55 | ||
+ | 555H 80H mw.w aaa 80 | ||
+ | 555H AAH mw.w aaa aa | ||
+ | 2AAH 55H mw.w 554 55 | ||
+ | SA 30H //往扇区地址写入30 mw.w 100000 30 | ||
+ | |||
+ | 执行完上述指令后测试 | ||
+ | 执行:md.w 100000 1 | ||
+ | 结果:00100000:ffff.. | ||
+ | 已被擦除,这个时候再次烧写就不会有问题了。 | ||
+ | |||
+ | 再烧写 | ||
+ | mw.w aaa aa | ||
+ | mw.w 554 55 | ||
+ | mw.w aaa a0 | ||
+ | mw.w 100000 5678 | ||
+ | |||
+ | 测试烧写结果 | ||
+ | 执行:md.w 100000 1 | ||
+ | 结果:00100000:5678 xV | ||
+ | 数据被烧写进去,烧写成功。 | ||
+ | |||
+ | 总结:我们烧写时,如果上面的数据,不是0ffff,没有被擦除过,我们就要先擦出,擦除完后,才可以烧写,擦除烧写的命令可以从芯片手册里面获得。 | ||
+ | |||
= 第002节_Nor Flash编程_识别 = | = 第002节_Nor Flash编程_识别 = | ||
第59行: | 第217行: | ||
<categorytree mode=all background-color:white;">ARM裸机加强版</categorytree> | <categorytree mode=all background-color:white;">ARM裸机加强版</categorytree> | ||
+ | [[Category:ARM裸机加强版 ]] | ||
+ | |||
[[Category:ARM裸机加强版 ]] | [[Category:ARM裸机加强版 ]] |
2018年1月18日 (四) 18:08的版本
目录
第001节_Nor Flash原理及硬件操作
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 | NAND |
---|---|---|
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:6001f833c001f8332002f8338002f833`..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 |
1),当执行过md.w 0 1 结果(输出厂家ID): 00000000:00c2..(00c2就是厂家ID) 2),当执行过md.w 2 1 结果(输出设备ID): 00000002:2249I"(2249就是设备ID)
3),当执行mw.w 0 f0,就退出读ID的状态, 执行:md.b0 结果: 00000000:17.(读到的就是Nor Flash地址·0的数据)
Nor Flash的两种规范
通常内核里面要识别一个 Nor Flash 有两种方法: 一种是 jedec 探测,就是在内核里面事先定义一个数组,该数组里面放有不同厂家各个芯片的一些参数,探测的时候将 flash 的 ID 和数组里面的 ID 一一比较,如果发现相同的,就使用该数组的参数。jedec 探测的优点就是简单,缺点是如果内核要支持的 flash 种类很多,这个数组就会很庞大。内核里面用 jedec 探测一个芯片时,是先通过发命令来获取 flash 的 ID,然后和数组比较,但是 flash.c 中连 ID 都是自己通过宏配置的。 一种是 CFI(commonoflashinterface)探测,就是直接发各种命令来读取芯片的信息,比如 ID、容量等,芯片本身就包含了电压有多大,容量有有多少等信息。 下面对在Nor Flash上操作,2440上操作,U-BOOT上操作cfi 探测(读取芯片信息)进行比较参考芯片手册。
Nor Flash上操作cfi | 2440上操作cfi | U-BOOT上操作cfi |
---|---|---|
往55H地址写入98H | 往AAH地址写入98H | mw.w aa 98 |
读地址10H得到0051 | 读地址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.. 在noroflash的10000的地址写数据下0x1234, mw.w 100000 1234 然后在这个地址读数据, md.w 100000 1 结果: 00100000:ffff(这个地址上的数据没有被修改,写操作无效)。
怎样把数据写进Nor Flash进去呢?参考图1-3,写数据之前必须保证,要写的地址是擦除的。下面是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 aa mw.w 554 55 mw.w aaa a0 mw.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 aa 2AAH 55H mw.w 554 55 555H 80H mw.w aaa 80 555H AAH mw.w aaa aa 2AAH 55H mw.w 554 55 SA 30H //往扇区地址写入30 mw.w 100000 30
执行完上述指令后测试 执行:md.w 100000 1 结果:00100000:ffff.. 已被擦除,这个时候再次烧写就不会有问题了。
再烧写 mw.w aaa aa mw.w 554 55 mw.w aaa a0 mw.w 100000 5678
测试烧写结果 执行:md.w 100000 1 结果:00100000:5678 xV 数据被烧写进去,烧写成功。
总结:我们烧写时,如果上面的数据,不是0ffff,没有被擦除过,我们就要先擦出,擦除完后,才可以烧写,擦除烧写的命令可以从芯片手册里面获得。