标题:
分析 u-boot 的第一阶段代码(cpu/arm920t/start.S)
[打印本页]
作者:
yuyang911220
时间:
2014-12-30 22:18
标题:
分析 u-boot 的第一阶段代码(cpu/arm920t/start.S)
uboot中start.S详解(zt)
[cpp]
view plain
copy
#include <config.h>
#include <version.h>
/* 这段代码的主要作用是初始化硬件设备、建立内存空间的映射图,从而将系统的软硬件环境带到一个合适的状态,以便为最终调用操作系统内核准备好正确的环境 */
#if defined(CONFIG_OMAP1610)
#include <./configs/omap1510.h>
#elif defined(CONFIG_OMAP730)
#include <./configs/omap730.h>
#endif
/*************************************************************************
*
* Jump vector table as in table 3.1 in [1]
*
*************************************************************************/
.globl _start
_start: /* 系统复位位置, 各个异常向量对应的跳转代码 */
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 /* 快速中断异常向量 */
_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
.balignl 16,0xdeadbeef
/************************************************分析****************************************************
* 从中我们可以看出,ARM支持7种异常。问题是发生了异常后ARM是如何响应的呢?
* 第一个复位异常很好理解,它放在0x0的位置,一上电就执行它,而且我们的程序总是从
* 复位异常处理程序开始执行的,因此复位异常处理程序不需要返回。那么什么时候会执行
* 到后面几个异常处理函数呢?步骤是这样的:
*
* 当一个异常出现以后,ARM会自动执行以下几个步骤:
* (1) 把下一条指令的地址放到连接寄存器LR(通常是R14),这样就能够在处理异常返回时从正确的位置继续执行。
* (2) 将相应的CPSR(当前程序状态寄存器)复制到SPSR(备份的程序状态寄存器)中。从异常退出的时候,就可以由SPSR来恢复CPSR。
* (3) 根据异常类型,强制设置CPSR的运行模式位。
* (4) PC(程序计数器)被强制成相关异常向量处理函数地址,从而跳转到相应的异常处理程序中。
*
* 当异常处理完毕后,ARM会执行以下几步操作从异常返回:
* (1) 将连接寄存器LR的值减去相应的偏移量后送到PC中
* (2) 将SPSR复制回CPSR中
* (3) 若在进入异常处理时设置了中断禁止位,要在此清除
*
* ARM规定了异常向量的地址:
* b reset ; 复位 0x0
* ldr pc, _undefined_instruction ; 未定义的指令异常 0x4
* ldr pc, _software_interrupt ; 软件中断异常 0x8
* ldr pc, _prefetch_abort ; 预取指令 0xc
* ldr pc, _data_abort ; 数据 0x10
* ldr pc, _not_used ; 未使用 0x14
* ldr pc, _irq ; 慢速中断异常 0x18
* ldr pc, _fiq ; 快速中断异常 0x1c
* 这样理解这段代码就非常简单了。碰到异常时,PC会被强制设置为对应的异常向量,从而跳转到
* 相应的处理程序,然后再返回到主程序继续执行。
*
* .balignl 16,0xdeadbeef, 将地址对齐到16的倍数,如果地址寄存器的值(PC)跳过4个字节才是16的倍数,
* 则使用0xdeadbeef填充这4个字节,如果它跳过1、2、3个字节,则填充值不确定。如果地址寄存器的值(PC)
* 是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
*
*************************************************************************/
/* 保存变量的数据区 */
_TEXT_BASE:
.word TEXT_BASE
.globl _armboot_start
_armboot_start:
.word _start
/* These are defined in the board-specific linker script.*/
.globl _bss_start
_bss_start:
.word __bss_start
.globl _bss_end
_bss_end:
.word _end
#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
/*************************************************分析**********************************************************
* 上面这段代码,主要保存一些全局变量,用于BOOT程序从FLASH拷贝到RAM,或者其它的使用。
* 还有一些变量的值是通过连接脚本得到的,比如TEXT_BASE位于/u-boot-1.1.6/board/xxx(开发板目录名称)/config.mk
* 文件里。__bss_start、_end位于/u-boot-1.1.6/board/xxx(开发板目录名称)/u-boot.lds文件里,具体值是由编译器算出来的。
***************************************************************************************************************/
/* the actual reset code*/
/* 系统的复位代码。系统一上电,就跳到这里运行 */
reset:
/*
* set the cpu to SVC32 mode
*/
mrs r0,cpsr /* 取得当前程序状态寄存器cpsr到r0 */
bic r0,r0,#0x1f /* 这里使用位清除指令,把中断全部清除,只置位模式控制位 为中断提供服务通常是 OS
*设备驱动程序的责任,因此在 Boot Loader 的执行全过程中可以不必响应任何中断。
*/
orr r0,r0,#0xd3 /* 计算为超级保护模式 */
msr cpsr,r0 /* 设置cpsr为超级保护模式 */
/***********************************************分析*************************************************************
* 设置cpu运行在SVC32模式。ARM共有7种模式:
* 用户模式(usr): arm处理器正常的程序执行状态
* 快速中断模式(fiq): 用于高速数据传输或通道处理
* 外部中断模式(irq): 用于通用的中断处理
* 超级保护模式(svc): 操作系统使用的保护模式
* 数据访问终止模式(abt): 当数据或指令预取终止时进入该模式,可用于虚拟存储及存储保护
* 系统模式(sys): 运行具有特权的操作系统任务
* 未定义指令中止模式(und): 当未定义的指令执行时进入该模式,可用于支持硬件协处理器的软件仿真
*
* 通过设置ARM的CPSR寄存器,让CPU运行在操作系统保护模式,为后面进行其它操作作好准备了。
****************************************************************************************************************/
/*
* we do sys-critical inits only at reboot,
* not when booting from ram!
*/
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
bl cpu_init_crit
/******************************************************************************
* BL为相对寻址,以程序计数器PC 的当前值为基地址,指令中的地址标号作为偏移量,将两者相加之后得到操作数的有效地址
* ARM 指令集中的4条跳转指令可以完成从当前指令向前或向后的32MB 的地址空间的跳转,
* 用的是相对寻址,它们是:B、BL、BLX、BX
*******************************************************************************/
欢迎光临 电子技术论坛_中国专业的电子工程师学习交流社区-中电网技术论坛 (http://bbs.eccn.com/)
Powered by Discuz! 7.0.0