S3C2440.s启动代码详细分析

;/*****************************************************************************/
;/* S3C2440.S: Startup file for Samsung S3C440                                */
;/*****************************************************************************/

; Standard definitions of Mode bits and Interrupt (I & F) flags in PSRs
;标准模式定义和中断标志使能位,不同处理器模式可能不同,需要修改

Mode_USR        EQU     0x10			;用户模式
Mode_FIQ        EQU     0x11			;快速中断模式
Mode_IRQ        EQU     0x12			;中断模式
Mode_SVC        EQU     0x13			;管理模式
Mode_ABT        EQU     0x17			;终止模式
Mode_UND        EQU     0x1B			;未定义模式
Mode_SYS        EQU     0x1F			;系统模式

I_Bit           EQU     0x80            ;I位设置为1,IRQ不使能
F_Bit           EQU     0x40            ;F位设置为1,FIQ不使能

;----------------------- Stack and Heap Definitions ----------------------------

UND_Stack_Size  EQU     0x00000000				;未定义模式栈的大小
SVC_Stack_Size  EQU     0x00000008				;管理模式栈的大小
ABT_Stack_Size  EQU     0x00000000				;终止模式栈的大小
FIQ_Stack_Size  EQU     0x00000000				;快速中断模式栈的大小
IRQ_Stack_Size  EQU     0x00000080				;中断模式栈的大小
USR_Stack_Size  EQU     0x00000400				;正常模式栈的大小

;中断程序堆栈的大小
ISR_Stack_Size  EQU     (UND_Stack_Size + SVC_Stack_Size + ABT_Stack_Size + \
                         FIQ_Stack_Size + IRQ_Stack_Size)
;定义名为STACK的区域,可读可写,以2的3次方对齐
                AREA    STACK, NOINIT, READWRITE, ALIGN=3
                
;分配内存空间
Stack_Mem       SPACE   USR_Stack_Size			;内存堆栈分配空间
__initial_sp    SPACE   ISR_Stack_Size			;汇编代码地址标号
Stack_Top										;标号,获得堆栈的地址

;堆的大小,用于动态分配内存
Heap_Size       EQU     0x00000000
;定义名为HEAP的区域,可读可写,以2的3次方对齐
                AREA    HEAP, NOINIT, READWRITE, ALIGN=3
__heap_base										;标号,获得堆的基地址
Heap_Mem        SPACE   Heap_Size				;分配堆的空间,获得堆的地址标号
__heap_limit									;分配结束


;----------------------- Memory Definitions ------------------------------------
;内存初始化定义
; Internal Memory Base Addresses
IRAM_BASE       EQU     0x40000000				;内存基地址

;----------------------- Watchdog Timer Definitions ----------------------------
;看门狗初始化定义,移植到其他处理器地址可能不同,需要修改
WT_BASE         EQU     0x53000000      ; 看门狗定时器基地址
WTCON_OFS       EQU     0x00            ; 看门狗控制寄存器相对于基地址的偏移地址
WTDAT_OFS       EQU     0x04            ; 看门狗数据寄存器相对于基地址的偏移地址
WTCNT_OFS       EQU     0x08            ; 看门口计数寄存器相对于及地址的偏移地址


WT_SETUP        EQU     1				;看门狗设置
WTCON_Val       EQU     0x00000000		;看门狗控制寄存器设置
WTDAT_Val       EQU     0x00008000		;看门狗数据寄存器设置,初始化为0x8000

;----------------------- Clock and Power Management Definitions ----------------
;时钟与电源管理定义,移植到其他处理器地址可能不同,需要修改
CLOCK_BASE      EQU     0x4C000000      ; 时钟基地址
LOCKTIME_OFS    EQU     0x00            ; 锁相环锁定时间计数寄存器相对于基地址偏移地址
MPLLCON_OFS     EQU     0x04            ; 主时钟锁相环配置寄存器相对于基地址偏移地址
UPLLCON_OFS     EQU     0x08            ; USB时钟锁相环配置寄存器相对于基地址偏移地址
CLKCON_OFS      EQU     0x0C            ; 时钟控制寄存器相对于基地址的偏移地址
CLKSLOW_OFS     EQU     0x10            ; 时钟减慢控制寄存器相对于基地址的偏移地址
CLKDIVN_OFS     EQU     0x14            ; 时钟分频控制寄存器相对于基地址的偏移地址
CAMDIVN_OFS     EQU     0x18            ; 相机时钟分频寄存器相对于基地址的偏移地址

CLOCK_SETUP     EQU     0				;时钟设置
LOCKTIME_Val    EQU     0x0FFF0FFF		;锁相环锁定时间计数器值
MPLLCON_Val     EQU     0x00043011		;主锁相环控制寄存器的值
UPLLCON_Val     EQU     0x00038021		;USB锁相环控制寄存器的值
CLKCON_Val      EQU     0x001FFFF0		;始终控制寄存器的值
CLKSLOW_Val     EQU     0x00000004		;始终减慢控制寄存器的值
CLKDIVN_Val     EQU     0x0000000F		;时钟分频控制寄存器的值
CAMDIVN_Val     EQU     0x00000000		;摄像头分频控制寄存器的值

;----------------------- Memory Controller Definitions -------------------------
;内存控制定义,移植到其他处理器地址可能不同,需要修改
MC_BASE         EQU     0x48000000      ; 存储控制器基地址
BWSCON_OFS      EQU     0x00            ; 总线宽度和等待控制寄存器偏移地址
BANKCON0_OFS    EQU     0x04            ; Bank0控制寄存器偏移地址
BANKCON1_OFS    EQU     0x08            ; Bank1控制寄存器偏移地址
BANKCON2_OFS    EQU     0x0C            ; Bank2控制寄存器偏移地址
BANKCON3_OFS    EQU     0x10            ; Bank3控制寄存器偏移地址
BANKCON4_OFS    EQU     0x14            ; Bank4控制寄存器偏移地址
BANKCON5_OFS    EQU     0x18            ; Bank5控制寄存器偏移地址
BANKCON6_OFS    EQU     0x1C            ; Bank6控制寄存器偏移地址
BANKCON7_OFS    EQU     0x20            ; Bank7控制寄存器偏移地址
REFRESH_OFS     EQU     0x24            ; SDRAM刷新控制寄存器偏移地址
BANKSIZE_OFS    EQU     0x28            ; 可调节的BANK大小寄存器的偏移地址
MRSRB6_OFS      EQU     0x2C            ; Bank6模式寄存器的偏移地址
MRSRB7_OFS      EQU     0x30            ; Bank7模式寄存器的偏移地址

MC_SETUP        EQU     0				;存储器寄存器设置
BWSCON_Val      EQU     0x22000000		;总线宽度和等待控制寄存器值
BANKCON0_Val    EQU     0x00000700		;BANK0控制寄存器的值
BANKCON1_Val    EQU     0x00000700		;BANK1控制寄存器的值
BANKCON2_Val    EQU     0x00000700		;BANK2控制寄存器的值
BANKCON3_Val    EQU     0x00000700		;BANK3控制寄存器的值
BANKCON4_Val    EQU     0x00000700		;BANK4控制寄存器的值
BANKCON5_Val    EQU     0x00000700		;BANK5控制寄存器的值
BANKCON6_Val    EQU     0x00018005		;BANK6控制寄存器的值
BANKCON7_Val    EQU     0x00018005		;BANK7控制寄存器的值
REFRESH_Val     EQU     0x008404F3		;DRAM/SDRAM控制寄存器的值
BANKSIZE_Val    EQU     0x00000032		;可调的BANK大小控制寄存器的值
MRSRB6_Val      EQU     0x00000020		;BANK6模式控制寄存器的值
MRSRB7_Val      EQU     0x00000020		;BANK6模式控制寄存器的值

