U-Boot NAND FLASH移植
——西伯利亚的风
为了使u-boot支持NAND FLASH,实现u-boot读写NAND FLASH,我们需要根据
开发板的具体情况修改u-boot,增加NAND FLASH驱动。
一、移植环境
1.u-boot版本1.1.6
NAND K9F2G08
SDRAM K4S561632 * 2)
3.Linux: ubuntu 9.10
二、移植思想
根据u-boot的框架,大致可以确定移植需要做的工作:
1.修改配置文件smdk2410.h,启用NAND FLASH设备
2.如有需要,根据实际情况增加开发板相关的NAND FLASH设备的底层驱动
3.根据出现的问题、错误进行细微调整
三、移植步骤
1.修改配置文件
参考韦老师的书《嵌入式Linux应用开发完全手册》,开始我们的移植工作。首先在配置文件smdk2410.h(路径:include/configs/smdk2410.h)的宏CONFIG_COMMANDS中增加CFG_CMD_NAND:
/***********************************************************
* Command defini
tion
***********************************************************/
#define CONFIG_COMMANDS
(CONFIG_CMD_DFL|
CFG_CMD_CACHE|
CFG_CMD_NAND|
/*CFG_CMD_EEPROM |*/
/*CFG_CMD_I2C|*/
/*CFG_CMD_USB|*/
CFG_CMD_REGINFO|
CFG_CMD_PING|
CFG_CMD_DATE|
CFG_CMD_ELF)
然后,增加NAND FLASH的一些宏,启用NAND FLASH设备。在配置文件smdk2410.h(路径:include/configs/smdk2410.h)中增加以下有关NAND FLASH的宏定义:
/*NAND FLASH config*/
#define CFG_NAND_BASE 0
#define CFG_MAX_NAND_DEVICE 1
#define NAND_MAX_CHIPS 1
至此,第一阶段“修改配置文件smdk2410.h,启用NAND FLASH设备”工作已经完成,我们编译看看会出现什么问题。在u-boot根目录make,结果如下:
In function `nand_init':
drivers/nand/nand.c:50: undefined reference to `board_nand_init'
make: *** [u-boot] Error 1
看来board_nand_init未定义。根据分析可知,board_nand_init在函数nand_init()中被调用。查看nand_init()发现,缺少函数board_nand_init()的定义。根据函数名,可以推断出主要是完成开发板上的NAND FLASH的初始化。
2.增加NAND FLASH底层驱动
board_nand_init()主要实现开发板上NAND FLASH芯片K9F2G08的底层驱动。包括芯片时序设置,底层函数的实现。
附件中Jz2440_nand.c就是已经移植好的NAND FLASH底层驱动,我们将它加入到u-boot中与CPU相关的文件夹cpu/arm920t/s3c24x0/,并修改当前文件夹下的Makefile(路径:cpu/arm920t/s3c24x0/Makefile):
COBJS = i2c.o interrupts.o serial.o speed.o
u***_ohci.o Jz2440_nand.o
红色为新增。
3.解决其他错误
增加驱动后,再次编译,出现错误:
In function `s3c2440_nand_select_chip':
undefined reference to `S3C2440_GetBase_NAND'
提示函数S3C2440_GetBase_NAND()未定义,参考S3C2410_GetBase_NAND(),在s3c2410.h(路径:include/s3c2410.h)中增加函数
static inline S3C2440_NAND * const S3C2440_GetBase_NAND(void)
{
return (S3C2440_NAND * const)S3C2440_NAND_BASE;
}
然后增加S3C2440_NAND_BASE的基址
#define S3C2410_NAND_BASE
0x4E000000
#define S3C2440_NAND_BASE
0x4E000000
红色为新增芯片s3c2440中nand 控制器的寄存器基址,查看s3c2440的芯片手册可以知道。
再次编译,通过!
四、NAND FLASH移植测试
将编译好的u-boot.bin通过OpenJtag烧入Jz2440开发板,重启开发板可以看到:
U-Boot 1.1.6 (Mar 28 2012 - 21:26:29)
DRAM: 64 MB
Flash: 512 kB
NAND: 256 MiB
显示NAND FLASH大小为256MB。
在u-boot界面,输入“?nand”命令, 查看nand相关的用法:
Jz2440 # ? nand
nand info - show available NAND devices
nand device [dev] - show or set current device
nand read[.jffs2] - addr off|partition size
nand write[.jffs2]……
可以看到一系列nand read、nand write命令,以及命令的使用方法。
1.擦除NAND FLASH测试
在u-boot界面输入nand erase 0 1000:
Jz2440 # nand erase 0 1000
NAND erase: device 0 offset 0x0, size 0x1000
Erasing at 0x0 -- 3200% complete.
OK
命令解释:擦除NAND FLASH偏移0个地址后的4K内容(0x1000)
2.读NAND FLASH测试
在u-boot界面输入nand read 30000000 0 1000:
Jz2440 # nand read 30000000 0 1000
NAND read: device 0 offset 0x0, size 0x1000
4096 bytes read: OK
命令解释:读NAND FLASH偏移0个地址 大小为4K的内容(0x1000),放到内存的0x30000000处
在u-boot界面使用md命令查看内存内容:
Jz2440 # md 30000000
30000000: ffffffff ffffffff ffffffff ffffffff ................
30000010: ffffffff ffffffff ffffffff ffffffff ................
30000020: ffffffff ffffffff ffffffff ffffffff ................
30000030: ffffffff ffffffff ffffffff ffffffff ................
30000040: ffffffff ffffffff ffffffff ffffffff ……
可以看到,内存0x30000000处全是f,说明nand read读到的是上一步擦除后NAND FLASH上的内容,说明上一步擦除NAND FLASH成功,本次读操作也OK。
3.写NAND FLASH测试
我们通过nand write写一个小程序leds(运行地址加载地址都是0)到NAND FLASH的0地址,开发板复位后,如果开机启动运行leds,说明写成功,否则写失败。
然后使用nand write,将程序从内存写到NAND FLASH的0地址。
注意:在写NAND FLASH之前先要擦除相应区域,否则会写失败。
擦除4K空间:
Jz2440 # nand erase 0 1000
NAND erase: device 0 offset 0x0, size 0x1000
Erasing at 0x0 -- 3200% complete.
OK
写NAND FLASH
Jz2440 # nand write 30000000 0 1000
NAND write: device 0 offset 0x0, size 0x1000
4096 bytes written: OK
重启Jz2440开发板,可以看到LED在缓慢闪烁了,说明写NAND FLASH 成功!
命令解释:将内存030000000地址处的内容写4K(0x1000)到NAND FLASH 偏移0地址处,前提条件是已经通过loadb命令将leds程序下载到了内存的0x30000000地址处。
由于将leds程序写在了NAND FLASH的0地址,而0地址又是u-boot的存放地址。写完之后,leds将u-boot程序破坏了,所以一上电就执行leds的闪灯程序,不再启动u-boot。如果想使用u-boot,请重新使用OpenJtag烧写u-boot到开发板。
五、移植yaffs注意问题
NAND支持yaffs读写,《嵌入式Linux应用开发完全手册》书上讲的很清楚了,有具体的移植步骤,原理讲解,非常详细,具体参看书《嵌入式Linux应用开发完全手册》P283页。这里有两点问题,需要特别注意:
1.页对齐问题
使用“nand write”命令写NAND FLASH时,每页大小是2K,但是如果使用“nand write.yaffs” 命令写 NAND FLASH,每页大小是2K+64字节。(Jz2440开发板上的NAND FLASH是2K(页) + 64字节(OOB)),也就是说,写文件时,写NAND FLASH空间的大小是2K+64字节的整数倍,否则会报错。
2.文件格式问题
本来想用“nand write.yaffs”将leds.bin烧写进NAND FLASH,看是否写成功,但是发现写完重启开发板,led总是没有反应,试过几次后,恍然大悟:“nand write.yaffs”命令写的是yaffs文件系统格式的文件,而leds.bin不符合yaffs格式,故数据写进NAND FLASH后,数据被打乱,运行不了。所以使用leds.bin测试时,只能验证yaffs写功能,无法看到写的结果。看来自己想错了,呵呵~
六、总结
至此,对NAND FLASH的移植、测试结束。
移植是一项非常耗时间的工作,移植NAND FLASH差不多花了一整天的时间,详细研读了《嵌入式Linux应用开发完全手册》中NAND FLASH的移植说明,翻遍了u-boot中关于NAND FLASH的源码,查阅了大量网上NAND FLASH移植的文章。终于移植成功,同时也明白了u-boot中NAND FLASH 的数据结构,函数调用关系,苦心没有白费。
留一个问题给初学者:u-boot中是如何知道NAND FLASH的容量大小的?要知道配置文件smdk2410.h(路径:include/configs/smdk2410.h)中根本就没有提及NAND FLASH的大小。正在学习NAND FLASH有兴趣的同学请回答。
七、参考文献
《嵌入式Linux应用开发完全手册》第15.2.5节 (P276)
八、附件
1.移植好NAND FLASH的U-Boot烧写文件u-boot.bin
2.u-boot中NAND FLASH驱动Jz2440_nand.c
3.测试代码leds
声明:本文为个人原创,边移植边写,完全来自实践。本文首先发表在百问网(www.100ask.net)转载请指明出处。