您的位置:首页 > 编程语言

玩转pandaboard之u-boot的编译及代码结构

2012-05-03 12:49 417 查看
本文以linaro提供的针对pandaboard的u-boot为例(之后用来加载Android),阐述u-boot编译及代码结构。

U-boot是神马

简单说来就是嵌入式设备的BIOS, 用来初始化嵌入式设备上的各种硬件资源,并引导linux kernel的加载及启动。

详细描述请从http://www.denx.de/wiki/U-Boot上获得你所想要的一切信息。

另外, http://www.ibm.com/developerworks/cn/linux/l-btloader/也是一篇不可多得的介绍bootloader的文章!

pandaboard u-boot的编译

相关代码如何下载,请参照《玩转pandaboard之初体验

首先通过device/linaro/pandaboard/目录下的各个mk文件把u-boot及对应kernel的编译融入到Android的整个编译体系当中。

这里就不多说了,熟悉Android编译体系结构的同学一看就明白(或者找到相应的变量, 在build/目录下grep,就一定能找到你想要的结果)
与u-boot编译相关的参数都在BoardConfig.mk中指定了, 从中可以看出, TI已经基本放弃了x-load, 转而使用u-boot自带的SPL来作为second stage的bootloader

(第一是, ROM boot, 第三则是u-boot自身)

UBOOT_CONFIG := omap4_panda_config

TARGET_USE_XLOADER := false

XLOADER_CONFIG := omap4430panda_config

首先,使用make omap_panda_config来初始化u-boot的config环境

这里需要注意从Makefile中可以看出, make指令会去解析你所输入的xxxxx_config的参数, 然后找到对应的board的相关配置信息.

比如,这里会调用mkconfig, 读取boards.cfg中的信息, 来确定相关的信息(ARCH, CPU, SoC, Vendor, Target)

然后调用, make CROOSS_COMPILE=xxxxx来编译u-boot,

请注意,这里目前使用的最新的Codesourcery的CodeBench, 会有编译错误, 从网上的资料来说是因为它使用了gcc4.6.1, 其中有bug(会导致编译oma4的clock.c出错)

,我又先后尝试了几个之前的版本, 发现arm-2011.03-41-arm-none-linux-gnueabi.bin这个版本的最近的能够编译成功的版本.

pandaboard u-boot的代码结构

目录结构

/arch Architecture 相关的文件

/arm ARM architecture相关的文件

/cpu CPU 相关

/include

/armv7 Files specific to ARM v7 CPUs

/omap4 omap4相关的一些相关的文件

*.c

...

/lib ARM Architecture相关的库文件

/api Machine/arch无关的与用户提供的app相关的一些接口

/board/ti/panda panda板卡相关的文件

/common 平台独立一些工具

/disk 经过config之后,与平台相关的磁盘分区代码

/doc 简单一些文档

/drivers 设备驱动代码

/examples

/fs 各种嵌入式文件系统的代码

/include

/lib 平台无关的各种库

/libfdt flattened device trees 库

/lzma LZMA decompression 库

/lzo LZO decompression 库

/net 支持network相关的代码

/post 上电之后的自我检测

/rtc Real Time Clock 驱动

/tools 帮助生成uboot image的一些工具, mkimage!

/spl 重用u-boot中既有的驱动, 来生成更小的secondary program loader. 目前omap4就已经使用它取代原来的x-loader. 也就是使用mkimage通过spl的编译结果生成的MLO

/README 重要的文件, 里面有个中板卡及kernel相关的配置的说明. 这个文档中也有简单如何增加新的board支持的说明及uboot各种命令及参数的说明!!!

所有经过make omap4_panda_config之后, 所有的跟板卡相关的设置信息都会在"include/configs/omap4_panda.h".

其中会引用其它一些板卡相关的configs头文件, 两者中包含了CPU/board/Serial port/console/linux内核/内存/autoboot/Device Tree/网络等的设置信息

