文章目录
- 前言
- 一、重新编写脚本
- 1. init_env.sh
- 2. build.sh
- 3. sdflush.sh
- 二、spl 启动流程
- 1. start.S
- 2. board_init_f()
- 2.1 setup_global_data()
- 2.2 do_lowlevel_init()
- 2.3 power_exit_wakeup()
- 2.4 copy_uboot_to_ram()
- 2.5 jump to uboot
- 三、点灯
- 1. 问题:spl.bin 不正确
- 2. 问题:灯亮一瞬间后熄灭
- 3. 亮一段时间后发生 reset
前言
???在 移植 u-boot-2020.07 到 iTOP-4412(一)地址无关码点灯 文中,因为三星比较恶心的 boot 方式(对学习而言),使用了 MOV 等地址无关指令点灯成功,因为不知道 bl2.bin 最终将 u-boot-spl 重定位在哪里,始终无法使用 ldr 等指令点灯。
???对讯为提供的资料经行一番搜索查找发现,讯为有帮助把 bl1 中的安全校验等恶心人的地方去掉,这方便了学习,并且可以看出 spl 的链接地址。所以才能有这一篇文章。
???本文主要讲 spl 的方面。
一、重新编写脚本
1. init_env.sh
???这绝对是一个大坑,最开始我是在 build.sh
中 export 环境变量,第一次编译没有问题,然后发现需要 make menuconfig
或是想手动 make
时发生了错误,肯定是编译器不对,胡乱编译后 make distclean
也不起效果。
???只好用 Beyond Compare 手动和原 u-boot 文件对比一个一个修改后才能正常编译,所以很有必要使用同一的脚本初始化环境变量。
. init_env.sh
2. build.sh
为了方便,build.sh
主要实现这几个功能:
- make xhr4412_defconfig
- make
- 检查编译是否成功
- 反汇编
- 连接 bl1 spl uboot
反汇编非常重要,调试的时候需要分析。
3. sdflush.sh
用于制作 tf 启动卡:
- 检查 bin 文件存在
- 使用 dd 命令将 bin 刷写到 tf card
二、spl 启动流程
[u-boot 2020.07] README
1. start.S
文件流程:
- arch/arm/lib/vectors.S
- arch/arm/cpu/armv7/start.S
- arch/arm/lib/crt0.S
vectors 中的其他 arm 向量不去关心。
???跳转到 reset 后,又跳转了几次看起来是无用功,应该是设计来增加函数的,还没研究怎么添加。最后由 save_boot_params_ret
跳转到 _main
。
???_main
中会根据 CONFIG_SPL_STACK
的值设置 SP,最后跳转到 board_init_f
。
2. board_init_f()
函数定义在:
arch/arm/mach-exynos/spl_boot.c
该初始化函数主要作用:
- 初始化全局变量
- lowlevel init
- 重定位 u-boot
- 跳转到 u-boot,不再返回
2.1 setup_global_data()
定义在 arch/arm/mach-exynos/spl_boot.c
初始化结构体 __aligned(8) gd_t local_gd;
,该结构体存放在堆栈中,具体什么用处还没搞懂。
2.2 do_lowlevel_init()
定义在 arch/arm/mach-exynos/lowlevel_init.c
???首先调用 get_reset_status()
获取 reset 状态,根据 reset 状态来判断需要完成哪些初始化操作。如果是正常启动,要做如下操作:
- DO_POWER
set_ps_hold_ctrl()
- DO_CLOCKS
system_clock_init()
- DO_MEM_RESET
mem_ctrl_init(actions & DO_MEM_RESET)
???如果配置了 UART ,将会初始化 UART,需要注意初始化哪一个 UART。最后初始化 TrustZone,这里修改代码,添加宏,不编译它。
#ifndef CONFIG_XHR4412tzpc_init();
#endif
2.3 power_exit_wakeup()
定义在:arch/arm/mach-exynos/power.c
该函数在 do_lowlevel_init() 返回非零时执行。
2.4 copy_uboot_to_ram()
调用 get_boot_mode()
函数判断从哪里 boot,然后将代码重定位。
2.5 jump to uboot
最后直接跳转到重定位的 u-boot 上执行。
三、点灯
???嵌入式大神鲁迅曾经说过:没有什么是点灯不能解决的,如果有,那就点两个流水灯。
???没想到这么简单的点灯程序仍然不简单。
void led_test(void)
{volatile unsigned long * GPL2CON;volatile unsigned long * GPL2DAT;GPL2CON = (volatile unsigned long *)0x11000100;GPL2DAT = (volatile unsigned long *)0x11000104;*GPL2CON = 1;*GPL2DAT = 1;while (1) ;
}
1. 问题:spl.bin 不正确
???在 out/spl/
目录中会自动生成 xhr4412-spl.bin
,一开始没弄懂这个文件怎么来的,不过就是普通的 u-boot-spl.bin
,加了 header 和 padding。
???因为这个 header,导致 spl 被 bl1 重定位后无法执行到 reset
,一直没能点灯成功。
???对整个 u-boot 文件夹搜索 grep -nr xhr4412
,发现了之前添加的 board 文件夹中有 mkxhr4412spl.c
源文件,应该就是该文件编译后制作的 xhr4412-spl.bin
,所以对它进行修改,注释掉 header 部分。
???并且仿造讯为提供的 u-boot 添加 checksum,可能 bl1 还是会对 xhr4412-spl.bin
进行简单校验。
???注意:需要 make distclean
后才能使上述修改生效。
2. 问题:灯亮一瞬间后熄灭
???最开始以为是 watchdog 的原因导致 cpu reset,但是关闭 watchdog 后也是这样的现象。
???后来发现 4412 比简单的 2440 复杂很多,需要电源管理芯片供电,看来应该是设置不对,供电断开了。
???设置 PS_HOLD_CONTROL 寄存器,并且我发现不能在设置该寄存器前 disable watchdog,不然灯完全不会亮,具体原因还没分析出来。
3. 亮一段时间后发生 reset
???设置了 PS_HOLD 后仍然是有问题的,现在可以亮一阵子,但是 6 7 秒后会熄灭重新亮,具体是 watchdog 还是电源管理芯片引起的还未分析出来,下一篇文章再研究这个问题,这里就先闪一闪灯吧。
void led_test(void)
{volatile unsigned long i; // volatile 不会被优化volatile unsigned long * GPL2CON;volatile unsigned long * GPL2DAT;volatile unsigned long * PS_HOLD;GPL2CON = (volatile unsigned long *)0x11000100;GPL2DAT = (volatile unsigned long *)0x11000104;PS_HOLD = (volatile unsigned long *)0x1002330C;*GPL2CON = 1;*GPL2DAT = 0;*PS_HOLD |= 0x300;while (1){*GPL2DAT ^= 1;for (i = 0; i < 500000; i++) ;}
}