【TINY4412】U-BOOT移植笔记:(4)U-BOOT执行流程
宿主机 : 虚拟机 Ubuntu 16.04 LTS / X64
目标板[底板]: Tiny4412SDK - 1506
目标板[核心板]: Tiny4412 - 1412
U-BOOT版本: 2017.03
交叉编译器: gcc-arm-none-eabi-5_4-2016q3
日期: 2017-4-22 12:01:27
作者: SY
SPL执行流程
root@ubuntu:/opt/u-boot-2017.03# more board/samsung/common/exynos-uboot-spl.lds
ENTRY(_start)
SECTIONS
{
.text :
{
__start = .;
*(.vectors)
arch/arm/cpu/armv7/start.o (.text*)
*(.text*)
} >.sram
. = ALIGN(4);
}
1. 根据ENTRY(_start),可知先执行 __start
2. 找到 arch/arm/lib/vectors.S
/*
*************************************************************************
*
* Symbol _start is referenced elsewhere, so make it global
*
*************************************************************************
*/
.globl _start
可知这个符号是一个全局符号。
_start:
#ifdef CONFIG_SYS_DV_NOR_BOOT_CFG
.word CONFIG_SYS_DV_NOR_BOOT_CFG
#endif
b reset
然后执行 reset
3. 找到 root@ubuntu:/opt/u-boot-2017.03# more arch/arm/cpu/armv7/start.S
4. 因为配置了CONFIG_SKIP_LOWLEVEL_INIT,
跳过 bl cpu_init_cp15,
跳过 bl cpu_init_crit,
执行 bl _main
5. root@ubuntu:/opt/u-boot-2017.03# more arch/arm/lib/crt0.S
6. 执行 bl board_init_f
7. 找到 root@ubuntu:/opt/u-boot-2017.03# more arch/arm/mach-exynos/spl_boot.c
执行 void board_init_f(unsigned long bootflag);
执行 void do_lowlevel_init();
8. 进入 root@ubuntu:/opt/u-boot-2017.03# more arch/arm/mach-exynos/lowlevel_init.c
9. 执行 system_clock_init(); 初始化系统时钟
10. 执行 exynos_pinmux_config(PERIPH_ID_UART0, PINMUX_FLAG_NONE);
debug_uart_init(); 初始化串口0
11. 执行 mem_ctrl_init(); 初始化SDRAM,为了下一步加载U-BOOT.bin做准备
12. 执行 tzpc_init(); 配置 TrustZone Protection Controller
13. 执行 copy_uboot_to_ram(), 将u-boo.bin从启动媒介拷贝到SDRAM的
CONFIG_SYS_TEXT_BASE 位置。
14. 跳转到u-boot执行:
/* Jump to U-Boot image */
uboot = (void *)CONFIG_SYS_TEXT_BASE;
(*uboot)();
U-BOOT 执行流程
1. 前面的步骤和SPL中执行的都一样。
2. 执行到 bl board_init_f时,查看文件`arch\arm\mach-exynos\Makefile`
ifdef CONFIG_SPL_BUILD
obj-$(CONFIG_EXYNOS5) += clock_init_exynos5.o
obj-$(CONFIG_EXYNOS5) += dmc_common.o dmc_init_ddr3.o
obj-$(CONFIG_EXYNOS4210)+= dmc_init_exynos4.o clock_init_exynos4.o
obj-$(CONFIG_EXYNOS4412)+= dmc_init_exynos4412.o clock_init_exynos4412.o
obj-y += spl_boot.o tzpc.o
obj-y += lowlevel_init.o
endif
当执行U-BOOT时,这些文件都不会被编译。因此,执行到`common\board_f.c`时,
会跳转到void board_init_f(ulong boot_flags)函数。
3. 紧接着:
if (initcall_run_list(init_sequence_f))
hang();
init_sequence_f是一个函数指针数组,initcall_run_list()函数会依次遍历
数组中的每一个元素,并执行。正常情况下不会执行到hang(),而数组的最后一个
元素为 NULL,作为退出条件:
for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr);
4. b relocate_code
5. bl relocate_vectors
6. bl coloured_LED_init
7. bl red_led_on
8. ldr pc, =board_init_r 执行`common\Board_r.c`中的
void board_init_r(gd_t *new_gd, ulong dest_addr);
9. 执行:
if (initcall_run_list(init_sequence_r))
hang();
init_sequence_r是一个函数指针数组,最后一个成员是 run_main_loop()
10. 执行 void main_loop(void);
11. 执行 void cli_loop(void);
12. 执行 cli_simple_loop();
常见问题
- 死机
- :使用
sd_fuse/tiny4412/sd_fusing.sh
生成的bl2.bin文件,烧录到开发板,经过放置小灯测试,在执行bl board_init_f_alloc_reserve
时,会出现死机情况? - 原因:
bl2.bin
使用u-boot根目录的u-boot.bin
制作而成,而在BL2阶段应该执行的文件是./spl/tiny4412-spl.bin
,该文件使用./spl/u-boot-spl.bin
制作而成。见:./script/Makefile.spl
中的259 $(obj)/$(BOARD)-spl.bin: $(obj)/u-boot-spl.bin
- 解决:修改 ./sd_fuse/tiny4412/sd_fusing.sh,
C
#<BL2 fusing>
echo "---------------------------------------"
echo "BL2 fusing"
#dd iflag=dsync oflag=dsync if=./bl2.bin of=$1 seek=$bl2_position
dd iflag=dsync oflag=dsync if=../../spl/tiny4412-spl.bin of=$1
seek=$bl2_position
- :使用