uboot移植之重定位之前的启动过程

uboot启动的第一阶段是cpu架构相关的初始化,用汇编完成,从arch/arm/cpu/arm920t/s3c24x0目录下的start.S文件开始看:

代码一开始就跳转到start_code:

uboot移植之重定位之前的启动过程

1、把cpu设为管理模式

uboot移植之重定位之前的启动过程

为什么要设置成管理模式:https://blog.csdn.net/rheostat/article/details/7734407

2、关看门狗

uboot移植之重定位之前的启动过程

 

 

3、屏蔽中断

uboot移植之重定位之前的启动过程

 

 

 4、设置时钟分频系数

5、调用cpu_init_crit函数

cpu_init_crit函数关闭了cache和mmu之后,调用lowlevel_init函数,在lowlevel_init里面初始化SDRAM。

6、设置栈,跳转到c函数board_init_f函数执行

uboot移植之重定位之前的启动过程

 

 

 board_init_f函数做的事:

①、遍历一个指针数组,循环调用各个初始化函数,如果这些初始化函数的返回值有一个不等于0,说明初始化出错,cpu陷入死循环函数hang()

uboot移植之重定位之前的启动过程

 

 

 指针数组成员如下:

 1 init_fnc_t *init_sequence[] = {
 2     board_early_init_f,
 3     timer_init,        /* initialize timer */
 4     env_init,        /* initialize environment */
 5     init_baudrate,        /* initialze baudrate settings */
 6     serial_init,        /* serial communications setup */
 7     console_init_f,        /* stage 1 init of console */
 8     display_banner,        /* say that we are here */
 9     print_cpuinfo,        /* display cpu info (and speed) */
10 };

②、把指针gd指向之前栈指针指向的地址0x30000f80,并把gd指针强制转化的gd_t结构体指针,从而设置各种参数(gd的意思是global_data):

uboot移植之重定位之前的启动过程

 

 

 设置参数代码:

1 memset((void *)gd, 0, sizeof(gd_t));//初始化结构体内容为0
2 gd->mon_len = _bss_end_ofs;
3 gd->fdt_blob = (void *)getenv_ulong("fdtcontroladdr", 16(uintptr_t)gd->fdt_blob);    
4 gd->tlb_addr = addr;    
5 ...
6 ...

③、把gd_t结构体搬移到地址为id的地方

uboot移植之重定位之前的启动过程

  id也是设置gd_t结构体的过程中得到的,所以一开始只能把gd_t结构体暂时放在原先设定的栈顶位置,等gd_t结构体设置完了再搬过去。

④、最后调用重定位函数relocate_code,三个参数从左到右依次赋值给寄存器R0,R1,R2

uboot移植之重定位之前的启动过程

 

 

addr_sp:新设置的栈指针地址

id:gd_t结构体所在的地址

addr:需要把uboot复制到的地址

 

addr一开始指向64M SDRAM的最高地址0x34000000,从最高地址开始安排内存分布,为各个外设保留内存区域,最后addr指向的地址就是为uboot开辟的内存空间的起始地址;

而addr_sp是所有内存安排完了以后,指向的空余内存空间的最高地址(栈向下生长);

id参数是为了uboot重定位完成之后,传给board_init_r函数用的。

 

上一篇:560.和为K的子数组


下一篇:力扣 - 560. 和为K的子数组