Cortex M0+ Keil MDK启动文件详解

 

;/*****************************************************************************
; * @file:    startup_MKL02Z4.s
; * @purpose: CMSIS Cortex-M0plus Core Device Startup File for the
; *           MKL02Z4
; * @version: 1.0
; * @date:    2012-10-4
; *
; * Copyright: 1997 - 2013 Freescale Semiconductor, Inc. All Rights Reserved.
;*
; *------- <<< Use Configuration Wizard in Context Menu >>> ------------------
; *
; *****************************************************************************/


;  Stack Configuration
;    Stack Size (in Bytes) <0x0-0xFFFFFFFF:8>
; 

Stack_Size      EQU     0x00000100
                ;EQU定义符号指示Stack大小
    
                AREA    STACK, NOINIT, READWRITE, ALIGN=3   
                ;AREA 通知汇编器汇编一段新的代码或数据节(section)
                ;STACK 为AREA所定义的新的节的节名称(sectionname)
                ;NOINIT 指示这段数据节不初始化或初始化为0,以SPACE等指示的空间初始化为0,但不能初始化为其它
                ;       备注:即这段不能指定初始化值,如果不加NOINIT的话,MAP文件SPACE的数据类型为Data,为RW Data
                ;             如果加NOINIT的话,MAP文件SPACE的数据类型为Zero,为ZI Data
                ;READWRITE 指示该节类型为RW
                ;ALIGN=3 指示该节对齐到8字节boundary,即为双字地址
                ;        备注:在MAP文件中,可以发现是通过添加PAD类型的数据进行节的对齐
                ;              PAD取何值可以指定
                                                            

Stack_Mem       SPACE   Stack_Size
                ;Stack_Mem 为一个标签(label),标签值为在当前节中的地址
                ;SPACE 指示(directive)一块内存(memory),这块内存所在节的特性由上面的AREA指定
__initial_sp
                ;__initial_sp 为上面SPACE块的顶端地址+1,即说明堆栈的初始值为顶端地址,堆栈是向下生长的满栈
                ;             备注:因为CM的入栈操作是,*(--R13)=R0类似的一种方式,R13指向最后的数据


;  Heap Configuration
;     Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>
; 

Heap_Size       EQU     0x00000100
                ;定义符号指示Heap大小

                AREA    HEAP, NOINIT, READWRITE, ALIGN=3
                ;定义一个新的节,节名称为HEAP,其它与STACK相同
                ;EXPORT __heap_base
__heap_base
                ;定义一个标签,指示HEAP的基地址,这个标签只用在使用MICROLIB时被EXPORT,即只有这时有效
                ;使用MICROLIB时,这个标签被EXPORT,类似于C语言中的extern,但只有当HEAP被使用的时候
                ;                才出现在MAP文件中,如在main()中可以这样来访问__heap_base
                ;                void main(void)
                ;                {
                ;                   extern int __heap_base;
                ;                   static int HEAPBASE;    //定义静态变量,在内存中有固定的存储空间
                ;                   ......
                ;                   HEAPBASE = __heap_base; //读取HEAP的即地址,只在MICROLIB时有效
                ;                   ......
                ;                 }
                ;如果要在不使用MICROLIB时,读取__heap_base, 那只需要在__heap_base前添加EXPORT __heap_base                   
Heap_Mem        SPACE   Heap_Size
                ;EXPORT Heap_Mem
                ;定义HEAP的内存段,标签为Heap_Mem,将Heap_Mem EXPORT之后,可以这样访问:
                ;       extern int Heap_Mem;
                ;       static int* pHEAPMEM;
                ;       pHEAPMEM = (int*)Heap_Mem;
__heap_limit
                ;定义一个标签,HEAP的地址范围为__heap_base ~ (__heap_limit - 1)
                
;这里结合MAP文件外插上几句
;1. 当:STACK 所在节属性为 AREA    STACK, NOINIT, READWRITE, ALIGN=3
;       HEAP  所在节属性为 AREA    HEAP,  NOINIT, READWRITE, ALIGN=3
;   时,MAP文件的执行时期RAM镜像为
;   Execution Region RW_IRAM2 (Base: 0x20000000, Size: 0x00000268, Max: 0x00000c00, ABSOLUTE)
;
;   Base Addr    Size         Type   Attr      Idx    E Section Name        Object
;
;   0x20000000   0x00000004   Data   RW            4    .data               system_mkl02z4.o
;   0x20000004   0x00000004   Data   RW           61    .data               blinky.o
;   0x20000008   0x00000060   Zero   RW          139    .bss                c_p.l(libspace.o)
;   0x20000068   0x00000100   Zero   RW           48    HEAP                startup_mkl02z4.o
;   0x20000168   0x00000100   Zero   RW           47    STACK               startup_mkl02z4.o
;
;   可见,在程序运行时,数据在内存中存放的顺序为有初始化的Data类型,和0初始化的Zero类型
;   此时,HEAP向上增长,STACK向下生长,二者的方向是相向的
;   全局变量,如果没有指定初始值,如static int gTestData; 是存放在.dada节,而不是.bss
;
;2. 当:STACK 所在节属性为 AREA    STACK,         READWRITE, ALIGN=3
;       HEAP  所在节属性为 AREA    HEAP,  NOINIT, READWRITE, ALIGN=3
;   时,MAP文件的执行时期RAM镜像为
;   Execution Region RW_IRAM2 (Base: 0x20000000, Size: 0x00000268, Max: 0x00000c00, ABSOLUTE)
;
;   Base Addr    Size         Type   Attr      Idx    E Section Name        Object
;
;   0x20000000   0x00000004   Data   RW            4    .data               system_mkl02z4.o
;   0x20000004   0x00000004   Data   RW           61    .data               blinky.o
;   0x20000008   0x00000100   Data   RW           47    STACK               startup_mkl02z4.o
;   0x20000108   0x00000060   Zero   RW          139    .bss                c_p.l(libspace.o)
;   0x20000168   0x00000100   Zero   RW           48    HEAP                startup_mkl02z4.o
;
;   此时HEAP向上增长,STACK向下生长,二者的方向是相背的
;   同时可以看出,不用NOINIT修饰时,STACK的数据类型为Data,是一种RW Type,否则是一种ZI Type
;
;部分细节看参见Linker User Guide: Type 2 image, one load region and non-contiguous execution regions
    
                PRESERVE8
                ;通知链接器(linker)当前文件是以堆栈8字节对齐,使用PRESERVE8的话,说明我们现在的文件堆栈是以8字节对齐的
                ;这样的话,这里的函数可以调用由REQUIRE8指示的文件的函数,而不引起错误,如LDRD and STRD指令,因为
                ;LDRD and STRD instructions (double-word transfers) only work correctly if the address they access 
                ;is 8-byte aligned.
                THUMB
                ;通知编译器采用THUMB指令集


