STM32F103启动文件解析


文章目录

  • 序言
  • 启动文件概述
  • 开辟堆栈区
  • 定义中断向量表
  • 编写启动函数
  • 定义默认中断函数
  • 堆栈初始化

序言 上篇文章MDK链接脚本解析中我介绍了程序在汇编完成后是如何最终形成镜像文件的,以及镜像文件在FLASH中的存储状态、加载状态、运行状态。今天我们就要进入更深入,更细节,更具体的源码分析阶段,首先从启动文件开始。
注:手边最好有一本ARM汇编手册,查指令方便点,这是我用的汇编手册ARM汇编手册
百度盘密码:gzo7
启动文件概述 我大概总结了一下,STM32F103的启动文件分成如下几个部分
  • 开辟堆栈区
  • 设置中断向量表
  • 编写启动函数
  • 定义默认中断函数
  • 初始化堆栈
我下面将会挨个探究上面的5个部分,代码也被顺序切分成了5个部分。
开辟堆栈区 【STM32F103启动文件解析】上源码,具体的解释都在代码注释里了
; Amount of memory (in bytes) allocated for Stack ; Tailor this value to your application needs ; Stack Configuration ; Stack Size (in Bytes) <0x0-0xFFFFFFFF:8> ; ; EQU指令的作用就是把0x00000400这个值定义一个标签Stack_Size,类似于C语言中的宏定义#define Stack_SizeEQU0x00000400 ; AREA指令指示汇编器汇编新的代码节或数据节。节是不可分的已命名独立代码或数据块,由链接器处理。 AREASTACK, NOINIT, READWRITE, ALIGN=3; SPACE 指令保留一个用零填充的内存块。 Stack_MemSPACEStack_Size __initial_sp; Heap Configuration ; Heap Size (in Bytes) <0x0-0xFFFFFFFF:8> ; Heap_SizeEQU0x00000200AREAHEAP, NOINIT, READWRITE, ALIGN=3 __heap_base Heap_MemSPACEHeap_Size __heap_limit; PRESERVE8 指令指定当前文件保持堆栈八字节对齐 PRESERVE8; 为了最有力地支持 Thumb‐2,引了一个“统一汇编语言(UAL)”语法机制。对于 16 位 ; 指令和 32 位指令均能实现的一些操作(常见于数据处理操作),有时虽然指令的实际操作数 ; 不同,或者对立即数的长度有不同的限制,但是汇编器允许开发者以相同的语法格式书写, ; 并且由汇编器来决定是使用 16 位指令,还是使用 32 位指令。以前,Thumb 的语法和 ARM ; 的语法不同,在有了 UAL 之后,两者的书写格式就统一了。 ; THUMB 指令使用 UAL 语法,指示汇编器将后续指令解释为 Thumb 指令。 THUMB

