我们人为的把uboot的启动分为stage1和stage2,区分的标准是以编程语言和代码的作用。
stage1主要用arm汇编及一部分C的混合编程,完成底层硬件的初始化设置;
stage2则完全用C实现,在进行一些硬件(外设)初始化的同时,为linux启动提供参数和软硬件环境。
Stage1源码分析
通过分析Makefile和u-boot.lds发现,cpu/arm920t/start.S文件经编译后最先执行。下面来分析一下这个文件。
因为之前写过不少的裸机编程,所以还是比较好理解的,所以硬件操作的部分不会深入再去说明。
#include <common.h> #include <config.h>
包含两个头文件,include/config.h文件是自动生成的
include/config.h:
#include <configs/mini2440.h> #include <asm/config.h>
configs/mini2440.h,这文件是规定了针对mini2440开发板的一些配置信息。
asm/config.h,你可能会觉得奇怪,为什么在/inclued/下找不到asm目录?还记得之前说过的软链接不,这里应该是asm-arm/config.h。它的内容:
#ifndef _ASM_CONFIG_H_ #define _ASM_CONFIG_H_ /* Relocation to SDRAM works on all ARM boards */ #define CONFIG_RELOC_FIXUP_WORKS #endif
接下来进入<span style="font-family: Verdana; font-size: 15.555556297302246px; line-height: 25.98958396911621px;">cpu/arm920t/start.S文件分析代码~~</span> .globl _start _start: b start_code 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
定义异常向量表
_TEXT_BASE: .word TEXT_BASE
指定代码的基地址TEXT_BASE,/board/tekkamanninjia/mini2440/config.mk中:
# # SMDK2410 has 1 bank of 64 MB DRAM # # 3000'0000 to 3400'0000 # # Linux-Kernel is expected to be at 3000'8000, entry 3000'8000 # optionally with a ramdisk at 3080'0000 # # we load ourself to 33F8'0000 # # download area is 3300'0000 TEXT_BASE = 0x33F80000
SMDK2410与mni2440同样是64M的SDRAM,这里应该是直接把SMDK2410的拿来用了。
Linux-Kernel的入口地址在uboot中规定为3000'8000, 如果使用ramdisk则把ramdisk放在3080'0000。
Uboot的入口地址为33F8'0000
.globl _armboot_start _armboot_start: .word _start
_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
__bss_start 在根目录的u-boot.lds文件中定义(按Makefile的意思是”These are defined in the board-specific linker script”.,但是我用的这个版本/board/tekkamanninja/mini2440目录下没有u-boot.lds,tekkamanninja把它放到了根目录下)
__bss_start = .
#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
如果定义了CONFIG_USE_IRQ那么标号IRQ_STACK_START所指向的地址作为IRQ的栈起始地址。起始地址为0x0badc0de你可能会觉得对这个值很奇怪,没关系,在后面会被修改,到时再说,现在先随意设置一个。
CONFIG_USE_IRQ显然是一个宏,在某个.h文件中被定义。前面讲过start.S包含了几个个头文件,在configs/mini2440.h中:
//#undef CONFIG_USE_IRQ /* we don't need IRQ/FIQ stuff */ #define CONFIG_USB_DEVICE 1 #ifdef CONFIG_USB_DEVICE #define CONFIG