;----------------------- I/O Port Definitions ----------------------------------
;I/O端口定义,移植到其他处理器地址可能不同,需要修改
GPA_BASE        EQU     0x56000000      ; GPA基地址
GPB_BASE        EQU     0x56000010      ; GPB基地址
GPC_BASE        EQU     0x56000020      ; GPC基地址
GPD_BASE        EQU     0x56000030      ; GPD基地址
GPE_BASE        EQU     0x56000040      ; GPE基地址
GPF_BASE        EQU     0x56000050      ; GPF基地址
GPG_BASE        EQU     0x56000060      ; GPG基地址
GPH_BASE        EQU     0x56000070      ; GPH基地址
GPJ_BASE        EQU     0x560000D0      ; GPJ基地址
GPCON_OFS       EQU     0x00            ; 控制寄存器偏移地址
GPDAT_OFS       EQU     0x04            ; 数据寄存器偏移地址
GPUP_OFS        EQU     0x08            ; 上拉寄存器偏移地址

GPA_SETUP       EQU     0					;端口A设置
GPACON_Val      EQU     0x000003FF			;端口A控制寄存器的值

GPB_SETUP       EQU     0					;端口B设置
GPBCON_Val      EQU     0x00000000			;端口B控制寄存器的值
GPBUP_Val       EQU     0x00000000 			;端口B上拉寄存器的值

GPC_SETUP       EQU     0						;端口C设置
GPCCON_Val      EQU     0x00000000				;端口C控制寄存器的值
GPCUP_Val       EQU     0x00000000				;端口C上拉寄存器的值

GPE_SETUP       EQU     0						;端口E设置
GPECON_Val      EQU     0x00000000				;端口E控制寄存器的值
GPEUP_Val       EQU     0x00000000				;端口E上拉寄存器的值

GPF_SETUP       EQU     0						;端口F设置
GPFCON_Val      EQU     0x00000000				;端口F控制寄存器的值
GPFUP_Val       EQU     0x00000000				;端口F上拉寄存器的值

GPG_SETUP       EQU     0						;端口G设置
GPGCON_Val      EQU     0x00000000				;端口G控制寄存器的值
GPGUP_Val       EQU     0x00000000				;端口G上拉寄存器的值

GPH_SETUP       EQU     0						;端口H设置
GPHCON_Val      EQU     0x00000000				;端口H控制寄存器的值
GPHUP_Val       EQU     0x00000000 				;端口H上拉寄存器的值

GPJ_SETUP       EQU     0						;端口J设置
GPJCON_Val      EQU     0x00000000				;端口J控制寄存器的值
GPJUP_Val       EQU     0x00000000				;端口J上拉寄存器的值

;----------------------- CODE --------------------------------------------------
;代码段,8字节对齐
                PRESERVE8
                
; 存储区定义和程序入口点
;  Startup Code must be linked first at Address at which it expects to run.
;resret区域,代码段,只读,ARM模式
                AREA    RESET, CODE, READONLY
                ARM
                
                IF      :LNOT::DEF:__EVAL 				;如果定义了__EVAL,则继续执行,如果没有则定义
                IMPORT  ||Image$$ER_ROM1$$RO$$Length||	;引入RO输出区字节长度
                IMPORT  ||Image$$RW_RAM1$$RW$$Length||	;引入RW输出区字节长度
                ENDIF									;结束IF

Vectors         LDR     PC, Reset_Addr         			;将复位地址装载到程序指针
                LDR     PC, Undef_Addr					;将未定义指令装载到程序指针
                LDR     PC, SWI_Addr					;将软件中断地址装载到程序指针
                LDR     PC, PAbt_Addr					;将预取终止地址装载到程序指针
                LDR     PC, DAbt_Addr					;将数据终止地址加载到程序指针
                
                IF      :DEF:__EVAL						;如果定义了__EVAL
                  DCD   0x4000							;分配空间
                ELSE 									;否则
                  DCD   ||Image$$ER_ROM1$$RO$$Length||+\;分配空间为RO输出区的字节长度
                        ||Image$$RW_RAM1$$RW$$Length||	;RW输出区的字节长度
                ENDIF									;结束IF
                LDR     PC, IRQ_Addr					;将外部中断地址装载到程序指针
                LDR     PC, FIQ_Addr					;将快速中断地址装载到程序指针

                IF      :DEF:__RTX						;如果定义__RTX
                IMPORT  SWI_Handler						;定义软中断服务程序
                IMPORT  IRQ_Handler_RTX					;引入外部中断服务程序
                ENDIF

