罗马不是一天建成的。
#include
int main()
{
printf("hello\n");
}
我想,如果你能够让上面的这个hello.c,能够在没有操作系统的帮助下正确运行,那离编写一个切实可用的bootload就不远了。
上面说了一大堆,总结下来要运行这个hello.c要以下几个步骤:
初始化硬件(CPU,SDRAM,串口)
定位hello到链接指定的位置
初始化bss段
初始化栈指针
实现printf等函数
执行main
那就开始干吧。
8、bootload版本的hello.c
软件可以到http://www.nidetech.com/download/boothello.rar下载,大致说一下几个文件作用。
[sjl@sjl boothello]$ ls -l
total 52
-rw-rw-r-- 1 sjl sjl 731 2009-07-31 09:53 board.c
-rw-rw-r-- 1 sjl sjl 112 2009-07-31 09:55 config.h
-rw-rw-r-- 1 sjl sjl 354 2009-07-31 10:00 config.mk
drwxrwxr-x 2 sjl sjl 4096 2009-07-31 10:02 drivers
drwxrwxr-x 5 sjl sjl 4096 2009-07-31 09:56 include
-rw-rw-r-- 1 sjl sjl 1906 2009-07-31 08:14 init.S
drwxrwxr-x 2 sjl sjl 4096 2009-07-31 10:02 lib
-rw-rw-r-- 1 sjl sjl 9448 2009-07-31 09:57 lowlevel.S
-rw-rw-r-- 1 sjl sjl 76 2009-07-31 08:27 main.c
-rw-rw-r-- 1 sjl sjl 891 2009-07-31 08:10 Makefile
-rw-rw-r-- 1 sjl sjl 342 2009-02-24 15:55 vmlinux.lds
Makefile,config.mk 基本上没什么好说的,参考了u-boot的做法。
board.c lowlevel.S是与板子相关的初始化内容。虽然都是基于mx31的板子,但选择不同的外围器件,初始化参数会有不同。比如不同的SDRAM芯片的参数,不同的SDRAM容量,不同的GPIO使用等等。
main.c 里面实现了我们的main函数。
vmlinux.lds是链接脚本文件。指定了段的分布。
[sjl@sjl boothello]$ ls drivers/
Makefile serial.c
drivers里面只有一个串口的“驱动”。要在调试串口输出当然要有“驱动”了。
[sjl@sjl boothello]$ ls lib
Makefile string.c stubs.c vsprintf.c
lib目录里面实现了printf,strlen等C的库函数。基本上都是从U-boot里面抄的。
下载软件包直接make,生成的image.bin可以直接烧到flash里面运行。你的调试串口(ttyS3)就会输出hello,当然你可以修改config.h来指定不同的调试串口。
顺便说明一下,因为MX31内部有SRAM,所以这个程序可以不初始化SDRAM,不使用SDRAM。也就是说不用焊接SDRAM也可以在MX31的板子上跑程序哦。
[sjl@sjl boothello]$ make
...
arm-linux-objcopy -O binary vmlinux image.bin
[sjl@sjl boothello]$ ls image.bin -l
-rwxrwxr-x 1 sjl sjl 4092 2009-07-31 10:13 image.bin
9、下一步
bootload版的hello,虽然能够说明bootload需要做的初始化动作,但毕竟离正真的bootload还是有距离。比如要操作flash,下载程序,加载操作系统,还有的甚至有网络功能,文件系统功能。这需要一点点往上面添加。还是那句话"罗马不是一天建成的"。 期待下一篇文章<<操作NOR Flash>>。
成都来的科技有限公司开发中心--软件工程师开发心得
成都莱得科技有限公司--是一家专注于嵌入式领域,为客户提供定制服务的高科技公司。根据客户的需求,为客户提供一站式服务:总体解决方案,嵌入式平台硬件设计,底层驱动设计(BSP),应用软件设计,产品生产。 专注于freescale,intel,marvell的嵌入式ARM的开发。www.nidetech.com