2020.1 u-boot C-SKY T910 启动分析
说在前面:
我参考了yanggx0929的博客,链接在下面。有些对不上的内容就只能自己看了。他的u-boot的版本是2015.1,我现在看的是2020.1
他分了十几篇,我只准备整理总结对我有用的部分。
链接: yanggx0929的博客
先定位一下是哪个start.S
通过xconfig来看下具体配置的是什么
(make ARCH=riscv CROSS_COMPILE=~/host/bin/riscv64-unknown-linux-gnu- xconfig)
从配置上看,定位到的是arch/riscv/cpu/start.S
这个文件里面会调用 board_init_f()
// arch/riscv/cpu/start.S
// lowlevel_init(); 并不会调用,因为配置内存等操作在别的地方做了
// 前面主要是做了一些CPU级别的初始化
// line 185 调用 board_init_f();
mv a0, zero /* a0 <-- boot_flags = 0 */
la t5, board_init_f
jalr t5 /* jump to board_init_f() */
// line 394 看注释是要进行第二阶段的init
/*
* We are done. Do not return, instead branch to second part of board
* initialization, now running from RAM.
*/
call_board_init_r:
jal invalidate_icache_all
jal flush_dcache_all
la t0, board_init_r
mv t4, t0 /* offset of board_init_r() */
add t4, t4, t6 /* real address of board_init_r() */
而board_init_f()是在下面的文件里面定义的。
里面主要是 initcall_run_list()来进行模块的顺序初始化,传入的init_sequence_f就是函数序列
common/board_f.c
// line 1017
void board_init_f(ulong boot_flags)
{
gd->flags = boot_flags;
gd->have_console = 0;
//initcall_run_list主要作用是初始化函数数组init_sequence_f.
if (initcall_run_list(init_sequence_f))
hang();
// 省略了几行
}
//board_init_f函数的功能也是遍历函数指针数组init_sequence_f,并调用init_sequence中的每一个函数,并判定函数返回值是否正确
static inline int initcall_run_list(const init_fnc_t init_sequence[])
{
const init_fnc_t *init_fnc_ptr; //定义函数指针init_fnc_ptr
int wh=0;
for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
//遍历函数指针数组init_sequence_f
unsigned long reloc_ofs = 0;
int ret;
wh++;
/*
* Sandbox is relocated by the OS, so symbols always appear at
* the relocated address.
*/
if (IS_ENABLED(CONFIG_SANDBOX) || (gd->flags & GD_FLG_RELOC))
reloc_ofs = gd->reloc_off;
#ifdef CONFIG_EFI_APP
reloc_ofs = (unsigned long)image_base;
#endif
if (reloc_ofs)
printf("initcall: %p (relocated to %p)\n",
(char *)*init_fnc_ptr - reloc_ofs,
(char *)*init_fnc_ptr);
else
printf("initcall: %p\n", (char *)*init_fnc_ptr - reloc_ofs);
ret = (*init_fnc_ptr)(); //调用init_fnc_ptr指向的函数
if (ret) {
printf("initcall sequence %p failed at call %p (err=%d)\n",
init_sequence,
(char *)*init_fnc_ptr - reloc_ofs, ret);
return -1;
}
}
return 0;
}
// common/board_f.c line 868
static const init_fnc_t init_sequence_f[] = {
setup_mon_len, //setup_mon_len功能是根据链接文件中的__bss_end 和_start标签计算uboot的大小,并初始化给gd->mon_len
#ifdef CONFIG_OF_CONTROL
fdtdec_setup, // 将dtb文件的地址放入gd->fdt_blob处
#endif
#ifdef CONFIG_TRACE_EARLY
trace_early_init,
#endif
initf_malloc, // 设置gd->malloc_limit和gd->malloc_ptr参数
log_init, // 是将.u_boot_list_2_log_driver_3和.u_boot_list_2_log_driver_1之间的所有struct log_driver结构体都加入到了gd->log_head的循环链表中,并初始化gd->default_log_level和gd->log_fmt
initf_bootstage, /* uses its own timer, so does not need DM */
// 为gd->bootstage分配空间,并初始化gd->bootstage,增加两条gd->bootstage->record,一条是reset,一条是board_init_f
#ifdef CONFIG_BLOBLIST
bloblist_init,
#endif
setup_spl_handoff,
initf_console_record,
#if defined(CONFIG_HAVE_FSP)
arch_fsp_init,
#endif
arch_cpu_init, /* basic arch cpu dependent setup */
mach_cpu_init, /* SoC/machine dependent CPU setup */
initf_dm, // 初始化驱动树和uclass树,并绑定含有DM_FLAG_PRE_RELOC标志位和特殊设备树特性的节点
arch_cpu_init_dm,
#if defined(CONFIG_BOARD_EARLY_INIT_F)
board_early_init_f,
#endif
#if defined(CONFIG_PPC) || defined(CONFIG_SYS_FSL_CLK) || defined(CONFIG_M68K)
/* get CPU and bus clocks according to the environment variable */
get_clocks, /* get CPU and bus clocks (etc.) */
#endif
#if !defined(CONFIG_M68K)
timer_init, /* initialize timer */
#endif
#if defined(CONFIG_BOARD_POSTCLK_INIT)
board_postclk_init,
#endif
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 */
#if defined(CONFIG_PPC) || defined(CONFIG_SH) || defined(CONFIG_X86)
checkcpu,
#endif