ARM Uboot经历——Uboot初始化代码解析
2013-07-24 23:42
821 查看
Uboot初始化代码主要是在Uboot重定位之前的一系列处理,起源于start.s文件,涉及crt0.s和board.c等文件,会完成最系统环境最初始的设置和结构体赋值。
save_boot_params 改函数为weak函数,未定义任何内容。用户如过有任何参数要传递的,那么需要再次定义这个函数。
将ARM的模式修改为supervisor模式
该宏已定义,表示会跳过底层设备的初始化
cpu_init_cp15 用来设置cp15的一些功能,主要包括禁止cache,关闭MMU和TBL等功能
cpu_init_crit 里面包含了lowlevel_init函数,用户可以自定义一些功能
跳转到main函数
这个SPL的主要目的就是当PLL等东西初始化完成后,第二级的boot时间会大幅度缩短;而由于第一级的boot内容很少,因此boot的过程也很短。因此采用SPL方式会缩短boot时间。这里最终SPL就是用来读写flash rom的。除此之外,SPL还会检查要刷的数据文件是否正确。
这并没有定义各种宏,因此最终的sp的地址为CONFIG_SYS_INIT_SP_ADDR = 0x0c001000 - 128 = 0xC000F80
GD的定义如下:
#define DECLARE_GLOBAL_DATA_PTR register volatile gd_t *gd asm ("r8")
表示GD永远使用r8寄存器来存储地址
调用board_init_f函数
1)调用一个函数指针数组,这个函数指针数组保存了需要初始化的多个函数指针;
2)配置并初始化gd结构体和bd结构体;
3)传递相应参数给uboot重定位模块;
对于第一个功能,代码如下:
对于第二个功能,gd和bd模块,gd主要管理了内存划分,bd主要记录了可用SDRAM的起始位置和大小。
gd和bd两个结构体是uboot里面最重要的两个结构体,我想以后会另起一章。
对于第三个功能,传递的参数如下:
第一个堆栈指针,这个指针的位置是进过计算得出的;
第二个参数为gd的指针,这个gd指针是重定位后的地址;
第三个地址为重定位后的uboot的Image的起始位置;
注意这个函数是没有返回值的,调用这里完毕之后就直接进入uboot代码重定位过程了,至此,uboot的第一部分就结束了。
reset的相关处理
从_start跳转到reset.globl _start _start: b reset
save_boot_params 改函数为weak函数,未定义任何内容。用户如过有任何参数要传递的,那么需要再次定义这个函数。
reset: bl save_boot_params #if defined(SIM_BREAKPOINT_WA) /* workaround to disable secure state */ mrc p15, #0, r0, c1, c1, #0 orr r0, r0, #1 mcr p15, #0, r0, c1, c1, #0 isb #endif
将ARM的模式修改为supervisor模式
mrs r0, cpsr bic r0, r0, #0x1f orr r0, r0, #0xd3 msr cpsr,r0
该宏已定义,表示会跳过底层设备的初始化
cpu_init_cp15 用来设置cp15的一些功能,主要包括禁止cache,关闭MMU和TBL等功能
cpu_init_crit 里面包含了lowlevel_init函数,用户可以自定义一些功能
#ifndef CONFIG_SKIP_LOWLEVEL_INIT bl cpu_init_cp15 bl cpu_init_crit #endif
跳转到main函数
bl _main
main函数的处理
SPL表示secondary program loader,是android等手机刷机的常用术语。二级boot的主要意思就是连续两次boot,第一次是一个很简单的boot,这boot完成的目的就是在初始化PLL和flash等东西,然后将真实的Image从flash中拷入实际内存,继而重新再启动一遍。第二遍就是真实的uboot流程。这个SPL的主要目的就是当PLL等东西初始化完成后,第二级的boot时间会大幅度缩短;而由于第一级的boot内容很少,因此boot的过程也很短。因此采用SPL方式会缩短boot时间。这里最终SPL就是用来读写flash rom的。除此之外,SPL还会检查要刷的数据文件是否正确。
这并没有定义各种宏,因此最终的sp的地址为CONFIG_SYS_INIT_SP_ADDR = 0x0c001000 - 128 = 0xC000F80
_main: #if defined(CONFIG_NAND_SPL) /* deprecated, use instead CONFIG_SPL_BUILD */ ldr sp, =(CONFIG_SYS_INIT_SP_ADDR) #elif defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK) ldr sp, =(CONFIG_SPL_STACK) #else ldr sp, =(CONFIG_SYS_INIT_SP_ADDR) #endif
GD的定义如下:
#define DECLARE_GLOBAL_DATA_PTR register volatile gd_t *gd asm ("r8")
表示GD永远使用r8寄存器来存储地址
调用board_init_f函数
bic sp, sp, #7 /* 8-byte alignment for ABI compliance */ sub sp, #GD_SIZE /* allocate one GD above SP */ bic sp, sp, #7 /* 8-byte alignment for ABI compliance */ mov r8, sp /* GD is above SP */ mov r0, #0 bl board_init_f
board_init_f函数
board_init_f函数是uboot主要完成初始化的函数,在arch/arm/lib/board.c中,这个函数的主要功能如下:1)调用一个函数指针数组,这个函数指针数组保存了需要初始化的多个函数指针;
2)配置并初始化gd结构体和bd结构体;
3)传递相应参数给uboot重定位模块;
对于第一个功能,代码如下:
for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) { if ((*init_fnc_ptr)() != 0) { hang (); } }其中init_sequence是一个全局的函数指针数组,这个数组最后以NULL结尾,因此for循环会自动遍历这个数组来完成用户定义的所有初始化函数。这些初始化函数主要包括,DDR初始化,Timer初始化,I2C等串口初始化,Serial初始化等,当然用户可以自己根据自己是否需要来选择。
对于第二个功能,gd和bd模块,gd主要管理了内存划分,bd主要记录了可用SDRAM的起始位置和大小。
gd和bd两个结构体是uboot里面最重要的两个结构体,我想以后会另起一章。
对于第三个功能,传递的参数如下:
void relocate_code (ulong, gd_t *, ulong) __attribute__ ((noreturn));
第一个堆栈指针,这个指针的位置是进过计算得出的;
第二个参数为gd的指针,这个gd指针是重定位后的地址;
第三个地址为重定位后的uboot的Image的起始位置;
注意这个函数是没有返回值的,调用这里完毕之后就直接进入uboot代码重定位过程了,至此,uboot的第一部分就结束了。
相关文章推荐
- ARM Uboot经历——Uboot初始化代码解析
- ARM Uboot经历——Uboot代码重定位
- ARM Uboot经历——makefile与uboot目录
- 基于ARM Cortex-M0+内核的bootloader程序升级原理及代码解析
- U-boot之flash初始化完全代码分析
- 静态数据的初始化(Think in java P95页代码解析)
- 详解SpringBoot程序启动时执行初始化代码
- u-boot-2009.11移植(适用于TQ2440和MINI2440)第三篇:修改初始化代码
- 【嵌入式开发】 Bootloader 详解 ( 代码环境 | ARM 启动流程 | uboot 工作流程 | 架构设计)
- 【ARM】Uboot代码分析
- arm 初始化代码中的{CONFIG}语句疑问
- CPU 的初始化(ARM & u-boot)
- arm 初始化代码中的{CONFIG}语句疑问
- 2013阿里java代码初始化题目笔试题解析
- 转载:discuz代码解析(一、初始化应用的过程)
- 【嵌入式开发】 Bootloader 详解 ( 代码环境 | ARM 启动流程 | uboot 工作流程 | 架构设计)
- Linux 0.1 版本内核 bootsect.s 代码解析
- discuz代码解析(一、初始化应用的过程)
- arm 初始化代码中的{CONFIG}
- ARM Uboot经历——makefile与uboot目录