uboot代码流程分析
程序员文章站
2022-03-06 08:14:50
在分析uboot之前,我们需要执行如下两条指令make make smdk2440_configmake上面两条指令执行完之后,在根目录下会生成一个名为uboot.lds的链接文件,这个脚本记录了uboot的入口,入口函数名为_start,位于arch/arm/cpu/arm920t/start.s文件:ENTRY(_start)SECTIONS{ . = 0x00000000; . = ALIGN(4); .text : { __image_copy_start = .; a...
在分析uboot之前,我们需要执行如下两条指令
make make smdk2440_config
make
上面两条指令执行完之后,在根目录下会生成一个名为uboot.lds的链接文件,这个脚本记录了uboot的入口,入口函数名为_start,位于arch/arm/cpu/arm920t/start.s文件:
ENTRY(_start)
SECTIONS
{
. = 0x00000000;
. = ALIGN(4);
.text :
{
__image_copy_start = .;
arch/arm/cpu/arm920t/start.o (.text)
board/samsung/smdk2440/libsmdk2440.o (.text)
*(.text)
}
接下来我们打开arch/arm/cpu/arm920t/start.S文件,可以看到文件中有一个_start函数:
.globl _start
_start: b start_code
ldr pc, _undefined_instruction
ldr pc, _software_interrupt
ldr pc, _prefetch_abort
在start.S文件中有几个比较重要的单板初始化函数:
- board_init_r
- board_init_f
board_init_f的作用是初始化运行board_init_r函数所需要的一些外设,比如串口、sdram等。在board_init_f可以设置全局变量,如全局变量gd就是在这个函数中初始化的,但是不能使用BSS段(未初始化变量)。
board_init_f初始化的数据位于init_sequence结构体中。
init_fnc_t *init_sequence[] = {
#if defined(CONFIG_ARCH_CPU_INIT)
arch_cpu_init, /* basic arch cpu dependent setup */
#endif
#if defined(CONFIG_BOARD_EARLY_INIT_F)
board_early_init_f,
#endif
#ifdef CONFIG_OF_CONTROL
fdtdec_check_fdt,
#endif
timer_init, /* initialize timer */
#ifdef CONFIG_FSL_ESDHC
get_clocks,
#endif
env_init, /* initialize environment */
init_baudrate, /* initialze baudrate settings */
serial_init, /* serial communications setup */
console_init_f, /* stage 1 init of console */
display_banner, /* say that we are here */
#if defined(CONFIG_DISPLAY_CPUINFO)
print_cpuinfo, /* display cpu info (and speed) */
#endif
#if defined(CONFIG_DISPLAY_BOARDINFO)
checkboard, /* display board info */
#endif
#if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C)
init_func_i2c,
#endif
dram_init, /* configure available RAM banks */
NULL,
};
board_init_r函数用来实现我们自己的应用代码,比如增加串口命令等功能。
这两个函数都位于arch\arm\lib\board.c文件中。
board_init_f中有一个main_loop函数,用来接收串口命令。
在指向完上面的命令之后,uboot会执行如下代码,判断是否启动内核或者进入命令模式
s = getenv ("bootcmd");
if (bootdelay >= 0 && s && !abortboot (bootdelay)) {
run_command(s, 0);
}
s = getenv (“bootcmd”);用来获取启动内核的命令,bootcmd的参数为 nand read.jffs2 0x30007FC0 kernel; bootm 0x30007FC0。bootdelay倒计时完毕前,如果有任何按键按下,则进入命令模式,否则调用run_command启动内核。
本文地址:https://blog.csdn.net/weixin_39270987/article/details/110132658