uboot启动流程详解(1)-_start

(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异常向量表

这里写图片描述

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值