; Vector Table Mapped to Address 0 at Reset

                AREA    RESET, DATA, READONLY
                ;指示当前节为RESET,节的属性为DATA(Contains data, not instructions),RO
                EXPORT  __Vectors
                EXPORT  __Vectors_End
                EXPORT  __Vectors_Size
                ;全局变量__Vectors,__Vectors_End,和__Vectors_Size
;分散加载文件SCT为
;   LR_IROM1 0x00000000 0x00008000  {       ; load region size_region
;       ER_IROM1 0x00000000 0x00008000  {   ; load address = execution address
;           *.o (RESET, +First)             ; +First指示执行时RESET节置于最开始
;           *(InRoot$Sections)             ; InRoot$Sections指代所有必须放在根区域的节
;                                           ; 如__main.o, __scatter*.o,
;                                           ;  __dc*.o, and * Region$Table
;           .ANY (+RO)                      ; Read only的数据执行时在这里
;       }
;       RW_IRAM1 0x1FFFFC00 0x00000400  {   ; RW data
;           .ANY (+RW +ZI)
;       }
;       RW_IRAM2 0x20000000 0x00000C00  {
;           .ANY (+RW +ZI)
;       }
;   }
;我们可以这样更改分散加载文件为
;   LR_IROM1 0x00000000 0x00008000  {    ; load region size_region
;       ER_IROM1 0x00000000 0x00008000  {  ; load address = execution address
;           *.o (RESET, +First)
;           *(InRoot$Sections)
;           .ANY (+RO)
;       }
;       RW_IRAM1 0x1FFFFC00 0x00000400  {  ; RW data
;           .ANY (+ZI)
;       }
;       RW_IRAM2 0x20000000 0x00000C00  {
;           .ANY (+RW)
;           *.o (.bss)
;       }
;   }
;这样,执行时候的内存镜像变成这样子了,我们利用起来了两块RAM区的特点
;    Execution Region RW_IRAM1 (Base: 0x1ffffc00, Size: 0x00000200, Max: 0x00000400, ABSOLUTE)
;
;    Base Addr    Size         Type   Attr      Idx    E Section Name        Object
;
;    0x1ffffc00   0x00000100   Zero   RW           48    HEAP                startup_mkl02z4.o
;    0x1ffffd00   0x00000100   Zero   RW           47    STACK               startup_mkl02z4.o
;
;
;    Execution Region RW_IRAM2 (Base: 0x20000000, Size: 0x00000068, Max: 0x00000c00, ABSOLUTE)
;
;    Base Addr    Size         Type   Attr      Idx    E Section Name        Object
;
;    0x20000000   0x00000004   Data   RW            4    .data               system_mkl02z4.o
;    0x20000004   0x00000004   Data   RW           61    .data               blinky.o
;    0x20000008   0x00000060   Zero   RW          139    .bss                c_p.l(libspace.o)

__Vectors       DCD     __initial_sp        ; Top of Stack
                                            ; DCD 申请4字节的空间,存放数据
                                            ; 由于分散加载文件SCT中的*.o (RESET, +First)属性
                                            ; RESET节被放在了LR_IROM1的开始位置,即__initial_sp存放在0地址
                DCD     Reset_Handler       ; Reset Handler
                DCD     NMI_Handler         ; NMI Handler
                DCD     HardFault_Handler   ; Hard Fault Handler
                DCD     0  ; Reserved
                DCD     0  ; Reserved
                DCD     0  ; Reserved
                DCD     0  ; Reserved
                DCD     0  ; Reserved
                DCD     0  ; Reserved
                DCD     0  ; Reserved
                DCD     SVC_Handler         ; SVCall Handler
                DCD     0  ; Reserved
                DCD     0  ; Reserved
                DCD     PendSV_Handler      ; PendSV Handler
                DCD     SysTick_Handler     ; SysTick Handler

                ; External Interrupts
                DCD     Reserved16_IRQHandler  ; Reserved interrupt 16
                DCD     Reserved17_IRQHandler  ; Reserved interrupt 17
                DCD     Reserved18_IRQHandler  ; Reserved interrupt 18
                DCD     Reserved19_IRQHandler  ; Reserved interrupt 19
                DCD     Reserved20_IRQHandler  ; Reserved interrupt 20
                DCD     FTFA_IRQHandler     ; FTFA command complete/read collision interrupt
                DCD     LVD_LVW_IRQHandler  ; Low Voltage Detect, Low Voltage Warning
                DCD     Reserved23_IRQHandler  ; Reserved interrupt 23
                DCD     I2C0_IRQHandler  ; I2C0 interrupt
                DCD     I2C1_IRQHandler  ; I2C1 interrupt
                DCD     SPI0_IRQHandler  ; SPI0 interrupt
                DCD     Reserved27_IRQHandler  ; Reserved interrupt 27
                DCD     UART0_IRQHandler  ; UART0 status/error interrupt
                DCD     Reserved29_IRQHandler  ; Reserved interrupt 29
                DCD     Reserved30_IRQHandler  ; Reserved interrupt 30
                DCD     ADC0_IRQHandler  ; ADC0 interrupt
                DCD     CMP0_IRQHandler  ; CMP0 interrupt
                DCD     TPM0_IRQHandler  ; TPM0 fault, overflow and channels interrupt
                DCD     TPM1_IRQHandler  ; TPM1 fault, overflow and channels interrupt
                DCD     Reserved35_IRQHandler  ; Reserved interrupt 35
                DCD     Reserved36_IRQHandler  ; Reserved interrupt 36
                DCD     Reserved37_IRQHandler  ; Reserved interrupt 37
                DCD     Reserved38_IRQHandler  ; Reserved interrupt 38
                DCD     Reserved39_IRQHandler  ; Reserved interrupt 39
                DCD     Reserved40_IRQHandler  ; Reserved interrupt 40
                DCD     Reserved41_IRQHandler  ; Reserved interrupt 41
                DCD     Reserved42_IRQHandler  ; Reserved interrupt 42
                DCD     MCG_IRQHandler  ; MCG interrupt
                DCD     LPTimer_IRQHandler  ; LPTimer interrupt
                DCD     Reserved45_IRQHandler  ; Reserved interrupt 45
                DCD     PORTA_IRQHandler  ; Port A interrupt
                DCD     PORTB_IRQHandler  ; Port B interrupt
__Vectors_End
                ;这里__Vectors_End的值为0x000000c0 (在MAP文件里查看)

__Vectors_Size         EQU     __Vectors_End - __Vectors   ;计算中断向量表的大小

