; Amount of memory (in bytes) allocated for Stack
; Tailor this value to your application needs
; <h> Stack Configuration
; <o> Stack Size (in Bytes) <0x0-0xFFFFFFFF:8>
; </h>

Stack_Size EQU 0x00000400      ;EQU定义栈空间的大小,栈空间由编译器自动分配变量所占内存,该汇编语句等效于#define Stack_Size 0x00000400

;AREA 命令指示汇编器汇编一个新的代码段或数据段。
;段是独立的、指定的、不可见的代码或数据块,它们由链接器处理.
;段是独立的、命名的、不可分割的代码或数据序列。一个代码段是生成一个应用程序的最低要求

;默认情况下,ELF 段在四字节边界上对齐。expression 可以拥有 0 到 31 的任何整数。
;段在 2expression 字节边界上对齐

AREA STACK, NOINIT, READWRITE, ALIGN=3    ;AREA开辟栈段,段名为STACK,栈属性为NOINIT, READWRITE,8字节对齐

; 说明: Cortex-M4的指令地址要求是字边界对齐(4字节);但是代码段是8字节边界对齐的
Stack_Mem SPACE Stack_Size    ;SPACE分配连续的栈存储空间,大小为0x00000400(1K),把首地址赋给Stack_Mem
__initial_sp                               ;初始化堆栈指针,指向堆栈顶。

; 此处有个一个问题讨论,关于栈顶在RAM中所处位置问题,很多初学者一直以为是编译器特意放在HEAP段之后是有意为之,并且认为这样可以利用heap未分配空间来防止未知的栈溢出问题
; 这种理解是错误的,链接器并不会为栈的位置做特殊的处理,而且这样做也并不会利用heap段,在此文件的最后对堆栈的初始化代码中可以看出他们是两个互相独立的数据区。此处出现的现象是因为MDK按数据段的字母顺序链接数据段的地址的,所以此处造成了堆的地址在栈的前面的假象,不要窃以为是有某种特殊的约定。

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

Heap_Size EQU 0x00000200       ;EQU定义堆空间的大小,堆空间由人为手动分配变量所占内存,该汇编语句等效于#define Heap_Size 0x00000200

AREA HEAP, NOINIT, READWRITE, ALIGN=3      ;AREA开辟堆段,段名为HEAP,堆属性为NOINIT, READWRITE,8字节对齐
__heap_base                             ;堆起始地址 
Heap_Mem SPACE Heap_Size      ;SPACE分配连续的堆存储空间,大小为0x00000200(512Bytes)
__heap_limit                              ;堆终止地址,与__heap_base配合限制堆的大小

PRESERVE8              ;告诉编译器以8字节对齐,命令指定当前文件保持栈的八字节对齐
                 THUMB                     ;告诉编译器使用THUMB指令集,THUMB 必须位于使用新语法的任何Thumb代码之前

;定义复位段(中断向量表),并初始化
; Vector Table Mapped to Address 0 at Reset
                 AREA RESET, DATA, READONLY ;定义RESET段,数据段,只读
                 EXPORT __Vectors                    ;声明全局变量_Vectors,该标号可在其他文件中使用,表示中断向量表入口地址
                 EXPORT __Vectors_End             ;向量表终止地址
                 EXPORT __Vectors_Size            ;向量表空间大小

;DCD 命令分配一个或多个字的存储器,在四个字节的边界上对齐,并定义存储器的运行时初值。

__Vectors DCD __initial_sp ; Top of Stack ,栈顶指针,被放在向量表的开始,FLASH的0地址,复位后首先装载栈顶指针
                DCD Reset_Handler ; Reset Handler,复位异常,装载完栈顶后,第一个执行的,并且不返回。
                DCD NMI_Handler ; NMI Handler, 不可屏蔽中断
                DCD HardFault_Handler ; Hard Fault Handler,硬件错误中断
                DCD MemManage_Handler ; MPU Fault Handler,内存管理错误中断
                DCD BusFault_Handler ; Bus Fault Handler, 总线错误中断,一般发生在数据访问异常,比如fsmc访问不当
                DCD UsageFault_Handler ; Usage Fault Handler,用法错误中断,一般是预取值,或者位置指令,数据处理等错误
                DCD 0 ; Reserved
                DCD 0 ; Reserved
                DCD 0 ; Reserved
                DCD 0 ; Reserved
                DCD SVC_Handler ; SVCall Handler, 系统调用异常,主要是为了调用操作系统内核服务
                DCD DebugMon_Handler ; Debug Monitor Handler, 调试监视异常
                DCD 0 ; Reserved
                DCD PendSV_Handler ; PendSV Handler,挂起异常,此处可以用作RTOS的上下文切换异常,这是被推荐使用的,因为Cortex-M4会在异常发生时自动保存R0-R3,R12,R13(堆栈指针SP),R14(链接地址,也叫返回地址LR,在异常返回时使用),R15(程序计数器PC,为当前应用程序+4)和中断完成时自动回复,我们只需保存R4-R11,大大减少了中断响应和上下文切换的时间。
                DCD SysTick_Handler ; SysTick Handler,滴答定时器,为操作系统内核时钟

; External Interrupts,外部中断
                DCD WWDG_IRQHandler ; Window WatchDog
                DCD PVD_IRQHandler ; PVD through EXTI Line detection
                DCD TAMP_STAMP_IRQHandler ; Tamper and TimeStamps through the EXTI line
                DCD RTC_WKUP_IRQHandler ; RTC Wakeup through the EXTI line
                DCD FLASH_IRQHandler ; FLASH
                DCD RCC_IRQHandler ; RCC
                DCD EXTI0_IRQHandler ; EXTI Line0
                DCD EXTI1_IRQHandler ; EXTI Line1
                DCD EXTI2_IRQHandler ; EXTI Line2
                DCD EXTI3_IRQHandler ; EXTI Line3
                DCD EXTI4_IRQHandler ; EXTI Line4
                DCD DMA1_Stream0_IRQHandler ; DMA1 Stream 0
                DCD DMA1_Stream1_IRQHandler ; DMA1 Stream 1
                DCD DMA1_Stream2_IRQHandler ; DMA1 Stream 2
                DCD DMA1_Stream3_IRQHandler ; DMA1 Stream 3
                DCD DMA1_Stream4_IRQHandler ; DMA1 Stream 4
                DCD DMA1_Stream5_IRQHandler ; DMA1 Stream 5
                DCD DMA1_Stream6_IRQHandler ; DMA1 Stream 6
                DCD ADC_IRQHandler ; ADC1, ADC2 and ADC3s
                DCD CAN1_TX_IRQHandler ; CAN1 TX
                DCD CAN1_RX0_IRQHandler ; CAN1 RX0
                DCD CAN1_RX1_IRQHandler ; CAN1 RX1
                DCD CAN1_SCE_IRQHandler ; CAN1 SCE
                DCD EXTI9_5_IRQHandler ; External Line[9:5]s
                DCD TIM1_BRK_TIM9_IRQHandler ; TIM1 Break and TIM9
                DCD TIM1_UP_TIM10_IRQHandler ; TIM1 Update and TIM10
                DCD TIM1_TRG_COM_TIM11_IRQHandler ; TIM1 Trigger and Commutation and TIM11
                DCD TIM1_CC_IRQHandler ; TIM1 Capture Compare
                DCD TIM2_IRQHandler ; TIM2
                DCD TIM3_IRQHandler ; TIM3
                DCD TIM4_IRQHandler ; TIM4
                DCD I2C1_EV_IRQHandler ; I2C1 Event
                DCD I2C1_ER_IRQHandler ; I2C1 Error
                DCD I2C2_EV_IRQHandler ; I2C2 Event
                DCD I2C2_ER_IRQHandler ; I2C2 Error
                DCD SPI1_IRQHandler ; SPI1
                DCD SPI2_IRQHandler ; SPI2
                DCD USART1_IRQHandler ; USART1
                DCD USART2_IRQHandler ; USART2
                DCD USART3_IRQHandler ; USART3
                DCD EXTI15_10_IRQHandler ; External Line[15:10]s
                DCD RTC_Alarm_IRQHandler ; RTC Alarm (A and B) through EXTI Line
                DCD OTG_FS_WKUP_IRQHandler ; USB OTG FS Wakeup through EXTI line
       DCD TIM8_BRK_TIM12_IRQHandler ; TIM8 Break and TIM12
       DCD TIM8_UP_TIM13_IRQHandler ; TIM8 Update and TIM13
       DCD TIM8_TRG_COM_TIM14_IRQHandler ; TIM8 Trigger and Commutation and TIM14
       DCD TIM8_CC_IRQHandler ; TIM8 Capture Compare
       DCD DMA1_Stream7_IRQHandler ; DMA1 Stream7
       DCD FSMC_IRQHandler ; FSMC
         DCD SDIO_IRQHandler ; SDIO
       DCD TIM5_IRQHandler ; TIM5
       DCD SPI3_IRQHandler ; SPI3
       DCD UART4_IRQHandler ; UART4
       DCD UART5_IRQHandler ; UART5
       DCD TIM6_DAC_IRQHandler ; TIM6 and DAC1&2 underrun errors
       DCD TIM7_IRQHandler ; TIM7
       DCD DMA2_Stream0_IRQHandler ; DMA2 Stream 0
       DCD DMA2_Stream1_IRQHandler ; DMA2 Stream 1
       DCD DMA2_Stream2_IRQHandler ; DMA2 Stream 2
       DCD DMA2_Stream3_IRQHandler ; DMA2 Stream 3
       DCD DMA2_Stream4_IRQHandler ; DMA2 Stream 4
       DCD ETH_IRQHandler ; Ethernet
       DCD ETH_WKUP_IRQHandler ; Ethernet Wakeup through EXTI line
       DCD CAN2_TX_IRQHandler ; CAN2 TX
       DCD CAN2_RX0_IRQHandler ; CAN2 RX0
       DCD CAN2_RX1_IRQHandler ; CAN2 RX1
       DCD CAN2_SCE_IRQHandler ; CAN2 SCE
       DCD OTG_FS_IRQHandler ; USB OTG FS
         DCD DMA2_Stream5_IRQHandler ; DMA2 Stream 5
       DCD DMA2_Stream6_IRQHandler ; DMA2 Stream 6
       DCD DMA2_Stream7_IRQHandler ; DMA2 Stream 7
       DCD USART6_IRQHandler ; USART6
       DCD I2C3_EV_IRQHandler ; I2C3 event
       DCD I2C3_ER_IRQHandler ; I2C3 error
       DCD OTG_HS_EP1_OUT_IRQHandler ; USB OTG HS End Point 1 Out
       DCD OTG_HS_EP1_IN_IRQHandler ; USB OTG HS End Point 1 In
       DCD OTG_HS_WKUP_IRQHandler ; USB OTG HS Wakeup through EXTI
       DCD OTG_HS_IRQHandler ; USB OTG HS
       DCD DCMI_IRQHandler ; DCMI
       DCD CRYP_IRQHandler ; CRYP crypto
       DCD HASH_RNG_IRQHandler ; Hash and Rng
       DCD FPU_IRQHandler ; FPU

