2013年8月30日 星期五

原理篇(硬/軟開機流程、ARM操作模式及暫存器、ARM assemble及ARM 例外處理)

 

 

硬開機流程

image

在硬体上的開機流程中,

由上面可以看出有那些東西"電源、時脈、例外及[記憶体模式]"

 

A.電源

image

ARM SOC中電源不只一個,且每個功用不同,其可用關閉某一power來省電;並不影響其它但也會使不易檢查錯誤。

B.時脈

image

這部分可參照各廠商的datasheet,可分為外部的及用振盪器。

而且會用它來設定PLL(提供給SDRAM用)。

image

 

C.系統重置

(Reset)主要是通知CPU系統要開始了,需依其datasheet的timing

 

D:記憶体的匯流排模式

  • memory bus width

設定是32bit /16 bit .

  • memory type

big endian or little endian

image

 

ARM的記憶体界面

image

對稱式非同步,其有nCE(chip enable)、nOE(read) and nWE(read)

image

同步非對稱memory(SDRAM),其控制有NSCS,nSRAS,nSCS,nWE,SCKE,SCLK及BA0,BA1

而其需設定記憶体控制器中的特殊暫存器(SPECIAL REGISTER)來初始化,設定參數。

往後只要對相對地址,ARM就會自動執行MEMORY R/W.

其中在memory controller中有對其分類:並且要依規定連接.而未用到的部份則可以用來連接外部device

image

image

image

ARM操作模式及記憶体格式

記憶体格式

image

image

image

image

image

image

 

 

image

image

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)
  • image 

中斷向量表(exception vector)

 

image

進入動作(*指有些是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的軟体開機程序

image

在上圖中的重置condiction,是在電源後發生 (system reset)。

在Reset腳位low後,再high時,CPU會執行下列動作,而其0的指令為RESET EXCEPTION VECTOR,共使ARM進入 SUPERVISOR MODE.

image

在發生system reset exception到進入韌体中,(bootloader)

image

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

image

稱為例外管理(exception Handler),因為是靜態故無法改變,所以為了可在程式中依設計者,自行創造一組位於SDRAM的例外向量表,

在SDRAM中的另一組

image

(由中斷發生後,到ROM/Flash中,找中斷vector後-->SDRAM中的Handlerxxx)

稱為第二次映射(remapping),即在接受例外(enable exception)前,需將程式管理例外管理程序(exception handle routing)放在SDRAM所對應的位址上。如IsrIRQ中,

整体流程如下:

image

上面的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指今分析

image

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

image

 

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指標連接。

  1. 當assembler caller C program,如果只有一個參數傳遞,則r0會當成C的參數傳入C function,而其傳回傳也是由r0傳回。c_swi_entry(unsigned unm){ switch(num) {case 0:..break; case 1:..break; default:.. break;}
  2. 如果assembler 中有超過一個以上參數要傳入,會利用r1,r2,r3傳入C funcion 參數,而C的宣告會變成: c_swi_entry(unsigned num,unsigned reg1,unsigned reg2,unsigned reg3);
  3. 超過四個時,就會用stack,而其stack point是放在r1,再用第2個(上一個)處理。但其C的宣告為。void c_swi_entry(unsigned num,unsigned *reg);
  4. mov r1,sp; bl c_swi_entry;

 

在監督模式下使用軟体中斷

當軟中斷指行時,會進入supervisor mode,CPU會:

  1. spsr_svc=cpsr
  2. 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)

  1. Area directive

    Area name,{attr},{attr}...
    name為Section name,Att等
    Area Init,CODE,READONLY
    b ResetHandler
    b HandlerUndef
    ..

  2. 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
    ]

 

未定義时:

image

image

檔案架構

image

first.mcp 專案

cwsettingswindows.stg: 環境設定

sysinit.obj : object file

targetdatawindows.tdt : debugrel之參數設定

image

image

image

ps.可用 ctrl + - 清除obj file

 

產生binary file

image

image

關於linker:

image

  1. first.bin是要從真實的記憶体的那裡開始執行?
  2. *.bin要用的記憶体從那裡開始?
  3. *.bin的進入點?
  4. 進入section?

image

image

image

image

image

image

 

ARM軟体開機流程

ADS中有

  1. 程式碼:Image$$RO$$Base, 程式起始位置(ROBase);Image$$RO$$Limit,程式結束位置
  2. 有初始值變數:Image$$RW$Base, 有初始值變數起始位置(RWBase); Image$$RW$Limit
  3. 沒有初始值的變數:Image$$ZI$Base ;Image$$ZI$Limit

image

image

image

image

而因為在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

 

image

image

 

image

image 

image

image

image

ARM的開機軟体初始化

硬体

  1. PLL及其它硬体
  2. 初始化SoC的記憶体控制器

軟体

  1. SoC不同模式所需堆疊
  2. 中斷服務
  3. 初始化變數

image

image

上圖為所產生的&.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的記憶体:

  1. ISR
  2. stack point
  3. Ap varible

故首先是決定其SDRAM大小,若其SDRAM大小為8M(0x80000)+起始位置(0xc00000)

image

_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

沒有留言:

張貼留言