; 以下为Freescale特有的配置方式(我的理解,在ST中不是采用的这种配置方法)
; Flash配置区域在Flash的0x0000_0400开始的空间,一共16字节
; 关于Flash配置区域在帖子 http://www.amobbs.com/thread-5588189-1-1.html 中有描述
; 以下定义的变量值,在下面有采用,这边略过Flash配置字的含义,详见Reference Mannual
;
;
;  Flash Configuration
;    16-byte flash configuration field that stores default protection settings (loaded on reset)
;    and security information that allows the MCU to restrict acces to the FTFL module.
;    Backdoor Comparison Key
;       Backdoor Key 0  <0x0-0xFF:2>
;       Backdoor Key 1  <0x0-0xFF:2>
;       Backdoor Key 2  <0x0-0xFF:2>
;       Backdoor Key 3  <0x0-0xFF:2>
;       Backdoor Key 4  <0x0-0xFF:2>
;       Backdoor Key 5  <0x0-0xFF:2>
;       Backdoor Key 6  <0x0-0xFF:2>
;       Backdoor Key 7  <0x0-0xFF:2>
BackDoorK0      EQU     0xFF
BackDoorK1      EQU     0xFF
BackDoorK2      EQU     0xFF
BackDoorK3      EQU     0xFF
BackDoorK4      EQU     0xFF
BackDoorK5      EQU     0xFF
BackDoorK6      EQU     0xFF
BackDoorK7      EQU     0xFF
;   
;    Program flash protection bytes (FPROT)
;      Each program flash region can be protected from program and erase operation by setting the associated PROT bit.
;      Each bit protects a 1/32 region of the program flash memory.
;      FPROT0
;        Program flash protection bytes
;        1/32 - 8/32 region
;          FPROT0.0
;          FPROT0.1
;          FPROT0.2
;          FPROT0.3
;          FPROT0.4
;          FPROT0.5
;          FPROT0.6
;          FPROT0.7
nFPROT0         EQU     0x00
FPROT0          EQU     nFPROT0:EOR:0xFF
;     
;      FPROT1
;        Program Flash Region Protect Register 1
;        9/32 - 16/32 region
;          FPROT1.0
;          FPROT1.1
;          FPROT1.2
;          FPROT1.3
;          FPROT1.4
;          FPROT1.5
;          FPROT1.6
;          FPROT1.7
nFPROT1         EQU     0x00
FPROT1          EQU     nFPROT1:EOR:0xFF
;     
;      FPROT2
;        Program Flash Region Protect Register 2
;        17/32 - 24/32 region
;          FPROT2.0
;          FPROT2.1
;          FPROT2.2
;          FPROT2.3
;          FPROT2.4
;          FPROT2.5
;          FPROT2.6
;          FPROT2.7
nFPROT2         EQU     0x00
FPROT2          EQU     nFPROT2:EOR:0xFF
;     
;      FPROT3
;        Program Flash Region Protect Register 3
;        25/32 - 32/32 region
;          FPROT3.0
;          FPROT3.1
;          FPROT3.2
;          FPROT3.3
;          FPROT3.4
;          FPROT3.5
;          FPROT3.6
;          FPROT3.7
nFPROT3         EQU     0x00
FPROT3          EQU     nFPROT3:EOR:0xFF
;     
;   
;   
;    Flash nonvolatile option byte (FOPT)
;      Allows the user to customize the operation of the MCU at boot time.
;       LPBOOT0
;       <0=> Core and system clock divider (OUTDIV1) is 0x7 (divide by 8) or 0x3 (divide by 4)
;       <1=> Core and system clock divider (OUTDIV1) is 0x1 (divide by 2) or 0x0 (divide by 1)
;       LPBOOT1
;       <0=> Core and system clock divider (OUTDIV1) is 0x7 (divide by 8) or 0x1 (divide by 2)
;       <1=> Core and system clock divider (OUTDIV1) is 0x3 (divide by 4) or 0x0 (divide by 1)
;       NMI_DIS
;       <0=> NMI interrupts are always blocked
;       <1=> NMI pin/interrupts reset default to enabled
;       RESET_PIN_CFG
;       <0=> RESET pin is disabled following a POR and cannot be enabled as RESET function
;       <1=> RESET pin is dedicated
;       FAST_INIT
;       <0=> Slower initialization
;       <1=> Fast Initialization
FOPT            EQU     0xFF
;   
;    Flash security byte (FSEC)
;      WARNING: If SEC field is configured as "MCU security status is secure" and MEEN field is configured as "Mass erase is disabled",
;      MCU's security status cannot be set back to unsecure state since Mass erase via the debugger is blocked !!!
;      SEC
;       <2=> MCU security status is unsecure
;       <3=> MCU security status is secure
;          Flash Security
;          This bits define the security state of the MCU.
;      FSLACC
;       <2=> Freescale factory access denied
;       <3=> Freescale factory access granted
;          Freescale Failure Analysis Access Code
;          This bits define the security state of the MCU.
;      MEEN
;       <2=> Mass erase is disabled
;       <3=> Mass erase is enabled
;          Mass Erase Enable Bits
;          Enables and disables mass erase capability of the FTFL module
;      KEYEN
;       <2=> Backdoor key access enabled
;       <3=> Backdoor key access disabled
;          Backdoor key Security Enable
;          These bits enable and disable backdoor key access to the FTFL module.
FSEC            EQU     0xFE
;   
;
; 在这里,定义了一个新的节,名称是.ARM,位于地址0x400,在MAP文件里是这样的
;   ......
;   0x000003cc   0x00000030   Data   RO          263    Region$Table       anon$obj.o
;   0x000003fc   0x00000004   PAD
;   0x00000400   0x00000010   Code   RO           50    .ARM.__at_0x400     startup_mkl02z4.o
;   0x00000410   0x00000174   Code   RO           59    .text               blinky.o
;   0x00000584   0x0000015a   Code   RO           93    .text               c_p.l(aeabi_sdiv.o)
;   ......
; 可见PAD补充字节空间,.ARM.__at_0x400放在了0x0400地址,而这些地址存放的数据,是CODE,RO类型
; 下面的DCB填充了这16个字节
                IF      :LNOT::DEF:RAM_TARGET
                    ; :DEF:A 语句,如果A定义,返回真,否则返回假
                    ; :LNOT:A 语句,是对A的逻辑取反
                    ; 结合上面的 IF,所以以下代码尽在RAM_TARGET没定义的时候会产生
                    ; 如果在RAM中调试的话,应该定义RAM_TARGET,那样的话也就不需要FLASH配置字了
                    ;
                AREA    |.ARM.__at_0x400|, CODE, READONLY
                    ; 定义一个节,存放配置数据,单片机复位后,FLASH控制器加载这些配置
                    ;
                DCB     BackDoorK0, BackDoorK1, BackDoorK2, BackDoorK3
                DCB     BackDoorK4, BackDoorK5, BackDoorK6, BackDoorK7
                DCB     FPROT0,     FPROT1,     FPROT2,     FPROT3
                DCB     FSEC,       FOPT,       0xFF,     0xFF
                ENDIF

