转自:http://zqwt.012.blog.163.com/blog/static/120446842013326690970/
/*****************************************************
* Startup Code (reset vector) // 启动代码(复位向量)
* do important init only if we don't start from memory!
* //如果不是一开始就从SDRAM里面启动,我们就在此做一些重要的初始化
* relocate armboot to ram //然后,搬运代码到SDRAM中的TEXT_BASE去执行
* setup stack // 设置堆栈
* jump to second stage // 跳到第二阶段去执行board.c */
_TEXT_BASE:
.word TEXT_BASE
l TEXT_BASE在开发板相关的目录中的board/smdk2410/config.mk文档中定义, 即uboot要加载到sdram中的TEXT_BASE地址处去执行。
.globl _armboot_start
_armboot_start:
.word _start
l 用.globl声明 _armboot_start 并用_start 来进行初始化。在board/u-boot.lds中定义 ( _start定义在start.s中 --转者)
l 下面这几行代码是在S3C2410开发板的链接脚本board/u-boot.lds中给出定义的。( 只是__bss_start等定义在board/u-boot.lds中,并非代码 --转者)
声明_bss_start并用__bss_start来初始化,其中__bss_start定义在和板相关的u-boot.lds中。_bss_start保存的是__bss_start这个标号所在的地址, 这里涉及到当前代码所在的地址不是编译时链接的地址的情况(就我理解,即加载地址和运行地址的区别),这里直接取得该标号对应的地址,不受编译时链接地址的影响. _bss_end也是同样的道理。
.globl _bss_start
_bss_start:
.word __bss_start
.globl _bss_end
_bss_end:
.word _end
#ifdef CONFIG_USE_IRQ // 如果定义了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
/*
* the actual reset code
* 复位或者上电之后,代码从这里开始执行
*/
reset:
l 设置CPU的状态类型为SVC特权模式(一共7种权限,这是其中的一种)。
Reset即复位,在系统中经常会用到,该操作是异常处理的第一个操作,其主要目的是设置CPU模式为SVC特权模式。在此,有必要介绍一下ARM处理器的7种工作模式。
l CPSR(当前程序状态寄存器)的低5位用于定义当前操作模式,如图示:
l 除用户模式外的其他6种模式称为特权模式。
特权模式中除系统模式以外的5种模式又称为异常模式,即 :
FIQ(Fast Interrupt Request)
IRQ(Interrupt ReQuest)
SVC(Supervisor)
中止(Abort)
未定义(Undefined)
l ARM处理器总共有37个32位寄存器,可以分为以下两类寄存器:
? 31个通用寄存器(R0~R15)
R0~R15;
R13_svc、R14_svc;
R13_abt、R14_abt;
R13_und、R14_und;
R13_irq、R14_irq;
R8_frq-R14_frq。
? 6个状态寄存器
CPSR;SPSR_svc、SPSR_abt、SPSR_und、SPSR_irq和SPSR_fiq 。
l 但是这32个寄存器不能同时被访问,具体哪些寄存器是可编程访问的,取决于微处理器的工作状态以及具体的运行模式。但在任何时候,通用寄存器R0~R14、程序计数器(R15)PC、一个或两个状态寄存器都是可访问的。通用寄存器包括R0~R15(31个),可以分为3类:
? 未分组寄存器R0~R7
R0~R7是不分组寄存器。在所有处理器模式下,未分组寄存器都指向同一个物理寄存器,也就是说它们每一个都访问的是同一个物理寄存器,它们未被系统用作特殊的用途。但必须得注意,未分组寄存器没有被系统用于特别的用途,任何可采用通用寄存器的应用场合都可以使用相同的未分组寄存器,这样可能会造成寄存器中数据的破坏,所以必须注意对同一寄存器在不同模式下使用时的数据保护。
? 分组寄存器R8~R14
分组寄存器R8-R12:
FIQ模式分组寄存器R8~R12。
FIQ以外的分组寄存器R8~R12。
分组寄存器R13、R14
寄存器R13通常用做堆栈指针SP。
寄存器R14用作子程序链接寄存器(Link Register-LR),也称为LR。
? 程序计数器R15
寄存器R15被用作程序计数器,也称为PC 。
R15值的改变将引起程序执行顺序的变化,这有可能引起程序执行中出现一些不可预料的结果。
ARM处理器采用多级流水线技术,因此保存在R15的程序地址并不是当前指令的地址。一些指令对于R15的用法有一些特殊的要求。在ARM状态下,R15的位[1:0]为0,位[31:2]用于保存PC;在Thumb状态下R15的位[0]为0,位[31:1]用于保存PC。
l 这里有必要了解一Thumb状态下的寄存器组织
Thumb状态下的寄存器集是ARM状态下寄存器集的子集。程序员可以直接访问8个通用的寄存器(R0~R7),程序计数器PC、堆栈指针SP、连接寄存器LR和当前状态寄存器CPSP。其实,每一种特权模式都各有一组SP,LR和SPSR。可以看看下面这张图:
l ARM程序状态寄存器
所有处理器模式下都可以访问当前的程序状态寄存器CPSR。CPSR包含条件码标志、中断禁止位、当前处理器模式以及其它状态和控制信息。
在每种异常模式下都有一个对应的物理寄存器——程序状态保存寄存器SPSR。当异常出现时,SPSR用于保存CPSR的状态,以便异常返回后恢复异常发生时的工作状态。
下面这张图是CPSR和SPSR的格式: