欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  科技

uboot代码流程分析

程序员文章站 2022-06-23 20:22:45
在分析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