您的位置:首页 > 其它

Uboot学习笔记④---(start.S简单分析)

2014-11-18 20:29 471 查看

本文所有资料来至互联网,笔者加以整理和归纳,仅供以后复习

对于uboot的start.S,主要做的事情就是系统的各个方面的初始化。

从大的方面分,可以分成这几个部分:

设置CPU模式

关闭看门狗

关闭中断

设置堆栈sp指针

清除bss段

异常中断处理
1、分析.globl _start

         . global的语法

DirectiveDescriptionSyntaxExample
.globalMakes
symbol visible to the linker
.global symbol.global MyAsmFunc
.globlSame as .global.globl symbol.globl MyOtherAsmFunc
所以,意思很简单,就是相当于C语言中的Extern,声明此变量,并且告诉链接器此变量是全局的,外部可以访问

所以,你可以看到

board\开发板名\u-boot.lds


中,有用到此变量:

ENTRY(_start)

即指定入口为_start,而由下面的_start的含义可以得知,_start就是整个start.S的最开始,即整个uboot的代码的开始。

2、分析 _start: b    reset

start的值,也就是这个代码的位置了,此处即为代码的最开始,相对的0的位置。

在程序开始运行的时候,如果是从NorFlash或NandFlash启动,那么其地址是0,

_start=0

如果是重新relocate代码之后,就是我们定义的值了,即,在

board\
开发板名
\config.mk


中的:

TEXT_BASE = 0x33D00000

表示是代码段的基地址,即

_start=TEXT_BASE=0x33D00000

2、分析 LDR

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

LDR R0,[R1] ;将存储器地址为R1的字数据读入寄存器R0。

LDR R0,[R1,R2] ;将存储器地址为R1+R2的字数据读入寄存器R0。

LDR R0,[R1,#8] ;将存储器地址为R1+8的字数据读入寄存器R0。

LDR R0,[R1,R2]! ;将存储器地址为R1+R2的字数据读入寄存器R0,并将新地址R1+R2写入R1。

LDR R0,[R1,#8]! ;将存储器地址为R1+8的字数据读入寄存器R0,并将新地址R1+8写入R1。

LDR R0,[R1],R2 ;将存储器地址为R1的字数据读入寄存器R0,并将新地址R1+R2写入R1。

LDR R0,[R1,R2,LSL#2]! ;将存储器地址为R1+R2×4的字数据读入寄存器R0,并将新地址R1+R2×4写入R1。

LDR R0,[R1],R2,LSL#2 ;将存储器地址为R1的字数据读入寄存器R0,并将新地址R1+R2×4写入R1。

3、分析 .word

_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

表 1.2. .word的语法

DirectiveDescriptionSyntaxExample
.wordDefine word expr (32bit numbers).word expr {, …}.word 144511, 0x11223
所以上面的含义,以_undefined_instruction为例,就是,此处分配了一个word=32bit=4字节的地址空间,里面存放的值是undefined_instruction。

而此处_undefined_instruction也就是该地址空间的地址了。用C语言来表达就是:

_undefined_instruction = &undefined_instruction



*_undefined_instruction = undefined_instruction

在后面的代码,我们可以看到,undefined_instruction也是一个标号,即一个地址值,对应着就是在发生“未定义指令”的时候,系统所要去执行的代码。

(其他几个对应的“软件中断”,“预取指错误”,“数据错误”,“未定义”,“(普通)中断”,“快速中断”,也是同样的做法,跳转到对应的位置执行对应的代码。)

3、分析 .balignl

.balignl 16,0xdeadbeef

表 1.3. balignl的语法

DirectiveDescriptionSyntaxExample
.balignlWord align the following code to
alignment byte boundary (default=4). Fill skipped words with
fill (default=0 or NOP). If the number of bytes skipped is greater than max, then don't align (default=alignment ).
.balignl {alignment} {, fill} {, max}.balignl
所以意思就是,接下来的代码,都要16字节对齐,不足之处,用0xdeadbeef填充。

其中关于所要填充的内容0xdeadbeef,此处0xdeadbeef本身没有真正的意义,但是很明显,字面上的意思是,(坏)死的牛肉。

虽然其本身没有实际意义,但是其是在十六进制下,能表示出来的,为数不多的,可读的单词之一了。

另外一个相对常见的是:0xbadc0de,意思是bad code,坏的代码,注意其中的o是0,因为十六进制中是没有o的。

这些“单词”,相对的作用是,使得读代码的人,以及在查看程序运行结果时,容易看懂,便于引起注意。

4、分析 _TEXT_BASE 和_armboot_start

/*
*************************************************************************
*
* 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
*
*************************************************************************
*/

_TEXT_BASE:
.word TEXT_BASE

/*
* Below variable is very important because we use MMU in U-Boot.
* Without it, we cannot run code correctly before MMU is ON.
* by scsuh.
*/
/* 此处的<pre name="code" class="objc">CFG_PHY_UBOOT_BASE应该在某处定义*/

_TEXT_PHY_BASE: .word CFG_PHY_UBOOT_BASE.globl _armboot_start_armboot_start: .word _start



TEXT_BASE在\board\开发板名\config.mk
中定义

同理,此含义可用C语言表示为:

*(_armboot_start) = _start

5、分析 bss_start和_bss_end

/*
* These are defined in the board-specific linker script.
*/
.globl _bss_start
_bss_start:
.word __bss_start

.globl _bss_end
_bss_end:
.word _end关于_bss_start和_bss_end都只是两个标号,对应着此处的地址。
而两个地址里面分别存放的值是__bss_start和_end,这两个的值,根据注释所说,是定义在开发板相关的链接脚本里面的,我们此处的开发板相关的链接脚本是:

board\开发板名\
u-boot.lds


__bss_start = .;
.bss : { *(.bss) }
_end = .;


详细解析参考博客:http://www.crifan.com/about/me/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  startS arm uboot分析