整个项目的入口:start.S文件,由链接脚本的ENTRY声明确定
第一部分:头文件包含:
#include <config.h>
#include <version.h>
#if defined(CONFIG_ENABLE_MMU)
#include <asm/proc/domain.h>
#endif
#include <regs.h>
#ifndef CONFIG_ENABLE_MMU
#ifndef CFG_PHY_UBOOT_BASE
#define CFG_PHY_UBOOT_BASE CFG_UBOOT_BASE
#endif
#endif
包含了四个文件:
- config.h文件。config.h是在include目录下的,这个文件不是源码中本身存在的文件,而是配置过程中自动生成的文件。(详见mkconfig脚本)。这个文件的内容其实是包含了一个头文件:#include <configs/x210_sd.h>",所以实际包含的是include/configs/x210_sd.h文件,该文件内容是uboot配置文件,内含各种宏
- version.h文件,这个文件包含uboot的版本信息
- 第三个是asm/proc/domain.h文件,asm和proc是符号链接(第三部分讲过了),所以实际文件是:include/asm-arm/proc-armv/domain.h
- regs.h文件,也是个符号链接,指向include/s5pc110.h
启动代码的16字节头部:
#if defined(CONFIG_EVT1) && !defined(CONFIG_FUSED)
.word 0x2000
.word 0x0
.word 0x0
.word 0x0
#endif
先用四个字(16字节)填充占位,后面还需要计算校验然后重新填充
异常向量表构建:
.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
_pad:
.word 0x12345678 /* now 16*4=64 */
- uboot只对异常进行了简单处理,因为uboot只是一段裸机代码
- 复位异常处的代码是:b reset,因此在CPU复位后真正去执行的有效代码是reset处的代码,因此reset符号处才是真正的有意义的代码开始的地方
.global _end_vect
_end_vect:
.balignl 16,0xdeadbeef
上述代码是让当前地址对齐排布,空的内存用0xdeadbeef(只是个16进制数,没什么特殊含义)填充
TEXT_BASE等变量:
_TEXT_BASE:
.word TEXT_BASE
- 链接时指定的uboot的链接地址,值就是c3e00000
- 源代码中和配置Makefile中很多变量是可以互相传递的。即有些符号的值可以从Makefile中传递到源代码中
_TEXT_PHY_BASE:
.word CFG_PHY_UBOOT_BASE
表示uboot在DDR中的物理地址 CFG_PHY_UBOOT_BASE 值为33e00000
开始真正的reset代码:
reset:
/*
* set the cpu to SVC32 mode and IRQ & FIQ disable
*/
@;mrs r0,cpsr
@;bic r0,r0,#0x1f
@;orr r0,r0,#0xd3
@;msr cpsr,r0
msr cpsr_c, #0xd3 @ I & F disable, Mode: 0x13 - SVC
- msr cpsr_c, #0xd3,表示设置cpsr寄存器,关快速中断和中断模式,设置mode为0x13(SVC模式)
- 整个uboot工作时都是SVC