__Vectors_End  ;向量表结束标志

__Vectors_Size EQU __Vectors_End - __Vectors  ;计算向量表地址空间大小

AREA |.text|, CODE, READONLY  ;定义C编译器源代码的代码段,只读。|.text|  表示由 C 编译程序产生的代码段,或用于以某种方式与 C 库关联的代码段。

; Reset handler
Reset_Handler PROC
        EXPORT Reset_Handler [WEAK]      ;此处[WEAK]表示弱定义,优先执行其他文件的定义
    IMPORT SystemInit
    IMPORT __main

        LDR R0, =SystemInit     ; 装载寄存器指令
        BLX R0                         ; 带链接的跳转,切换指令集  
        LDR R0, =__main
        BX R0                          ; 切换指令集,main函数不返回
        ENDP

; Dummy Exception Handlers (infinite loops which can be modified)

NMI_Handler PROC
        EXPORT NMI_Handler [WEAK]
        B .     ;死循环
        ENDP
HardFault_Handler\
        PROC
        EXPORT HardFault_Handler [WEAK]
        B .
        ENDP
MemManage_Handler\
        PROC
        EXPORT MemManage_Handler [WEAK]
        B .
        ENDP
BusFault_Handler\
        PROC
        EXPORT BusFault_Handler [WEAK]
        B .
        ENDP
UsageFault_Handler\
        PROC
        EXPORT UsageFault_Handler [WEAK]
        B .
        ENDP
SVC_Handler PROC
        EXPORT SVC_Handler [WEAK]
        B .
        ENDP