; 下面是程序端的开始
                AREA    |.text|, CODE, READONLY
                    ; AREA定义.text节存放代码,因为.text不是有效的变量名,所以加||限定


; Reset Handler

Reset_Handler   PROC
                    ; 同FUNCTION,标记一个函数的开始
                EXPORT  Reset_Handler             [WEAK]
                    ; 弱引用,通知链接器,其它文件中的同名函数的优先级高于这个函数,即只有当其它文件中无
                    ; Reset_Handler函数时,Reset_Handler()才指向这里
                IMPORT  SystemInit
                    ; 告诉链接器到其它文件中查找SystemInit函数
                IMPORT  __main
                    ; 告诉链接器到其它文件中查找__main函数
                LDR     R0, =SystemInit
                    ; 执行SystemInit();
                BLX     R0
                LDR     R0, =__main
                    ; 执行__main(); __main()调用main(),因而正常情况下不返回
                BX      R0
                ENDP
                    ; 标记函数的结束


; Dummy Exception Handlers (infinite loops which can be modified)
; 异常函数,弱引用,需要在其它文件中自定义相同名称的函数,以进行异常的处理
;
NMI_Handler     PROC
                EXPORT  NMI_Handler               [WEAK]
                B       .   ; B . 表示跳转到当前地址
                ENDP
HardFault_Handler\
                PROC
                EXPORT  HardFault_Handler         [WEAK]
                B       .
                ENDP
SVC_Handler     PROC
                EXPORT  SVC_Handler               [WEAK]
                B       .
                ENDP
PendSV_Handler  PROC
                EXPORT  PendSV_Handler            [WEAK]
                B       .
                ENDP
SysTick_Handler PROC
                EXPORT  SysTick_Handler           [WEAK]
                B       .
                ENDP

Default_Handler PROC
                EXPORT  Reserved16_IRQHandler     [WEAK]
                EXPORT  Reserved17_IRQHandler     [WEAK]
                EXPORT  Reserved18_IRQHandler     [WEAK]
                EXPORT  Reserved19_IRQHandler     [WEAK]
                EXPORT  Reserved20_IRQHandler     [WEAK]
                EXPORT  FTFA_IRQHandler     [WEAK]
                EXPORT  LVD_LVW_IRQHandler     [WEAK]
                EXPORT  Reserved23_IRQHandler     [WEAK]
                EXPORT  I2C0_IRQHandler     [WEAK]
                EXPORT  I2C1_IRQHandler     [WEAK]
                EXPORT  SPI0_IRQHandler     [WEAK]
                EXPORT  Reserved27_IRQHandler     [WEAK]
                EXPORT  UART0_IRQHandler     [WEAK]
                EXPORT  Reserved29_IRQHandler     [WEAK]
                EXPORT  Reserved30_IRQHandler     [WEAK]
                EXPORT  ADC0_IRQHandler     [WEAK]
                EXPORT  CMP0_IRQHandler     [WEAK]
                EXPORT  TPM0_IRQHandler     [WEAK]
                EXPORT  TPM1_IRQHandler     [WEAK]
                EXPORT  Reserved35_IRQHandler     [WEAK]
                EXPORT  Reserved36_IRQHandler     [WEAK]
                EXPORT  Reserved37_IRQHandler     [WEAK]
                EXPORT  Reserved38_IRQHandler     [WEAK]
                EXPORT  Reserved39_IRQHandler     [WEAK]
                EXPORT  Reserved40_IRQHandler     [WEAK]
                EXPORT  Reserved41_IRQHandler     [WEAK]
                EXPORT  Reserved42_IRQHandler     [WEAK]
                EXPORT  MCG_IRQHandler     [WEAK]
                EXPORT  LPTimer_IRQHandler     [WEAK]
                EXPORT  Reserved45_IRQHandler     [WEAK]
                EXPORT  PORTA_IRQHandler     [WEAK]
                EXPORT  PORTB_IRQHandler     [WEAK]
                EXPORT  DefaultISR                      [WEAK]

Reserved16_IRQHandler
Reserved17_IRQHandler
Reserved18_IRQHandler
Reserved19_IRQHandler
Reserved20_IRQHandler
FTFA_IRQHandler
LVD_LVW_IRQHandler
Reserved23_IRQHandler
I2C0_IRQHandler
I2C1_IRQHandler
SPI0_IRQHandler
Reserved27_IRQHandler
UART0_IRQHandler
Reserved29_IRQHandler
Reserved30_IRQHandler
ADC0_IRQHandler
CMP0_IRQHandler
TPM0_IRQHandler
TPM1_IRQHandler
Reserved35_IRQHandler
Reserved36_IRQHandler
Reserved37_IRQHandler
Reserved38_IRQHandler
Reserved39_IRQHandler
Reserved40_IRQHandler
Reserved41_IRQHandler
Reserved42_IRQHandler
MCG_IRQHandler
LPTimer_IRQHandler
Reserved45_IRQHandler
PORTA_IRQHandler
PORTB_IRQHandler
DefaultISR
    ;上面这些函数的地址都是一样的,即标号的值都相同,但都是弱引用
                B       .

                ENDP


                ALIGN
                    ; ALIGN不指定参数时,将当前地址对起到4字节,填0或NOP,或其它给定值


; User Initial Stack & Heap

                IF      :DEF:__MICROLIB
                    ; 如果定义使用MICROLIB,则将下面的标号声明为全局变量,供MICROLIB使用
                    ;
                EXPORT  __initial_sp
                EXPORT  __heap_base
                EXPORT  __heap_limit

                ELSE

                IMPORT  __use_two_region_memory
                    ; 指定存储器模式为双区模式
                    ; 单区模型:(r0, r1)是单个堆栈和堆区,r1大于r0,忽略r2和r3
                    ;           堆和栈共用一块内存区域
                    ; 双区模型:(r0, r2)是初始堆,(r3, r1)是初始栈
                    ;           堆和栈分别指定了单独的内存区域
                    ;
                EXPORT  __user_initial_stackheap
                    ; 声明一个全局标号 __user_initial_stackheap作为函数使用
__user_initial_stackheap
                    ; C标准库调用__user_initial_stackheap()函数,获得堆栈信息
                    ; 这里没有使用PROC标记
                    ;
                LDR     R0, =  Heap_Mem
                LDR     R1, =(Stack_Mem + Stack_Size)
                LDR     R2, = (Heap_Mem +  Heap_Size)
                LDR     R3, = Stack_Mem
                BX      LR

                ALIGN

                ENDIF


                END

