;-----------------------------------------------------------------------
;配置時鐘
;如果邏輯上沒有定義 NO_CLOCK_SETUP并且 CLOCK_SETUP != 0執行下面程序
;-----------------------------------------------------------------------
IF (:LNOT:(:DEF:NO_CLOCK_SETUP)):LAND:(CLOCK_SETUP != 0)
LDR R0, =CLOCK_BASE ;加載時鐘基址
LDR R1, =LOCKTIME_Val ;加載PLL鎖定時間計數值
STR R1, [R0, #LOCKTIME_OFS] ;并將該值配置到PLL鎖定時間計數器
MOV R1, #CLKDIVN_Val
STR R1, [R0, #CLKDIVN_OFS] ;配置時鐘分頻器
LDR R1, =CAMDIVN_Val
STR R1, [R0, #CAMDIVN_OFS] ;配置攝像頭分頻控制寄存器
LDR R1, =MPLLCON_Val
STR R1, [R0, #MPLLCON_OFS] ;配置MPLL配置寄存器
LDR R1, =UPLLCON_Val
STR R1, [R0, #UPLLCON_OFS] ;配置UPLL配置寄存器
MOV R1, #CLKSLOW_Val
STR R1, [R0, #CLKSLOW_OFS] ;配置時鐘減慢控制寄存器
LDR R1, =CLKCON_Val
STR R1, [R0, #CLKCON_OFS] ;配置時鐘配控制寄存器
ENDIF
;-----------------------------------------------------------------------
;存儲器設定
;如果沒有定義NO_MC_SETUP且CLOCK_SETUP != 0則執行下面的程序
;-----------------------------------------------------------------------
IF (:LNOT:(:DEF:NO_MC_SETUP)):LAND:(CLOCK_SETUP != 0)
LDR R0, =MC_BASE ;加載存儲控制器基址
LDR R1, =BWSCON_Val
STR R1, [R0, #BWSCON_OFS] ;配置總線寬度和等待控制寄存器
LDR R1, =BANKCON0_Val
STR R1, [R0, #BANKCON0_OFS] ;配置BLANK0控制寄存器
LDR R1, =BANKCON1_Val
STR R1, [R0, #BANKCON1_OFS] ;配置BLANK1控制寄存器
LDR R1, =BANKCON2_Val
STR R1, [R0, #BANKCON2_OFS] ;配置BLANK2控制寄存器
LDR R1, =BANKCON3_Val
STR R1, [R0, #BANKCON3_OFS] ;配置BLANK3控制寄存器
LDR R1, =BANKCON4_Val
STR R1, [R0, #BANKCON4_OFS] ;配置BLANK4控制寄存器
LDR R1, =BANKCON5_Val
STR R1, [R0, #BANKCON5_OFS] ;配置BLANK5控制寄存器
LDR R1, =BANKCON6_Val
STR R1, [R0, #BANKCON6_OFS] ;配置BLANK6控制寄存器
LDR R1, =BANKCON7_Val
STR R1, [R0, #BANKCON7_OFS] ;配置BLANK7控制寄存器
LDR R1, =REFRESH_Val
STR R1, [R0, #REFRESH_OFS] ;配置DRAM/SDRAM刷新控制寄存器
MOV R1, #BANKSIZE_Val
STR R1, [R0, #BANKSIZE_OFS] ;配置可調的bank大小寄存器
MOV R1, #MRSRB6_Val
STR R1, [R0, #MRSRB6_OFS] ;配置bank6模式控制寄存器
MOV R1, #MRSRB7_Val
STR R1, [R0, #MRSRB7_OFS] ;配置bank7模式控制寄存器
ENDIF
;-----------------------------------------------------------------------
;IO端口配置
;如果沒有定義NO_GP_SETUP并且GP_SETUP != 0則執行下面的程序
;-----------------------------------------------------------------------
IF (:LNOT:(:DEF:NO_GP_SETUP)):LAND:(GP_SETUP != 0)
IF GPA_SETUP != 0
LDR R0, =GPA_BASE ;配置端口A功能
LDR R1, =GPACON_Val ;A口有25個口,做IO時只能做輸出口
STR R1, [R0, #GPCON_OFS]
ENDIF
IF GPB_SETUP != 0
LDR R0, =GPB_BASE ;配置端口B功能
LDR R1, =GPBCON_Val
STR R1, [R0, #GPCON_OFS]
LDR R1, =GPBUP_Val ;配置端口B上拉寄存器
STR R1, [R0, #GPUP_OFS]
ENDIF
IF GPC_SETUP != 0
LDR R0, =GPC_BASE ;配置端口C功能
LDR R1, =GPCCON_Val
STR R1, [R0, #GPCON_OFS]
LDR R1, =GPCUP_Val ;配置端口C上拉寄存器
STR R1, [R0, #GPUP_OFS]
ENDIF
IF GPD_SETUP != 0
LDR R0, =GPD_BASE ;配置端口D功能
LDR R1, =GPDCON_Val
STR R1, [R0, #GPCON_OFS]
LDR R1, =GPDUP_Val ;配置端口D上位寄存器
STR R1, [R0, #GPUP_OFS]
ENDIF
IF GPE_SETUP != 0
LDR R0, =GPE_BASE
LDR R1, =GPECON_Val ;配置端口E功能
STR R1, [R0, #GPCON_OFS]
LDR R1, =GPEUP_Val ;配置端口E上位寄存器
STR R1, [R0, #GPUP_OFS]
ENDIF
IF GPF_SETUP != 0
LDR R0, =GPF_BASE
LDR R1, =GPFCON_Val ;配置端口F功能
STR R1, [R0, #GPCON_OFS]
LDR R1, =GPFUP_Val ;配置端口F上位寄存器
STR R1, [R0, #GPUP_OFS]
ENDIF
IF GPG_SETUP != 0
LDR R0, =GPG_BASE
LDR R1, =GPGCON_Val ;配置端口G功能
STR R1, [R0, #GPCON_OFS]
LDR R1, =GPGUP_Val ;配置端口G上位寄存器
STR R1, [R0, #GPUP_OFS]
ENDIF
IF GPH_SETUP != 0
LDR R0, =GPH_BASE
LDR R1, =GPHCON_Val ;配置端口H功
STR R1, [R0, #GPCON_OFS]
LDR R1, =GPHUP_Val ;配置端口H上位寄存器
STR R1, [R0, #GPUP_OFS]
ENDIF
IF GPJ_SETUP != 0
LDR R0, =GPJ_BASE
LDR R1, =GPJCON_Val ;配置端口J功
STR R1, [R0, #GPCON_OFS]
LDR R1, =GPJUP_Val ;配置端口J上位寄存
STR R1, [R0, #GPUP_OFS]
ENDIF
ENDIF
;-----------------------------------------------------------------------
;拷貝異常向量到內部RAM
;如果定義了RAM_INTVEC就執行下面一段程序
;-----------------------------------------------------------------------
IF :DEF:RAM_INTVEC
ADR R8, Vectors ; 讀取向量源地址
LDR R9, =IRAM_BASE ; 讀取片上SRAM的基地址
LDMIA R8!, {R0-R7} ; 批量加載異常向量
STMIA R9!, {R0-R7} ; 批量存儲向量
LDMIA R8!, {R0-R7} ; 加載程序入口地址(Load Handler Addresses )
STMIA R9!, {R0-R7} ; 存儲程序入口地址(Store Handler Addresses)
ENDIF
;-----------------------------------------------------------------------
;配置相應模式棧的大小(Setup Stack for each mode )
;下面這一段主要是設置各個異常模式的堆棧,注意在設置的時候需要禁止IRQ和FIQ.
;這段代碼也是系統復位后執行的第一段代碼。執行完這段代碼后系統處于系統模
;式,并且IRQ和FIQ都是禁止的。
;-----------------------------------------------------------------------
LDR R0, =Stack_Top ;加載棧頂指針地址
;-----------------------------------------------------------------------
;進入未定義模式,并設定其棧指針
;-----------------------------------------------------------------------
;將(Mode_UND | I_Bit | F_Bit)賦值給 CPSR_c即CPSR[7:0]
MSR CPSR_c, #Mode_UND:OR:I_Bit:OR:F_Bit
MOV SP, R0 ;棧頂指針地址賦值給SP指針
SUB R0, R0, #UND_Stack_Size ;分其棧指針
;-----------------------------------------------------------------------
;進入異常中斷模式,并設定其棧指針
;下面這三句話與上面原理一樣
;-----------------------------------------------------------------------
MSR CPSR_c, #Mode_ABT:OR:I_Bit:OR:F_Bit
MOV SP, R0
SUB R0, R0, #ABT_Stack_Size
;-----------------------------------------------------------------------
;進入FIQ模式,并設定其棧指針
;下面這三句話與上面原理一樣
;-----------------------------------------------------------------------
MSR CPSR_c, #Mode_FIQ:OR:I_Bit:OR:F_Bit
MOV SP, R0
SUB R0, R0, #FIQ_Stack_Size
;-----------------------------------------------------------------------
;進入IRQ模式,并設定其棧指針
;下面這三句話與上面原理一樣
;-----------------------------------------------------------------------
MSR CPSR_c, #Mode_IRQ:OR:I_Bit:OR:F_Bit
MOV SP, R0
SUB R0, R0, #IRQ_Stack_Size
;-----------------------------------------------------------------------
;進入Supervisor模式,并設定其棧指針
;下面這三句話與上面原理一樣
;-----------------------------------------------------------------------
MSR CPSR_c, #Mode_SVC:OR:I_Bit:OR:F_Bit
MOV SP, R0
SUB R0, R0, #SVC_Stack_Size
;-----------------------------------------------------------------------
;進入用戶模式,并設定其棧指針
;下面這三句話與上面原理一樣
;-----------------------------------------------------------------------
; Enter User Mode and set its Stack Pointer
MSR CPSR_c, #Mode_USR
MOV SP, R0
SUB SL, SP, #USR_Stack_Size
;-----------------------------------------------------------------------
;進入用戶模式
;-----------------------------------------------------------------------
MSR CPSR_c, #Mode_USR
IF :DEF:__MICROLIB ;如果定義了__MICROLIB
EXPORT __initial_sp ;那么就聲明__initial_sp
ELSE
MOV SP, R0 ;否則就設定用戶模式棧指針
SUB SL, SP, #USR_Stack_Size
ENDIF
;-----------------------------------------------------------------------
;些處開始正式進入C代碼區
;反匯編以后C程序中的main函數名就變成了__main
;-----------------------------------------------------------------------
IMPORT __main ;聲明__main 函數
LDR R0, =__main ;加載__main 函數入口地址
BX R0 ;跳轉到__main處
IF :DEF:__MICROLIB ;如果定義了__MICROLIB
EXPORT __heap_base ;則聲明__heap_base
EXPORT __heap_limit ;聲明__heap_limit
ELSE
;-----------------------------------------------------------------------
;用戶初始化堆與棧,用于動態申請內存使用
;__use_two_region_memory這是MDK的庫函
;__user_initial_stackheap也是一個庫函數,它的返回值有
; * 堆基址(heap base) --> R0
; * ;(stack base) --> R1 一般為棧的最高地址
; * 堆頂(heap limit) --> R2
; * 棧頂(stack limit) --> R3
;
;-----------------------------------------------------------------------
AREA |.text|, CODE, READONLY
IMPORT __use_two_region_memory
EXPORT __user_initial_stackheap
__user_initial_stackheap
LDR R0, = Heap_Mem ;堆內存起始地址 -->R0
LDR R1, =(Stack_Mem + USR_Stack_Size) ;棧起始地址 -->R1
LDR R2, = (Heap_Mem + Heap_Size) ;堆頂 -->R2
LDR R3, = Stack_Mem ;棧頂地址 --> R3
BX LR ;子程序返回
ENDIF
END
|