彙編碼 bootloader分析 44b0

; *******************************************************
; * NAME    : 44BINIT.S         *
; * Version : 10.April.2000        *
; * Description:          *
; * C start up codes         *
; * Configure memory, Initialize ISR ,stacks   *
; * Initialize C-variables        *
; * Fill zeros into zero-initialized C-variables  *
; *******************************************************
 
    ;GET option.a
    ;GET memcfg.a
    GET memcfg.s
;Memory Area
;GCS6 64M 16bit(8MB) DRAM/SDRAM(0xc000000-0xc7fffff)
;APP    RAM=0xc000000~0xc7effff
;44BMON RAM=0xc7f0000-0xc7fffff
;STACK    =0xc7ffa00    
;Interrupt Control
INTPND     EQU 0x01e00004  ;指示中斷請求狀態寄存器,每一位代變一種中斷請求
INTMOD     EQU 0x01e00008  ;中斷模式寄存器,有兩種中斷模式對應位爲:1代表fip mode ,0代表riq mode
INTMSK     EQU 0x01e0000c  ;確定哪個中斷源被屏蔽 屏蔽的中斷源將不被服務
I_ISPR     EQU 0x01e00020  ;中斷服務掛起寄存器
I_CMST     EQU 0x01e0001c  ;當前主寄存器irq優先級
;Watchdog timer
WTCON     EQU 0x01d30000  ;看門狗定時器控制寄存器
;Clock Controller
PLLCON     EQU 0x01d80000  ;pll控制寄存器
CLKCON     EQU 0x01d80004  ;時鐘控制寄存器
LOCKTIME    EQU 0x01d8000c  ;鎖定時間計數值寄存器
 
;Memory Controller
REFRESH     EQU 0x01c80024  ;Dram/sdram刷新控制寄存器
;BDMA destination register
BDIDES0     EQU 0x1f80008  ;???DMA???
BDIDES1     EQU 0x1f80028  ;???DMA???
;Pre-defined constants
USERMODE    EQU 0x10   ;0b10000 用戶模式
FIQMODE     EQU 0x11   ;0b10001 FIQ模式
IRQMODE     EQU 0x12   ;0b10010 IRQ模式
SVCMODE     EQU 0x13   ;0b10011 管理模式
ABORTMODE   EQU 0x17   ;0b10111 中止模式
UNDEFMODE   EQU 0x1b   ;0b11011 未定義
MODEMASK    EQU 0x1f   ;0b11111 mode mask
NOINT     EQU 0xc0   ;0b1100 0000 ???關中斷???
;=========================================================================================================================
;check if tasm.exe is used.
;arm處理器有兩種工作狀態 1.arm:32位 這種工作狀態下執行字對準的arm指令 2.Thumb:16位 這種工作狀態執行半字對準的Thumb指令
;因爲處理器分爲16位 32位兩種工作狀態 程序的編譯器也是分16位和32兩種編譯方式 所以下面的程序用於根據處理器工作狀態確定編譯器編譯方式
;code16僞指令指示彙編編譯器後面的指令爲16位的thumb指令
;code32僞指令指示彙編編譯器後面的指令爲32位的arm指令
;這段是爲了統一目前的處理器工作狀態和軟件編譯方式(16位編譯環境使用tasm.exe編譯)
    GBLL    THUMBCODE    ;global logical variable, init. to {false}
    [ {CONFIG} = 16      ;[=if,{CONFIG}:build-in variable defined by ARM assembler,16=assembing Thumbcode.
THUMBCODE SETL {TRUE}   ;SETL:set the logic variable
    CODE32               ;changing from Thumb state to Arm state
    |                    ;|=else
THUMBCODE SETL {FALSE}
    ]                    ;]=endif
    [ THUMBCODE
    CODE32               ;for start-up code for Thumb mode???
    ]
