u-boot在2013开始将kbuild/Kconfig逐步引入,用于控制编译。引入kbuild后移植u-boot和之前有一些不同,这里以2015.04-rc1为例介绍,如何将u-boot移植到虚拟机gxemul上。
1. 下载解压u-boot代码,这里不赘述了
2. 在u-boot/configs/下增加gxemul的编译配置文件:gxemul_config
a) gxemul_config 配置cpu内核属性
i. CONFIG_MIPS=y //mips内核
ii. CONFIG_TARGET_GXEMUL=y //使用gxemul cpu
iii. CONFIG_SYS_BIG_ENDIAN=y //大端模式
iv. CONFIG_CPU_MIPS32_R1=y //MIPS32 R1
3. 在u-boot/configs/下增加gxemul的配置文件:gxemul.h
a) 配置gxemul board相关的信息,例如内存大小,地址,启动延时等等
4. 在u-boot/board/下增加gxemul的板级文件夹gxemul,并在其中放置以下文件
a) gxemul.c 里面包含与板子特征相关的代码
b) lowlevel_init.S 里面包含与板子特征相关的底层初始化代码
c) Kconfig 配置了board, soc, config name
i. if TARGET_GXEMUL
ii. config SYS_BOARD
iii. default "gxemul"
iv. config SYS_SOC
v. default "gxemul"
vi. config SYS_CONFIG_NAME
vii. default "gxemul"
viii. endif
d) Makefile 控制那些文件要进入编译
i. obj-y = gxemul.o
ii. obj-y += lowlevel_init.o
5. 修改u-boot/arch/mips/Kconfig文件,增加对gxemul的支持
a) 在Kconfig中添加于gxemul相关的内容:
i. config TARGET_GXEMUL //这部分内容是手动配置的时候选择用
ii. bool "Support gxemul"
iii. select SUPPORTS_BIG_ENDIAN
iv. select SUPPORTS_LITTLE_ENDIAN
v. select SUPPORTS_CPU_MIPS32_R1
vi. select SUPPORTS_CPU_MIPS32_R2
vii. source "board/gxemul/Kconfig" //包含到board下的Kconfig
6. 修改u-boot/drivers/serial/下内容,增加对gxemul serial的支持
a) 添加文件serial_gxemul.c,在其中实现驱动gxemul串口的代码,并封装出serial_device结构,提供gxemul_serial_initialize函数用于注册gxemul的串口到serial
i. static struct serial_device gxemul_serial_drv = {
ii. .name = "gxemul_serial",
iii. .start = gxemul_serial_init,
iv. .stop = NULL,
v. .setbrg = gxemul_serial_setbrg,
vi. .putc = gxemul_serial_putc,
vii. .puts = gxemul_serial_puts,
viii. .getc = gxemul_serial_getc,
ix. .tstc = gxemul_serial_tstc,
x. };
xi.
xii. void gxemul_serial_initialize(void)
xiii. {
xiv. serial_register(&gxemul_serial_drv);
xv. }
xvi.
xvii. __weak struct serial_device *default_serial_console(void)
xviii. {
xix. return &gxemul_serial_drv;
xx. }
b) 在serial.c的serial_initialize中调用gxemul_serial_initialize注册gxemul的串口操作函数
i. #ifdef CONFIG_GXEMUL
ii. gxemul_serial_initialize();
iii. #endif
c) 修改Makefile能编译到serial_gxemul.c
i. obj-$(CONFIG_GXEMUL_SERIAL) += serial_gxemul.o
u-boot编译gxemul:
1. 设置工具链环境变量
a) export PATH=/home/cd00010/mipsvm/mips-2011.03/bin/:$PATH
2. 设置交叉编译环境变量
a) export CROSS_COMPILE=mips-linux-gnu-
3. 编译
a) make gxemul_config
b) make
遇到的问题及解决:
1. 编译出来的代码在start.S的时候死掉:
a) 原因: 使用gcc-4.4进行编译将以下加粗字体部分
bal 1f
nop
PTR _gp //此处是.word _gp , _gp在u-boot.lds中定义,这里直接放置为0,而非u-boot.lds中_gp的正确值,从而在PTR_L gp, 0(ra)获取gp错误,而导致死机
1:
PTR_L gp, 0(ra)
b) 解决方法: 更换编译器到gcc-4.5解决。
2. relocate_code重定位后执行到board_init_r死掉
a) 原因:在gxemul.h中配置了CONFIG_NEEDS_MANUAL_RELOC,因此在board_init_r算初始化函数指针的时候加了reloc_off,导致函数地址错误,mips的引导代码已经将gp设置正确,无需再做reloc_off
b) 解决: 不配置CONFIG_NEEDS_MANUAL_RELOC