既然不能使用新的U-boot,那就优化一点是一点,慢慢干吧。
1.去掉启动时的按键等待
U-boot 启动的时候出现一个 Hit any key to stop autoboot
static __inline__ int abortboot(int bootdelay)
#ifdef CONFIG_SILENT_CONSOLE
#endif
这样,就不需要等待了,如果想进入U-boot,就在上电的时候按住u吧,把它改成一个固定的键而不是任意键,因为串口线很容易受到干扰,如果是任意键的话,运行时即使不想进去有时也会进入U-boot的命令行。
2.去掉网卡的初始化
每次上电,U-boot 都会初始化网卡,其实这根本不需要,把配置文件中
#define CONFIG_MII
去掉,启动时就不会初始化了,需要使用TFTP时,它会自动初始化,又节省了3.4秒的启动时间。
3.智能读取OS Image
U-boot 通过nand read 来读取OS Image,通常为了避免麻烦,我们设置的读取长度要比实际OS长度长一些,多读的那部分纯粹是浪费CPU时间,能不能精确判断读取长度呢,当然可以,为了不影响系统的正常功能,扩展一个nand read.os 指令来读取,修改方法如下:
在 nand_read_options_t 里面添加一个成员 int is_os_img
在函数 int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
修改读操作的判断语句,添加 !strcmp(s, ".os"),然后设置opts.is_os_img = !strcmp(s, ".os");大概修改后结果参考第7步代码。
代码,检测如果opts->is_os_img == 1 并且是第一次读取(2024B)之后,检查度取得结果是否是OS Image,如果是更新需要读取的长度,否则,也不需要再往下读了,直接返回错误就可以了
4.去掉OS Image 内存复制过程
使用 nand read 读取OS Image 后,U-boot 使用 bootm 指令来启动Linux,检查其实现代码
int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
发现他会把已经读取到内存中的OS Image 在复制到一个指定的位置,OS Image 中的头部参数,这个值一般是固定的,本系统使用的是 0x70008000, 如果在 nand read 时读到的内存位置恰好合适,就可以省掉这些毫秒数了,做法如下:
nand read.os 0x70007FC0 0x100000 0x500000
(其中 0x70007FC0 = 0x70008000 - sizeof(sizeof(image_header_t)))
然后在内存复制的地方(函数do_bootm中),加入修改,跳过内存复制
对于我们的Kernel,修改后大小是1.4M,省去这个搬移过程,节省了大约800ms的时间
5.减少内存初始化的时间
在U-boot 初始化时,在 start_armboot 函数中,多次使用到了 memset函数,其中最耗时的是在mem_malloc_init函数中调用memset 初始化 512K内存的调用,检查U-boot 1.3.4对memset的实现,发现是最简单的字节复制,把它改为按32bits复制的方式,这些memset 调用所花费的时间立即从202ms减少到了45ms
修改方法,再 string.c 中,找到memset函数,修改其实现(代码是从U-boot 2011.12 中复制过来的)
void * memset(void * s,int c,size_t count)
6.减少NAND初始化时间
7.添加Yaffs2支持
从网上各位前辈的论述中,都发现YAFFS比JFFS2要快,也决定测试一下,从YAFFS网站下载最新的代码,按照说明加入到Linux 中,重新编译内核,让内核支持YAFFS2(按照默认的选项就可以了),弄一个空的分区,格式化成YAFFS2格式,感觉的确比较快,把ROOTFS复制到这个分区,然后修改Linux启动参数让它把YAFFS2分区当作根分区启动,发现果然快了不少,初始化和挂载根分区仅需要370ms,比JFFS2的速度快多了,决定就采用YAFFS2作为根文件系统了。自己在u-boot中添加对yaffs2 image的支持
说起来容易,真正做起来还是很麻烦的,总是不能把yaffs2的image 烧写成功,不知道是Image不正确还是Uboot没改对,折腾了几天也没搞定,最后终于发现了一个第三方的工具
http://code.google.com/p/yaffs2utils/
下载,编译,制作Image,验证,OK,把新工具生成的IMAGE与YAFFS2自带的工具对照,发现YAFFS2自带的工具生成的IMAGE不正确,晕死。
重新修改UBoot,改了很少一部份代码,就可以了。
依然是在函数do_nand中修改,添加一个扩展 nand write.y 指令来写入Image:
按照惯例,YAFFS2的第一个块不使用,留给文件系统自己使用,在 nand_write_options_t 里面添加一个成员 int skip_first_block;
在函数 int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
修改读写操作的判断语句,添加 !strcmp(s, ".y"),然后设置opts.is_os_img = !strcmp(s, ".os");大概修改后结果如下(红色部分)