;=========================================================================================================================
;注意下面這段程序是個宏定義,下面包含的HandlerXXX HANDLER HandleXXX將都被下面這段程序展開
;這段程序用於把中斷服務程序的首地址裝載到pc中
;本初始化程序定義了一個數據區(在文件最後),34個字空間,存放相應中斷服務程序的首地址。
;每個字空間都有一個標號,以Handle***命名。

    MACRO
$HandlerLabel HANDLER $HandleLabel
$HandlerLabel
    sub     sp,sp,#4     ;decrement sp(to store jump address)
    stmfd   sp!,{r0}     ;PUSH the work register to stack(lr does't push because it return to original address)
    ldr     r0,=$HandleLabel;load the address of HandleXXX to r0
    ldr     r0,[r0]         ;load the contents(service routine start address) of HandleXXX
    str     r0,[sp,#4]     ;store the contents(ISR) of HandleXXX to stack
    ldmfd   sp!,{r0,pc}     ;POP the work register and pc(jump to ISR)
    MEND
 
;=========================================================================================================================
;一個arm程序由RO,RW,ZI三個斷組成 其中RO爲代碼段,RW是已經初始化的全局變量,ZI是未初始化的全局變量(對於GNU工具 對應的概念是TEXT ,DATA,BSS)
;bootloader要將RW段複製到ram中並將ZI段清零 編譯器使用下列段來記錄各段的起始和結束地址
; |Image$$RO$$Base| ; RO段起始地址
; |Image$$RO$$Limit| ; RO段結束地址加1
; |Image$$RW$$Base| ; RW段起始地址
; |Image$$RW$$Limit| ; RW段結束地址加1
; |Image$$ZI$$Base| ; ZI段起始地址
; |Image$$ZI$$Limit| ; ZI段結束地址加1
;這些標號的值是通過編譯器的設定來確定的 如編譯軟件中對ro-base和rw-base的設定,例如 ro-base=0xc000000 rw-base=0xc5f0000
    IMPORT |Image$$RO$$Limit|  ; End of ROM code (=start of ROM data)
    IMPORT |Image$$RW$$Base|   ; Base of RAM to initialise
    IMPORT |Image$$ZI$$Base|   ; Base and limit of area
    IMPORT |Image$$ZI$$Limit|  ; to zero initialise;
    IMPORT  Main    ; The main entry of mon program
;=========================================================================================================================
;下面爲代碼段
    AREA    Init,CODE,READONLY
    ENTRY
;****************************************************************************
;異常表
 ;上電和復位後,程序開始從位於0x0處開始執行.程序從這裏開始執行跳轉到標號爲ResetHandler處執行
    b      ResetHandler                      ;    Reset       
    ldr    pc, =(_IRQ_BASEADDRESS + 0x04)    ;    HandlerUndef
    ldr    pc, =(_IRQ_BASEADDRESS + 0x08)    ;    HandlerSWI
    ldr    pc, =(_IRQ_BASEADDRESS + 0x0C)    ;    HandlerPabort
    ldr    pc, =(_IRQ_BASEADDRESS + 0x10)    ;    HandlerDAbort
    ldr    pc, =(_IRQ_BASEADDRESS + 0x14)    ;    HandlerReserved
    ldr    pc, =(_IRQ_BASEADDRESS + 0x18)    ;    HandlerIRQ
    ldr    pc, =(_IRQ_BASEADDRESS + 0x1C)    ;    HandlerFIQ
;***************************************************************************   
 ;***IMPORTANT NOTE***
 ;If the H/W vectored interrutp mode is enabled, The above two instructions should
 ;be changed like below, to work-around with H/W bug of S3C44B0X interrupt controller.
 ; b HandlerIRQ  ->  subs pc,lr,#4
 ; b HandlerIRQ  ->  subs pc,lr,#4
;中斷表
 ;向量中斷模式和非向量中斷模式的概念
 ;A)  向量中斷模式是當cpu讀取位於0x18處的IRQ中斷指令的時候,系統自動讀取對應於該中斷源確定地址上的指令取代0x18處的指令,
 ;    通過跳轉指令系統就直接跳轉到對應地址.ADC中斷的向量地址爲0xC0,則在0xC0處放如下代碼:ldr PC,=HandlerADC ,
 ;    當ADC中斷產生的時候系統會自動跳轉到HandlerADC函數中
 
 ;B)  向量中斷模式處理方式是一種傳統的中斷處理方法,當系統產生中斷的時候,系統將interrupt pending寄存器中對應標誌位置位,
 ;    然後跳轉到位於0x18處的統一中斷函數中,該函數通過讀取interrupt pending寄存器中對應標誌位,來判斷中斷源,
 ;    並根據優先級關係再跳到對應中斷源的處理代碼中
 
