BootLoader指系统启动后,在操作系统内核运行之前运行的一段小程序。通过BootLoader,我们可以初始化硬件设备、建立内存空间的映射图,从而将系统的软硬件环境带到一个合适的状态,以便为最终调用操作系统内核准备好正确的环境。通常,BootLoader是严重地依赖于硬件而实现的,特别是在嵌入式世界。因此,在嵌入式世界里建立一个通用的 BootLoader 几乎是不可能的。尽管如此,我们仍然可以对BootLoader归纳出一些通用的概念来,以指导用户特定的BootLoader设计与实现。
BootLoader 的实现依赖于CPU的体系结构,因此大多数 BootLoader 都分为stage1 和stage2 两大部分。依赖于CPU体系结构的代码,比如设备初始化代码等,通常都放在 stage1中,而且通常都用汇编语言来实现,以达到短小精悍的目的。而stage2 则通常用C 语言来实现,这样可以实现更复杂的功能,而且代码会具有更好的可读性和可移植性。
BootLoader 的 stage1 通常包括以下步骤:
·硬件设备初始化;
·为加载Boot Loader的stage2准备 RAM 空间;
·拷贝Boot Loader的stage2 到RAM空间中;
·设置好堆栈;
·跳转到 stage2 的 C 入口点。
Boot Loader的stage2通常包括以下步骤:
·初始化本阶段要使用到的硬件设备;
·检测系统内存映射(memory map);
·将kernel 映像和根文件系统映像从flash上读到 RAM 空间中;
·为内核设置启动参数;
·调用内核。
本系统中的BootLoader参照韩国mizi公司的vivi进行修改。
我们购买了武汉创维特信息技术有限公司开发的具有自主知识产权的应用于嵌入式软件开发的集成软、硬件开发平台ADT(ARM Development Tools)它为基于ARM 核的嵌入式应用提供了一整套完备的开发方案,包括程序编辑、工程管理和设置、程序编译、程序调试等。
ADT嵌入式开发环境由ADT Emulator for ARM 和ADT IDE for ARM组成。ADT Emulator for ARM 通过JTAG 实现主机和目标机之间的调试支持功能。它无需目标存储器,不占用目标系统的任何端口资源。目标程序直接在目标板上运行,通过ARM 芯片的JTAG 边界扫描口进行调试,属于完全非插入式调试,其仿真效果接近真实系统。
ADT IDE for ARM 为用户提供高效明晰的图形化嵌入式应用软件开发环境,包括一整套完备的面向嵌入式系统的开发和调试工具:源码编辑器、工程管理器、工程编译器(编译器、汇编器和连接器)、集成调试环境、ADT Emulator for ARM 调试接口等。其界面同Microsoft Visual Studio 环境相似,用户可以在ADT IDE for ARM 集成开发环境中创建工程、打开工程,建立、打开和编辑文件,编译、连接、设置、运行、调试嵌入式应用程序。
ADT嵌入式软件开发环境采用主机-目标机交叉开发模型。ADT IDE for ARM 运行于主机端,而ADT Emulator for ARM 实现ADT IDE for ARM 与目标机之间的连接。开发时,首先由ADT IDE for ARM 编译连接生成目标代码,然后建立与ADT Emulator for ARM 之间的调试通道,调试通道建立成功后,就可以在ADT IDE for ARM 中通过ADT Emulator for ARM 控制目标板实现目标程序的调试,包括将目标代码下载到目标机中,控制程序运行,调试信息观察等等。
ARM本身属于RISC指令系统,指令条数就很少,而其编程又以C等高级语言为主,我们仅需要在Bootloader的第一阶段用到少量汇编指令:
(1)+-运算
ADD r0, r1, r2
―― r0 := r1 + r2
SUB r0, r1, r2
―― r0 := r1 - r2
其中的第二个操作数可以是一个立即数:
ADD r3, r3, #1
―― r3 := r3 + 1
第二个操作数还可以是位移操作后的结果:
ADD r3, r2, r1, LSL #3
―― r3 := r2 + 8.r1
(2)位运算
AND r0, r1, r2
―― r0 := r1 and r2
ORR r0, r1, r2
―― r0 := r1 or r2
EOR r0, r1, r2
―― r0 := r1 xor r2
BIC r0, r1, r2
―― r0 := r1 and not r2
(3)寄存器搬移
MOV r0, r2
―― r0 := r2
MVN r0, r2
―― r0 := not r2
(4)比较
CMP r1, r2
―― set cc on r1 - r2
CMN r1, r2
―― set cc on r1 + r2
TST r1, r2
―― set cc on r1 and r2
TEQ r1, r2
―― set cc on r1 or r2
这些指令影响CPSR寄存器中的 (N, Z, C, V) 位
(5)内存操作
LDR r0, [r1]
―― r0 := mem [r1]
STR r0, [r1]
―― mem [r1] := r0
LDR r0, [r1, #4]
―― r0 := mem [r1+4]
LDR r0, [r1, #4] !
―― r0 := mem [r1+4] r1 := r1 + 4
LDR r0, [r1], #4
―― r0 := mem [r1] r1 := r1 +4
LDRB r0 , [r1]
―― r0 := mem8 [r1]
LDMIA r1, {r0, r2, r5}
―― r0 := mem [r1] r2 := mem [r1+4] r5 := mem [r1+8]
{..} 可以包括r0~r15中的所有寄存器,若包括r15 (PC)将导致程序的跳转。
(6)控制流
例1:
MOV r0, #0 ; initialize counter
LOOP:
ADD r0, r0, #1 ; increment counter
CMP r0, #10 ; compare with limit
BNE LOOP ; repeat if not equal
例2:
CMP r0, #5
ADDNE r1, r1, r0
SUBNE r1, r1, r2
――
if (r0 != 5) {
r1 := r1 + r0 - r2
}