首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

分析 u-boot 的第一阶段代码(cpu/arm920t/start.S)

分析 u-boot 的第一阶段代码(cpu/arm920t/start.S)

uboot中start.S详解(zt)
[cpp] view plaincopy

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


继承事业,薪火相传
返回列表