在之前我们移植的代码中,都没看到明显的效果,这节我们实现控制台的打印信息。
在上节,我们看到调用 relocate_code 重定位。在 u-boot 的帮助文档 doc/README.arm-relocation 中对重定位有说明。u-boot 为了生成位置无关码,在链接时指定了-pie 选项,这个选项在 u-boot-2014.04/arch/arm/config.mk 中指定:
当使用-pie 选项后,链接器会生成一个修正表(fixup tables),在最终的二进制文件 u-boot.bin 中表现为多了 2 个段 .rel.dyn 和 .dynsym,还需要在链接脚本文件中增加这 2 个段,u-boot.bin 的链接脚本文件为 u-boot-2014.04/arch/arm/cpu/u-boot.lds,有了这 2 个段,u-boot 可以根据这 2 个段的信息将重定位后的代码的链接地址修正为其运行地址,这样
u-boot 就可以重定位到任何地址。在 crt0.S 中调用 relocate_code 完成重定位,并进行地址修正,返回后进行清 BSS 操作,然后跳转到 board.c 中的 board_init_r 函数,进行更进一步的初始化,比如网卡,然后进入 main_loop 循环。重定位后的 u-boot 内存布局如下图:
现在执行 make all 编译 u-boot.bin 和 u-boot-spl.bin,但是编译错误:
在clock.c的 s5pv210_get_arm-clk中使用了samsung_get_base_clock这个宏和相关的寄存器,因为之前我们的时钟代码是用汇编实现的,所以我们在arch/arm/include/asm/arch-s5pc1xx/clock.h来定义这些寄存器:
最终生成了 u-boot.bin 和 spl/tiny210-spl.bin。查看一下 u-boot.bin 的大小:
有201588B,换成块大小201588/512 =393 我们需要修改 u-boot-spl.bin 中的 BL2 拷贝函数copy_bl2_to_ram,其定义在 u-boot-2014.04/board/samsung/tiny210/tiny210.c 将拷贝大小改为 400,拷贝 400 块,保存后再次执行 make all.使用dd命令烧写到sd卡中:
打开串口终端,选择从sd卡启动,令人兴奋的事情发生了:
但是却卡在这里不走了,通过跟踪代码发现,在 board.c 中的 board_init_r 函数调用了 enable_caches。现在已经可以使用 puts、 printf等函数了,我们可以通过打印信息来判断程序卡在哪里了。 一路调试下去,最终发现程序卡在
onenand_init 里:
这个宏 CONFIG_CMD_ONENAND 在 tiny210.h 中定义,我们的 tiny210 开发板没有 onenand,所以将这个宏屏蔽掉:
另外,还有一些和单板相关的信息,我们可以修改一下,修改 tiny210.h
与 onenand 相关的,我们查看 u-boot-2014.04/common/Makefile,看下 env_onenand.c 是怎么被编译进u-boot.bin 的是由于定义了 CONFIG_ENV_IS_IN_ONENAND 这个宏,这个宏在 tiny210.h 中定义,我们将它屏蔽掉:
但是编译,还是出错:
我们查看 u-boot-2014.04/common/cmd_nvedit.c说明必须指定环境变量保存位置,我们可以将环境变量保存到 SD 卡或 NAND,但是现在还没移植好,所以先暂时将 CONFIG_CMD_ONENAND 和 CONFIG_ENV_IS_IN_ONENAND 这 2 个宏打开,然后在 board.c 中屏蔽 onenand 初始化代码。
再次编译,成功。
由于这次的修改只针对 u-boot.bin,对 u-boot-spl.bin 没有影响,因此可以只烧写 u-boot.bin 到 SD 卡的扇
区 32。
好了,移植了这么久,控制台终于可以看到效果了。试试基本的u-boot命令可不可以用:
弄了这么多天,终于有了效果,之后的事情就是在这基础上进行完善了。我把这个版本的代码放在这:tiny210_u-boot_201404_v1.1.tar.bz2有兴趣的朋友可以看看,帮忙一起完善。