Reset_Addr      DCD     Reset_Handler			;将复位中断服务程序入口地址赋给Reset_Addr
Undef_Addr      DCD     Undef_Handler			;将未定义中断服务程序入口地址赋给Undef_Addr
SWI_Addr        DCD     SWI_Handler				;将软中断中断服务程序入口地址赋给SWI_Addr
PAbt_Addr       DCD     PAbt_Handler			;将预取终止中断服务程序入口地址赋给PAbt_Addr
DAbt_Addr       DCD     DAbt_Handler			;将数据终止中断服务程序入口地址赋给DAbt_Addr
                DCD     0                   	;保留地址
                IF      :DEF:__RTX				;如果定义__RTX
IRQ_Addr        DCD     IRQ_Handler_RTX			;将快速中断中断服务程序入口地址赋给IRQ_Addr
                ELSE;否则
IRQ_Addr        DCD     IRQ_Handler				;将外部中断中断服务程序入口地址赋给IRQ_Addr
                ENDIF;结束IF
FIQ_Addr        DCD     FIQ_Handler				;将快速中断中断服务程序入口地址赋给FIQ_Addr

Undef_Handler   B       Undef_Handler			;跳转循环
                IF      :DEF:__RTX				;如果定义__RTX
                ELSE							;否则
SWI_Handler     B       SWI_Handler				;跳转到软中断服务程序
                ENDIF							;结束IF
PAbt_Handler    B       PAbt_Handler			;跳转到预取终止服务程序
DAbt_Handler    B       DAbt_Handler			;跳转到数据终止服务程序
IRQ_Handler     PROC
                EXPORT  IRQ_Handler               [WEAK];声明一个全局变量,同名符优先于本符号被使用
                B       .
                ENDP
FIQ_Handler     B       FIQ_Handler				;跳转到快速中断服务程序


; Reset Handler

                EXPORT  Reset_Handler			;声明一个全局变量,同名符优先于本符号被使用
Reset_Handler   


