硬開機流程
在硬体上的開機流程中,
由上面可以看出有那些東西"電源、時脈、例外及[記憶体模式]"
A.電源
ARM SOC中電源不只一個,且每個功用不同,其可用關閉某一power來省電;並不影響其它但也會使不易檢查錯誤。
B.時脈
這部分可參照各廠商的datasheet,可分為外部的及用振盪器。
而且會用它來設定PLL(提供給SDRAM用)。
C.系統重置
(Reset)主要是通知CPU系統要開始了,需依其datasheet的timing
D:記憶体的匯流排模式
- memory bus width
設定是32bit /16 bit .
- memory type
big endian or little endian
ARM的記憶体界面
對稱式非同步,其有nCE(chip enable)、nOE(read) and nWE(read)
同步非對稱memory(SDRAM),其控制有NSCS,nSRAS,nSCS,nWE,SCKE,SCLK及BA0,BA1
而其需設定記憶体控制器中的特殊暫存器(SPECIAL REGISTER)來初始化,設定參數。
往後只要對相對地址,ARM就會自動執行MEMORY R/W.
其中在memory controller中有對其分類:並且要依規定連接.而未用到的部份則可以用來連接外部device
ARM操作模式及記憶体格式
記憶体格式
ARM 例外處理
例外事件,指的是正常程式因為一些"固定"的理由而被CPU暫停,稱為例外事年(Exception),例外是由CPU所產生,不同的理由會產生不同的例外事件,而CPU也借由exception改變操作模式,而在發生例外事件後會改計數暫存器,其計數暫存器以不同的例外事件去exception vector查詢其中斷address。而當例外事件結束後,是必須要回到程式的主要流程中,所以在發生exception時要存某些register來返回,而在多個exception中,也必須有一定的順序。
(exception 種類,產生理由、進入動作、離開動作及重要性)
exception 種類
- system exception:
- 指使用者無法自行去enable/disable exception。
- abort exception:發生prefetch abort/data abort,無法存取
- undefined exception:執行無定義的code
- interrupt exception:
- IRQ/FIQ ,使用者可在cpsr中f-bit/I-bit中去enable/disable.
- SWI(software interrupt exception,SWI)
中斷向量表(exception vector)
進入動作(*指有些是CPU自行完成)
1*.將下一指令位址放在link register中(LR=PC+4,other/PC+8,data abort)
2*.將目前程式的CPSR放入SPSR(SPSR=CPSR),並停止中斷(改I/F BIT)
3*.改改目前CPSR的BIT 4:0(MODE)
4*.改變PC至相對的中斷向量表
(
LR=PC+4/PC+8;
SPSR=CPSR;
CPSR=(CPSR&0XFFFF40)|0X13|0XC0;operator mode,fiq/irq
PC=0X00;
)
離開動作(使用者自行)
1.CPSR=SPSR
2.CPSR|=0X80,CPSR!=0X40,enable irq/fiq
3.PC=LR-4/LR-8
ARM的軟体開機程序
在上圖中的重置condiction,是在電源後發生 (system reset)。
在Reset腳位low後,再high時,CPU會執行下列動作,而其0的指令為RESET EXCEPTION VECTOR,共使ARM進入 SUPERVISOR MODE.
在發生system reset exception到進入韌体中,(bootloader)
Setup1 .設定各operator mode stack
AREA RamData, DATA, READWRITE
^ (_ISR_STARTADDRESS-10240)
UserStack # 2048 ;(c7)ffa00
SVCStack # 2048 ;(c7)ffb00
UndefStack # 2048 ;(c7)ffc00
AbortStack # 2048 ;(c7)ffd00
IRQStack # 2048 ;(c7)ffe00
FIQStack # 0 ;(c7)fff00
Setup 2.分別定義Undefined mode,abort mode,IRQ mode,FIQ mode及supervisor mode的堆疊,並各別指向UndefStack,AbortStack...
;****************************************************
;* The function for initializing stack *
;****************************************************
InitStacks
;Don't use DRAM,such as stmfd,ldmfd......
;SVCstack is initialized before
;Under toolkit ver 2.50, 'msr cpsr,r1' can be used instead of 'msr cpsr_cxsf,r1'
mrs r0,cpsr
bic r0,r0,#MODEMASK
orr r1,r0,#UNDEFMODE|NOINT
msr cpsr_cxsf,r1 ;UndefMode
ldr sp,=UndefStack
orr r1,r0,#ABORTMODE|NOINT
msr cpsr_cxsf,r1 ;AbortMode
ldr sp,=AbortStack
orr r1,r0,#IRQMODE|NOINT
msr cpsr_cxsf,r1 ;IRQMode
ldr sp,=IRQStack
orr r1,r0,#FIQMODE|NOINT
msr cpsr_cxsf,r1 ;FIQMode
ldr sp,=FIQStack
bic r0,r0,#MODEMASK|NOINT
orr r1,r0,#SVCMODE
msr cpsr_cxsf,r1 ;SVCMode
ldr sp,=SVCStack
Setup 3.改變cpu operator mode==>user mode
mrs r0,cpsr
bic r0,r0,#0x1f
orr r1,r0,#10|0xc0
msr cpsr_cxsf,r1 ;UserfMode
ldr sp,=UserStack
ARM的例外事件
; IMPORT Main ; The main entry of mon program
AREA Init,CODE,READONLY
ENTRY
b ResetHandler ;for debug
b HandlerUndef ;for handlerUndef
b SWI_Handler ;SWI interrupt handler
b HandlerAbort ;abort data
b .
b .
b .
b .
一個例外處理程序到底要處理那些事情?
1.如何將例外跳至應用程式所指定的位置執行:上述所寫的程式是燒在ROM/Flash記憶体上,但系統執行時,如何可以讓程式設計者的程式動態被例外程序所呼叫。
2.例外返回時如何回到例外發生前的將態:
(cpsr=spsr;cpsr=(cpsr&0xx)|0xx|0xx;pc=lr)
3.快速中斷要求及中斷要求例外如何正確地跳至中斷服務程式(interrupt service routine):因為快速中斷要求(FIQ)及中斷要求(IRQ),是ARM給SoC系統業者設計中斷控制器的唯一窗口,換句話說,中斷控制器可提供50組的中斷源(interrupt source),但是無論那一組中斷源所產中斷,起黠都是FIQ/IRQ,也就A程式可定義中斷服務程式至A_Srv(),當A程式執行結束後B程式可重新定義,使之中斷跳到B_srv()中。
ROM/FLASH中的位置0
稱為例外管理(exception Handler),因為是靜態故無法改變,所以為了可在程式中依設計者,自行創造一組位於SDRAM的例外向量表,
在SDRAM中的另一組
(由中斷發生後,到ROM/Flash中,找中斷vector後-->SDRAM中的Handlerxxx)
稱為第二次映射(remapping),即在接受例外(enable exception)前,需將程式管理例外管理程序(exception handle routing)放在SDRAM所對應的位址上。如IsrIRQ中,
整体流程如下:
上面的Handler XX中程序目的:是為了相對應例外管理程序的位址取得例外管程序的進入點(IsrXXX),再跳至例外管理程序執行,而R0有用到所以把它原始推入stack再回複.
例外管理程序(IsrXXX)中,其中其進入例外前需把register push stack中。返回時,則需把stack 中pop 出來及設定pc=ld。
其IsrXXX assemble
STMFD sp!,{r0-r12}
..
..
LDMFD sp!,{r0-r12,pc}^
SUBS pc,ld,#4
IsrXXX for C(只有r0-r4 and r12,lr
irq void IsrIRQ(void)
{..
}
IsrIRQ
STMFD sp!,{r0-r4,r12,lr}
.
.
LDMFD sp!,{r0-r4,r12,lr}
SUB pc,ld,#4
軟体中斷例外
用途: 提供使用者系統建構函式庫(ROM),而不需自行開發程式佔用主記憶体(RAM).
ARM的硬体提供了軟体中斷例外的機制,系統建置者可基本函式或公用函式加以編號。ARM的硬体機制就會用特定的軟体中斷例外方法,呼叫到系統基本函式及系統函式。
SWI指今分析
bit 23-0為其編號。
軟体中斷的動作
除了標準的例外動作外(*1),ARM CPU會將軟体中斷指令存入連結暫存器(link register,LR) –4的記憶体中所要籫寫軟体中斷控制程序的第一步,就是要將連結暫存器(lr)-4 的內容讀出,第二步就是要計算軟体中斷的號碼,均為組語。
------------*1---------------
lr=pc+4/8; dabort
spsr=cpsr;
cpsr=(cpsr | 0xx)| 0xxI | 0xxF ;
-------------------------------
LDR r0,[lr ,#-4]; ro=lr-4=pc+4-4
BIC r0,r0,#ff000_000; get the soft interrupt number
SWI_Handler
STMFD sp!,{r0-r12,lr}
LDR r0,[lr,#-4]
BIC r0,#ff000_000;
;由r0決定編號來執行所表代的程式
;
;
LDMFD sp!,{r0-r12,pc}; 將在堆的暫存器存回在對應的暫存器中,並將pc=lr-4結束SWI
ARM assemble
ADR r2,SWI_JumpTable
ldr pc,{r2,r0,lsl #1] ;pc=r2+r0<<2
SWI_JumpTable
dcd swi_num0 ; use dcd define swi number
dcd swi_num1
dcd swi_num2
swi_num0
;swi num process
b endofswi
swi_num1
;swi num process
b endofswi
swi_num2
;swi num process
b endofswi
endofswi
LDMFD sp!,{r0-r12,pc}
C program,來寫軟体中斷
當assembler caller C program how to 傳遞,當C和assembler的連接都是用r0或stack指標連接。
- 當assembler caller C program,如果只有一個參數傳遞,則r0會當成C的參數傳入C function,而其傳回傳也是由r0傳回。c_swi_entry(unsigned unm){ switch(num) {case 0:..break; case 1:..break; default:.. break;}
- 如果assembler 中有超過一個以上參數要傳入,會利用r1,r2,r3傳入C funcion 參數,而C的宣告會變成: c_swi_entry(unsigned num,unsigned reg1,unsigned reg2,unsigned reg3);
- 超過四個時,就會用stack,而其stack point是放在r1,再用第2個(上一個)處理。但其C的宣告為。void c_swi_entry(unsigned num,unsigned *reg);
- mov r1,sp; bl c_swi_entry;
在監督模式下使用軟体中斷
當軟中斷指行時,會進入supervisor mode,CPU會:
- spsr_svc=cpsr
- lr_svc= return address(pc+4)
但若在soft interrupt 中又有 soft interrupt 則會使spsr_svc及lr_svc改變。即有巢回中斷
因此:(要去推入stack中)
stmfd sp!,{r0-r3,r12,lr} ; register store into stack
mov r1,sp ;start of sp –>r1
mrs r0,spsr ;spsr –>r0
stmfd sp!,{r0} ;spsr push stack
ldreq r0,[lr,#-4] ;取出中斷num
biceq r0,r0,#ff000_000 ; cal the soft interrupt
;r0 contain swi number
;r1 contain pointer to stack register
bl C_SWI_Handler ;caller the function
ldmfd sp!,{r0} ;pop to spsr
msr spsr_cf,r0 ;store the spsr
ldmfd sp!,{r0-r3,r12,pc}^ ;store the reg
從應用程式caller soft interrupt
ARM assembler
mov r0,#65 ;r0=0x65
swi 0x0 ;caller swi 0 參數為0x65
ARM C program
Q1.
_swi(0) my_swi(int argu1)
當如此宣告後,compiler會將所有my_swi()的函式變成inline _swi(0),而r0=argu1
Q2.
多參,用r0,r1,r2,r3
///swi.h
__swi(0) int multiply_two(int,int);
__swi(1) int add_two(int,int);
__swi(2) int add_multiply_two(int,int,int,int);
struct four
{
int a;
int b;
int c;
int d;
};
__swi(3) __value_int_regs struct four many_operations(int,int,int,int);
//若回傳是傳回多值時,需用__value_int_regs
/*
* Copyright (C) ARM Limited, 1998. All rights reserved.
*/
void C_SWI_Handler( int swi_num, int *regs )
{
switch( swi_num )
{
case 0:
regs[0] = regs[0] * regs[1];
break;
case 1:
regs[0] = regs[0] + regs[1];
break;
case 2:
regs[0] = (regs[0] * regs[1]) + (regs[2] * regs[3]);
break;
/*
Re-entrant SWI:
case 2:
regs[0] = add_two(multiply_two(regs[0], regs[1]), multiply_two(regs[2], regs[3]));
break;
*/
case 3:
{
int w, x, y, z;
w = regs[0];
x = regs[1];
y = regs[2];
z = regs[3];
regs[0] = w + x + y + z;
regs[1] = w - x - y - z;
regs[2] = w * x * y * z;
regs[3] =(w + x) * (y - z);
}
break;
}
}
//**regs[0]=xxxxxxxx, 由C傳回組言,
//value_in_argu0=reg[0];組語傳回C
ADS(arm develop suit)
首先我們知道一般的program的流程是如何? preprocess -> assembler—>compiler –> linker –>loader
而在我們的ADS中,也大約是如此。但它沒有compiler,而是直接assembler(還有一個preassembler)輸出object,並跳過compiler到linker(將多object,並分配位置)會成一個*.bin(可執行檔)。
其中pre-assembler中,為增加可讀性(以常數定義)
CLKCON EQU 0x01d800004
…
…
ldr r0,=CLKCON
以及去定位位置(0),也增加假指令(pseudo instruction)
- Area directive
Area name,{attr},{attr}...
name為Section name,Att等
Area Init,CODE,READONLY
b ResetHandler
b HandlerUndef
.. - if condiction
[ if
| else
]endif
這個用於就是告訴編譯器那些要compiler不要compiler
[ Version="1.0"
Code of Version=1.0
|
Code of Version <> 1.0
]
而linker則是:
- 將不同檔案的object,linker to one binary file
- calcute and 分配於不同程式節區(Read only,RO)、資料節區(read-write,RW)及零節區(zero-initialized,ZI),這些節區結合成一個
- 將程式和記憶体位址相關,結合。
- 可產生除了二進制碼以外的其它檔案的格式
file1.s
AREA RamData, DATA, READWRITE
UserStack # 2048 ;
SVCStack # 2048 ;
…
…
FIQStack #0
file2.s
AREA RamData, DATA, READWRITE
HandleReset #4
HandleUndef #4
…
…
HandleFIQ #4
EX:
[ BUSWIDTH=16
DCD 0x11111190 ;Bank0=OM[1:0], Bank1~Bank7=16bit
| ;BUSWIDTH=32
DCD 0x222222a0 ;Bank0=OM[1:0], Bank1~Bank7=32bit
]
未定義时:
檔案架構
first.mcp 專案
cwsettingswindows.stg: 環境設定
sysinit.obj : object file
targetdatawindows.tdt : debugrel之參數設定
ps.可用 ctrl + - 清除obj file
產生binary file
關於linker:
- first.bin是要從真實的記憶体的那裡開始執行?
- *.bin要用的記憶体從那裡開始?
- *.bin的進入點?
- 進入section?
ARM軟体開機流程
ADS中有
- 程式碼:Image$$RO$$Base, 程式起始位置(ROBase);Image$$RO$$Limit,程式結束位置
- 有初始值變數:Image$$RW$Base, 有初始值變數起始位置(RWBase); Image$$RW$Limit
- 沒有初始值的變數:Image$$ZI$Base ;Image$$ZI$Limit
而因為在CH10中只有Init.s,且其中沒有變數存在。故只有code 存在,而在CH10.bin檔案中應為
無初始變數 Image$$ZI$$Limit---Image$$ZI$$Base
初始變數 Image$$RW$$Limit---Image$$RW$$Base
code :無初始變數 Image$$RO$$Limit---Image$$RO$$Base
ARM的開機軟体初始化
硬体
- PLL及其它硬体
- 初始化SoC的記憶体控制器
軟体
- SoC不同模式所需堆疊
- 中斷服務
- 初始化變數
上圖為所產生的&.bin 內容,可以看出只有RO及RW。而這個寫入到flash後,因為我們需要把RW(初始化變數) copy 到SDRAM上.
即將flash上 Image$$RO$$Limit到Image$$ZI$$Base間, copy 到SDRAM中>
;********************************************************
;* Copy and paste RW data/zero initialized data *
;********************************************************
LDR r0, =|Image$$RO$$Limit| ; Get pointer to ROM data
LDR r1, =|Image$$RW$$Base| ; and RAM copy
LDR r3, =|Image$$ZI$$Base|
;Zero init base => top of initialised data
CMP r0, r1 ; Check that they are different
BEQ %F1
0
CMP r1, r3 ; Copy init data
LDRCC r2, [r0], #4 ;--> LDRCC r2, [r0] + ADD r0, r0, #4
STRCC r2, [r1], #4 ;--> STRCC r2, [r1] + ADD r1, r1, #4
BCC %B0
1
LDR r1, =|Image$$ZI$$Limit| ; Top of zero init segment
MOV r2, #0
2
CMP r3, r1 ; Zero init
STRCC r2, [r3], #4
BCC %B2
; BL Main ;Don't use main() because ......
ARM的系統規劃
ARM的系統規劃其實就是記憶体規劃。以下都有用到SDRAM的記憶体:
- ISR
- stack point
- Ap varible
故首先是決定其SDRAM大小,若其SDRAM大小為8M(0x80000)+起始位置(0xc00000)
_ISR_STARTADDRESS EQU 0xc7fff00
;Pre-defined constants
USERMODE EQU 0x10
FIQMODE EQU 0x11
IRQMODE EQU 0x12
SVCMODE EQU 0x13
ABORTMODE EQU 0x17
UNDEFMODE EQU 0x1b
MODEMASK EQU 0x1f
NOINT EQU 0xc0
T_bit EQU 0x20
AREA RamData, DATA, READWRITE
^ (_ISR_STARTADDRESS-10240)
UserStack # 2048 ;(c7)ffa00
SVCStack # 2048 ;(c7)ffb00
UndefStack # 2048 ;(c7)ffc00
AbortStack # 2048 ;(c7)ffd00
IRQStack # 2048 ;(c7)ffe00
FIQStack # 0 ;(c7)fff00
^ _ISR_STARTADDRESS
HandleReset # 4
HandleUndef # 4
HandleSWI # 4
HandlePabort # 4
HandleDabort # 4
HandleReserved # 4
HandleIRQ # 4
HandleFIQ # 4
沒有留言:
張貼留言