同时,为其它相关的代码生成对应的.depend,其中包含各种相关的文件引用

来看看pandaboard的各种config设定,

include/configs/omap4-common.h include/configs/omap4-panda.h

其中有各种编译参数, 生成的image地址, 硬件端口的设置等

比如, SPL的启用,及mkimage生成uboot.img时指定的TEXT地址都在其中

/* Defines for SPL */
#define CONFIG_SPL
#define CONFIG_SPL_TEXT_BASE        0x40303080
#define CONFIG_SPL_MAX_SIZE     (38 * 1024)
#define CONFIG_SPL_STACK        LOW_LEVEL_SRAM_STACK

/*
* 64 bytes before this address should be set aside for u-boot.img's
* header. That is 80E7FFC0--0x80E80000 should not be used for any
* other needs.
*/
#define CONFIG_SYS_TEXT_BASE        0x80E80000
这里相关的地址为什么定义为这个区间, 是跟各个板卡的RAM map相关的, pandaboard的ram划分参看<OMAP4430_ES2.x_PUBLIC_TRM_vR.pdf>的27.4.2 Memory Maps

Table 2-1. Global Memory Space Mapping

spl相关代码是独立与其它的uboot object来编译的, 有它自己的一些include及相关设定, 并通过mkimage生成对应的MLO



