初始化異常向量表:
異常:因爲外部或內部一些事件,導致處理器停下正在處理的工作,轉而處理這些發生的事件。共七種異常:reset,undefined instructions, Software Interruption(SWI),Prefetch Abort,Data Absort,IRQ,FIQ。當一種異常發生,ARM處理器會跳轉到對應該異常的固定地址去執行異常程序,而這個固定地址就是異常向量。
由七個異常向量及其處理函數跳轉關係組成的表即爲異常向量表:
關閉看門狗:
Watchdog:在硬件上實現定時器的功能,當啓動後系統要在計時結束之前重新對計時器計時, 當系統死機時候能感知到事情的發生,然後重啓系統,
左邊PCLK經過分頻操作後輸出的就是定時器的時鐘,中間是計數的邏輯,一旦開始計數之後,每個時鐘WTCNT就會減一,減到0時WTDAT還沒有設置新的值,他就認爲系統死機,後面就會產生重啓信號,讓CPU重啓。
關閉中斷:
中斷處理過程:當中斷產生之後,寄存器SRCPND記錄中斷產生的請求狀態,通過mask屏蔽寄存器設置要屏蔽的中斷請求,下面就通過mask屏蔽中斷請求,最終不會送到處理器。
關閉mmu和cache:
ARM存儲體系,頂端:CPU內部寄存器,訪問速度快,數量太少。中間:緊耦合存儲器(cache,主存儲器)。下層:輔助存儲器(nandflash, SD卡)。
上面爲沒有使用cache的系統,CPU直接訪問主存儲器,由於兩者間速度巨大區別導致CPU訪問低效率,爲了改善這個情況,引入cache相比內存訪問速度更快,cache存放的是主存儲區一些數據的拷貝,當CPU訪問主存找數據時,CPU會根據地址在cache裏找有無這塊數據,如果沒有主存會把數據傳給CPU,還會把數據放入cache,第二次再訪問數據時,cache裏已有數據拷貝,不會在訪問慢的主存,直接從cache取走數據。
cache是容量小但訪問速度快的存儲器,他保存最近用到存儲器數據的拷貝。I-Cache指令cache用於存放指令。D-Cache,數據cache,存放數據。
虛擬地址:1:比如Linux有多個應用程序,都要用到同一個物理地址造成地址衝突。2:僅僅使用物理地址範圍只有64M,使用地址範圍較小。引入虛擬地址後多個應用程序使用同一個地址爲虛擬地址,但是經過硬件的映射能夠把相同的虛擬地址映射到不同地方,有效解決衝突問題。空間變大了,任何應用訪問的虛擬地址空間都是4G,真正使用的時候才映射,使進程使用更大的地址空間。mmu完成虛擬地址到物理地址的映射,要使用mmu需要一個正常的配置,才能正確的使用mmu,但是在進行arm初始化時還沒有配置好mmu,不能使用否則導致錯誤發生,在初始化階段暫時關掉,mmu和cache都通過cp15協處理器控制。
//2440 , 6410版本
_start: b reset
ldr pc, _undefined_instruction
ldr pc, _software_interrupt
ldr pc, _prefetch_abort
ldr pc, _data_abort
ldr pc, _not_used
ldr pc, _irq
ldr pc, _fiq
下面編寫三個部分的代碼:
Start.s uboot.lds makefile
// Start.S
.text ; 指明代碼段
_global _start ;聲明全局
_start: ;程序入口
b reset
ldr pc, _undefined_instruction
ldr pc, _software_interrupt
ldr pc,_prefetch_abort
ldr pc, _data_abort
ldr pc, _not_used
ldr pc, _irq
ldr pc, _fiq
_undefined_instruction: .word undefined_instruction
//在_undefined_instruction處存儲_undefined_instruction大小爲_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 fiq
undefined_instruction:
nop
software_interrupt:
nop
prefetch_abort:
nop
data_abort:
nop
not_used:
nop
irq:
nop
fiq:
nop
reset:
bl set_svc
bl disable_watchdog ;關閉看門狗
bl disable_interrupt ;屏蔽中斷,往INTMSK全部寫入1
bl diable_mmu
mov pc, lr
set_svc: ;設置爲svc工作模式
mrs r0, cpsr
bic r0, r0, #0x1f ;第二操作數哪些位爲1,第一操作數哪些就清除
orr r0, r0, #0x13
msr cpsr , r0
mov pc, lr
#define pwTCON 0x53000000
disable_watchdog: ;通過WTCON控制看門狗
ldr r0, =pwTCON
mov r1, 0x0
str r1, [r0]
mov pc, lr
disable_interrupt:
mov r1, #0x0
ldr r0, =0x40000008
str r1, [r0]
mov pc, lr
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
mov pc, lr
uboot.lds鏈接器腳本,整個程序的構成將根據鏈接器腳本。
//uboot.lds
OUTPUT_ARCH(arm) ;指明輸出格式
ENTRY (_start) ;輸出程序的入口
SECTIONS {
. = 0x30008000 ;整個程序鏈接起始地址
. = ALIGN(4) ;4字節對齊
.text : ;代碼段
{
start.o (.text)
*(.text)
}
. = ALIGN(4); ;4字節對齊
.data :
{
*(.data)
}
. = ALIGN(4); ;4字節對齊
bss_start = .; ;記錄bss開始結束
.bss :
{
*(.bss)
}
bss_end = .;
}
//編寫makefile,makefile由一條條規則構成,首先創建兩條通用規則
all : start.o
arm-linux-ld -Tuboot.lds -o uboot.elf $^
Arm-linux-objcopy -O -bin uboot.elf uboot.bin
%.o = %.s
arm-linux-gcc -o -c $^
%.o = %.s
arm-linux-gcc -g -c $^