VECTOR_BRANCH
    ldr pc,=HandlerEINT0    ;mGA    H/W interrupt vector table
    ldr pc,=HandlerEINT1    ;
    ldr pc,=HandlerEINT2    ;
    ldr pc,=HandlerEINT3    ;
    ldr pc,=HandlerEINT4567 ;
    ldr pc,=HandlerTICK     ;mGA
    b .
    b .
    ldr pc,=HandlerZDMA0    ;mGB
    ldr pc,=HandlerZDMA1    ;
    ldr pc,=HandlerBDMA0    ;
    ldr pc,=HandlerBDMA1    ;
    ldr pc,=HandlerWDT     ;
    ldr pc,=HandlerUERR01   ;mGB
    b .
    b .
    ldr pc,=HandlerTIMER0   ;mGC
    ldr pc,=HandlerTIMER1   ;
    ldr pc,=HandlerTIMER2   ;
    ldr pc,=HandlerTIMER3   ;
    ldr pc,=HandlerTIMER4   ;
    ldr pc,=HandlerTIMER5   ;mGC
    b .
    b .
    ldr pc,=HandlerURXD0    ;mGD
    ldr pc,=HandlerURXD1    ;
    ldr pc,=HandlerIIC     ;
    ldr pc,=HandlerSIO     ;
    ldr pc,=HandlerUTXD0    ;
    ldr pc,=HandlerUTXD1    ;mGD
    b .
    b .
    ldr pc,=HandlerRTC     ;mGKA
    b .      ;
    b .      ;
    b .      ;
    b .      ;
    b .      ;mGKA
    b .
    b .
    ldr pc,=HandlerADC     ;mGKB
    b .      ;
    b .      ;
    b .      ;
    b .      ;
    b .      ;mGKB
    b .
    b .
;0xe0=EnterPWDN
    ldr pc,=EnterPWDN
;=============================================================================================================================
;下面是具體的中斷處理函數跳轉的宏,通過上面的$HandlerLabel的宏定義展開後跳轉到對應的中斷處理函數(對於向量中斷)
    LTORG
HandlerFIQ HANDLER HandleFIQ
HandlerIRQ HANDLER HandleIRQ
HandlerUndef HANDLER HandleUndef
HandlerSWI HANDLER HandleSWI
HandlerDabort HANDLER HandleDabort
HandlerPabort HANDLER HandlePabort
HandlerADC HANDLER HandleADC
HandlerRTC HANDLER HandleRTC
HandlerUTXD1 HANDLER HandleUTXD1
HandlerUTXD0 HANDLER HandleUTXD0
HandlerSIO HANDLER HandleSIO
HandlerIIC HANDLER HandleIIC
HandlerURXD1 HANDLER HandleURXD1
HandlerURXD0 HANDLER HandleURXD0
HandlerTIMER5 HANDLER HandleTIMER5
HandlerTIMER4 HANDLER HandleTIMER4
HandlerTIMER3 HANDLER HandleTIMER3
HandlerTIMER2 HANDLER HandleTIMER2
HandlerTIMER1 HANDLER HandleTIMER1
HandlerTIMER0 HANDLER HandleTIMER0
HandlerUERR01 HANDLER HandleUERR01
HandlerWDT HANDLER HandleWDT
HandlerBDMA1 HANDLER HandleBDMA1
HandlerBDMA0 HANDLER HandleBDMA0
HandlerZDMA1 HANDLER HandleZDMA1
HandlerZDMA0 HANDLER HandleZDMA0
HandlerTICK HANDLER HandleTICK
HandlerEINT4567 HANDLER HandleEINT4567
HandlerEINT3 HANDLER HandleEINT3
HandlerEINT2 HANDLER HandleEINT2
HandlerEINT1 HANDLER HandleEINT1
HandlerEINT0 HANDLER HandleEINT0
;*************************************************************************
;IRQ  ==the program put this phrase to 0xc000000
;???可能是給用戶程序使用的異常表???
ExceptionHanlderBegin
    b      .
    ldr    pc, MyHandleUndef            ;    HandlerUndef
    ldr    pc, MyHandleSWI              ;    HandlerSWI
    ldr    pc, MyHandlePabort           ;    HandlerPabort
    ldr    pc, MyHandleDabort           ;    HandlerDAbort
    b .                                 ;    HandlerReserved
    ldr    pc, MyHandleIRQ              ;    HandlerIRQ
    ldr    pc, MyHandleFIQ              ;    HandlerFIQ
   