; Watchdog Setup ---------------------------------------------------------------
;看门狗设置
                IF      WT_SETUP != 0			;如果WT_SETUP不为0
                LDR     R0, =WT_BASE			;加载看门狗基地址
                LDR     R1, =WTCON_Val			;加载看门口控制寄存器的值
                LDR     R2, =WTDAT_Val			;加载看门狗数据寄存器的值
                STR     R2, [R0, #WTCNT_OFS]	;将WTDAT_Val加载到看门狗计数寄存器
                STR     R2, [R0, #WTDAT_OFS]	;将WTDAT_Val加载到看门狗数据寄存器
                STR     R1, [R0, #WTCON_OFS]	;将WTCON_Val加载到看门狗控制寄存器
                ENDIF
                
; Clock Setup ------------------------------------------------------------------
;时钟设置 ,如果没有定义NO_CLOCK_SETUP并且CLOCK_SETUP != 0则执行下面程序             
                IF      (:LNOT:(:DEF:NO_CLOCK_SETUP)):LAND:(CLOCK_SETUP != 0)
                LDR     R0, =CLOCK_BASE       	;将时钟基地址加载到R0
                LDR     R1,      =LOCKTIME_Val	;加载PLL锁定时间计数器的值
                STR     R1, [R0, #LOCKTIME_OFS]	;将该值配置到PLL锁定时间计数器
                MOV     R1,      #CLKDIVN_Val  	;将时钟分频计数器的值加载到R1
                STR     R1, [R0, #CLKDIVN_OFS]	;将该值配置到时钟分频寄存器
                LDR     R1,      =CAMDIVN_Val	;将摄像头分频值加载到R1
                STR     R1, [R0, #CAMDIVN_OFS]	;配置摄像头分频控制寄存器
                LDR     R1,      =MPLLCON_Val	;将主锁相环控制寄存器的值加载到R1
                STR     R1, [R0, #MPLLCON_OFS]	;配置MPLL寄存器
                LDR     R1,      =UPLLCON_Val	;将USB锁相环控制寄存器的值加载到R1
                STR     R1, [R0, #UPLLCON_OFS]	;配置UPLL寄存器
                MOV     R1,      #CLKSLOW_Val	;将时钟减慢控制寄存器的值加载到R1
                STR     R1, [R0, #CLKSLOW_OFS]	;配置时钟减慢寄存器
                LDR     R1,      =CLKCON_Val	;将时钟控制寄存器的值加载到R1
                STR     R1, [R0, #CLKCON_OFS]	;配置时钟控制寄存器
                ENDIF;结束IF

; Memory Controller Setup ------------------------------------------------------
;存储控制设置,如果没有定义NO_MC_SETUP并且CLOCK_SETUP != 0,则执行下面程序
                IF      (:LNOT:(:DEF:NO_MC_SETUP)):LAND:(CLOCK_SETUP != 0)
                LDR     R0, =MC_BASE			;将存储控制寄存器基地址加载到R0
                LDR     R1,      =BWSCON_Val	;将总线宽度和等待控制寄存器的值加载到R1
                STR     R1, [R0, #BWSCON_OFS]	;配置总线宽度和等待寄存器
                LDR     R1,      =BANKCON0_Val	;将BANK0控制寄存器的值加载到R1
                STR     R1, [R0, #BANKCON0_OFS]	;配置BANK0寄存器
                LDR     R1,      =BANKCON1_Val	;将BANK1控制寄存器的值加载到R1
                STR     R1, [R0, #BANKCON1_OFS]	;配置BANK1寄存器
                LDR     R1,      =BANKCON2_Val	;将BANK2控制寄存器的值加载到R1
                STR     R1, [R0, #BANKCON2_OFS]	;配置BANK2寄存器
                LDR     R1,      =BANKCON3_Val	;将BANK3控制寄存器的值加载到R1
                STR     R1, [R0, #BANKCON3_OFS]	;配置BANK3寄存器
                LDR     R1,      =BANKCON4_Val	;将BANK4控制寄存器的值加载到R1
                STR     R1, [R0, #BANKCON4_OFS]	;配置BANK4寄存器
                LDR     R1,      =BANKCON5_Val	;将BANK5控制寄存器的值加载到R1
                STR     R1, [R0, #BANKCON5_OFS]	;配置BANK5寄存器
                LDR     R1,      =BANKCON6_Val	;将BANK6控制寄存器的值加载到R1
                STR     R1, [R0, #BANKCON6_OFS]	;配置BANK6寄存器
                LDR     R1,      =BANKCON7_Val	;将BANK7控制寄存器的值加载到R1
                STR     R1, [R0, #BANKCON7_OFS]	;配置BANK7寄存器
                LDR     R1,      =REFRESH_Val	;将DRAM/SDRAM控制寄存器的值加载到R1
                STR     R1, [R0, #REFRESH_OFS]	;配置DRAM/SDRAM刷新寄存器的值
                MOV     R1,      #BANKSIZE_Val	;将可调节BANK大小的值加载到R1
                STR     R1, [R0, #BANKSIZE_OFS]	;配置可调节BANK大小寄存器
                MOV     R1,      #MRSRB6_Val	;将BANK6模式控制寄存器的是加载到R1
                STR     R1, [R0, #MRSRB6_OFS]	;配置BANK6模式控制寄存器
                MOV     R1,      #MRSRB7_Val	;将BANK7模式控制寄存器的值加载到R1
                STR     R1, [R0, #MRSRB7_OFS]	;配置BANK7模式控寄存器
                ENDIF          	             	 ;结束IF
                      
; I/O Pins Setup ---------------------------------------------------------------
;I/O端口设置,如果没有定义NO_GP_SETUP并且GP_SETUP != 0,则执行以下程序              
                IF      (:LNOT:(:DEF:NO_GP_SETUP)):LAND:(GP_SETUP != 0)

                IF      GPA_SETUP != 0			;如果端口A设置不为0
                LDR     R0, =GPA_BASE			;将端口A的基地址加载到R0
                LDR     R1, =GPACON_Val			;将端口A的控制寄存器的值加载到R1
                STR     R1, [R0, #GPCON_OFS]	;配置端口A控制寄存器
                ENDIF							;结束IF

                IF      GPB_SETUP != 0			;如果端口B设置不为0
                LDR     R0, =GPB_BASE			;将端口B的基地址加载到R0
                LDR     R1, =GPBCON_Val			;将端口B的控制寄存器的值加载到R1
                STR     R1, [R0, #GPCON_OFS]	;配置端口B控制寄存器
                LDR     R1, =GPBUP_Val			;将端口B上拉控制寄存器的值加载到R1
                STR     R1, [R0, #GPUP_OFS]		;配置端口B上拉控制寄存器
                ENDIF							;结束IF

                IF      GPC_SETUP != 0			;如果端口C设置不为0
                LDR     R0, =GPC_BASE			;将端口C的基地址加载到R0
                LDR     R1, =GPCCON_Val			;将端口C的控制寄存器的值加载到R1
                STR     R1, [R0, #GPCON_OFS]	;配置端口C控制寄存器
                LDR     R1, =GPCUP_Val			;将端口C上拉控制寄存器的值加载到R1
                STR     R1, [R0, #GPUP_OFS]		;配置端口C上拉控制寄存器
                ENDIF							;结束IF

                IF      GPD_SETUP != 0			;如果端口D设置不为0
                LDR     R0, =GPD_BASE			;将端口D的基地址加载到R0
                LDR     R1, =GPDCON_Val			;将端口D的控制寄存器的值加载到R1
                STR     R1, [R0, #GPCON_OFS]	;配置端口D控制寄存器
                LDR     R1, =GPDUP_Val			;将端口D上拉控制寄存器的值加载到R1
                STR     R1, [R0, #GPUP_OFS]		;配置端口D上拉控制寄存器
                ENDIF							;结束IF

                IF      GPE_SETUP != 0			;如果端口E设置不为0
                LDR     R0, =GPE_BASE			;将端口E的基地址加载到R0
                LDR     R1, =GPECON_Val			;将端口E的控制寄存器的值加载到R1
                STR     R1, [R0, #GPCON_OFS]	;配置端口E控制寄存器
                LDR     R1, =GPEUP_Val			;将端口E上拉控制寄存器的值加载到R1
                STR     R1, [R0, #GPUP_OFS]		;配置端口E上拉控制寄存器
                ENDIF							;结束IF

                IF      GPF_SETUP != 0			;如果端口F设置不为0
                LDR     R0, =GPF_BASE			;将端口F的基地址加载到R0
                LDR     R1, =GPFCON_Val			;将端口F的控制寄存器的值加载到R1
                STR     R1, [R0, #GPCON_OFS]	;配置端口F控制寄存器
                LDR     R1, =GPFUP_Val			;将端口F上拉控制寄存器的值加载到R1
                STR     R1, [R0, #GPUP_OFS]		;配置端口F上拉控制寄存器
                ENDIF							;结束IF

                IF      GPG_SETUP != 0			;如果端口G设置不为0
                LDR     R0, =GPG_BASE			;将端口G的基地址加载到R0
                LDR     R1, =GPGCON_Val			;将端口G的控制寄存器的值加载到R1
                STR     R1, [R0, #GPCON_OFS]	;配置端口G控制寄存器
                LDR     R1, =GPGUP_Val			;将端口G上拉控制寄存器的值加载到R1
                STR     R1, [R0, #GPUP_OFS]		;配置端口G上拉控制寄存器上拉控制寄存器
                ENDIF							;结束IF
  
                IF      GPH_SETUP != 0			;如果端口H设置不为0
                LDR     R0, =GPH_BASE			;将端口H的基地址加载到R0
                LDR     R1, =GPHCON_Val			;将端口H的控制寄存器的值加载到R1
                STR     R1, [R0, #GPCON_OFS]	;配置端口H控制寄存器
                LDR     R1, =GPHUP_Val			;将端口H上拉控制寄存器的值加载到R1
                STR     R1, [R0, #GPUP_OFS]		;配置端口H上拉控制寄存器
                ENDIF							;结束IF

                IF      GPJ_SETUP != 0			;如果端口J设置不为0
                LDR     R0, =GPJ_BASE			;将端口J的基地址加载到R0
                LDR     R1, =GPJCON_Val			;将端口J的控制寄存器的值加载到R1
                STR     R1, [R0, #GPCON_OFS]	;配置端口J控制寄存器
                LDR     R1, =GPJUP_Val			;将端口J上拉控制寄存器的值加载到R1
                STR     R1, [R0, #GPUP_OFS]		;配置端口J上拉控制寄存器
                ENDIF							;结束IF
               
                ENDIF							;结束IF
                

; Copy Exception Vectors to Internal RAM ---------------------------------------
;拷贝异畅向量到内部RAM
                IF      :DEF:RAM_INTVEC			;如果定义RAM_INTVEC,则执行下面程序
                ADR     R8,  Vectors    		;读取向量原地址
                LDR     R9, =IRAM_BASE  		;读取偏上SRAM的基地址
                LDMIA   R8!, {R0-R7}    		;批量加载异常向量
                STMIA   R9!, {R0-R7}    		;批量存储异常向量
                LDMIA   R8!, {R0-R7}    		;加载程序入口地址
                STMIA   R9!, {R0-R7}    		;存储程序入口地址
                ENDIF
             
; Setup Stack for each mode ----------------------------------------------------
;配置每种模式栈的大小
                LDR     R0, =Stack_Top						;加载栈顶指针

;  Enter Undefined Instruction Mode and set its Stack Pointer
;进入未定义模式并设定栈指针
                MSR     CPSR_c, #Mode_UND:OR:I_Bit:OR:F_Bit	;将(Mode_UND | I_Bit | F_Bit)赋值给 CPSR_c即CPSR[7:0]
                MOV     SP, R0; 							 ;栈顶指针地址赋值给SP指针
                SUB     R0, R0, #UND_Stack_Size				 ;分其栈指针

;  Enter Abort Mode and set its Stack Pointer
;进入预取终止模式并设定栈指针
                MSR     CPSR_c, #Mode_ABT:OR:I_Bit:OR:F_Bit	;将(Mode_UND | I_Bit | F_Bit)赋值给 CPSR_c即CPSR[7:0]
                MOV     SP, R0								;栈顶指针地址赋值给SP指针
                SUB     R0, R0, #ABT_Stack_Size 			;分其栈指针

;  Enter FIQ Mode and set its Stack Pointer
;进入快速中断式并设定栈指针
                MSR     CPSR_c, #Mode_FIQ:OR:I_Bit:OR:F_Bit	;将(Mode_UND | I_Bit | F_Bit)赋值给 CPSR_c即CPSR[7:0]
                MOV     SP, R0								;栈顶指针地址赋值给SP指针
                SUB     R0, R0, #FIQ_Stack_Size 			;分其栈指针

;  Enter IRQ Mode and set its Stack Pointer
;进入外部中断模式并设定栈指针
                MSR     CPSR_c, #Mode_IRQ:OR:I_Bit:OR:F_Bit	;将(Mode_UND | I_Bit | F_Bit)赋值给 CPSR_c即CPSR[7:0]
                MOV     SP, R0								;栈顶指针地址赋值给SP指针
                SUB     R0, R0, #IRQ_Stack_Size 			;分其栈指针

;  Enter Supervisor Mode and set its Stack Pointer
;进入管理模式并设定栈指针
                MSR     CPSR_c, #Mode_SVC:OR:I_Bit:OR:F_Bit	;将(Mode_UND | I_Bit | F_Bit)赋值给 CPSR_c即CPSR[7:0]
                MOV     SP, R0								;栈顶指针地址赋值给SP指针
                SUB     R0, R0, #SVC_Stack_Size 			;分其栈指针

;  Enter User Mode and set its Stack Pointer
;进入正常模式并设定栈指针
                MSR     CPSR_c, #Mode_USR					;将Mode_USR赋值给 CPSR_c即CPSR[7:0]
                MOV     SP, R0								;栈顶指针地址赋值给SP指针
                SUB     SL, SP, #USR_Stack_Size 			;分其栈指针

;  Enter User Mode and set its Stack Pointer
;进入正常模式并设定栈指针
                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

; Enter the C code -------------------------------------------------------------
;进入C代码区
                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
; User Initial Stack & Heap
;用户初始化堆与栈,名称|.text|,代码区,只读
                AREA    |.text|, CODE, READONLY

                IMPORT  __use_two_region_memory				;__use_two_region_memory这是MDK的库函
                EXPORT  __user_initial_stackheap			;__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										;结束IF

                END

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值