專題5-核心初始化
一、異常向量表
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