;/*****************************************************************************
; * @file:    startup_MKL02Z4.s
; * @purpose: CMSIS Cortex-M0plus Core Device Startup File for the
; *           MKL02Z4
; * @version: 1.0
; * @date:    2012-10-4
; *
; * Copyright: 1997 - 2013 Freescale Semiconductor, Inc. All Rights Reserved.
;*
; *------- <<< Use Configuration Wizard in Context Menu >>> ------------------
; *
; *****************************************************************************/


; Stack Configuration
;   Stack Size (in Bytes) <0x0-0xFFFFFFFF:8>
;

Stack_Size      EQU     0x00000100
                ;EQU定义符号指示Stack大小
    
                AREA    STACK, NOINIT, READWRITE, ALIGN=3   
                ;AREA 通知汇编器汇编一段新的代码或数据节(section)
                ;STACK 为AREA所定义的新的节的节名称(sectionname)
                ;NOINIT 指示这段数据节不初始化或初始化为0,以SPACE等指示的空间初始化为0,但不能初始化为其它
                ;       备注:即这段不能指定初始化值,如果不加NOINIT的话,MAP文件SPACE的数据类型为Data,为RW Data
                ;             如果加NOINIT的话,MAP文件SPACE的数据类型为Zero,为ZI Data
                ;READWRITE 指示该节类型为RW
                ;ALIGN=3 指示该节对齐到8字节boundary,即为双字地址
                ;        备注:在MAP文件中,可以发现是通过添加PAD类型的数据进行节的对齐
                ;              PAD取何值可以指定
                                                            

Stack_Mem       SPACE   Stack_Size
                ;Stack_Mem 为一个标签(label),标签值为在当前节中的地址
                ;SPACE 指示(directive)一块内存(memory),这块内存所在节的特性由上面的AREA指定
__initial_sp
                ;__initial_sp 为上面SPACE块的顶端地址+1,即说明堆栈的初始值为顶端地址,堆栈是向下生长的满栈
                ;             备注:因为CM的入栈操作是,*(--R13)=R0类似的一种方式,R13指向最后的数据


; Heap Configuration
;    Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>
;

Heap_Size       EQU     0x00000100
                ;定义符号指示Heap大小

                AREA    HEAP, NOINIT, READWRITE, ALIGN=3
                ;定义一个新的节,节名称为HEAP,其它与STACK相同
                ;EXPORT __heap_base
__heap_base
                ;定义一个标签,指示HEAP的基地址,这个标签只用在使用MICROLIB时被EXPORT,即只有这时有效
                ;使用MICROLIB时,这个标签被EXPORT,类似于C语言中的extern,但只有当HEAP被使用的时候
                ;                才出现在MAP文件中,如在main()中可以这样来访问__heap_base
                ;                void main(void)
                ;                {
                ;                   extern int __heap_base;
                ;                   static int HEAPBASE;    //定义静态变量,在内存中有固定的存储空间
                ;                   ......
                ;                   HEAPBASE = __heap_base; //读取HEAP的即地址,只在MICROLIB时有效
                ;                   ......
                ;                 }
                ;如果要在不使用MICROLIB时,读取__heap_base, 那只需要在__heap_base前添加EXPORT __heap_base                   
Heap_Mem        SPACE   Heap_Size
                ;EXPORT Heap_Mem
                ;定义HEAP的内存段,标签为Heap_Mem,将Heap_Mem EXPORT之后,可以这样访问:
                ;       extern int Heap_Mem;
                ;       static int* pHEAPMEM;
                ;       pHEAPMEM = (int*)Heap_Mem;
__heap_limit
                ;定义一个标签,HEAP的地址范围为__heap_base ~ (__heap_limit - 1)
                
;这里结合MAP文件外插上几句
;1. 当:STACK 所在节属性为 AREA    STACK, NOINIT, READWRITE, ALIGN=3
;       HEAP  所在节属性为 AREA    HEAP,  NOINIT, READWRITE, ALIGN=3
;   时,MAP文件的执行时期RAM镜像为
;   Execution Region RW_IRAM2 (Base: 0x20000000, Size: 0x00000268, Max: 0x00000c00, ABSOLUTE)
;
;   Base Addr    Size         Type   Attr      Idx    E Section Name        Object
;
;   0x20000000   0x00000004   Data   RW            4    .data               system_mkl02z4.o
;   0x20000004   0x00000004   Data   RW           61    .data               blinky.o
;   0x20000008   0x00000060   Zero   RW          139    .bss                c_p.l(libspace.o)
;   0x20000068   0x00000100   Zero   RW           48    HEAP                startup_mkl02z4.o
;   0x20000168   0x00000100   Zero   RW           47    STACK               startup_mkl02z4.o
;
;   可见,在程序运行时,数据在内存中存放的顺序为有初始化的Data类型,和0初始化的Zero类型
;   此时,HEAP向上增长,STACK向下生长,二者的方向是相向的
;   全局变量,如果没有指定初始值,如static int gTestData; 是存放在.dada节,而不是.bss
;
;2. 当:STACK 所在节属性为 AREA    STACK,         READWRITE, ALIGN=3
;       HEAP  所在节属性为 AREA    HEAP,  NOINIT, READWRITE, ALIGN=3
;   时,MAP文件的执行时期RAM镜像为
;   Execution Region RW_IRAM2 (Base: 0x20000000, Size: 0x00000268, Max: 0x00000c00, ABSOLUTE)
;
;   Base Addr    Size         Type   Attr      Idx    E Section Name        Object
;
;   0x20000000   0x00000004   Data   RW            4    .data               system_mkl02z4.o
;   0x20000004   0x00000004   Data   RW           61    .data               blinky.o
;   0x20000008   0x00000100   Data   RW           47    STACK               startup_mkl02z4.o
;   0x20000108   0x00000060   Zero   RW          139    .bss                c_p.l(libspace.o)
;   0x20000168   0x00000100   Zero   RW           48    HEAP                startup_mkl02z4.o
;
;   此时HEAP向上增长,STACK向下生长,二者的方向是相背的
;   同时可以看出,不用NOINIT修饰时,STACK的数据类型为Data,是一种RW Type,否则是一种ZI Type
;
;部分细节看参见Linker User Guide: Type 2 image, one load region and non-contiguous execution regions
    
                PRESERVE8
                ;通知链接器(linker)当前文件是以堆栈8字节对齐,使用PRESERVE8的话,说明我们现在的文件堆栈是以8字节对齐的
                ;这样的话,这里的函数可以调用由REQUIRE8指示的文件的函数,而不引起错误,如LDRD and STRD指令,因为
                ;LDRD and STRD instructions (double-word transfers) only work correctly if the address they access 
                ;is 8-byte aligned.
                THUMB
                ;通知编译器采用THUMB指令集


