国嵌上学期笔记-自己实现bootloader-第一节
一、思路
1、分析异常向量表
arm920T有7个异常。
Reset重启时产生该异常。
Undefined instructions未定义指令异常。
SWI软中断。
Prefetch Aboart预取指令失败产生。
Data Abort预取数据失败。
IRQ中断。
FIQ快速中断。
发生异常的时候,会自动跳转到固定的地址来执行,这个地址叫异常向量。表中每个异常对应两个地址,默认前面的,如果要用后面的,需要配置CP15协处理器。
注意:第5和6之间有个间隔,写代码时要插入一个无关指令占位。
用到的指令:ldr指令把内存单元地址里面的内容装载。
arm-linux-ld -Tgboot.lds -o gboot.elf $^ -T加上链接器脚本的文件名。
arm-linux-objcopy -O binary gboot.elf gboot.bin 转换成二进制
bootloader工作在SVC模式,可以使用更多的指令,有很高的权限。
2、设置为SVC模式
设置为SVC模式:通过程序状态寄存器CPSR(补充:程序状态寄存器有6个CPSR和5个SPSR)。
相关指令:bic清零,orr位或指令置一,msr,mrs指令。程序状态寄存器不能直接修改,放到通用寄存器修改,之后再写回去。
设置0到4可以改变工作模式。后五位和0x13位或。uboot里面是设置0xd3,改变了I和F,屏蔽了中断。
3、关闭看门狗
看门狗作用:例如雪山上的基站,如果死机,自动重启,不需要人去操作。实质是硬件定时器,在计时结束之前,要重新设置定时器(喂狗),到时间还没有喂狗,就重启。
由于bootloader运行的简单程序,不需要看门狗,喂狗太麻烦,所以关闭。
相关指令:mov只能在寄存器之间传递数据,不能操作内存。
STR Rd, [Rbase] 存储 Rd 到 Rbase 所包含的有效地址
4、关闭中断
设置SVC模式的时候已经顺便关闭了I和F的中断。
另外还需要设置中断屏蔽寄存器,屏蔽中断。
MASK屏蔽寄存器。
指令:mvn把操作数取反,在存到某个寄存器
5、关闭MMU和Catch
看芯片手册。
MMU:内存管理单元。
Catch:处理器通过Catch访问数据,主存储器要访问的数据没在Catch中,则内存中的数据会传给处理器,同时copy一份到Catch中。
MMU:如果没有MMU,则程序员必须知道有多少程序运行,占用了哪些地址,哪些地址可以用。如果随意选择,会产生冲突。
如果有64M空间,使用物理地址只能使用64M,使用的地址范围较小。引入虚拟地址,程序员可以随意写地址,经过MMU可以映射到不同的物理地址。解决地址冲突问题。访问地址空间变大,比如可以使用4G空间,MMU会映射到实际的物理地址。
如下图,ARM11之前,可以直接用虚拟地址访问。ARM11开始,虚拟地址要经过MMU映射为物理地址来访问Catch。
看内核ARM920T的手册:
找到CP15,control寄存器,下面是读写该寄存器的方法。第12位控制ICatch,第2位控制DCatch,第0位控制MMU。
还要使ICatch和DCatch的失效,指令如下,Rd代表某个寄存器,写代码的时候可以用R0。
总结为:先使ICatch和DCatch失效,然后关闭ICatch和DCatch,关闭MMU。ICatch关不关无所谓,DCatch必须关闭,因为bootloader要把内核copy到内存,如果使用了DCatch,但是DCatch没配置好,会导致很多数据在DCatch中,影响内核的运行。(本次代码没关闭ICatch)
核心初始化完成,补充:bl跳转指令会将返回地址放到lr寄存器,要记得做完每一步,加上:mov pc,lr。