u-boot启动流程分析(一)从上电到命令行

u-boot启动流程分析(一)从上电到命令行

这里使用之前移植的配置文件和设备树
157使用的是myboard_defconfig配置文件,详情请看这篇文章
首先执行下面的命令生成对应的文件

make myboard_defconfig
make DEVICE_TREE=stm32mp157c-myboard all -j64

编译结束后生成过程文件以及最终镜像

由于当前(2022.12.5)对于u-boot的Makefile分析还不熟练,所以先采用比较取巧的方式来学习u-boot的启动流程

配置文件

首先打开.config文件,搜索lds,可以看到我们的157使用的链接文件是arch/arm/cpu/u-boot-spl.lds,因为我们的157是arm架构的处理器
在这里插入图片描述

链接脚本

我们需要通过这个链接文件去找到我们的启动文件在哪里
在这里插入图片描述

_start函数

在这里可以看到,入口函数是_start函数,这个函数不是定义在start.S里面,而是它定义在arch/arm/lib/vectors.S这个文件里。我们打开这个文件,找到_start函数
在这里插入图片描述

中断向量表

这里可以看到,它首先设置了中断向量表,这里是我们的ARM_VECTORS,这个ARM_VECTORS是这样子定义的,就在vectors.S里面,_start函数前面的地方

        .macro ARM_VECTORS
#ifdef CONFIG_ARCH_K3
	ldr     pc, _reset
#else
	b	reset
#endif
	ldr	pc, _undefined_instruction
	ldr	pc, _software_interrupt
	ldr	pc, _prefetch_abort
	ldr	pc, _data_abort
	ldr	pc, _not_used
	ldr	pc, _irq
	ldr	pc, _fiq
	.endm

可以看到复位异常会跳转到我们的reset函数去执行,也就是我们摁下开发板复位键的一刻,在157的fsbl执行完毕之后就会根据引脚配置的启动方式加载我们的u-boot,然后跳转到reset函数执行,而这个reset函数就定义在start.S文件里头

reset函数

看到reset函数,它首先执行跳转,跳转到save_boot_params处执行
在这里插入图片描述
然后发现这个save_boot_params啥也没干就直接返回到了reset函数继续执行
在这里插入图片描述
不过,这里我们的157重写了save_boot_params函数,不过内容也很简单
在这里插入图片描述
保存了r2的一个值,这里先不管这个变量的具体含义,不过以后肯定是需要了解157的fsbl阶段发生过什么的。

接着往下看
在这里插入图片描述
注释这里,注释也写的很清楚,禁用中断,设置处理器到SVC模式

然后是设置中断向量表的地址
在这里插入图片描述
这里的CONFIG_OMAP44XX是没有定义的,并且定义了CONFIG_SPL_BUILD,在我们的spl/u-boot.cfg里面可以找到它的定义
在这里插入图片描述
然后这一整段就是设置中断向量表为我们_start函数的地址
接着往下看
在这里插入图片描述
这里会执行cpu_init_cp15函数,下面的CONFIG_SKIP_LOWLEVEL_INIT_ONLY编译选项没有找到定义
cpu_init_cp15做了关闭I-Cache、关闭D-Cache和关闭MMU等一系列工作,然后就跳转回来继续执行了

我们接着往下看
在这里插入图片描述
reset函数的最后一步就是跳转到_main函数运行,这个函数定义在arch/arm/lib/crt0.S里面

_main函数

我们把目光聚焦到这个_main函数
在这里插入图片描述
这个函数首先设置栈指针,然后调用俩函数
首先是board_init_f_alloc_reserve函数,它定义在common\init\board_init.c文件中
在这里插入图片描述
这里我猜是为global_data预留空间,然后在下面的一行更新了栈指针(我猜是这样)
然后用r9寄存器保存了global_data的地址,然后调用board_init_f_init_reserve函数,这个函数和前面的函数定义的位置一样,这个函数负责初始化工作

接着往下看
在这里插入图片描述
这里没有找到CONFIG_SPL_EARLY_BSS的定义,这里应该不会执行

然后是跳转到board_init_f函数
在这里插入图片描述
这个函数定义在common\board_f.c
在这里插入图片描述

init_sequence_f函数列表

设置了gd的一些标志之后,它就去执行init_sequence_f里面的函数了
这个列表有一点长,初步筛选之后如下

