;-----------------------------------------------------------------------
;配置时钟
;如果逻辑上没有定义 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
|