NanoPC-T2 Uboot启动过程分析 - 2-1 初始启动
来源:互联网 发布:网络管理高级题库 编辑:程序博客网 时间:2024/05/08 04:35
从上一章的分析可看到,UBoot已经从SD卡或Flash被复制到 0x42C0_0000 内存上,并开始从这里开始执行。
为了方便说明,以下将UBoot源码的根目录位置表示为 /uboot-root 。
首先,先找到 /uboot-root/u-boot.lds,这是uboot编译时的链接文件,打开后重点关注以下内容:
ENTRY(_stext)SECTIONS{ . = 0x00000000; . = ALIGN(4); .text : { *(.__image_copy_start) arch/arm/cpu/slsiap/s5p4418/start.o (.text*) *(.text*) } ... #以下内容省略。}
从上面的内容可以看出两个信息,一是代码从 _stext 标签开始执行,二是该标签位于 /uboot-root/arch/arm/cpu/slsiap/s5p4418/start.S 。
打开 /uboot-root/arch/arm/cpu/slsiap/s5p4418/start.S 并找到 _stext 标签。代码如下所示:
.globl _stext_stext: b reset 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
这是S5P4418的 Exception Handlers Vectors。这是芯片所规定的,可以参考S5P4418的用户手册说明。按照执行规律,CPU会先执行 b reset 的指令,跳转到 reset 标签继续执行。该标签在同一个文件中的第78行。从这里开始就是uboot正式开始工作的地方。
首先要将CPU设置为SVC32的模式。
.globl resetreset: bl save_boot_params /* * set the cpu to SVC32 mode */ mrs r0, cpsr bic r0, r0, #0x1f orr r0, r0, #0xd3 msr cpsr,r0
具体的设置方式与所涉及的寄存器,和CPU的内核有关,此处可以到ARM官网搜索 cortex-a9 内核相关的用户手册。接下来会遇到这样的一段代码:
#ifndef CONFIG_SKIP_LOWLEVEL_INIT bl cpu_init_cp15 bl cpu_init_crit#endif
这段代码是否被执行取决于 CONFIG_SKIP_LOWLEVEL_INIT 这个宏的定义。通常这些选择性开关的宏会定义在 /uboot-root/include/configs/XXX.h 中。此处找到 /uboot-root/include/configs/s5p4418_nanopi2.h 。发现这个头文件中并没有定义 CONFIG_SKIP_LOWLEVEL_INIT 这个宏,即上述这段代码是要被执行的。
首先是执行 bl cpu_init_cp15 这条语句。由于此时系统栈还没有初始化,因此只能靠 lr 寄存器来记录调用返回地址。因此,先记录当前相关寄存器的内容:
lr = &( bl cpu_init_cp15 ) @ /uboot-root/arch/arm/cpu/slsiap/s5p4418/start.S
标签 cpu_init_cp15 在同一文件中的第207行。根据注释可以看出这里主要完成了两件事,一是让一级的Icache和Dcache失效,二是禁用MMU和Caches。完成这两个任务后就根据 lr 寄存器的内容返回了。接下来是执行 bl cpu_init_crit 这条语句。同样,记录当前相关寄存器的内容:
lr = &( bl cpu_init_crit ) @ /uboot-root/arch/arm/cpu/slsiap/s5p4418/start.S
cpu_init_crit的代码如下:
#ifndef CONFIG_SKIP_LOWLEVEL_INIT/************************************************************************* * * CPU_init_critical registers * * setup important registers * setup memory timing * *************************************************************************/ENTRY(cpu_init_crit) /* * Jump to board specific initialization... * The Mask ROM will have already initialized * basic memory. Go here to bump up clock rate and handle * wake up conditions. */ b lowlevel_init @ go setup pll,mux,memoryENDPROC(cpu_init_crit)#endif
从代码可以看出, cpu_init_crit 标签仅调用了 lowlevel_init 这个标签。由于使用的是 b 跳转命令,因此 lr 寄存器的值没变,从而直接跳转到 lowlevel_init 标签。该标签位于 /uboot-root/arch/arm/cpu/slsiap/s5p4418/low_init.S 中。在这个过程中主要完成了4件事,由于这4件事是和CPU有关的,因此不在Uboot分析的讨论范围内,这里忽略了部分代码:
#ifndef CONFIG_SKIP_LOWLEVEL_INIT/* ************************************************************************* * * CPU_init_critical * ************************************************************************* */ .globl lowlevel_initlowlevel_init: /* get cpu id */ ... /* secure SCU invalidate */ ... /* join SMP */ ... /* enable maintenance broadcast */ ... mov pc, lr @ back to caller#endif /* CONFIG_SKIP_LOWLEVEL_INIT */
过程的最后一句,是根据 lr 寄存器进行返回。因此uboot返回到 lr 的地址继续执行。重新回到 /uboot-root/arch/arm/cpu/slsiap/s5p4418/start.S 的94行,出现以下语句:
#ifdef CONFIG_RELOC_TO_TEXT_BASE
由于宏 CONFIG_RELOC_TO_TEXT_BASE 已定义在 /uboot-root/include/configs/s5p4418_nanopi2.h 中,因此被该宏包括的语句都要执行。首先是这样的一段代码:
relocate_to_text: /* * relocate u-boot code on memory to text base * for nexell arm core (add by jhkim) */ adr r0, _stext /* r0 <- current position of code */ ldr r1, TEXT_BASE /* test if we run from flash or RAM */ cmp r0, r1 /* don't reloc during debug */ beq clear_bss ldr r2, _bss_start_ofs add r2, r0, r2 /* r2 <- source end address */
这段代码是用来判断当前运行的位置是否在RAM上。代码中的 adr r0, _stext 这条语句是用来获取当前 _stext 标签所位于的真实地址。然后用 ldr r1, TEXT_BASE 来获取目标运行的地址。经过搜索,TEXT_BASE这个标签位于同一文件的第50行:
.globl TEXT_BASETEXT_BASE: .word CONFIG_SYS_TEXT_BASE
可以看到,TEXT_BASE的值由宏 CONFIG_SYS_TEXT_BASE 来决定。该宏同样定义在 /uboot-root/include/configs/s5p4418_nanopi2.h 中,其值为 0x42C0_0000 。在第一章上电启动的时候已经分析过,UBoot被拷贝到 0x42C0_0000 的地址上,并且从 _stext 标签开始执行。因此, _stext 与 TEXT_BASE 的值相同,即 UBoot 已在RAM上运行。根据程序流程,UBoot会继续执行 clear_bss 标签上的内容。以下是该标签的代码:
clear_bss: ldr r0, _bss_start_ofs ldr r1, _bss_end_ofs ldr r4, TEXT_BASE /* text addr */ add r0, r0, r4 add r1, r1, r4 mov r2, #0x00000000 /* clear */clbss_l:str r2, [r0] /* clear loop... */ add r0, r0, #4 cmp r0, r1 bne clbss_l
从代码中可以看出,这部分的功能主要是用0去填充bss段的内容。bss段是存放未初始化的变量,经过这一步骤后,所有未初始化的变量都被初始化为0了。接下来会执行到这样的一段代码:
#ifdef CONFIG_MMU_ENABLE bl mmu_turn_on#endif
经过搜索,宏 CONFIG_MMU_ENABLE 在 /uboot-root/include/configs/s5p4418_nanopi2.h 中已被定义,因此UBoot会执行 bl mmu_turn_on 这条指令。同样,由于使用 bl 指令跳转,因此先记录相关寄存器的值:
lr = &( bl mmu_turn_on ) @ /uboot-root/arch/arm/cpu/slsiap/s5p4418/start.S
该标签的内容位于 /uboot-root/arch/arm/cpu/slsiap/s5p4418/mmu_asm.S 中,其内容如下:
.globl mmu_turn_onmmu_turn_on: ldr sp, =(CONFIG_SYS_INIT_SP_ADDR) mov r13, lr bl mmu_on mov pc, r13 @ back to caller
这部分的代码是为调用 mmu_on 做准备的。由于 mmu_on 是用c语言编写的,所以这里要为c语言构造一个运行环境,包括设置系统栈等等。在调用到 bl mmu_on 的时候,相关寄存器的内容如下:
r13 = &( bl mmu_turn_on ) @ /uboot-root/arch/arm/cpu/slsiap/s5p4418/start.Ssp = 0x42C0_0000lr = &( bl mmu_on ) @ /uboot-root/arch/arm/cpu/slsiap/s5p4418/mmu_asm.S
到这里,终于可以先解释一个问题了。那就是根据芯片手册的说明,RAM的起始地址在0x4000_0000,为什么UBoot不是复制到RAM起始地址,而是在0x42C0_0000这里呢?那是因为0x4000_0000到0x42BF_FFFF这44KB已作为了UBoot的栈空间了。因此目前的内容空间使用分配如下:
0xC000_0000 UBoot0x42C0_0000 UBoot-Stack0x4000_0000
言归正传, mmu_on 这一个函数位于 /uboot-root/arch/arm/cpu/slsiap/s5p4418/mmu.c 中,其代码如下:
void mmu_on(void){ //void *vector_base = (void *)0xFFFF0000; dcache_disable(); arm_init_before_mmu(); /* Flush DCACHE */ /* copy vector table */ //memcpy(vector_base, (void const *)CONFIG_SYS_TEXT_BASE, 64); mmu_page_table_flush(PAGE_TABLE_START, PAGE_TABLE_SIZE); make_page_table((u32*)ptable); /* Make MMU PAGE TABLE */ enable_mmu(PAGE_TABLE_START);#if defined (SMP_SCU_ENABE) scu_enable((void __iomem *)MPPR_REG);#endif}
由于本人对MMU还没有深入的研究,而且这部分代码也与UBoot的执行流程没多大的影响。因此这部分的解析暂时先省略,等以后有了深入的了解后再进行补充说明。该函数返回后将回到 /uboot-root/arch/arm/cpu/slsiap/s5p4418/mmu_asm.S 继续执行 mov pc, r13 这一条语句,这里又是一次返回。根据寄存器的记录,这次返回到 /uboot-root/arch/arm/cpu/slsiap/s5p4418/start.S 中,并从第134行继续执行。
由于篇幅原因,并且之后的内容又是另一个小阶段,因此本节先暂且结束。
- NanoPC-T2 Uboot启动过程分析 - 2-1 初始启动
- NanoPC-T2 Uboot启动过程分析- 1 上电启动
- NanoPC-T2 Uboot启动过程分析 - 2-2 board_init_f
- NanoPC-T2 Uboot启动过程分析 - 2-3 init_sequence_f[] part 1
- NanoPC-T2 Uboot启动过程分析 - 2-5 board_init_r() part 1
- NanoPC-T2 Uboot启动过程分析 - 3-2 启动命令的执行
- NanoPC-T2 Uboot启动过程分析 - 2-4 init_sequence_f[] part 2
- NanoPC-T2 Uboot启动过程分析 - 2-6 board_init_r() part 2
- NanoPC-T2 Uboot启动过程分析 - 3-1 main_loop()初认识
- NanoPC-T2 uboot分析(1)
- NanoPC-T2 以太网分析(2)
- NanoPC-T2 以太网分析(1)
- UBOOT启动过程分析
- uboot分析之uboot启动过程分析
- uboot启动过程完全分析
- uboot启动过程完全分析
- uboot启动过程完全分析
- uboot - 启动内核过程分析
- eCryptfs - open系统调用
- 在EditText中显示提示文本,在提示文本后面可以输入文本
- Openstack liberty 云主机迁移源码分析之在线迁移2
- 排序(二)——冒泡排序及其改进
- struts2 ajax图片上传
- NanoPC-T2 Uboot启动过程分析 - 2-1 初始启动
- 短信验证码
- Jquery EasyUI增删改查代码
- 【Cqoi2011】【BZOJ3295】动态逆序对
- inno setup详细使用教程
- Hash表
- 九度-1463-招聘会
- ios alert对话框 弹出菜单
- c++引用lib库