; Vector Table Mapped to Address 0 at Reset

                AREA    RESET, DATA, READONLY
                ;指示当前节为RESET,节的属性为DATA(Contains data, not instructions),RO
                EXPORT  __Vectors
                EXPORT  __Vectors_End
                EXPORT  __Vectors_Size
                ;全局变量__Vectors,__Vectors_End,和__Vectors_Size
;分散加载文件SCT为
;   LR_IROM1 0x00000000 0x00008000  {       ; load region size_region
;       ER_IROM1 0x00000000 0x00008000  {   ; load address = execution address
;           *.o (RESET, +First)             ; +First指示执行时RESET节置于最开始
;           *(InRoot$Sections)             ; InRoot$Sections指代所有必须放在根区域的节
;                                           ; 如__main.o, __scatter*.o,
;                                           ;  __dc*.o, and * Region$Table
;           .ANY (+RO)                      ; Read only的数据执行时在这里
;       }
;       RW_IRAM1 0x1FFFFC00 0x00000400  {   ; RW data
;           .ANY (+RW +ZI)
;       }
;       RW_IRAM2 0x20000000 0x00000C00  {
;           .ANY (+RW +ZI)
;       }
;   }
;我们可以这样更改分散加载文件为
;   LR_IROM1 0x00000000 0x00008000  {    ; load region size_region
;       ER_IROM1 0x00000000 0x00008000  {  ; load address = execution address
;           *.o (RESET, +First)
;           *(InRoot$Sections)
;           .ANY (+RO)
;       }
;       RW_IRAM1 0x1FFFFC00 0x00000400  {  ; RW data
;           .ANY (+ZI)
;       }
;       RW_IRAM2 0x20000000 0x00000C00  {
;           .ANY (+RW)
;           *.o (.bss)
;       }
;   }
;这样,执行时候的内存镜像变成这样子了,我们利用起来了两块RAM区的特点
;    Execution Region RW_IRAM1 (Base: 0x1ffffc00, Size: 0x00000200, Max: 0x00000400, ABSOLUTE)
;
;    Base Addr    Size         Type   Attr      Idx    E Section Name        Object
;
;    0x1ffffc00   0x00000100   Zero   RW           48    HEAP                startup_mkl02z4.o
;    0x1ffffd00   0x00000100   Zero   RW           47    STACK               startup_mkl02z4.o
;
;
;    Execution Region RW_IRAM2 (Base: 0x20000000, Size: 0x00000068, Max: 0x00000c00, ABSOLUTE)
;
;    Base Addr    Size         Type   Attr      Idx    E Section Name        Object
;
;    0x20000000   0x00000004   Data   RW            4    .data               system_mkl02z4.o
;    0x20000004   0x00000004   Data   RW           61    .data               blinky.o
;    0x20000008   0x00000060   Zero   RW          139    .bss                c_p.l(libspace.o)

__Vectors       DCD     __initial_sp        ; Top of Stack
                                            ; DCD 申请4字节的空间,存放数据
                                            ; 由于分散加载文件SCT中的*.o (RESET, +First)属性
                                            ; RESET节被放在了LR_IROM1的开始位置,即__initial_sp存放在0地址
                DCD     Reset_Handler       ; Reset Handler
                DCD     NMI_Handler         ; NMI Handler
                DCD     HardFault_Handler   ; Hard Fault Handler
                DCD     0  ; Reserved
                DCD     0  ; Reserved
                DCD     0  ; Reserved
                DCD     0  ; Reserved
                DCD     0  ; Reserved
                DCD     0  ; Reserved
                DCD     0  ; Reserved
                DCD     SVC_Handler         ; SVCall Handler
                DCD     0  ; Reserved
                DCD     0  ; Reserved
                DCD     PendSV_Handler      ; PendSV Handler
                DCD     SysTick_Handler     ; SysTick Handler

                ; External Interrupts
                DCD     Reserved16_IRQHandler  ; Reserved interrupt 16
                DCD     Reserved17_IRQHandler  ; Reserved interrupt 17
                DCD     Reserved18_IRQHandler  ; Reserved interrupt 18
                DCD     Reserved19_IRQHandler  ; Reserved interrupt 19
                DCD     Reserved20_IRQHandler  ; Reserved interrupt 20
                DCD     FTFA_IRQHandler     ; FTFA command complete/read collision interrupt
                DCD     LVD_LVW_IRQHandler  ; Low Voltage Detect, Low Voltage Warning
                DCD     Reserved23_IRQHandler  ; Reserved interrupt 23
                DCD     I2C0_IRQHandler  ; I2C0 interrupt
                DCD     I2C1_IRQHandler  ; I2C1 interrupt
                DCD     SPI0_IRQHandler  ; SPI0 interrupt
                DCD     Reserved27_IRQHandler  ; Reserved interrupt 27
                DCD     UART0_IRQHandler  ; UART0 status/error interrupt
                DCD     Reserved29_IRQHandler  ; Reserved interrupt 29
                DCD     Reserved30_IRQHandler  ; Reserved interrupt 30
                DCD     ADC0_IRQHandler  ; ADC0 interrupt
                DCD     CMP0_IRQHandler  ; CMP0 interrupt
                DCD     TPM0_IRQHandler  ; TPM0 fault, overflow and channels interrupt
                DCD     TPM1_IRQHandler  ; TPM1 fault, overflow and channels interrupt
                DCD     Reserved35_IRQHandler  ; Reserved interrupt 35
                DCD     Reserved36_IRQHandler  ; Reserved interrupt 36
                DCD     Reserved37_IRQHandler  ; Reserved interrupt 37
                DCD     Reserved38_IRQHandler  ; Reserved interrupt 38
                DCD     Reserved39_IRQHandler  ; Reserved interrupt 39
                DCD     Reserved40_IRQHandler  ; Reserved interrupt 40
                DCD     Reserved41_IRQHandler  ; Reserved interrupt 41
                DCD     Reserved42_IRQHandler  ; Reserved interrupt 42
                DCD     MCG_IRQHandler  ; MCG interrupt
                DCD     LPTimer_IRQHandler  ; LPTimer interrupt
                DCD     Reserved45_IRQHandler  ; Reserved interrupt 45
                DCD     PORTA_IRQHandler  ; Port A interrupt
                DCD     PORTB_IRQHandler  ; Port B interrupt
__Vectors_End
                ;这里__Vectors_End的值为0x000000c0 (在MAP文件里查看)

__Vectors_Size         EQU     __Vectors_End - __Vectors   ;计算中断向量表的大小