DebugMon_Handler\
        PROC
        EXPORT DebugMon_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

         ; 输出异常向量表标号,方便外部实现异常的具体功能 , [WEAK] 是弱定义的意思,如果外部定义了,优先执行外部定义,否则执行下面的函数定义

        EXPORT WWDG_IRQHandler [WEAK]
        EXPORT PVD_IRQHandler [WEAK]
        EXPORT TAMP_STAMP_IRQHandler [WEAK]
        EXPORT RTC_WKUP_IRQHandler [WEAK]
        EXPORT FLASH_IRQHandler [WEAK]
        EXPORT RCC_IRQHandler [WEAK]
        EXPORT EXTI0_IRQHandler [WEAK]
        EXPORT EXTI1_IRQHandler [WEAK]
        EXPORT EXTI2_IRQHandler [WEAK]
        EXPORT EXTI3_IRQHandler [WEAK]
        EXPORT EXTI4_IRQHandler [WEAK]
        EXPORT DMA1_Stream0_IRQHandler [WEAK]
        EXPORT DMA1_Stream1_IRQHandler [WEAK]
        EXPORT DMA1_Stream2_IRQHandler [WEAK]
        EXPORT DMA1_Stream3_IRQHandler [WEAK]
        EXPORT DMA1_Stream4_IRQHandler [WEAK]
        EXPORT DMA1_Stream5_IRQHandler [WEAK]
        EXPORT DMA1_Stream6_IRQHandler [WEAK]
        EXPORT ADC_IRQHandler [WEAK]
        EXPORT CAN1_TX_IRQHandler [WEAK]
        EXPORT CAN1_RX0_IRQHandler [WEAK]
        EXPORT CAN1_RX1_IRQHandler [WEAK]
        EXPORT CAN1_SCE_IRQHandler [WEAK]
        EXPORT EXTI9_5_IRQHandler [WEAK]
        EXPORT TIM1_BRK_TIM9_IRQHandler [WEAK]
        EXPORT TIM1_UP_TIM10_IRQHandler [WEAK]
        EXPORT TIM1_TRG_COM_TIM11_IRQHandler [WEAK]
        EXPORT TIM1_CC_IRQHandler [WEAK]
        EXPORT TIM2_IRQHandler [WEAK]
        EXPORT TIM3_IRQHandler [WEAK]
        EXPORT TIM4_IRQHandler [WEAK]
        EXPORT I2C1_EV_IRQHandler [WEAK]
        EXPORT I2C1_ER_IRQHandler [WEAK]
        EXPORT I2C2_EV_IRQHandler [WEAK]
        EXPORT I2C2_ER_IRQHandler [WEAK]
        EXPORT SPI1_IRQHandler [WEAK]
        EXPORT SPI2_IRQHandler [WEAK]
        EXPORT USART1_IRQHandler [WEAK]
        EXPORT USART2_IRQHandler [WEAK]
        EXPORT USART3_IRQHandler [WEAK]
        EXPORT EXTI15_10_IRQHandler [WEAK]
        EXPORT RTC_Alarm_IRQHandler [WEAK]
        EXPORT OTG_FS_WKUP_IRQHandler [WEAK]
        EXPORT TIM8_BRK_TIM12_IRQHandler [WEAK]
        EXPORT TIM8_UP_TIM13_IRQHandler [WEAK]
        EXPORT TIM8_TRG_COM_TIM14_IRQHandler [WEAK]
        EXPORT TIM8_CC_IRQHandler [WEAK]
        EXPORT DMA1_Stream7_IRQHandler [WEAK]
        EXPORT FSMC_IRQHandler [WEAK]
        EXPORT SDIO_IRQHandler [WEAK]
        EXPORT TIM5_IRQHandler [WEAK]
        EXPORT SPI3_IRQHandler [WEAK]
        EXPORT UART4_IRQHandler [WEAK]
        EXPORT UART5_IRQHandler [WEAK]
        EXPORT TIM6_DAC_IRQHandler [WEAK]
        EXPORT TIM7_IRQHandler [WEAK]
        EXPORT DMA2_Stream0_IRQHandler [WEAK]
        EXPORT DMA2_Stream1_IRQHandler [WEAK]
        EXPORT DMA2_Stream2_IRQHandler [WEAK]
        EXPORT DMA2_Stream3_IRQHandler [WEAK]
        EXPORT DMA2_Stream4_IRQHandler [WEAK]
        EXPORT ETH_IRQHandler [WEAK]
        EXPORT ETH_WKUP_IRQHandler [WEAK]
        EXPORT CAN2_TX_IRQHandler [WEAK]
        EXPORT CAN2_RX0_IRQHandler [WEAK]
        EXPORT CAN2_RX1_IRQHandler [WEAK]
        EXPORT CAN2_SCE_IRQHandler [WEAK]
        EXPORT OTG_FS_IRQHandler [WEAK]
        EXPORT DMA2_Stream5_IRQHandler [WEAK]
        EXPORT DMA2_Stream6_IRQHandler [WEAK]
        EXPORT DMA2_Stream7_IRQHandler [WEAK]
        EXPORT USART6_IRQHandler [WEAK]
        EXPORT I2C3_EV_IRQHandler [WEAK]
        EXPORT I2C3_ER_IRQHandler [WEAK]
        EXPORT OTG_HS_EP1_OUT_IRQHandler [WEAK]
        EXPORT OTG_HS_EP1_IN_IRQHandler [WEAK]
        EXPORT OTG_HS_WKUP_IRQHandler [WEAK]
        EXPORT OTG_HS_IRQHandler [WEAK]
        EXPORT DCMI_IRQHandler [WEAK]
        EXPORT CRYP_IRQHandler [WEAK]
        EXPORT HASH_RNG_IRQHandler [WEAK]
        EXPORT FPU_IRQHandler [WEAK]

; 如下只是定义一个空函数

WWDG_IRQHandler
PVD_IRQHandler
TAMP_STAMP_IRQHandler
RTC_WKUP_IRQHandler
FLASH_IRQHandler
RCC_IRQHandler
EXTI0_IRQHandler
EXTI1_IRQHandler
EXTI2_IRQHandler
EXTI3_IRQHandler
EXTI4_IRQHandler
DMA1_Stream0_IRQHandler
DMA1_Stream1_IRQHandler
DMA1_Stream2_IRQHandler
DMA1_Stream3_IRQHandler
DMA1_Stream4_IRQHandler
DMA1_Stream5_IRQHandler
DMA1_Stream6_IRQHandler
ADC_IRQHandler
CAN1_TX_IRQHandler
CAN1_RX0_IRQHandler
CAN1_RX1_IRQHandler
CAN1_SCE_IRQHandler
EXTI9_5_IRQHandler
TIM1_BRK_TIM9_IRQHandler
TIM1_UP_TIM10_IRQHandler
TIM1_TRG_COM_TIM11_IRQHandler
TIM1_CC_IRQHandler
TIM2_IRQHandler
TIM3_IRQHandler
TIM4_IRQHandler
I2C1_EV_IRQHandler
I2C1_ER_IRQHandler
I2C2_EV_IRQHandler
I2C2_ER_IRQHandler
SPI1_IRQHandler
SPI2_IRQHandler
USART1_IRQHandler
USART2_IRQHandler
USART3_IRQHandler
EXTI15_10_IRQHandler
RTC_Alarm_IRQHandler
OTG_FS_WKUP_IRQHandler
TIM8_BRK_TIM12_IRQHandler
TIM8_UP_TIM13_IRQHandler
TIM8_TRG_COM_TIM14_IRQHandler
TIM8_CC_IRQHandler
DMA1_Stream7_IRQHandler
FSMC_IRQHandler
SDIO_IRQHandler
TIM5_IRQHandler
SPI3_IRQHandler
UART4_IRQHandler
UART5_IRQHandler
TIM6_DAC_IRQHandler
TIM7_IRQHandler
DMA2_Stream0_IRQHandler
DMA2_Stream1_IRQHandler
DMA2_Stream2_IRQHandler
DMA2_Stream3_IRQHandler
DMA2_Stream4_IRQHandler
ETH_IRQHandler
ETH_WKUP_IRQHandler
CAN2_TX_IRQHandler
CAN2_RX0_IRQHandler
CAN2_RX1_IRQHandler
CAN2_SCE_IRQHandler
OTG_FS_IRQHandler
DMA2_Stream5_IRQHandler
DMA2_Stream6_IRQHandler
DMA2_Stream7_IRQHandler
USART6_IRQHandler
I2C3_EV_IRQHandler
I2C3_ER_IRQHandler
OTG_HS_EP1_OUT_IRQHandler
OTG_HS_EP1_IN_IRQHandler
OTG_HS_WKUP_IRQHandler
OTG_HS_IRQHandler
DCMI_IRQHandler
CRYP_IRQHandler
HASH_RNG_IRQHandler
FPU_IRQHandler

        B .

        ENDP

        ALIGN    ; 默认是字对齐方式,也说明了代码是4字节对齐的

;*******************************************************************************
; User Stack and Heap initialization
;*******************************************************************************
        IF :DEF:__MICROLIB    ;如果勾选了microlib

        EXPORT __initial_sp
        EXPORT __heap_base
        EXPORT __heap_limit

        ELSE

        IMPORT __use_two_region_memory  ; 两区堆栈空间,堆和栈有各自的空间地址
        EXPORT __user_initial_stackheap

__user_initial_stackheap

; 此处是初始化两区的堆栈空间,堆是从由低到高的增长,栈是由高向低生长的,两个是互相独立的数据段,并不能交叉使用。

        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    ; END 命令指示汇编器,已到达一个源文件的末尾。

;************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE*****

04-26 17:31