;/*****************************************************************************/
;/* STM32F10x.s: Startup file for ST STM32F10x device series */
;/*****************************************************************************/
;/* <<< Use Configuration Wizard in Context Menu >>> */
;/*****************************************************************************/
;/* This file is part of the uVision/ARM development tools. */
;/* Copyright (c) 2005-2007 Keil Software. All rights reserved. */
;/* This software may only be used under the terms of a valid, current, */
;/* end user licence from KEIL for a compatible version of KEIL software */
;/* development tools. Nothing else gives you the right to use this software. */
;/*****************************************************************************/
;// <h> Stack Configuration
;// <o> Stack Size (in Bytes) <0x0-0xFFFFFFFF:8>
;// </h>
//堆和栈的初始化
Stack_Size EQU 0x00000200 //栈大小
AREA STACK, NOINIT, READWRITE, ALIGN=3
//AREA定义一个新的段 开辟一个堆栈段,段名为STACK,定义为可读可写(READWRITE),将内存单元初始化为0(NOINIT),对齐方式(ALIGN)为8(2^3)字节对齐 联系到STM32的内部存储介质,可知具有只读属性的段保存于FLASH区,即0x8000000地址后
Stack_Mem SPACE Stack_Size
//开辟一段大小为Stack_Size的内存空间作为栈,并初始化为0
__initial_sp
//汇编代码地址标号,表示栈空间顶地址
;// <h> Heap Configuration
;// <o> Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>
;// </h>
Heap_Size EQU 0x00000000
//堆大小
AREA HEAP, NOINIT, READWRITE, ALIGN=3
__heap_base
//标号__heap_base,表示堆空间基地址
Heap_Mem SPACE Heap_Size
__heap_limit
//标号__heap_limit,表示堆空间结束地址
PRESERVE8
//指定当前堆栈8位对齐
THUMB
//告诉汇编器下面使用32位的THUMB指令,需要保证对齐
; Vector Table Mapped to Address 0 at Reset
//中断向量表
AREA RESET, DATA, READONLY
//定义复位向量段,只读,实际上是在CODE区,地址为0(假设STM32从FLASH启动,则此中断向量表起始地址即 //为0x8000000) “可读写”段保存于SRAM区,即0x2000000地址后
EXPORT __Vectors
//将标号__Vectors声明为全局标号,这样外部文件就可以使用这个标号
//标号__Vectors,表示中断向量表入口地址(STM32使用32位总线,因此存储空间为4字节对齐)
__Vectors DCD __initial_sp ; Top of Stack
//栈顶地址分配4字节32位的地址 0x0 //建立中断向量表 DCD:分配一片连续的字存储单元并初始化
DCD Reset_Handler ; Reset Handler
//复位中断入口地址 0x00000004
DCD NMI_Handler ; NMI Handler
// 0x00000008
DCD HardFault_Handler ; Hard Fault Handler
//标号主要用于表示一片内存空间的某个位置,等价于C语言中的“地址”概念
DCD MemManage_Handler ; MPU Fault Handler
DCD BusFault_Handler ; Bus Fault Handler
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
DCD SysTick_Handler ; SysTick Handler
; External Interrupts
DCD WWDG_IRQHandler ; Window Watchdog
DCD PVD_IRQHandler ; PVD through EXTI Line detect
DCD TAMPER_IRQHandler ; Tamper
DCD RTC_IRQHandler ; RTC
DCD FLASH_IRQHandler ; Flash
DCD RCC_IRQHandler ; RCC
DCD EXTI0_IRQHandler ; EXTI Line 0
DCD EXTI1_IRQHandler ; EXTI Line 1
DCD EXTI2_IRQHandler ; EXTI Line 2
DCD EXTI3_IRQHandler ; EXTI Line 3
DCD EXTI4_IRQHandler ; EXTI Line 4
DCD DMAChannel1_IRQHandler ; DMA Channel 1
DCD DMAChannel2_IRQHandler ; DMA Channel 2
DCD DMAChannel3_IRQHandler ; DMA Channel 3
DCD DMAChannel4_IRQHandler ; DMA Channel 4
DCD DMAChannel5_IRQHandler ; DMA Channel 5
DCD DMAChannel6_IRQHandler ; DMA Channel 6
DCD DMAChannel7_IRQHandler ; DMA Channel 7
DCD ADC_IRQHandler ; ADC
DCD USB_HP_CAN_TX_IRQHandler ; USB High Priority or CAN TX
DCD USB_LP_CAN_RX0_IRQHandler ; USB Low Priority or CAN RX0
DCD CAN_RX1_IRQHandler ; CAN RX1
DCD CAN_SCE_IRQHandler ; CAN SCE
DCD EXTI9_5_IRQHandler ; EXTI Line 9..5
DCD TIM1_BRK_IRQHandler ; TIM1 Break
DCD TIM1_UP_IRQHandler ; TIM1 Update
DCD TIM1_TRG_COM_IRQHandler ; TIM1 Trigger and Commutation
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 ; EXTI Line 15..10
DCD RTCAlarm_IRQHandler ; RTC Alarm through EXTI Line
DCD USBWakeUp_IRQHandler ; USB Wakeup from suspend
AREA |.text|, CODE, READONLY
//定义代码段
; Reset Handler
Reset_Handler PROC
//复位中断服务程序,PROC…ENDP结构表示程序的开始和结束利用这对伪指令把程序段分为若干个过程,使程 //序的结构加清晰
EXPORT Reset_Handler [WEAK]
//声明复位中断向量Reset_Handler为全局变量 WEAK:说明此优先级低,如果其他地方用到同名符号,此符号被覆盖 即在外部没有定义该符号时导出该符号Reset_Handler
IMPORT __main
//声明导入__main,此标号在其他文件
LDR R0, =__main
//使用"="表示LDR目前是伪指令不是标准指令。这里是把__main的地址给RO
BX R0
//跳到main地址执行
ENDP
//__main标号并不表示C程序中的main函数入口地址,而表示C/C++标准实时库函数里的一个初始化子程序__main的
//入口地址
; 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
EXPORT WWDG_IRQHandler [WEAK]
EXPORT PVD_IRQHandler [WEAK]
EXPORT TAMPER_IRQHandler [WEAK]
EXPORT RTC_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 DMAChannel1_IRQHandler [WEAK]
EXPORT DMAChannel2_IRQHandler [WEAK]
EXPORT DMAChannel3_IRQHandler [WEAK]
EXPORT DMAChannel4_IRQHandler [WEAK]
EXPORT DMAChannel5_IRQHandler [WEAK]
EXPORT DMAChannel6_IRQHandler [WEAK]
EXPORT DMAChannel7_IRQHandler [WEAK]
EXPORT ADC_IRQHandler [WEAK]
EXPORT USB_HP_CAN_TX_IRQHandler [WEAK]
EXPORT USB_LP_CAN_RX0_IRQHandler [WEAK]
EXPORT CAN_RX1_IRQHandler [WEAK]
EXPORT CAN_SCE_IRQHandler [WEAK]
EXPORT EXTI9_5_IRQHandler [WEAK]
EXPORT TIM1_BRK_IRQHandler [WEAK]
EXPORT TIM1_UP_IRQHandler [WEAK]
EXPORT TIM1_TRG_COM_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 RTCAlarm_IRQHandler [WEAK]
EXPORT USBWakeUp_IRQHandler [WEAK]
WWDG_IRQHandler
PVD_IRQHandler
TAMPER_IRQHandler
RTC_IRQHandler
FLASH_IRQHandler
RCC_IRQHandler
EXTI0_IRQHandler
EXTI1_IRQHandler
EXTI2_IRQHandler
EXTI3_IRQHandler
EXTI4_IRQHandler
DMAChannel1_IRQHandler
DMAChannel2_IRQHandler
DMAChannel3_IRQHandler
DMAChannel4_IRQHandler
DMAChannel5_IRQHandler
DMAChannel6_IRQHandler
DMAChannel7_IRQHandler
ADC_IRQHandler
USB_HP_CAN_TX_IRQHandler
USB_LP_CAN_RX0_IRQHandler
CAN_RX1_IRQHandler
CAN_SCE_IRQHandler
EXTI9_5_IRQHandler
TIM1_BRK_IRQHandler
TIM1_UP_IRQHandler
TIM1_TRG_COM_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
RTCAlarm_IRQHandler
USBWakeUp_IRQHandler
B .
ENDP
ALIGN
//填充字节使地址对齐
; User Initial Stack & Heap
//堆和栈的初始化
IF :DEF:__MICROLIB
//IF…ELSE…ENDIF结构,判断是否使用DEF:__MICROLIB(此处为不使用MICROLIB)
//DEF的用法——:DEF:X 就是说X定义了则为真,否则为假
EXPORT __initial_sp
//若使用DEF:__MICROLIB,则将__initial_sp,__heap_base,__heap_limit亦即栈顶地址,堆始末地址赋予全局属//性,使外部程序可以使用
EXPORT __heap_base
EXPORT __heap_limit
ELSE
//使用默认C库
IMPORT __use_two_region_memory
//导入全局标号__use_two_region_memory
EXPORT __user_initial_stackheap
//声明全局标号__user_initial_stackheap,这样外程序也可调用此标号
__user_initial_stackheap
//标号__user_initial_stackheap,表示用户堆栈初始化程序入口 进行栈和堆的赋值,在__main函数执行过程中调用
LDR R0, = Heap_Mem
//保存堆基指针至R0寄存器
LDR R1, =(Stack_Mem + Stack_Size)
//保存栈的大小至R1寄存器
LDR R2, = (Heap_Mem + Heap_Size)
//保存堆的大小至R2寄存器
LDR R3, = Stack_Mem
//保存栈顶指针至R3寄存器
BX LR
ALIGN
ENDIF
END
/*
至此可以总结一下STM32的启动文件和启动过程。首先对栈和堆的大小进行定义,并在代码区的起始处建立中断向量表,其第一个表项是栈顶地址,第二个表项是复位中断服务入口地址。然后在复位中断服务程序中跳转??C/C++标准实时库的__main函数,完成用户堆栈等的初始化后,跳转.c文件中的main函数开始执行C程序。假设STM32被设置为从内部FLASH启动(这也是最常见的一种情况),中断向量表起始地位为0x8000000,则栈顶地址存放于0x8000000处,而复位中断服务入口地址存放于0x8000004处。当STM32遇到复位信号后,则从0x80000004处取出复位中断服务入口地址,继而执行复位中断服务程序,然后跳转__main函数,最后进入mian函数,来到C的世界。
*/