static const init_fnc_t init_sequence_f[] = {
	setup_mon_len,
	fdtdec_setup,
	initf_malloc,
	log_init,
	initf_bootstage,	/* uses its own timer, so does not need DM */
	setup_spl_handoff,
	initf_console_record,
	arch_cpu_init,		/* basic arch cpu dependent setup */
	mach_cpu_init,		/* SoC/machine dependent CPU setup */
	initf_dm,
	arch_cpu_init_dm,
	board_early_init_f,
	timer_init,		/* initialize timer */
	env_init,		/* initialize environment */
	init_baud_rate,		/* initialze baudrate settings */
	serial_init,		/* serial communications setup */
	console_init_f,		/* stage 1 init of console */
	display_options,	/* say that we are here */
	display_text_info,	/* show debugging info if required */
	checkcpu,
	print_resetinfo,
	print_cpuinfo,		/* display cpu info (and speed) */
	show_board_info,
	INIT_FUNC_WATCHDOG_INIT
	INIT_FUNC_WATCHDOG_RESET
	announce_dram_init,
	dram_init,		/* configure available RAM banks */
	INIT_FUNC_WATCHDOG_RESET
	INIT_FUNC_WATCHDOG_RESET
	INIT_FUNC_WATCHDOG_RESET
	/*
	 * Now that we have DRAM mapped and working, we can
	 * relocate the code and continue running from DRAM.
	 *
	 * Reserve memory at end of RAM for (top down in that order):
	 *  - area that won't get touched by U-Boot and Linux (optional)
	 *  - kernel log buffer
	 *  - protected RAM
	 *  - LCD framebuffer
	 *  - monitor code
	 *  - board info struct
	 */
	setup_dest_addr,
	reserve_round_4k,
	arch_reserve_mmu,
	reserve_video,
	reserve_trace,
	reserve_uboot,
	reserve_malloc,
	reserve_board,
	setup_machine,
	reserve_global_data,
	reserve_fdt,
	reserve_bootstage,
	reserve_bloblist,
	reserve_arch,
	reserve_stacks,
	dram_init_banksize,
	show_dram_config,
	INIT_FUNC_WATCHDOG_RESET
	setup_bdinfo,
	display_new_sp,
	INIT_FUNC_WATCHDOG_RESET
	reloc_fdt,
	reloc_bootstage,
	reloc_bloblist,
	setup_reloc,
	clear_bss,
	NULL,
};

最后我们的ARM架构的u-boot不会执行jump_to_copy函数,也就是说会返回_main函数继续执行

我们继续看到_main函数,它在完成一系列初始化之后,会清除BSS段
在这里插入图片描述
在前面的init_sequence_f函数列表里面有一个clear_bss函数,不过它是定义成这样的
在这里插入图片描述
也就是CLEAR_BSS会覆盖这个函数,调用这个函数实际调用的就是CLEAR_BSS

最后调用board_init_r函数

init_sequence_r函数列表

board_init_r函数去调用init_sequnence_r函数列表,最后进入到u-boot的命令行界面

static init_fnc_t init_sequence_r[] = {
	initr_trace,
	initr_reloc,
	initr_caches,
	initr_reloc_global_data,
	initr_barrier,
	initr_malloc,
	log_init,
	initr_bootstage,	/* Needs malloc() but has its own timer */
	initr_console_record,
	initr_noncached,
	initr_of_live,
	initr_dm,
	board_init,	/* Setup chipselects */
	efi_memory_init,
	initr_binman,
	initr_dm_devices,
	stdio_init_tables,
	serial_initialize,
	initr_announce,
	initr_watchdog,
	INIT_FUNC_WATCHDOG_RESET
	INIT_FUNC_WATCHDOG_RESET
	INIT_FUNC_WATCHDOG_RESET
	power_init_board,
	INIT_FUNC_WATCHDOG_RESET
	initr_nand,
	initr_mmc,
	initr_env,
	INIT_FUNC_WATCHDOG_RESET
	initr_secondary_cpu,
	INIT_FUNC_WATCHDOG_RESET
	stdio_add_devices,
	initr_jumptable,
	console_init_r,		/* fully init console as a device */
	arch_misc_init,		/* miscellaneous arch-dependent init */
	INIT_FUNC_WATCHDOG_RESET
	interrupt_init,
	/* PPC has a udelay(20) here dating from 2002. Why? */
	initr_ethaddr,
	gpio_hog_probe_all,
	board_late_init,
	INIT_FUNC_WATCHDOG_RESET
	initr_net,
	run_main_loop,
};

实验 在启动时添加打印信息

有了前面的铺垫,我们修改board/st/stm32mp1/stm32mp1.c里面的checkboard函数,在显示Model之后输出一句Welcome to MyBoard,这个函数由init_sequence_f里的show_board_info函数里面调用的checkboard函数,这个函数实际会调用到我们stm32mp1.c里面的checkboard函数
修改如下:
在这里插入图片描述
然后重新编译烧录到SD卡,启动效果如下所示
在这里插入图片描述
成功显示信息!!!
这里输出了两次U-Boot的版本信息,我猜是u-boot-spl和u-boot的缘故,u-boot-spl简单初始化之后,把u-boot.img加载进内存,然后跳转执行

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值