uboot启动流程详解(1)-_start
2016-11-12 16:12
435 查看
(1)代码及注释
.globl _start /*声明一个符号可被其它文件引用,相当于声明了一个全局变量, .globl与.global相同*/ _start: b reset /* b是不带返回的跳转(bl是带返回的跳转), 意思是无条件直接跳转到reset标号处执行程序*/ ldr pc, _undefined_instruction /*未定义指令异常向量,ldr的作用是, 将符号_undefined_instruction指向的地址的内容加载到pc*/ ldr pc, _software_interrupt /*软件中断向量*/ ldr pc, _prefetch_abort /*预取指令异常向量*/ ldr pc, _data_abort /*数据操作异常向量*/ ldr pc, _not_used /*未使用*/ ldr pc, _irq /*irq中断向量*/ ldr pc, _fiq /*fiq中断向量*/ #ifdef CONFIG_SPL_BUILD //我的uboot中没有定义这个宏,关于这个宏的介绍,请看下文 _undefined_instruction: .word _undefined_instruction _software_interrupt: .word _software_interrupt _prefetch_abort: .word _prefetch_abort _data_abort: .word _data_abort _not_used: .word _not_used _irq: .word _irq _fiq: .word _fiq _pad: .word 0x12345678 /* now 16*4=64 */ #else .globl _undefined_instruction _undefined_instruction: .word undefined_instruction /*就是在当前地址,即 _undefined_instruction 处存放 undefined_instruction。 通过下面的反汇编代码可以看到,这个地址存放的内容是0x87800120*/ .globl _software_interrupt _software_interrupt: .word software_interrupt .globl _prefetch_abort _prefetch_abort: .word prefetch_abort .globl _data_abort _data_abort: .word data_abort .globl _not_used _not_used: .word not_used .globl _irq _irq: .word irq .globl _fiq _fiq: .word fiq _pad: .word 0x12345678 /* now 16*4=64 */ #endif /* CONFIG_SPL_BUILD */ .global _end_vect _end_vect: .balignl 16,0xdeadbeef /*这句代码使下面的代码开始处16字节对齐, 即当上段的代码运行完后不是16字节对齐,就填充0xdeadbeef,直到使下段 的代码开始处16字节对齐。*/ /************************************************************************* * * Startup Code (reset vector) * * do important init only if we don't start from memory! * setup Memory and board specific bits prior to relocation. * relocate armboot to ram * setup stack * *************************************************************************/ /************************************************* 下面是IRQ中断,放了一个IRQ_STACK_START标号,标号内容为:0x0badc0de, 此内容没有意义,只是为了占一个坑。程序刚刚运行,还没有进入初始化,根本不知 道堆栈指针现在应该放在什么地方,所以一开始,作者做了一个小技巧,填充一个无 效的数字,等初始化以后堆栈指针建立好后,再将实际的堆栈指针写到这里。然而在 我的平台里CONFIG_USE_IRQ这个宏并没有定义!!! *************************************************/ #ifdef CONFIG_USE_IRQ /* IRQ stack memory (calculated at run-time) */ .globl IRQ_STACK_START IRQ_STACK_START: .word 0x0badc0de /* IRQ stack memory (calculated at run-time) */ .globl FIQ_STACK_START FIQ_STACK_START: .word 0x0badc0de #endif /* IRQ stack memory (calculated at run-time) + 8 bytes */ /*下面也是不能确定堆栈指针地址,所以填充无效数字,当堆栈指针确定以后,将其加8填充到这里*/ .globl IRQ_STACK_START_IN IRQ_STACK_START_IN: .word 0x0badc0de
(2)反汇编代码
为了更好的理解上面用到的汇编指令,对uboot进行反汇编。使用命令:arm-fsl-linux-gnueabi-objdump -D u-boot > u-boot.s
uboot.s就是反汇编出来的文件,以上这段代码对应的反汇编代码如下:
u-boot: file format elf32-littlearm Disassembly of section .text: 87800000 <__image_copy_start>: 87800000: ea00000f b 87800044 <reset> 87800004: e59ff014 ldr pc, [pc, #20] ; 87800020 <_undefined_instruction> 87800008: e59ff014 ldr pc, [pc, #20] ; 87800024 <_software_interrupt> 8780000c: e59ff014 ldr pc, [pc, #20] ; 87800028 <_prefetch_abort> 87800010: e59ff014 ldr pc, [pc, #20] ; 8780002c <_data_abort> 87800014: e59ff014 ldr pc, [pc, #20] ; 87800030 <_not_used> 87800018: e59ff014 ldr pc, [pc, #20] ; 87800034 <_irq> 8780001c: e59ff014 ldr pc, [pc, #20] ; 87800038 <_fiq> 87800020 <_undefined_instruction>: 87800020: 87800120 strhi r0, [r0, r0, lsr #2] 87800024 <_software_interrupt>: 87800024: 87800180 strhi r0, [r0, r0, lsl #3] 87800028 <_prefetch_abort>: 87800028: 878001e0 strhi r0, [r0, r0, ror #3] 8780002c <_data_abort>: 8780002c: 87800240 strhi r0, [r0, r0, asr #4] 87800030 <_not_used>: 87800030: 878002a0 strhi r0, [r0, r0, lsr #5] 87800034 <_irq>: 87800034: 87800300 strhi r0, [r0, r0, lsl #6] 87800038 <_fiq>: 87800038: 87800360 strhi r0, [r0, r0, ror #6] 8780003c <_pad>: 8780003c: 12345678 eorsne r5, r4, #125829120 ; 0x7800000 87800040 <IRQ_STACK_START_IN>: 87800040: 0badc0de bleq 863703c0 <__image_copy_start-0x148fc40>
请看语句:
ldr pc, [pc, #20] ; 87800020 <_undefined_instruction>,当要跳转到_undefined_instruction时,为什么是将当前pc的值加20后再赋给pc呢?
流水线操作:取址—>译码—>运行;
把内存中的代码取到CPU中,把e59ff014翻译成对应的命令,ldr pc,[pc,#20],然后运行。所以pc指针并不是指向当前运行的命令,而是指向当前运行的指令加8,加8超前两个指令,一个用来取址,一个用来译码,即:
pc=0x87800004+0x08=0x8780000c, pc= 0x8780000c+0x14(即20)=0x87800020
即把0x87800020地址处的数字0x87800120放到pc指针里面,即直接跳转到0x87800120地址处运行。
(3) CONFIG_SPL_BUILD介绍
这个宏定义的主要作用就是生成 BL1 文件,提到 BL1 文件肯定又会有朋友产生疑问,在这里就这个 BL1 文件给大家简单的介绍一下:BL1 文件是一段外部代码,存放在 SD 卡或者 nandflash 上,大小为(4K\8K\16K)。除了 BL1 文件,还有 BL0 和 BL2 文件。BL0 文件是存放在 CPU 内部 IROM 中的一段固化代码,CPU 上点之后,首先去运行BL0 文件。BL2 文件是完整的 U-Boot 代码。
这三个文件之间的关系就是:BL0 运行时会将 BL1 拷贝到 CPU 的 IRAM 中,然后执行BL1,BL1 文件执行起来之后会先进行内存的初始化,之后将 BL2 文件拷贝到外部内存中运行。
(4)ARM异常向量表
相关文章推荐
- uboot启动流程详解(5)-_main
- uboot启动流程详解(3)-cpu_init_cp15
- Uboot启动流程分析:启动阶段1 Start.S
- uboot启动流程详解(1)-_start
- 1.移植uboot-分析uboot启动流程(详解)
- uboot启动流程详解(3)-cpu_init_cp15
- uboot启动流程详解(2)-reset
- HISI3520DV300 折腾记录(一)之 《Uboot-Start.S分析 以及 相关启动流程分析》
- uboot启动流程详解(5)-_main
- uboot启动流程详解(4)-cpu_init_crit
- uboot启动流程详解(2)-reset
- u-boot启动代码start.S详解
- Uboot启动分析笔记-----Stage1(start.S与lowlevel_init.S详解)
- Uboot启动分析笔记-----Stage1(start.S与lowlevel_init.S详解)
- Uboot优美代码赏析2:第一阶段_硬件平台启动start.s分析
- Uboot启动分析之stage1-Nand-Flash启动部分详解
- uboot启动流程分析图
- 详解ARM-linux的启动流程[转帖]
- Uboot启动流程分析
- linux 启动流程详解