定义中断向量表
; Vector Table Mapped to Address 0 at Reset ; AREA指令指示汇编器汇编一个叫做RESET的DATA段,段是READONLY的 AREARESET, DATA, READONLY ; 使用 EXPORT 可使其他文件中的代码能够访问当前文件中的符号。 ; 使用 [WEAK] 属性可通知链接器,如果可以使用其他源中的不同 symbol 实例,则 ; 不同实例将优先于此实例。[WEAK] 属性可与任何符号可见性属性一起使用。 EXPORT__Vectors EXPORT__Vectors_End EXPORT__Vectors_Size; 下面是中断向量表,放在在STM32中代码段的最开头,当对应的中断发生的时候就会寻找这个表里面的内容,也就是对应的函数指针 ; 这里的地址在M3中应该是0x00000000,但是ST对它进行了地址重映射,所以这里是0x08000000 __VectorsDCD__initial_sp; Top of Stack DCDReset_Handler; Reset Handler DCDNMI_Handler; NMI Handler DCDHardFault_Handler; Hard Fault Handler DCDMemManage_Handler; MPU Fault Handler DCDBusFault_Handler; Bus Fault Handler DCDUsageFault_Handler; Usage Fault Handler DCD0; Reserved DCD0; Reserved DCD0; Reserved DCD0; Reserved DCDSVC_Handler; SVCall Handler DCDDebugMon_Handler; Debug Monitor Handler DCD0; Reserved DCDPendSV_Handler; PendSV Handler DCDSysTick_Handler; SysTick Handler; External Interrupts DCDWWDG_IRQHandler; Window Watchdog DCDPVD_IRQHandler; PVD through EXTI Line detect DCDTAMPER_IRQHandler; Tamper DCDRTC_IRQHandler; RTC DCDFLASH_IRQHandler; Flash DCDRCC_IRQHandler; RCC DCDEXTI0_IRQHandler; EXTI Line 0 DCDEXTI1_IRQHandler; EXTI Line 1 DCDEXTI2_IRQHandler; EXTI Line 2 DCDEXTI3_IRQHandler; EXTI Line 3 DCDEXTI4_IRQHandler; EXTI Line 4 DCDDMA1_Channel1_IRQHandler; DMA1 Channel 1 DCDDMA1_Channel2_IRQHandler; DMA1 Channel 2 DCDDMA1_Channel3_IRQHandler; DMA1 Channel 3 DCDDMA1_Channel4_IRQHandler; DMA1 Channel 4 DCDDMA1_Channel5_IRQHandler; DMA1 Channel 5 DCDDMA1_Channel6_IRQHandler; DMA1 Channel 6 DCDDMA1_Channel7_IRQHandler; DMA1 Channel 7 DCDADC1_2_IRQHandler; ADC1 & ADC2 DCDUSB_HP_CAN1_TX_IRQHandler; USB High Priority or CAN1 TX DCDUSB_LP_CAN1_RX0_IRQHandler ; USB LowPriority or CAN1 RX0 DCDCAN1_RX1_IRQHandler; CAN1 RX1 DCDCAN1_SCE_IRQHandler; CAN1 SCE DCDEXTI9_5_IRQHandler; EXTI Line 9..5 DCDTIM1_BRK_IRQHandler; TIM1 Break DCDTIM1_UP_IRQHandler; TIM1 Update DCDTIM1_TRG_COM_IRQHandler; TIM1 Trigger and Commutation DCDTIM1_CC_IRQHandler; TIM1 Capture Compare DCDTIM2_IRQHandler; TIM2 DCDTIM3_IRQHandler; TIM3 DCDTIM4_IRQHandler; TIM4 DCDI2C1_EV_IRQHandler; I2C1 Event DCDI2C1_ER_IRQHandler; I2C1 Error DCDI2C2_EV_IRQHandler; I2C2 Event DCDI2C2_ER_IRQHandler; I2C2 Error DCDSPI1_IRQHandler; SPI1 DCDSPI2_IRQHandler; SPI2 DCDUSART1_IRQHandler; USART1 DCDUSART2_IRQHandler; USART2 DCDUSART3_IRQHandler; USART3 DCDEXTI15_10_IRQHandler; EXTI Line 15..10 DCDRTCAlarm_IRQHandler; RTC Alarm through EXTI Line DCDUSBWakeUp_IRQHandler; USB Wakeup from suspend DCDTIM8_BRK_IRQHandler; TIM8 Break DCDTIM8_UP_IRQHandler; TIM8 Update DCDTIM8_TRG_COM_IRQHandler; TIM8 Trigger and Commutation DCDTIM8_CC_IRQHandler; TIM8 Capture Compare DCDADC3_IRQHandler; ADC3 DCDFSMC_IRQHandler; FSMC DCDSDIO_IRQHandler; SDIO DCDTIM5_IRQHandler; TIM5 DCDSPI3_IRQHandler; SPI3 DCDUART4_IRQHandler; UART4 DCDUART5_IRQHandler; UART5 DCDTIM6_IRQHandler; TIM6 DCDTIM7_IRQHandler; TIM7 DCDDMA2_Channel1_IRQHandler; DMA2 Channel1 DCDDMA2_Channel2_IRQHandler; DMA2 Channel2 DCDDMA2_Channel3_IRQHandler; DMA2 Channel3 DCDDMA2_Channel4_5_IRQHandler ; DMA2 Channel4 & Channel5 __Vectors_End__Vectors_SizeEQU__Vectors_End - __Vectors