; 以下为Freescale特有的配置方式(我的理解,在ST中不是采用的这种配置方法)
; Flash配置区域在Flash的0x0000_0400开始的空间,一共16字节
; 关于Flash配置区域在帖子 http://www.amobbs.com/thread-5588189-1-1.html 中有描述
; 以下定义的变量值,在下面有采用,这边略过Flash配置字的含义,详见Reference Mannual
;
;
; Flash Configuration
;   16-byte flash configuration field that stores default protection settings (loaded on reset)
;   and security information that allows the MCU to restrict acces to the FTFL module.
;   Backdoor Comparison Key
;      Backdoor Key 0  <0x0-0xFF:2>
;      Backdoor Key 1  <0x0-0xFF:2>
;      Backdoor Key 2  <0x0-0xFF:2>
;      Backdoor Key 3  <0x0-0xFF:2>
;      Backdoor Key 4  <0x0-0xFF:2>
;      Backdoor Key 5  <0x0-0xFF:2>
;      Backdoor Key 6  <0x0-0xFF:2>
;      Backdoor Key 7  <0x0-0xFF:2>
BackDoorK0      EQU     0xFF
BackDoorK1      EQU     0xFF
BackDoorK2      EQU     0xFF
BackDoorK3      EQU     0xFF
BackDoorK4      EQU     0xFF
BackDoorK5      EQU     0xFF
BackDoorK6      EQU     0xFF
BackDoorK7      EQU     0xFF
;  

;   Program flash protection bytes (FPROT)
;     Each program flash region can be protected from program and erase operation by setting the associated PROT bit.
;     Each bit protects a 1/32 region of the program flash memory.
;     FPROT0
;       Program flash protection bytes
;       1/32 - 8/32 region
;         FPROT0.0
;         FPROT0.1
;         FPROT0.2
;         FPROT0.3
;         FPROT0.4
;         FPROT0.5
;         FPROT0.6
;         FPROT0.7
nFPROT0         EQU     0x00
FPROT0          EQU     nFPROT0:EOR:0xFF
;    

;     FPROT1
;       Program Flash Region Protect Register 1
;       9/32 - 16/32 region
;         FPROT1.0
;         FPROT1.1
;         FPROT1.2
;         FPROT1.3
;         FPROT1.4
;         FPROT1.5
;         FPROT1.6
;         FPROT1.7
nFPROT1         EQU     0x00
FPROT1          EQU     nFPROT1:EOR:0xFF
;    

;     FPROT2
;       Program Flash Region Protect Register 2
;       17/32 - 24/32 region
;         FPROT2.0
;         FPROT2.1
;         FPROT2.2
;         FPROT2.3
;         FPROT2.4
;         FPROT2.5
;         FPROT2.6
;         FPROT2.7
nFPROT2         EQU     0x00
FPROT2          EQU     nFPROT2:EOR:0xFF
;    

;     FPROT3
;       Program Flash Region Protect Register 3
;       25/32 - 32/32 region
;         FPROT3.0
;         FPROT3.1
;         FPROT3.2
;         FPROT3.3
;         FPROT3.4
;         FPROT3.5
;         FPROT3.6
;         FPROT3.7
nFPROT3         EQU     0x00
FPROT3          EQU     nFPROT3:EOR:0xFF
;    

;  

;  

;   Flash nonvolatile option byte (FOPT)
;     Allows the user to customize the operation of the MCU at boot time.
;      LPBOOT0
;       <0=> Core and system clock divider (OUTDIV1) is 0x7 (divide by 8) or 0x3 (divide by 4)
;       <1=> Core and system clock divider (OUTDIV1) is 0x1 (divide by 2) or 0x0 (divide by 1)
;      LPBOOT1
;       <0=> Core and system clock divider (OUTDIV1) is 0x7 (divide by 8) or 0x1 (divide by 2)
;       <1=> Core and system clock divider (OUTDIV1) is 0x3 (divide by 4) or 0x0 (divide by 1)
;      NMI_DIS
;       <0=> NMI interrupts are always blocked
;       <1=> NMI pin/interrupts reset default to enabled
;      RESET_PIN_CFG
;       <0=> RESET pin is disabled following a POR and cannot be enabled as RESET function
;       <1=> RESET pin is dedicated
;      FAST_INIT
;       <0=> Slower initialization
;       <1=> Fast Initialization
FOPT            EQU     0xFF
;  

;   Flash security byte (FSEC)
;     WARNING: If SEC field is configured as "MCU security status is secure" and MEEN field is configured as "Mass erase is disabled",
;     MCU's security status cannot be set back to unsecure state since Mass erase via the debugger is blocked !!!
;     SEC
;       <2=> MCU security status is unsecure
;       <3=> MCU security status is secure
;         Flash Security
;         This bits define the security state of the MCU.
;     FSLACC
;       <2=> Freescale factory access denied
;       <3=> Freescale factory access granted
;         Freescale Failure Analysis Access Code
;         This bits define the security state of the MCU.
;     MEEN
;       <2=> Mass erase is disabled
;       <3=> Mass erase is enabled
;         Mass Erase Enable Bits
;         Enables and disables mass erase capability of the FTFL module
;     KEYEN
;       <2=> Backdoor key access enabled
;       <3=> Backdoor key access disabled
;         Backdoor key Security Enable
;         These bits enable and disable backdoor key access to the FTFL module.
FSEC            EQU     0xFE
;  

;
; 在这里,定义了一个新的节,名称是.ARM,位于地址0x400,在MAP文件里是这样的
;   ......
;   0x000003cc   0x00000030   Data   RO          263    Region$Table       anon$obj.o
;   0x000003fc   0x00000004   PAD
;   0x00000400   0x00000010   Code   RO           50    .ARM.__at_0x400     startup_mkl02z4.o
;   0x00000410   0x00000174   Code   RO           59    .text               blinky.o
;   0x00000584   0x0000015a   Code   RO           93    .text               c_p.l(aeabi_sdiv.o)
;   ......
; 可见PAD补充字节空间,.ARM.__at_0x400放在了0x0400地址,而这些地址存放的数据,是CODE,RO类型
; 下面的DCB填充了这16个字节
                IF      :LNOT::DEF:RAM_TARGET
                    ; :DEF:A 语句,如果A定义,返回真,否则返回假
                    ; :LNOT:A 语句,是对A的逻辑取反
                    ; 结合上面的 IF,所以以下代码尽在RAM_TARGET没定义的时候会产生
                    ; 如果在RAM中调试的话,应该定义RAM_TARGET,那样的话也就不需要FLASH配置字了
                    ;
                AREA    |.ARM.__at_0x400|, CODE, READONLY
                    ; 定义一个节,存放配置数据,单片机复位后,FLASH控制器加载这些配置
                    ;
                DCB     BackDoorK0, BackDoorK1, BackDoorK2, BackDoorK3
                DCB     BackDoorK4, BackDoorK5, BackDoorK6, BackDoorK7
                DCB     FPROT0,     FPROT1,     FPROT2,     FPROT3
                DCB     FSEC,       FOPT,       0xFF,     0xFF
                ENDIF

