一、异常向量表
1.1 异常定义–execption
因为内部或外部的一些事件,导致处理器停下正在处理的工作,转而去处理发生的事件。
1.2 异常类型
7种异常:复位异常、未定义指令异常、软中断异常(SWI)、预取失败异常、数据存储异常、IRQ、FIQ。
1.3 异常向量
当一种异常发生的时候,arm处理器会跳转到对应异常的固定地址去执行异常处理程序,而这个固定的地址,就称之为异常向量。
1.4 异常向量表
2、手把手教你写代码
start.S的代码如下(先写异常向量表)
.text
.global _start
_start:
b reset
ldr pc, _undifined_instruction
ldr pc, _software_interrupt
ldr pc, _prefetch_abort
ldr pc, _data_abort
ldr pc, _not_used
ldr pc, _irq
ldr pc, _fiq
#采用宏的方式,否则上面可以写为 eg:ldr pc, =undifined_instruction,此时ldr是一个伪指令
_undifined_instruction: .word undifined_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
undifined_instruction:
nop
software_interrupt:
nop
prefetch_abort:
nop
data_abort:
nop
not_used:
nop
irq:
nop
fiq:
nop
reset:
nop
链接器脚本gboot.lds如下:
OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS{ #注意这里是{}不是()
. = 0x30008000;#2440
. =ALIGN(4);#4字节对齐,c语言中是用#pragma pack(4)来对齐
.text :
{
start.o(.text)
*(.text)
}
. =ALIGN(4);
.data :
{
*(.data)
}
. =ALIGN(4);
bss_start = .;
.bss :
{
*(.bss)
}
bss_end = .;
}
makefile如下:
all : start.o
arm-linux-ld -Tgboot.lds -o gboot.elf $^ #-o 不要忘记了
arm-linux-objcopy -O binary gboot.elf gboot.bin
%.o : %.S
arm-linux-gcc -g -c $^
%.0 : %.c
arm-linux-gcc -g -c $^
210处理器BL1头信息添加:(2440和6410不用加头)
二、设置svc模式
通过程序状态寄存器来设置:
设置方法:因为状态寄存器是不能直接01操作的,要先将其复制到通用寄存器(指令:mrs),再对通用寄存器进行01操作(清零:bic 置1:orr),再复制到状态寄存器(指令:msr)。
备注:bl是一个分支指令,在分支之前,在寄存器14中装载寄存器15中的内容。即会将链接寄存器lr的值赋给pc指针。
reset:
bl set_svc
set_svc:
mrs r0,cpsr
bic r0,r0,#0x1f
orr r0,r0,#0xd3
msr cpsr,r0
mov pc,lr
上面置1操作时,对最后5位进行操作可以写为:orr r0,r0,#0x13(10011),之所以写为0xd3(11010011),最后5位是一样的,同时对I、F位进行了置1操作(目的:关闭中断)。
三、关闭看门狗
3.1 原理:
3.2 看门狗控制寄存器:
#define pwTCON 0x53000000
disable_watchdog:
ldr r0,=pwTCON
mov r1,#0x0 #干脆全赋值为0
str r1,[r0] #把寄存器的值赋给内存,str为存储器访问指令
mov pc,lr
四、关闭中断
首先:cpsr寄存器的 I 、F为设置为1(在设置处理器的工作模式时已经完成)
其次:设置中断屏蔽寄存器(MASK),设为全1
2440:
reset:
bl disable_interrupt
#define inmask 0x4A000008
disable_interrupt:
mvn r1,#0x0 #先取反再赋值,写入全1
ldr r0,=inmask
str r1,[r0]
mov pc,lr
6410:
reset:
bl disable_interrupt
disable_interrupt:
mvn r1,#0x0
ldr r0,=0x71200014
str r1,[r0]
ldr r0,=0x71300014
str r1,[r0]
mov pc,lr
210:
reset:
bl disable_interrupt
disable_interrupt:
mvn r1,#0x0
ldr r0,=0xf2000014
str r1,[r0]
ldr r0,=0xf2100014
str r1,[r0]
ldr r0,=0xf2200014
str r1,[r0]
ldr r0,=0xf2300014
str r1,[r0]
mov pc,lr
五、关闭mmu和cache
5.1 cache:
5.2 mmu之前,先介绍虚拟地址:
那么谁来帮助系统完成虚拟地址和物理地址之间的转化呢?—-mmu来完成
(在arm11及以后,访问cache要经过mmu)
5.3 为什么要关闭?
在arm初始化的时候并没有正确的去配置mmu,所以在使用之前要关闭它,防止一些意想不到的错误。后面再使用的时候,会配置好再打开。
5.4 怎么关闭?—通过协处理器cp15来关闭
第一步:使Icache和Dcache失效
第二步:关闭IDcache、mmu
先将控制寄存器(control register)读到r0寄存器
reset:
bl disable_mmu
disable_mmu:
mcr p15,0,r0,c7,c7,0 #第一步:使Icache和Dcache失效
#第二步:关闭Dcache、mmu
mrc p15,0,r0,c1,c0,0
bic r0,r0,#0x00000007
mcr p15,0,r0,c1,c0,0
mov pc,lr