一、異常向量表
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