一、添加DDR初始化1
1、分析下一步的移植路线
(1) cpu_init_crit 函数成功初始化串口、时钟后,转入 _main 函数,函数在 arch/arm/lib/crt0.S 文件中。
(2) 在 crt0.S 中首先设置栈,将 sp 指向 DDR 中的栈地址;
#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK)
ldr sp, =(CONFIG_SPL_STACK)
#else
ldr sp, =(CONFIG_SYS_INIT_SP_ADDR)
#endif
#define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SYS_LOAD_ADDR - 0x1000000) //0x33000000
#define CONFIG_SYS_LOAD_ADDR (CONFIG_SYS_SDRAM_BASE + 0x4000000) //0x34000000
/* DRAM Base */
#define CONFIG_SYS_SDRAM_BASE 0x30000000
然后调用 board_init_f 函数进行板级初始化。函数在 arch/arm/lib/board.c 中。
(3) 在这个版本的 uboot 中,把以前 uboot 的第二阶段 start_armboot 函数分成了 2 部分:board_init_f 和 board_init_r。所以在这里,就和以前版本的 uboot 接轨上了,推测 board_init_f 中肯定是做了板级初始化,board_init_r 中进入了uboot的命令行。
(4) 分析到这里,在 uboot2013.10 版本中思路已经很清晰了:uboot 的第二阶段就在 crt0.S 文件中,第二阶段的入口就是 _main 函数。第一阶段工作主要就是 cpu_init_crit 函数,所以我们要在 cpu_init_crit 函数中添加 DDR 初始化和 uboot 的重定位。
(5) 分析到这里,下一步工作方向就确定了。我们要先在 cpu_init_crit 函数中添加 DDR 初始化,然后在 start.S 中 bl _main 之前,添加 uboot 的重定位,然后将 bl _main 改成 ldr pc, __main(__main: .word _main) 长跳转。然后在 crt0.S 中 board_init_f 后,删除那些重定位代码,至此 uboot 的第二阶段就应该能启动起来了。后续的移植就是第二阶段了。
2、分析 DDR 初始化代码移植思路
(1) 如果本来 uboot 中有 DDR 初始化代码,那我们可以就着这些代码来修改。但是问题是这个 uboot2013.10 中根本没有DDR初始化,所以我们需要完全从头去另外添加 DDR 初始化代码。
(2) 我们的思路就是,从三星版本的 uboot 中直接移植 DDR 初始化代码过来即可。三星版本的 uboot 中,DDR 初始化函数在 cpu/s5pc11x/s5pc110/cpu_init.S 文件中,直接将这个文件移植过来即可。
3、动手移植
(1) 添加 cpu_init.S 文件到 uboot2013.10 中。注意,这里的代码必须保证在前 8kb 内,所以必须和 lowlevel_init.S 文件一样的链接处理。
主要是在 board/samsung/goni/Makefile 中和 arch/arm/cpu/u-boot.lds 文件中做修改添加。
(2) 添加头文件 s5pc110.h 到 include 目录下。
(3) 对 cpu_init.S 文件代码进行修整,把一些无用的代码去掉,把一些相关的条件编译人工处理一下。
二、添加DDR初始化2
1、移植必要的宏定义
(1) DDR 配置参数,从三星版本的 smdkv210single.h 中复制到 s5p_goni.h 中。
1、
(2) s5pc110.h 中进行修整。
2、代码同步、编译、再修整
3、添加调试信息,验证 DDR 初始化完成。
(1) 调试信息有 LED 点亮和串口输出两种。优先选用串口调试的方法。
(2) 在 DDR 初始化完成后,添加串口输出字符 “K”,这样启动时如果看到了"OK",就说明 DDR 已经被成功初始化了。
(3) 结果:看到了 “OK” 标志,说明 DDR 添加实验成功。
三、添加uboot第二阶段重定位1
1、在重定位代码前,加调试信息定位
(1) 逻辑上来说,重定位部分的代码,应该在 DDR 初始化之后和 uboot 第二阶段来临前之间。
(2) uboot 的第一阶段和第二阶段的划分并不是绝对的,唯一必须遵循的原则就是:第一阶段不能大于 8KB。所以 uboot 的第一阶段最少要完成 DDR 初始化和重定位,最多不能超过 8KB。在满足这些条件时,第一阶段和第二阶段的接点可以随便挑。
(3) 找到合适的地方来写重定位代码,重定位之后远跳转到第二阶段的入口。
(4)
2、重定位代码移植
- 设置栈指针
最终修改:
- 判断运行地址。
最终修改:
- 判断启动介质。
- 跳转 BL2 copy 函数。
最终修改结果:
3、清 bss 段移植
最终修改结果:
4、movi_bl2_copy 函数移植
(1) 从三星版本的 uboot 中复制 movi.c 和 movi.h 到 uboot2013.10 中。
movi.c 文件的修改:
修改后:
(2) 改 makefile 和 u-boot.lds。
四、添加 uboot 第二阶段重定位 2
1、_mian 函数中基本处理
(1) 主要就是把里面的重定位代码部分给删除掉。剩下就是:设置栈、调用 board_init_f 函数和 board_init_r 函数。
2、代码同步及编译
(1) 主要是 crt0.S 和 movi.h。
3、编译中出现问题解决
(1) movi.h 中宏定义出错,最后在 s5p_goni.h 中添加了 CONFIG_EVT1 这个宏解决了。
(2) 连接错误:u-boot contains relocations other than R_ARM_RELATIVE
在 uboot 下用 grep “R_ARM_RELATIVE” -nR * 搜索,发现 Makefile 中有一个检查重定位的规则,屏蔽掉这个规则后编译连接成功。
4、结果验证及下阶段展望
(1) 看到了 uboot 启动打印出来的一系列信息,但是 uboot 没有进入命令行。
(2) 这说明 uboot 中的 DDR 初始化和重定位功能都已经完美实现,后面就是第二阶段的继续移植了。
源自朱有鹏老师.