; 下面是程序端的开始
                AREA    |.text|, CODE, READONLY
                    ; AREA定义.text节存放代码,因为.text不是有效的变量名,所以加||限定


; Reset Handler

Reset_Handler   PROC
                    ; 同FUNCTION,标记一个函数的开始
                EXPORT  Reset_Handler             [WEAK]
                    ; 弱引用,通知链接器,其它文件中的同名函数的优先级高于这个函数,即只有当其它文件中无
                    ; Reset_Handler函数时,Reset_Handler()才指向这里
                IMPORT  SystemInit
                    ; 告诉链接器到其它文件中查找SystemInit函数
                IMPORT  __main
                    ; 告诉链接器到其它文件中查找__main函数
                LDR     R0, =SystemInit
                    ; 执行SystemInit();
                BLX     R0
                LDR     R0, =__main
                    ; 执行__main(); __main()调用main(),因而正常情况下不返回
                BX      R0
                ENDP
                    ; 标记函数的结束


; Dummy Exception Handlers (infinite loops which can be modified)
; 异常函数,弱引用,需要在其它文件中自定义相同名称的函数,以进行异常的处理
;
NMI_Handler     PROC
                EXPORT  NMI_Handler               [WEAK]
                B       .   ; B . 表示跳转到当前地址
                ENDP
HardFault_Handler\
                PROC
                EXPORT  HardFault_Handler         [WEAK]
                B       .
                ENDP
SVC_Handler     PROC
                EXPORT  SVC_Handler               [WEAK]
                B       .
                ENDP
PendSV_Handler  PROC
                EXPORT  PendSV_Handler            [WEAK]
                B       .
                ENDP
SysTick_Handler PROC
                EXPORT  SysTick_Handler           [WEAK]
                B       .
                ENDP

Default_Handler PROC
                EXPORT  Reserved16_IRQHandler     [WEAK]
                EXPORT  Reserved17_IRQHandler     [WEAK]
                EXPORT  Reserved18_IRQHandler     [WEAK]
                EXPORT  Reserved19_IRQHandler     [WEAK]
                EXPORT  Reserved20_IRQHandler     [WEAK]
                EXPORT  FTFA_IRQHandler     [WEAK]
                EXPORT  LVD_LVW_IRQHandler     [WEAK]
                EXPORT  Reserved23_IRQHandler     [WEAK]
                EXPORT  I2C0_IRQHandler     [WEAK]
                EXPORT  I2C1_IRQHandler     [WEAK]
                EXPORT  SPI0_IRQHandler     [WEAK]
                EXPORT  Reserved27_IRQHandler     [WEAK]
                EXPORT  UART0_IRQHandler     [WEAK]
                EXPORT  Reserved29_IRQHandler     [WEAK]
                EXPORT  Reserved30_IRQHandler     [WEAK]
                EXPORT  ADC0_IRQHandler     [WEAK]
                EXPORT  CMP0_IRQHandler     [WEAK]
                EXPORT  TPM0_IRQHandler     [WEAK]
                EXPORT  TPM1_IRQHandler     [WEAK]
                EXPORT  Reserved35_IRQHandler     [WEAK]
                EXPORT  Reserved36_IRQHandler     [WEAK]
                EXPORT  Reserved37_IRQHandler     [WEAK]
                EXPORT  Reserved38_IRQHandler     [WEAK]
                EXPORT  Reserved39_IRQHandler     [WEAK]
                EXPORT  Reserved40_IRQHandler     [WEAK]
                EXPORT  Reserved41_IRQHandler     [WEAK]
                EXPORT  Reserved42_IRQHandler     [WEAK]
                EXPORT  MCG_IRQHandler     [WEAK]
                EXPORT  LPTimer_IRQHandler     [WEAK]
                EXPORT  Reserved45_IRQHandler     [WEAK]
                EXPORT  PORTA_IRQHandler     [WEAK]
                EXPORT  PORTB_IRQHandler     [WEAK]
                EXPORT  DefaultISR                      [WEAK]

Reserved16_IRQHandler
Reserved17_IRQHandler
Reserved18_IRQHandler
Reserved19_IRQHandler
Reserved20_IRQHandler
FTFA_IRQHandler
LVD_LVW_IRQHandler
Reserved23_IRQHandler
I2C0_IRQHandler
I2C1_IRQHandler
SPI0_IRQHandler
Reserved27_IRQHandler
UART0_IRQHandler
Reserved29_IRQHandler
Reserved30_IRQHandler
ADC0_IRQHandler
CMP0_IRQHandler
TPM0_IRQHandler
TPM1_IRQHandler
Reserved35_IRQHandler
Reserved36_IRQHandler
Reserved37_IRQHandler
Reserved38_IRQHandler
Reserved39_IRQHandler
Reserved40_IRQHandler
Reserved41_IRQHandler
Reserved42_IRQHandler
MCG_IRQHandler
LPTimer_IRQHandler
Reserved45_IRQHandler
PORTA_IRQHandler
PORTB_IRQHandler
DefaultISR
    ;上面这些函数的地址都是一样的,即标号的值都相同,但都是弱引用
                B       .

                ENDP


                ALIGN
                    ; ALIGN不指定参数时,将当前地址对起到4字节,填0或NOP,或其它给定值


; User Initial Stack & Heap

                IF      :DEF:__MICROLIB
                    ; 如果定义使用MICROLIB,则将下面的标号声明为全局变量,供MICROLIB使用
                    ;
                EXPORT  __initial_sp
                EXPORT  __heap_base
                EXPORT  __heap_limit

                ELSE

                IMPORT  __use_two_region_memory
                    ; 指定存储器模式为双区模式
                    ; 单区模型:(r0, r1)是单个堆栈和堆区,r1大于r0,忽略r2和r3
                    ;           堆和栈共用一块内存区域
                    ; 双区模型:(r0, r2)是初始堆,(r3, r1)是初始栈
                    ;           堆和栈分别指定了单独的内存区域
                    ;
                EXPORT  __user_initial_stackheap
                    ; 声明一个全局标号 __user_initial_stackheap作为函数使用
__user_initial_stackheap
                    ; C标准库调用__user_initial_stackheap()函数,获得堆栈信息
                    ; 这里没有使用PROC标记
                    ;
                LDR     R0, =  Heap_Mem
                LDR     R1, =(Stack_Mem + Stack_Size)
                LDR     R2, = (Heap_Mem +  Heap_Size)
                LDR     R3, = Stack_Mem
                BX      LR

                ALIGN

                ENDIF


                END
 

你可能感兴趣的:(software)