ARM裸機開發(fā)bootloader核心初始化
1、異常的定義
本文引用地址:http://cafeforensic.com/article/201611/318209.htm異常:因為內(nèi)部或者外部的一些事件,導(dǎo)致處理器停下正在處理的工作,轉(zhuǎn)而去處理這些發(fā)生的事情。
2、異常的類型
ARM處理器有7種Exception type分別為:Reset、Undefined instructions、Software interrupt、Prefetch Abort、Data Abort、IRQ、FIQ
2、什么是異常向量
當一種異常發(fā)生的時候,ARM處理器會跳轉(zhuǎn)到對應(yīng)該異常的固定地址去執(zhí)行異常處理程序,而這個固定的地址,就稱為異常向量。
3、異常向量表
由七個異常向量及其處理函數(shù)跳轉(zhuǎn)關(guān)系組成的表為異常向量表。
下面是一個例子:
start.S
.text.global _start_start:b resetldr pc, _undefined_instructionldr pc, _software_interruptldr pc, _prefetch_abortldr pc, _data_abortldr pc, _irqldr pc, _fiq_undefined_instruction: .word undefined_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 fiqundefined_instruction:nopsoftware_interrupt:nopprefetch_abort:nopdata_abort:nopnot_used:nopirq:nopfiq:nopreset:nopgboot.lds
OUTPUT_ARCH(arm)ENTRY(_start)SECTIONS{. = 0x50008000;. = ALIGN(4);.text :{start.o(.text)*(.text)}. = ALIGN(4);.data :{*(.data)}. = ALIGN(4);bss_start = .;.bss :{*(.bss)}bss_end = .;}
Makefile
all : start.oarm-linux-ld -Tgboot.lds -o gboot.elf $^arm-linux-objcopy -O binary gboot.elf gboot.bin%.o : %.Sarm-linux-gcc -g -c %.S %.o : %.carm-linux-gcc -g -c %.c .PHONY: cleanclean:rm *.o *.elf *.bin關(guān)于異常向量表,對于2440和6410以上就結(jié)束了,不過對于210還要添加BL1頭
./mkv210_image led.bin 210.bin
/home/dnw 210.bin 0x50008000
如果不加頭的話,就無法正常工作。原因是210在上電后會運行廠家已經(jīng)固化在SRAM中的BL0,這個時候,由BL0來調(diào)用BL1,BL1運行會產(chǎn)生校驗碼(這個校驗碼就在添加的頭里面)并與BL0里的校驗碼進行比對,確認是否為要運行的BL1。成功后就運行BL1.
Header Info (check sum(user writing)、BL1 size(user writing)).
二、設(shè)置SVC模式
此時設(shè)置ARM的工作模式為SVC(supervisor),這樣可以使用更多的寄存器,同時擁有很大的操作權(quán)限。具體可以參考下圖
通過上圖對ARM的狀態(tài)寄存器的解釋,我們可以得知將CPSR的后五位設(shè)置為0b10011就可以使用SVC模式。同時我們還要關(guān)閉irq和fiq。
具體實現(xiàn)代碼:
續(xù)上start.S
reset:bl set_svcset_svc:mrs r0, cpsrbic r0, r0, #ox1forr r0, r0, #oxd3msr cpsr, r0
三、關(guān)閉看門狗
1、什么是看門狗
有些嵌入式設(shè)備要長期工作在無人看管的情況下,這個時候就需要,當發(fā)生死機時,設(shè)備可以實現(xiàn)自啟動。而watchdog就可以完成這樣一種功能。watchdog模塊是一硬件設(shè)備。其作用就是當系統(tǒng)發(fā)生死機時,幫助系統(tǒng)實現(xiàn)自啟動。
2、看門狗如何工作
看門狗模塊有三部分組成,分別為時鐘產(chǎn)生器,計時器,重啟器。當開啟看門狗時,計時器就開始了計時,系統(tǒng)必須在計時結(jié)束前對看門狗重新設(shè)置使其重新計時,簡稱喂狗。否則它會認為系統(tǒng)發(fā)生了死機,就重啟系統(tǒng)。
3、為什么要關(guān)閉看門狗
一般情況下,bootloader的運行過程中不會發(fā)生死機,所以我們就關(guān)閉看門狗。否則我們還要不斷的喂狗,而占用系統(tǒng)時間。
下面是6410中的watchdog的解釋
代碼編寫:
reset:bl set_svcbl disable_watchdogset_svc:mrs r0, cpsrbic r0, r0, #0x1forr r0, r0, #0xd3msr cpsr, r0#define pWTCON 0x7E004000disable_watchdog:ldr r0, =pWTCON /*mov的操作數(shù)最多為8位*/mov r1, #0x0str r1, [r0]注:我們這里把watchdog的控制寄存器直接清零,也可以達到效果。
四、關(guān)閉中斷
關(guān)閉中斷要兩個環(huán)節(jié):1、CPSR中的I F位 置1,在設(shè)置SVC時我們已經(jīng)做過,所以這里就不做了。2、對中斷屏蔽寄存器進行設(shè)置
2440的板子需要設(shè)置INTMSK寄存器
210的板子需要設(shè)置4組寄存器VICINTENCLEAR
6410的板子需要設(shè)置2組寄存器VIC0INTENCLEAR和VIC1INTENCLEAR
下面我們以6410為例子進行介紹:
編碼如下
disable_interrupt:mvn r1, #0x0ldr r0, =0x71200014str r1, [r0]ldr r0, =0x71300014str r1, [r0]
五、關(guān)閉MMU和Cache
1、前言
從ARM的存儲體系,我們可以看到,位于金子塔頂端的是處理器的寄存器,后面依次為TCM和輔助存儲器。顯然從金子塔的底部到頂部存儲器的存取速度愈來愈快,價格也越來越高,而數(shù)量卻越來越少。
2、什么是Cache
我們都知道處理器的訪問速度是非??斓模鴥?nèi)存的速度卻慢的很。這樣當處理器在訪問內(nèi)存時就出現(xiàn)了問題。而Cache恰恰就用來解決這個問題。從物理結(jié)構(gòu)上來講,Cache位于處理器與內(nèi)存之間,cache中存儲了處理器經(jīng)常從內(nèi)存訪問的數(shù)據(jù)與指令,也就是cache是內(nèi)存的部分拷貝。這時處理器往往先訪問cache,如果cache中沒有想要的數(shù)據(jù),才去內(nèi)存查找。而cache的訪問速度要比內(nèi)存大的多,這樣就提高了整個的運行效率。
cache又分為:I-Cache和D-Cache
3、MMU
談到MMU這個時候就要先說一下虛擬地址:作為一個程序員,大家都知道有邏輯地址和物理地址之分,如果我們不直接和硬件打交道,我們根本不用去管物理地址,只要用邏輯地址就可以了。而MMU就是把邏輯地址轉(zhuǎn)換為物理地址的協(xié)議。
假如我們只使用物理地址就會出現(xiàn)兩個問題要解決:1、地址沖突(兩段程序使用同一物理地址)。2、范圍小
我們使用了MMU就可以把邏輯地址映射到物理地址,再具體的說就是兩段程序使用的是同一邏輯地址,而經(jīng)過映射后,它們都被映射到不同的物理地址。還有就是地址空間變大了。具體的物理地址的分配不用程序員來管,都要MMU來分配,這樣就可以更好的利用物理空間。
ARM11之間Cache位于MMU前面靠近處理器,也就是說cache使用的是虛擬地址(邏輯地址),而ARM11之后包括ARM11的MMU靠近內(nèi)存,這個時候使用的是物理地址。
4、為什么要關(guān)閉MMU和Cache
MMU和Cache在使用之前要進行配置,在ARM初始化的時候還沒有進行配置,所以這個時候要關(guān)閉它們。還有就是避免Bootloader將linux內(nèi)核下載到D-cache中,而I-cache這個時候可以不管它。
關(guān)閉MMU和Cache的步驟:
1、使I-cache和D-cache失效
2、關(guān)閉I-Cache和D-Cache,關(guān)閉MMU
下面是cp15的寄存器解釋:
代碼如下:
disable_mmu:
mcr p15, 0, r0, c7, c7, 0
mrc p15, 0, r0, c1, c0, 0
bic r0, r0, #0x00000007
mcr p15, 0, r0, c1, c0, 0
2440、6410和210的cp15是一樣的。所以這里的代碼也是一樣的。
整個核心初始化的代碼為:
.text.global _start_start:b resetldr pc, _undefined_instructionldr pc, _software_interruptldr pc, _prefetch_abortldr pc, _data_abortldr pc, _irqldr pc, _fiq_undefined_instruction: .word undefined_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 fiqundefined_instruction:nopsoftware_interrupt:nopprefetch_abort:nopdata_abort:nopnot_used:nopirq:nopfiq:nopreset:bl set_svcbl disable_watchdogbl disable_interruptbl disable_mmuset_svc:mrs r0, cpsrbic r0, r0, #0x1forr r0, r0, #0xd3msr cpsr, r0mov pc, lr#define pWTCON 0x7E004000disable_watchdog:ldr r0, =pWTCON /*mov的操作數(shù)最多為8位*/mov r1, #0x0str r1, [r0]mov pc, lrdisable_interrupt:mvn r1, #0x0ldr r0, =0x71200014str r1, [r0]ldr r0, =0x71300014str r1, [r0]mov pc, lrdisable_mmu:mcr p15, 0, r0, c7, c7, 0mrc p15, 0, r0, c1, c0, 0bic r0, r0, #0x00000007mcr p15, 0, r0, c1, c0, 0mov pc, lr
評論