/home/test/pandaboard/u-boot-linaro-stable/u-boot-linaro_2012.04.2/tools/mkimage -T omapimage \
-a 0x40303080 -d /home/test/pandaboard/u-boot-linaro-stable/u-boot-linaro_2012.04.2/spl/u-boot-spl.bin /home/test
/pandaboard/u-boot-linaro-stable/u-boot-linaro_2012.04.2/ MLOSection CHSETTINGS offset 40 length cCHSETTINGS (c0c0c0c1) valid:0 version:1 reserved:0 flags:0GP Header: Size 8270 LoadAddr 40303080make[1]: Leaving directory `/home/test/pandaboard/u-boot-linaro-stable/u-boot-linaro_2012.04.2/spl'



关于根目录下的Makefile

请参看<UBOOT中的MAKEFILE详解>

关于uboot及spl中用到的ld script

请参看http://zqwt.012.blog.163.com/blog/static/120446842010320101137932/

其中解释下文中作者没明白的事情

. = .; //这里没有搞清楚为什么要这样做!
__u_boot_cmd_start = .;
/*把当前位置赋值给__u_boot_cmd_start,即定义了.u_boot_cmd段空间的开始位置 */

.u_boot_cmd : { *(.u_boot_cmd) }
__u_boot_cmd_end = .;
/*把当前位置赋值给__u_boot_cmd_end,即定义了.u_boot_cmd段空间的结束位置
注意这个问题是由一个ld与binutil联动生成address map造成的

参见: http://git.linaro.org/gitweb?p=boot/u-boot-linaro-stable.git;a=commit;h=807d5d7319330e336ab34a5623c5e0d73b87d540
http://sourceware.org/ml/binutils/2005-08/msg00412.html

最终的解释在gnu ld的官方manual里面就有http://sourceware.org/binutils/docs-2.22/ld/Location-Counter.html#index-dot-outside-sections-517

在两个section之间, 加入以下的赋值, 是为了告诉ld, 在ld工作时(即处理ld script之前), 不会在ld script 中的". = ." 之后的section中, 再插入新的section. 从而导致链接出错误的地址及map

. = .;


以及http://lionwq.spaces.eepw.com.cn/articles/article/item/18928

其中关于链接地址及运行时地址的心得很有用

既然程序有了两种地址,就涉及到一些跳转指令的区别,这里正好写下来,以后万一忘记了也可查看,以前不少东西没记下来现在忘得差不多了。。。
ARM汇编中,常有两种跳转方法:b跳转指令、ldr指令向PC赋值。
我自己经过归纳如下:
(1)       b step1 :b跳转指令是相对跳转,依赖当前PC的值,偏移量是通过该指令本身的bit[23:0]算出来的,这使得使用b指令的程序不依赖于要跳到的代码
的位置,只看指令本身。
(2)       ldr pc, =step1 :该指令是从内存中的某个位置(step1)读出数据并赋给PC,同样依赖当前PC的值,但是偏移量是那个位置(step1)的连接地址
(运行时的地址),所以可以用它实现从Flash到RAM的程序跳转。
(3)       此外,有必要回味一下adr伪指令,U-boot中那段relocate代码就是通过adr实现当前程序是在RAM中还是flash中。仍然用我当时的注释:
relocate: /* 把U-Boot重新定位到RAM */
adr r0, _start /* r0是代码的当前位置 */
/* adr伪指令,汇编器自动通过当前PC的值算出 如果执行到_start时PC的值,放到r0中:
当此段在flash中执行时r0 = _start = 0;当此段在RAM中执行时_start = _TEXT_BASE(在board/smdk2410/config.mk中指定的值为0x33F80000,
即u-boot在把代码拷贝到RAM中去执行的代码段的开始) */
ldr r1, _TEXT_BASE /* 测试判断是从Flash启动,还是RAM */
/* 此句执行的结果r1始终是0x33FF80000,因为此值是又编译器指定的(ads中设置,或-D设置编译器参数) */
cmp r0, r1 /* 比较r0和r1,调试的时候不要执行重定位 */


pandaboard的uboot的lds在arch/arm/cpu/u-boot.lds(最新的u-boot为所有的arm提供这么一个通用的script, 具体可以参看该文件的git log)及arch/arm/cpu/armv7/omap-common/u-boot-spl.lds

各种与pandaboard相关的配置文件

arch/arm/include/asm/arch-omap4/*

arch/arm/cpu/armv7/omap-common/*

board/ti/panda/*

arch/arm/cpu/armv7/omap4/*

arch/arm/cpu/armv7/omap-common/*

include/configs/omap4_common.h, include/configs/omap4_panda.h

详细请参看<玩转pandaboard之u-boot启动过程详述>

其它,

uboot使用-march=armv5来编译, 而不是使用armv7来编译pandaboard的uboot.

具体原因我没能找到,但是从一些代码注释中,可以看出为了应付armv7的新的指令, uboot是如何做的

参见arch/arm/include/asm/armv7.h

/*
* CP15 Barrier instructions
* Please note that we have separate barrier instructions in ARMv7
* However, we use the CP15 based instructtions because we use
* -march=armv5 in U-Boot
*/
#define CP15ISB asm volatile ("mcr     p15, 0, %0, c7, c5, 4" : : "r" (0))
#define CP15DSB asm volatile ("mcr     p15, 0, %0, c7, c10, 4" : : "r" (0))
#define CP15DMB asm volatile ("mcr     p15, 0, %0, c7, c10, 5" : : "r" (0))


比如, 这里ISB, DSB, DMB都是armv7才提供的barrier instructions, uboot使用armv5类似的直接控制CP15的方式来实现它们.

MLO的生成, 是由spl编译出的u-boot-spl.bin等文件, 由mkimage按照omapimage的配置生成的

具体MLO是什么请参照http://www.embedded-bits.co.uk/2011/writeanmlo

请注意beagleboard的spl起始地址是0x40200800, 而pandaboard是0x40303080(see omap4_common.h)

参考资料:

http://free-electrons.com/doc/u-boot.pdf 很好的关于u-boot的介绍

<玩转pandaboard之u-boot再体验>

http://omappedia.org/wiki/Bootloader_Project, 很好一个关于TI的板卡bringup的文章!!!
http://www.denx.de/en/pub/Documents/Presentations/EWC2012_Roeder_Zundel_Fastboot.pdf 关于SPL的比较详细介绍, 同时,代码目录doc/README.SPL也有详细的介绍
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: