一、原理
S3C2410 是三星公司基於ARM920T 設計的一款處理器,在開發基於S3C2410 的系統的過程中,如何讓系統快速穩定地啟動是一個重要問題。嵌入式系統的資源有限,程式通常都是固化在ROM 中運行。但在實際應用中,為提高系統的即時性,加快代碼的執行速度,系統啟動後程式往往要被搬移到RAM 中,因為RAM 的存取速度要比ROM 快得多,這樣大大提升系統的效能。啟動程式要完成的任務包括:硬體初始化,系統儲存系統的配置,複製二級中斷向量表。
二、啟動程式過程
● 系統硬體初始化
系統上電或複位後,程式從位於地址0x0 的Reset Exception Vector 處開始執行,因此需要在這裡放置Bootloader 的第一條指令:b ResetHandler,跳轉到標號為ResetHandler 處進行第一階段的硬體初始化,主要內容為:關看門狗定時器,關中斷,初始化PLL 和時鐘,初始化儲存空間系統。執行完以上程式後,系統進行堆棧和儲存空間的初始化。系統堆棧初始化取決於使用者使用了哪些中斷,以及系統需要處理哪些錯誤類型。一般情況下,管理者堆棧必須設定,如果使用了IRQ 中斷,則IRQ 堆棧也必須設定。如果系統使用了外設,則需要設定相關的寄存器,以確定其重新整理頻率、匯流排寬度等資訊。
● 程式碼片段複製到RAM 中運行
因為嵌入式系統的代碼通常都是固化在ROM或者Flash 中,上電後開始運行。由於ROM和Flash 的讀取速度相對較慢,這樣無疑會降低代碼的執行速度和系統的運行效率。為此,需要把系統的代碼複製到RAM 中運行。使用SDT 連結器ARMLink 產生的定位資訊,把RO 的有效代碼和資料區段到RAM 中。ARMLink 將編譯後的程式連結成ELF 檔案。映像檔案內部共有三種輸出段:RO 段、RW 段和ZI 段。這三種輸出段分別包含了唯讀代碼及包含在程式碼片段中的少量資料、可讀寫的資料、初始化為0 的資料,ARMLink 同時還產生了這三種輸出段的起始和終止定位資訊: Image$$RO$$Base 、Image$$RO$$Limit 、image$$RW$$Base、Image$$Limit、Image$$Linit 和Image$$ZI$$Limit。可以在程式中使用這些定位資訊。將ROM 中的代碼和資料搬移到RAM 中。
● 建立二級中斷向量表
在ARM 系統中,中斷向量表位於0x000000000 開始的地址處,意味著無論運行什麼樣的上層軟體,一旦發生中斷,程式就得到Flash 儲存空間中的中斷向量表裡去,降低系統的運行效率。因此在RAM 中建立自己的二級中斷向量表,當中斷髮生後,程式直接從RAM 中取中斷向量進入中斷子程式。尤其是在中斷頻繁發生的系統裡,這種方法可以大大提高系統的運行效率。
● MMU 的應用
MMU 是儲存空間嵌入式管理單元的縮寫,是用來管理虛擬記憶體系統的器件。MMU 通常是CPU的一部分,本身有少量儲存空間存放從虛擬位址到物理地址的匹配表,此表稱作TLB(轉換旁置緩衝區)。所有資料請求都送往MMU,由MMU 決定資料是在RAM 內還是在大容量外部儲存空間裝置內。如果資料不在儲存空間內,MMU 將產生分頁錯誤中斷。MMU 儲存空間系統的結構允許對儲存空間系統的精細控制,大部分的控制細節由存在儲存空間中的轉換表提供。
這些表的入口定義了從1KB~1MB 的各種儲存空間地區的屬性。MMU 完成的兩個主要功能是:將虛地址轉換成物理地址,控制儲存空間存取允許。MMU 關掉時,虛地址直接輸出到物理地址匯流排。
SDRAM 地址分配
三、啟動程式碼完成的主要功能
1) 建立異常中斷的入口向量
2) 建立中斷向量表
3) 為ARM 每種運行模式設定堆棧
4) 初始化ARM 的MPLL 時鐘
5) 初始化MMU(記憶體管理單元)
6) 初始化儲存空間控制器
7) 關閉看門狗、關閉中斷
8) 判斷IRQ 中斷的中斷入口
9) 將RW 段的內容從flash 拷貝到SDRAM,初始化ZI 段為0
10) 跳轉到應用程式(C 代碼)
四、S3C2410 初始化說明
1 建立中斷向量表
中斷向量表建立到SDRAM 高位地址上,主要是因為SDRAM 的地址位置需要放置執行的映象程式,而且在SDRAM 中尋找向量錶速度會快很多。中斷向量表放置時需要字對齊。
ALIGN ;通過添加補丁位元組使當前位置滿足一定的對齊
;可讀寫的資料區段
AREA RamData, DATA, READWRITE
;^=MAP:定義一個結構化的記憶體表(storage map)的首地址,地址為0x33ff8000
^ _ISR_STARTADDRESS ;0x33ff8000
HandleReset # 4 ;#--Field:定義一個結構化記憶體表中的資料域,該域為4 個位元組
HandleUndef # 4
HandleSWI # 4
HandlePabort # 4
HandleDabort # 4
HandleReserved # 4
HandleIRQ # 4
HandleFIQ # 4
;Don't use the label 'IntVectorTable',
;The value of IntVectorTable is different with the address you think it may be.
;IntVectorTable'
HandleEINT0 # 4
HandleEINT1 # 4
HandleEINT2 # 4
HandleEINT3 # 4
HandleEINT4_7 # 4
HandleEINT8_23 # 4
HandleRSV6 # 4
HandleBATFLT # 4
HandleTICK # 4
HandleWDT # 4
HandleTIMER0 # 4
HandleTIMER1 # 4
HandleTIMER2 # 4
HandleTIMER3 # 4
HandleTIMER4 # 4
HandleUART2 # 4
HandleLCD # 4
HandleDMA0 # 4
HandleDMA1 # 4
HandleDMA2 # 4
HandleDMA3 # 4
HandleMMC # 4
HandleSPI0 # 4
HandleUART1 # 4
HandleRSV24 # 4
HandleUSBD # 4
HandleUSBH # 4
HandleIIC # 4
HandleUART0 # 4
HandleSPI1 # 4
HandleRTC # 4
HandleADC # 4
2 建立異常中斷的入口函數
b ResetHandler
b HandlerUndef ;handler for Undefined mode
b HandlerSWI ;handler for SWI interrupt
b HandlerPabort ;handler for PAbort
b HandlerDabort ;handler for DAbort
b . ;reserved
b HandlerIRQ ;handler for IRQ interrupt
b HandlerFIQ ;handler for FIQ interrupt
異常向量的入口函數是由8 個跳轉指令組成的,這8 個跳轉指令需要按照順序放置到固定的地址上,地址是0x00~0x1c,這8 個跳轉指令是ARM 彙編指令,所以條指令佔4 個位元組的位置。
3 關閉看門狗、關閉中斷
ldr r0,=WTCON ;watch dog disable
ldr r1,=0x0
str r1,[r0]
ldr r0,=INTMSK
ldr r1,=0xffffffff ;all interrupt disable
str r1,[r0]
ldr r0,=INTSUBMSK
ldr r1,=0x3ff ;all sub interrupt disable
str r1,[r0]
4 設定ARM 的主始終頻率
;To reduce PLL lock time, adjust the LOCKTIME register.
ldr r0,=LOCKTIME
ldr r1,=0xffffff
str r1,[r0]
;Configure MPLL
ldr r0,=MPLLCON
ldr r1,=((M_MDIV<<12)+(M_PDIV<<4)+M_SDIV) ;Fin=12MHz,Fout=50MHz
str r1,[r0]
5 設定儲存空間控制器
;Set memory control registers
adr r0, SMRDATA
ldr r1,=BWSCON ;BWSCON Address
add r2, r0, #52 ;End address of SMRDATA 一共13 個寄存器
0
ldr r3, [r0], #4
str r3, [r1], #4
cmp r2, r0
bne %B0
LTORG ;聲明一個資料緩衝池的開始
SMRDATA DATA
DCD 0x2211D110 ; BWSCON
DCD 0x0700 ; BANKCON0
DCD 0x7FFC ; BANKCON1
DCD 0x0700 ; BANKCON2
DCD 0x0700 ; BANKCON3
DCD 0x0700 ;BANKCON4
DCD 0x0700 ;BANKCON5
DCD 0x18005 ;BANKCON6
DCD 0x18005 ; BANKCON7
DCD 0x008E0459 ;REFRESH
DCD 0x32 ;BANKSIZE=0x32
DCD 0x30 ;MRSR6 CL=3clk
DCD 0x30 ;MRSR7
以上是對S3C2410A 的儲存空間進行初始化,儲存空間的初始化是和具體的硬體平台相關的,具體的內容見S3C2410A 的使用手冊。
6 堆棧初始化及ARM 工作模式轉換
UserStack EQU (_STACK_BASEADDRESS-0x3800) ;0x33ff4800 ~
SVCStack EQU (_STACK_BASEADDRESS-0x2800) ;0x33ff5800 ~
UndefStack EQU (_STACK_BASEADDRESS-0x2400) ;0x33ff5c00 ~
AbortStack EQU (_STACK_BASEADDRESS-0x2000) ;0x33ff6000 ~
IRQStack EQU (_STACK_BASEADDRESS-0x1000) ;0x33ff7000 ~
FIQStack EQU (_STACK_BASEADDRESS-0x0) ;0x33ff8000 ~ InitStacks
;UndefMode 堆棧
mrs r0,cpsr
bic r0,r0,#MODEMASK
orr r1,r0,#UNDEFMODE|NOINT
msr cpsr_cxsf,r1 ;UndefMode
ldr sp,=UndefStack
;AbortMode 堆棧
orr r1,r0,#ABORTMODE|NOINT
msr cpsr_cxsf,r1 ;AbortMode
ldr sp,=AbortStack
;IRQMode 堆棧
orr r1,r0,#IRQMODE|NOINT
msr cpsr_cxsf,r1 ;IRQMode
ldr sp,=IRQStack
;FIQMode 堆棧
orr r1,r0,#FIQMODE|NOINT
msr cpsr_cxsf,r1 ;FIQMode
ldr sp,=FIQStack
;SVCMode 堆棧
bic r0,r0,#MODEMASK|NOINT
orr r1,r0,#SVCMODE
msr cpsr_cxsf,r1 ;SVCMode
ldr sp,=SVCStack
mov pc,lr
7 將RW 內容從flash 中copy 到SDRAM 中,並將ZI 內容初始化為0
adr r0, ResetEntry
ldr r2, BaseOfROM
cmp r0, r2
ldreq r0, TopOfROM
beq InitRam
ldr r3, TopOfROM
;將RO 地區的代碼copy 到RW 域中並且將ZI 地區初始化為0。
0
ldmia r0!, {r4-r7}
stmia r2!, {r4-r7}
cmp r2, r3
bcc %B0
sub r2, r2, r3
sub r0, r0, r2
InitRam
ldr r2, BaseOfBSS
ldr r3, BaseOfZero
0
cmp r2, r3 ;copy 初始化代碼
ldrcc r1, [r0], #4
strcc r1, [r2], #4
bcc %B0
mov r0, #0 ;初始化ZI 地區為0
ldr r3, EndOfBSS
1
cmp r2, r3
8 建立尋找IRQ 中斷來源程式
ldr r0,=HandleIRQ ;This routine is needed
ldr r1,=IsrIRQ ;if there isn't 'subs pc,lr,#4' at 0x18, 0x1c'
str r1,[r0]
IsrIRQ
sub sp,sp,#4
stmfd sp!,{r8-r9}
ldr r9,=INTOFFSET
ldr r9,[r9]
ldr r8,=HandleEINT0
add r8,r8,r9,lsl #2
ldr r8,[r8]
str r8,[sp,#8]
ldmfd sp!,{r8-r9,pc}