编写启动函数
; 定义代码段,READONLY AREA|.text|, CODE, READONLY; Reset handler ; PROC标记函数的开始,与FUNCTION功能相同,下面的EXPORT和IMPORT的用法见手册 Reset_HandlerPROC EXPORTReset_Handler[WEAK] IMPORT__main IMPORTSystemInit LDRR0, =SystemInit BLXR0; 进行系统初始化 LDRR0, =__main BXR0; 跳转到__main,这个__main是C库里面的函数,它完成一些工作后,最终会跳到我们的main函数 ENDP

定义默认中断函数
; 下面定义了一堆的中断函数,函数的实体是一个死循环 NMI_HandlerPROC EXPORTNMI_Handler[WEAK] B. ENDP HardFault_Handler\ PROC EXPORTHardFault_Handler[WEAK] B. ENDP MemManage_Handler\ PROC EXPORTMemManage_Handler[WEAK] B. ENDP BusFault_Handler\ PROC EXPORTBusFault_Handler[WEAK] B. ENDP UsageFault_Handler\ PROC EXPORTUsageFault_Handler[WEAK] B. ENDP SVC_HandlerPROC EXPORTSVC_Handler[WEAK] B. ENDP DebugMon_Handler\ PROC EXPORTDebugMon_Handler[WEAK] B. ENDP PendSV_HandlerPROC EXPORTPendSV_Handler[WEAK] B. ENDP SysTick_Handler PROC EXPORTSysTick_Handler[WEAK] B. ENDP; 下面这个函数我看了半天没看懂,后来才明白,我们把多个函数映射到了一个函数实体,如果这些函数没有被重写,它就是一个死循环,这些函数被用到的时候,一般都是要被我们重写的 Default_Handler PROCEXPORTWWDG_IRQHandler[WEAK] EXPORTPVD_IRQHandler[WEAK] EXPORTTAMPER_IRQHandler[WEAK] EXPORTRTC_IRQHandler[WEAK] EXPORTFLASH_IRQHandler[WEAK] EXPORTRCC_IRQHandler[WEAK] EXPORTEXTI0_IRQHandler[WEAK] EXPORTEXTI1_IRQHandler[WEAK] EXPORTEXTI2_IRQHandler[WEAK] EXPORTEXTI3_IRQHandler[WEAK] EXPORTEXTI4_IRQHandler[WEAK] EXPORTDMA1_Channel1_IRQHandler[WEAK] EXPORTDMA1_Channel2_IRQHandler[WEAK] EXPORTDMA1_Channel3_IRQHandler[WEAK] EXPORTDMA1_Channel4_IRQHandler[WEAK] EXPORTDMA1_Channel5_IRQHandler[WEAK] EXPORTDMA1_Channel6_IRQHandler[WEAK] EXPORTDMA1_Channel7_IRQHandler[WEAK] EXPORTADC1_2_IRQHandler[WEAK] EXPORTUSB_HP_CAN1_TX_IRQHandler[WEAK] EXPORTUSB_LP_CAN1_RX0_IRQHandler [WEAK] EXPORTCAN1_RX1_IRQHandler[WEAK] EXPORTCAN1_SCE_IRQHandler[WEAK] EXPORTEXTI9_5_IRQHandler[WEAK] EXPORTTIM1_BRK_IRQHandler[WEAK] EXPORTTIM1_UP_IRQHandler[WEAK] EXPORTTIM1_TRG_COM_IRQHandler[WEAK] EXPORTTIM1_CC_IRQHandler[WEAK] EXPORTTIM2_IRQHandler[WEAK] EXPORTTIM3_IRQHandler[WEAK] EXPORTTIM4_IRQHandler[WEAK] EXPORTI2C1_EV_IRQHandler[WEAK] EXPORTI2C1_ER_IRQHandler[WEAK] EXPORTI2C2_EV_IRQHandler[WEAK] EXPORTI2C2_ER_IRQHandler[WEAK] EXPORTSPI1_IRQHandler[WEAK] EXPORTSPI2_IRQHandler[WEAK] EXPORTUSART1_IRQHandler[WEAK] EXPORTUSART2_IRQHandler[WEAK] EXPORTUSART3_IRQHandler[WEAK] EXPORTEXTI15_10_IRQHandler[WEAK] EXPORTRTCAlarm_IRQHandler[WEAK] EXPORTUSBWakeUp_IRQHandler[WEAK] EXPORTTIM8_BRK_IRQHandler[WEAK] EXPORTTIM8_UP_IRQHandler[WEAK] EXPORTTIM8_TRG_COM_IRQHandler[WEAK] EXPORTTIM8_CC_IRQHandler[WEAK] EXPORTADC3_IRQHandler[WEAK] EXPORTFSMC_IRQHandler[WEAK] EXPORTSDIO_IRQHandler[WEAK] EXPORTTIM5_IRQHandler[WEAK] EXPORTSPI3_IRQHandler[WEAK] EXPORTUART4_IRQHandler[WEAK] EXPORTUART5_IRQHandler[WEAK] EXPORTTIM6_IRQHandler[WEAK] EXPORTTIM7_IRQHandler[WEAK] EXPORTDMA2_Channel1_IRQHandler[WEAK] EXPORTDMA2_Channel2_IRQHandler[WEAK] EXPORTDMA2_Channel3_IRQHandler[WEAK] EXPORTDMA2_Channel4_5_IRQHandler [WEAK]WWDG_IRQHandler PVD_IRQHandler TAMPER_IRQHandler RTC_IRQHandler FLASH_IRQHandler RCC_IRQHandler EXTI0_IRQHandler EXTI1_IRQHandler EXTI2_IRQHandler EXTI3_IRQHandler EXTI4_IRQHandler DMA1_Channel1_IRQHandler DMA1_Channel2_IRQHandler DMA1_Channel3_IRQHandler DMA1_Channel4_IRQHandler DMA1_Channel5_IRQHandler DMA1_Channel6_IRQHandler DMA1_Channel7_IRQHandler ADC1_2_IRQHandler USB_HP_CAN1_TX_IRQHandler USB_LP_CAN1_RX0_IRQHandler CAN1_RX1_IRQHandler CAN1_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 TIM8_BRK_IRQHandler TIM8_UP_IRQHandler TIM8_TRG_COM_IRQHandler TIM8_CC_IRQHandler ADC3_IRQHandler FSMC_IRQHandler SDIO_IRQHandler TIM5_IRQHandler SPI3_IRQHandler UART4_IRQHandler UART5_IRQHandler TIM6_IRQHandler TIM7_IRQHandler DMA2_Channel1_IRQHandler DMA2_Channel2_IRQHandler DMA2_Channel3_IRQHandler DMA2_Channel4_5_IRQHandler B.ENDP; 四字节对齐 ALIGN

堆栈初始化
; ******************************************************************************* ; User Stack and Heap initialization ; ******************************************************************************* ; 用户栈和堆的初始化 IF:DEF:__MICROLIBEXPORT__initial_sp EXPORT__heap_base EXPORT__heap_limitELSEIMPORT__use_two_region_memory EXPORT__user_initial_stackheap__user_initial_stackheapLDRR0, =Heap_Mem LDRR1, =(Stack_Mem + Stack_Size) LDRR2, = (Heap_Mem +Heap_Size) LDRR3, = Stack_Mem BXLRALIGNENDIFEND ; ******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE*****

    推荐阅读