想移植uboot1.4到板子上,搞了半天沒成功,決心弄明白uboot原理,大概流程,所以決定寫個簡單的bootloader來理順一下應該做些什么,怎么做~~~~
首先應該描述一下該bootloader的基本功能:板子上電后能進行LED流水燈(萬能的流水燈啊
)。實現該功能分兩步:第一步,真正的bootloader功能,即實現硬件的初始化以及將內核程序(LED流水燈)從ROM(flash)搬移到RAM(sdram);第二步,內核程序的實現
第一步也可分兩段:1,板子硬件初始化;2,內核程序的搬移。代碼文件:boot.s
板子硬件初始化:1. 異常向量初始化
2. 初始化CPSR,包括關閉中斷及設定svc模式等
3. 關閉看門狗定時器
4. 初始化系統時鐘
5. 初始化CPU Cache(這步可以不做,但是系統效率會明顯下降許多)
內核執行流程:1,內核異常向量初始化
2,初始化堆棧
3,跳轉到C程序中執行萬能的流水燈~~~~
代碼如下:
equ SYSCFG, 0x01c00000
.equ BWSCON, 0x01c80000
.equ WTCON, 0x01d30000
.equ PLLCON, 0x01d80000
.equ CLKCON, 0x01d80004
.equ KERNEL_START, 0x0c000100 @ 內核執行的起始位置(RAM)
.equ KERNEL_VECTOR, 0x0c000000 @ 內核的異常向量入口(RAM)
.equ KERNEL_DATA, 0x00000100 @ 內核數據在ROM中的起始位置
.equ KERNEL_CPLMT, 0x00001000 @ 復制界限(內核數據在ROM中的終止位置,4KB)
.equ REFEN, 0x01
.equ TREFMD, 0x0
.equ Trp, 0x1
.equ Trc, 0x1
.equ Tchr, 0x2
.equ REFCNT, 1550
vectors:
b reset
ldr pc, = KERNEL_VECTOR @ 未定義協處理器指令
ldr pc, = KERNEL_VECTOR + 4 @ SWI(軟中斷)
ldr pc, = KERNEL_VECTOR + 8 @ 預取指令中止
ldr pc, = KERNEL_VECTOR + 12 @ 數據中止
b .
ldr pc, = KERNEL_VECTOR + 16 @ IRQ(普通中斷請求)
ldr pc, = KERNEL_VECTOR + 20 @ FIQ(快速中斷請求)
reset:
mov r0,0xd3 ;禁止IRQ,FIQ,SVC模式
msr cpsr_c,r0
ldr r0,=WTCON ;關看門狗
mov r1,#0
str r1,[r0]
ldr r0,=PLLCON ;初始化PLLCON
mov r1,#0x48032 ;Fin=10M Fpllo=40M Mdiv=0x48 Pdiv=0x3 Sdiv=0x2
str r1,[r0]
ldr r0,=CLKCON
ldr r1,=0x7f88 ;提供給所有外設時鐘
str r1,[r0]
ldr r0,=SYSCFG ;初始化cpu cach
mov r1,#0x0e ;8K cache 寫緩沖使能
str r1,[r0]
ldr r0,=SMRDATA ;初始化存儲器
ldmia r0,{r1-r13}
ldr r0,=BWSCON
stmia r0,{r1-r13}
;將內核程序(LED流水燈)從0x00000100(flash)復制到0x0c000000(sdram)
ldr fp,=KERNEL_DATA
ldr ip,=KERNEL_VECTOR
ldr sp,=KERNEL_CPLMT
1: ldmia fp!,{r0-r7}
stmia ip!,{r0-r7}
cmp fp,ip
bcc 1b
ldr pc,=KERNEL_START
smrdata :
.word 0x11110090
.word 0x00000600
.word 0x00000700 @ BANKCON1: 默認
.word 0x00000700 @ BANKCON2: 默認
.word 0x00000700 @ BANKCON3: 默認
.word 0x00000700 @ BANKCON4: 默認
.word 0x00000700 @ BANKCON5: 默認
.word 0x00018000 @ BANKCON6: SDRAM,SCAN=8位,Trcd=2個時鐘
.word 0x00000700 @ BANKCON7: 默認
.word ((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Trc<<18)+(Tchr<<16)+REFCNT) ;refresh register
.word 0x00000016 @ BANKSIZE: SLCKEN=1, BK76MAP=8M
.word 0x00000020 @ MRSRB6: CL=2個時鐘
.word 0x20 @MRSRB7
第二步:內核程序的實現,代碼文件 head.s
內核程序大致三步:1,內核異常向量初始化;2,內核堆棧初始化;3,執行LED程序;
代碼如下:
.equ KERNEL_STACK, 0x0c002000
.equ KERNEL_LIMIT, 0x0c001000
vectors:
b undef_handler @ 內核異常向量0
b swi_handler @ 內核異常向量1
b pabort_handler @ 內核異常向量2
b dabort_handler @ 內核異常向量3
b irq_handler @ 內核異常向量4
b fiq_handler @ 內核異常向量5
.space 0x100-6*4 @字節填充至地址:0x0c000100
start:
ldr sp,=KERNEL_STACK
ldr sl,=KERNEL_LIMIT
bl entry
undef_handler:
swi_handler:
pabort_handler:
dabort_handler:
irq_handler:
fiq_handler:
b . @ 目前什么都不做
以上兩個文本程序基本實現了一個bootloader的功能,至少符合我的板子,只要再加上上一篇LED篇中的LED程序,就是一個完整的bootloader程序了。當然,還是需要幾番調試的。而大debug之前還是有很多工作要做滴。下一篇再說吧,這里太長了~~~~
