Chinaunix首页 | 论坛 | 博客
  • 博客访问: 9837
  • 博文数量: 3
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 0
  • 用 户 组: 普通用户
  • 注册时间: 2013-10-17 12:11
文章分类
文章存档

2013年(3)

我的朋友

分类: 嵌入式

2013-10-17 12:14:26

要跑操作系统免不了需要bootloader,我理解吧,bootloader这类的东西就是为操作系统准备一个好的启动环境,把什么内存啊、 网络都初始化好,让操作系统能够快乐的启动起来。嵌入式系统的硬件环境千变万化,嵌入式工程师常常要面对一个全新的硬件环境,而一个软件系统,往往就像一辆汽车,起步时是最艰难的,起步的好,各方面都初始化的合适,往后的运行就爽歪歪,否则,可能开了两步就熄火了。软件系统的起步就是bootloader,为了能够方便开发,使bootloader与操作系统分离,各公司、组织开发了许多bootloader,比如什么Windows里面用的ntloader、Linux桌面版用得比较多的grub、以及嵌入式系统里面的bootRom、redBoot和现在大红大紫的uboot。我们这篇文章要移植Vxwork,虽然有个官方推荐的bootRom,不过本人打算以后再弄,先学习一下uboot吧,毕竟资源比较多。

  1. 现在就正式开始引导过程,单片机、微机系统这些基础课程里面我了解到,CPU通电后会从地址0开始执行代码。这个过程在不同的处理器架构中会略有不同,但是思路是一致的。CPU通电后,一切都是新的,它也不知道该干什么,所以只能从0开始执行。那么这个0地址在物理上是映射到哪里呢,这里就要提到存储器的一点知识了。首先,0地址在RAM或者ROM的话肯定没问题,CPU读取、执行就OK了,但是前者断电丢失、后者无法轻易擦鞋,所以常用的软件都是保存在FLASH中,FLASH有很多种,一般用得比较多的就是NOR FLASH、NAND FLASH还有SPI FLASH,他们都有各自的历史和特点,有兴趣的可以看看。其中NOR的特点是接口简单,可以像RAM那样用,同时不容易出错。而NAND的特点是读写速度快,但是接口复杂,不能直接寻址,并且可能会出现坏块,所以需要运用ECC校验技术,总的一个字:烦!SPI FLASH就更不靠谱了,用的串行方式传输数据,那就注定更加不能直接寻址了。所以这三种FLASH里面只有NOR FLASH上可以直接跑代码,也就是CPU可以直接从NOR FLASH取指令、执行;其他两种FLASH都做不到这一点。针对这个问题,一般有两种思路,一是用ROM或者NOR FLASH固化一段程序,执行引导任务,把uboot什么的之类加载到RAM里面再跑;另外就是像一些2410那样,在上电时自动把NAND的前4K数据拷贝到RAM,再从RAM开始跑。
  2. OMAP采用的是前者的方式,在片内的ROM中固化了一个D800K00x系列的RBL(ROM bootloader),然后它会搜索每个FLASH块的第一个Page,如果在这个Page上找到一个Magic Number(0x41504954,要是我设计这个bootloader会用老婆的生日做magic number),之后跟着很多命令(详细参考http://focus.ti.com/lit/an/sprab04f/sprab04f.pdf ),例如加载一个UBL(User Bootloader)。在OMAP L137中,由于上电后ARM还处于休眠状态,需要DSP来将其唤醒,所以RBL需要先加载一个DSP上跑的UBL,其中初始化内存、激活ARM,最后开始原地踏步;ARM上电后会从一个默认片内RAM地址开始跑程序,它把uboot这样的高级bootloader加载到片外RAM(片内的太小放不下),再从相应地址开始跑。这样一个过程里,要开发DSP的UBL,ARM的UBL,以及uboot这三级bootloader,UBL代码的模板可以从OMAP L137的PSP(Plateform Support Package)中获取。虽然从模板出发只要做很少的修改,但是还是显得很麻烦。下面,真正的神器要登场了:

  3. 为了省事,TI推出了一种AIS机制(Application Image Script),并且有专门的一套工具,D800K00x AISGen,以及raw2coff.exe.这套工具用图形化的方式生成一个镜像,里面包含了上述所有的功能。只要将uboot或者其他bootloader的elf镜像经过raw2coff转化,再用AISGen生成AIS镜像,烧入到OMAP L137的NAND FLASH即可。参考http://focus.ti.com/lit/an/sprab04f/sprab04f.pdf 补充一下:L137的FLASH烧写也挺麻烦的,有个专门的程序,在DSP上面跑的,一般EVM和DEC的开发包里有,叫做nandwrite,在CCS里面加载运行后会弹出对话框,提示输入镜像路径(真神啊!)。
    下面就详细解析一下这套工具:

编一个helloworld程序

交叉编译生成main,这个main是elf格式的,用objcopy生成二进制文件
  1. arm-linux-objcopy --gap-fill=0xff -O binary u-boot u-boot.bin
再用TI提供的raw2coff转换为coff格式
  1. raw2coff 0xC1080000 main.out main
打开AisGen for D800K001这个软件,用默认设置,根据上面资料的提示生成main.ais
这个ais可以烧到FLASH里面,可以用aisparse.exe 来解析main.ais的结构:
  1. unsigned int nvram_image[] = {

  2. /* 0x00000000 */ 0x41504954, // MAGIC 标示符

  3. /* 0x00000004 */ 0x5853590D, // Function Execute 初始化PLL
  4. /* 0x00000008 */ 0x00020000, // Function[0]
  5. /* 0x0000000C */ 0x18010104, // Arg[0]
  6. /* 0x00000010 */ 0x000601B9, // Arg[1]

  7. /* 0x00000014 */ 0x5853590D, // Function Execute 初始化SDRAM-EMIFB
  8. /* 0x00000018 */ 0x00040002, // Function[2]
  9. /* 0x0000001C */ 0x00018421, // Arg[0]
  10. /* 0x00000020 */ 0x10912A08, // Arg[1]
  11. /* 0x00000024 */ 0x70090005, // Arg[2]
  12. /* 0x00000028 */ 0x000003FA, // Arg[3]

  13. /* 0x0000002C */ 0x58535904, // Disable CRC

  14. /* 0x00000030 */ 0x58535901, // Section Load 加载一段DSP要执行的代码,初始化FLASH、开启ARM等等
  15. /* 0x00000034 */ 0x11800020, // Address
  16. /* 0x00000038 */ 0x00000340, // Size
  17. /* 0x0000003C */ // Data
  18. /* 0x0000003C */ 0x01BD14F6,
  19. /* 0x00000040 */ 0x00002000,
  20. ................省略

  21. /* 0x000003D4 */ 0x58535905, // Jump 执行刚刚加载的DSP代码
  22. /* 0x000003D8 */ 0x11800280, // Address

  23. /* 0x000003DC */ 0x58535901, // Section Load
  24. /* 0x000003E0 */ 0xC1080000, // Address 加载hello world代码到SDRAM
  25. /* 0x000003E4 */ 0x00001F47, // Size
  26. /* 0x000003E8 */ // Data
  27. /* 0x000003E8 */ 0x464C457F,
  28. /* 0x000003EC */ 0x00010101,
  29. /* 0x000003F0 */ 0x00000000,
  30. /* 0x000003F4 */ 0x00000000,
  31. /* 0x000003F8 */ 0x00280002,
  32. ...........................
  33. /* 0x00002330 */ 0x58535965, // ARM Entry Point 设定ARM程序入口
  34. /* 0x00002334 */ 0xC1080000, // Address

  35. /* 0x00002338 */ 0x58535901, // Section Load
  36. /* 0x0000233C */ 0x11800000, // Address 加载DSP代码为原地踏步
  37. /* 0x00002340 */ 0x00000020, // Size
  38. /* 0x00002344 */ // Data
  39. /* 0x00002344 */ 0x0001E000,
  40. /* 0x00002348 */ 0x00000012,
  41. /* 0x0000234C */ 0x00008000,
  42. /* 0x00002350 */ 0x00000000,
  43. /* 0x00002354 */ 0x00000000,
  44. /* 0x00002358 */ 0x00000000,
  45. /* 0x0000235C */ 0x00000000,
  46. /* 0x00002360 */ 0x00000000,

  47. /* 0x00002364 */ 0x58535906, // Jump N Close 结束,交出执行权
  48. /* 0x00002368 */ 0x11800000, // Address
  49. };

这个工具可以说非常方便,但是有一些帖子反映新版本的RBL(D800K003)及工具对ARM的启动支持有问题,貌似很多机制发生了变化。这个放到后面再深入探讨吧。

以下是乱七八糟的参考资料:
http://hi.baidu.com/614/blog/item/d630e7c11b5762db38db4965.html

阅读(1051) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~