MyHandleUndef  DCD  HandleUndef         ;reserve a word(32bit)
MyHandleSWI    DCD  HandleSWI
MyHandlePabort DCD  HandlePabort
MyHandleDabort DCD  HandleDabort
MyHandleIRQ    DCD  HandleIRQ
MyHandleFIQ    DCD  HandleFIQ
ExceptionHanlderEnd
;*************************************************************************
;============================================================================================================================
;以下兩個例程都可以用來處理非向量中斷
;具體判斷I_ISPR中各位是否置1 :置1表示目前此中斷等待響應(每次只能有一位置1),從最高優先級中斷位開始判斷,檢測到等待服務
;One of the following two routines can be used for non-vectored interrupt.
IsrIRQ ;using I_ISPR register.
    sub     sp,sp,#4       ;reserved for PC
    stmfd   sp!,{r8-r9}  
 ;IMPORTANT CAUTION
 ;if I_ISPC isn't used properly, I_ISPR can be 0 in this routine.
    ldr     r9,AddrISPR;=I_ISPR       <=> ldr r9,=I_ISPR
    ldr     r9,[r9]
 cmp  r9, #0x0 ;If the IDLE mode work-around is used,
      ;r9 may be 0 sometimes.
 beq  %F2
    mov     r8,#0x0
0
    movs    r9,r9,lsr #1  ;將最低位送入C
    bcs     %F1
    add     r8,r8,#4   ;r8充當索引
    b     %B0
1
    ldr     r9,AddrHandleADC;=HandleADC 找到中斷表的首地址
    add     r9,r9,r8  ;首地址+索引 = 中斷服務地址
    ldr     r9,[r9]   ;加載中斷服務
    str     r9,[sp,#8]  ;放入事先預留的堆棧位置
    ldmfd   sp!,{r8-r9,pc} ;進入中斷服務
2
 ldmfd sp!,{r8-r9}  ;???IDLE MODE故不進行中斷服務,返回了事???
 add  sp,sp,#4
 subs pc,lr,#4
 
AddrISPR;There is no this phrases in original 44binit.s  爲什麼不直接寫ldr r9,=I_ISPR 和ldr r9,=HandleADC,而要這麼做呢???
    DCD     I_ISPR
AddrHandleADC   
    DCD     HandleADC
IsrIRQEnd 
;****************************************************
;* START           *
;****************************************************
;上電和復位後 程序開始從位於0x0執行b ResetHandler 程序從跳轉到這裏執行
ResetHandler
 ;1.禁止看門狗
    ldr     r0,=WTCON     ;watch dog disable
    ldr     r1,=0x0  
    str     r1,[r0]
 ;屏蔽所有中斷
    ldr     r0,=INTMSK
    ldr     r1,=0x07ffffff  ;all interrupt disable
    str     r1,[r0]
    ;****************************************************
    ;* Set clock control registers      *
    ;****************************************************
 ;2.根據工作頻率設置pll
  ;計算公式
  ;Fpllo=(m*Fin)/(p*2^s)
  ;m=MDIV+8,p=PDIV+2,s=SDIV
  ;Fpllo必須大於20Mhz小於66Mhz
  ;Fpllo*2^s必須小於170Mhz
  ;如下面的PLLCON設定中的M_DIV P_DIV S_DIV是取自option.h中
  ;#elif (MCLK==40000000)
  ;#define PLL_M (0x48)
  ;#define PLL_P (0x3)
  ;#define PLL_S (0x2)
  ;所以m=MDIV+8=80,p=PDIV+2=5,s=SDIV=2
  ;硬件使用晶振爲10Mhz,即Fin=10Mhz
  ;Fpllo=80*10/5*2^2=40Mhz
    ldr r0,=LOCKTIME
    ldr r1,=0xfff
    str r1,[r0]
    [ PLLONSTART
 ldr r0,=PLLCON   ;temporary setting of PLL
 ldr r1,=((M_DIV<<12)+(P_DIV<<4)+S_DIV) ;Fin=10MHz,Fout=40MHz
 str r1,[r0]
    ]
    ldr     r0,=CLKCON  
    ldr     r1,=0x7ff8     ;All unit block CLK enable
    str     r1,[r0]
    ;****************************************
    ;*  change BDMACON reset value for BDMA *  
    ;****************************************
    ldr     r0,=BDIDES0      
    ldr     r1,=0x40000000   ;BDIDESn reset value should be 0x40000000 
    str     r1,[r0]
    ldr     r0,=BDIDES1     
    ldr     r1,=0x40000000   ;BDIDESn reset value should be 0x40000000 
    str     r1,[r0]
    ;****************************************************
    ;* Set memory control registers     * 
    ;****************************************************
    ldr     r0,=SMRDATA
    ldmia   r0,{r1-r13}
    ldr     r0,=0x01c80000  ;BWSCON Address
    stmia   r0,{r1-r13}
    ;****************************************************
    ;* Initialize stacks        *
    ;****************************************************
    ldr     sp, =SVCStack ;
    bl     InitStacks
   
    ;****************************************************
    ;* Setup IRQ handler        *
    ;****************************************************
 ;Setup IRQ handler 主體就是將0x0處的異常表搬運到_IRQ_BASEADDRESS,並設置irq服務(none vector mode)
 ;爲什麼要這麼做?中斷髮生時不是自動轉到0x0處的中斷異常表嗎?
 ;莫非日後,再修改此表使他指向_IRQ_BASEADDRESS處?這樣都在ram中,加快速度???
 ;————不是的!!!看一下分析即可知道。
 
 
 ;下面這段代碼看似將_IRQ_BASEADDRESS + 0x100之後的0x100全部初始化爲_IRQ_BASEADDRESS
 ;事實上,結合44b.h中的isr部分就清楚了,那裏是安裝isr的地方,而起始地址正是_IRQ_BASEADDRESS + 0x100!
 ;當irq到來時,無論是非vector mode還是vector mode,都要跳轉到HandleXXX處,
 ;而HandleXXX的首地址正是(_IRQ_BASEADDRESS+0x100)!
 
 ;再回顧一下中斷或異常到來後的行爲:
 ; 1,異常發生
 ; 2,轉到0x0爲首地址的異常表
 ; 3,根據異常類型,轉入某個項,比如SWI
 ;  ldr    pc, =(_IRQ_BASEADDRESS + 0x08)    ;    HandlerSWI
 ; 4,那麼(_IRQ_BASEADDRESS + 0x08)處放的是什麼呢?
 ;  見下表
 ;    ^ (_IRQ_BASEADDRESS)
 ;    HandleReset     # 4
 ;    HandleUndef     # 4
 ;    HandleSWI       # 4
 ;    ...
 ; 由此可知HandleSWI是位於_IRQ_BASEADDRESS + 0x08處的,而44b.h中定義:
 ;  #define pISR_SWI (*(unsigned *)(_IRQ_BASEADDRESS+0x8))
 ; 我們可以安裝這個異常處理函數!
 
 ; irq到來時,情況差不多。
 ; A) 如果是vector mode
 ;  那麼直接載入0x20開始的指令,比如ldr pc,=HandlerEINT4567 ;
 ;  HandlerEINT4567的定義可知:
 ;        ^ (_IRQ_BASEADDRESS+0x100)
 ;     HandleADC     # 4
 ;     HandleRTC     # 4
 ;     ...
 ;     HandleEINT4567  # 4
 ;  他位於_IRQ_BASEADDRESS+0x154處,而44b.h中定義:
 ;   #define pISR_EINT4567 (*(unsigned *)(_IRQ_BASEADDRESS+0x154))//0x74))
 ;  於是我們可以安裝處理函數。
 ;
 ; B) 如果是none vector mode
 ;  那麼僅在裝入HandlerEINT4567時方法不同,它是通過判斷程序來完成的,剩下的步驟還是相同的。
 
 
    ldr     r0,=(_IRQ_BASEADDRESS + 0x100)
    ldr     r2,=_IRQ_BASEADDRESS
    add     r3,r0, #0x100            ;r3指向_IRQ_BASEADDRESS+0x200處
0   
    CMP     r0, r3      ;do what?  <- 哈哈,我知道了,居然你們立宇泰的人不知道!!!
    STRCC   r2, [r0], #4;cc:Carry clear;save R2 to R0 address, R0 + 4=R0。
    BCC     %B0
   
 ;----------------------------------------------------------------------------------------
 ;將0x0處的vector table 拷貝到 _IRQ_BASEADDRESS(0xc000000)
    ldr     r1,=_IRQ_BASEADDRESS           
    ldr     r0,=ExceptionHanlderBegin ;if there isn't 'subs pc,lr,#4' at 0x18, 0x1c
    ldr     r3,=ExceptionHanlderEnd
0   
    CMP     r0, r3              ;put the vector table at _IRQ_BASEADDRESS(0xc000000)
    LDRCC   r2, [r0], #4 
    STRCC   r2, [r1], #4
    BCC     %B0
           
 ;----------------------------------------------------------------------------------------
 ;下面代碼將非向量模式下的中斷判斷處理函數拷貝到_IRQ_BASEADDRESS+0x80(0xc000080)
    ldr     r1,=DIsrIRQ     ;put the IRQ judge program at _IRQ_BASEADDRESS+0x80(0xc000080)      
    ldr     r0,=IsrIRQ      ;if there isn't 'subs pc,lr,#4' at 0x18, 0x1c
    ldr     r3,=IsrIRQEnd
0   
    CMP     r0, r3
    LDRCC   r2, [r0], #4
    STRCC   r2, [r1], #4
    BCC     %B0
 ;----------------------------------------------------------------------------------------
 ;將非向量模式的中斷處理函數裝入_IRQ_BASEADDRESS處的HandleIRQ
    ldr     r1, =MyHandleIRQ   ;MyHandleIRQ point to DIsrIRQ
    ldr     r0, =ExceptionHanlderBegin
    ldr     r4, =_IRQ_BASEADDRESS;////
    sub     r0, r1, r0   ;計算MyHandleIRQ在ExceptionHanlderBegin這個中斷表中的偏移
    ;add     r0, r0, #_IRQ_BASEADDRESS
    add     r0, r0,r4   ;r0指向_IRQ_BASEADDRESS+(MyHandleIRQ的偏移),即0xc000000處的HandleIRQ
    ldr     r1, =DIsrIRQ     ;將非向量模式的中斷處理函數裝入0xc000000處的HandleIRQ
    str     r1, [r0]   
;    ldr     r0,=HandleIRQ  ;This routine is needed
;    ldr     r1,=IsrIRQ   ;if there isn't 'subs pc,lr,#4' at 0x18, 0x1c
;    str     r1,[r0]
 ;-----------------------------------------------------------------------------------------
; --- Initialise memory required by C code
    ;********************************************************
    ;* 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

    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

    LDR     r1, =|Image$$ZI$$Limit| ; Top of zero init segment
    MOV     r2, #0

    CMP     r3, r1     ; Zero init 初始化bss段
    STRCC   r2, [r3], #4
    BCC     %B2
   
;--------Now we enter the C code
    [ :LNOT:THUMBCODE   ;if(!thumbcode) arm state;
 BL Main         ;Don't use main() because ...... 爲什麼呢?
 B .     
    ];
    [ THUMBCODE      ;for start-up code for Thumb mode;
 orr     lr,pc,#1
 bx      lr
 CODE16
 bl      Main     ;Don't use main() because ......
 b       .
 CODE32
   ]
;****************************************************
;* The function for initializing stack    *
;****************************************************
;4.初始化各模式下的棧指針
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
 ;USER mode is not initialized.
    mov     pc,lr ;The LR register may be not valid for the mode changes.
;****************************************************
;* The function for entering power down mode  *
;****************************************************
;void EnterPWDN(int CLKCON);
EnterPWDN
    mov     r2,r0               ;r0=CLKCON
    ldr     r0,=REFRESH 
    ldr     r3,[r0]
    mov     r1, r3
    orr     r1, r1, #0x400000   ;self-refresh enable
    str     r1, [r0]
    nop     ;Wait until self-refresh is issued. May not be needed.
    nop     ;If the other bus master holds the bus, ...
    nop     ; mov r0, r0
    nop
    nop
    nop
    nop
;enter POWERDN mode
    ldr     r0,=CLKCON
    str     r2,[r0]
;wait until enter SL_IDLE,STOP mode and until wake-up
    ldr     r0,=0x10
0   subs    r0,r0,#1
    bne     %B0
;exit from DRAM/SDRAM self refresh mode.
    ldr     r0,=REFRESH
    str     r3,[r0]
    mov     pc,lr
    ;LTORG
SMRDATA DATA
;*****************************************************************
;* Memory configuration has to be optimized for best performance *
;* The following parameter is not optimized.                     *
;*****************************************************************
;*** memory access cycle parameter strategy ***
; 1) Even FP-DRAM, EDO setting has more late fetch point by half-clock
; 2) The memory settings,here, are made the safe parameters even at 66Mhz.
; 3) FP-DRAM Parameters:tRCD=3 for tRAC, tcas=2 for pad delay, tcp=2 for bus load.
; 4) DRAM refresh rate is for 40Mhz.
;bank0 16bit BOOT ROM
;bank1 8bit NandFlash
;bank2 16bit IDE
;bank3 8bit UDB
;bank4 rtl8019
;bank5 8bit usb host
;bank6 16bit SDRAM
;bank7 16bit SDRAM
    [ BUSWIDTH=16
    DCD 0x11010101 ;Bank0=16bit BootRom(AT29C010A*2) :0x0 8bit usb host![20:23]=0
    | ;BUSWIDTH=32
 DCD 0x22222220 ;Bank0=OM[1:0], Bank1~Bank7=32bit
    ]
 DCD ((B0_Tacs<<13)+(B0_Tcos<<11)+(B0_Tacc<<8)+(B0_Tcoh<<6)+(B0_Tah<<4)+(B0_Tacp<<2)+(B0_PMC)) ;GCS0
 DCD ((B1_Tacs<<13)+(B1_Tcos<<11)+(B1_Tacc<<8)+(B1_Tcoh<<6)+(B1_Tah<<4)+(B1_Tacp<<2)+(B1_PMC)) ;GCS1
 DCD ((B2_Tacs<<13)+(B2_Tcos<<11)+(B2_Tacc<<8)+(B2_Tcoh<<6)+(B2_Tah<<4)+(B2_Tacp<<2)+(B2_PMC)) ;GCS2
 DCD ((B3_Tacs<<13)+(B3_Tcos<<11)+(B3_Tacc<<8)+(B3_Tcoh<<6)+(B3_Tah<<4)+(B3_Tacp<<2)+(B3_PMC)) ;GCS3
 DCD ((B4_Tacs<<13)+(B4_Tcos<<11)+(B4_Tacc<<8)+(B4_Tcoh<<6)+(B4_Tah<<4)+(B4_Tacp<<2)+(B4_PMC)) ;GCS4
 DCD ((B5_Tacs<<13)+(B5_Tcos<<11)+(B5_Tacc<<8)+(B5_Tcoh<<6)+(B5_Tah<<4)+(B5_Tacp<<2)+(B5_PMC)) ;GCS5
 [ BDRAMTYPE="DRAM"
     DCD ((B6_MT<<15)+(B6_Trcd<<4)+(B6_Tcas<<3)+(B6_Tcp<<2)+(B6_CAN)) ;GCS6 check the MT value in parameter.a
     DCD ((B7_MT<<15)+(B7_Trcd<<4)+(B7_Tcas<<3)+(B7_Tcp<<2)+(B7_CAN)) ;GCS7
 | ;"SDRAM"
  DCD ((B6_MT<<15)+(B6_Trcd<<2)+(B6_SCAN)) ;GCS6
  DCD ((B7_MT<<15)+(B7_Trcd<<2)+(B7_SCAN)) ;GCS7
 ]
 DCD ((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Trc<<18)+(Tchr<<16)+REFCNT) ;REFRESH RFEN=1, TREFMD=0, trp=3clk, trc=5clk, tchr=3clk,count=1019
 DCD 0x10   ;SCLK power down mode, BANKSIZE 32M/32M
 DCD 0x20   ;MRSR6 CL=2clk
 DCD 0x20   ;MRSR7
 ALIGN               ;?
;==========================================================================================================================================
;以下的數據段充分的說明了中斷處理程序的存儲結構
;分爲3個區域
;   1,異常向量表(_IRQ_BASEADDRESS ~ _IRQ_BASEADDRESS+0x4*8)
;   2,none vector mode的判斷程序(_IRQ_BASEADDRESS+0x80~...)
;   3,isr表(中斷處理服務表)(_IRQ_BASEADDRESS+0x100~...)
;最後還有堆棧區域
 AREA RamData, DATA, READWRITE

    ^ (_IRQ_BASEADDRESS)
HandleReset     # 4
HandleUndef     # 4
HandleSWI       # 4
HandlePabort    # 4
HandleDabort    # 4
HandleReserved  # 4
HandleIRQ       # 4
HandleFIQ       # 4
 
  ^ (_IRQ_BASEADDRESS+0x80)
DIsrIRQ       # 4

;Don't use the label 'IntVectorTable',
;because armasm.exe cann't recognize this label correctly.
;the value is different with an address you think it may be.
;IntVectorTable
    ^ (_IRQ_BASEADDRESS+0x100)
HandleADC     # 4
HandleRTC     # 4
HandleUTXD1   # 4
HandleUTXD0   # 4
HandleSIO     # 4
HandleIIC     # 4
HandleURXD1   # 4
HandleURXD0   # 4
HandleTIMER5  # 4
HandleTIMER4  # 4
HandleTIMER3  # 4
HandleTIMER2  # 4
HandleTIMER1  # 4
HandleTIMER0  # 4
HandleUERR01  # 4
HandleWDT     # 4
HandleBDMA1   # 4
HandleBDMA0   # 4
HandleZDMA1   # 4
HandleZDMA0   # 4
HandleTICK    # 4
HandleEINT4567  # 4
HandleEINT3   # 4
HandleEINT2   # 4
HandleEINT1   # 4
HandleEINT0   # 4  
 ^ (_ISR_STARTADDRESS-0x1400)
   
UserStack # 1024 ;c1(c7)fe600
SVCStack # 1024 ;c1(c7)feb00
UndefStack # 1024 ;c1(c7)ff000
AbortStack # 1024 ;c1(c7)ff500
IRQStack # 1024 ;c1(c7)ffa00
FIQStack # 0 ;c1(c7)fff00
  END

 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章