启动文件是STM32在上电或复位时最先运行的一段程序,启动文件一般都是由汇编语言编写,不同的编译器启动文件的编写方式也不同,下面就以MD5开发软件为例子,来简单说一下STM32的启动文件。启动文件主要做了以下几个工作:
EQU:可以理解成C语言的宏定义,将Stack_Size的大小定义为0x400个字节大小,也就是将栈设置为1K。
AREA:AREA是定义一个新的段,段名叫STACK,NOINIT表示不初始化这个段,READWRITE表示该段可读可写,ALIGN=3表示该段是2^3(8字节对齐)。
SPACE:表示申请一段内存,大小为Stack_Size,也就是1K
__initial_sp:__initial_sp标号紧挨着SPACE,表示SP的栈顶指针为分配的栈空间的结束地址,因为栈的生长方向是从高到低。
EQU:将Heap_Size的大小定义为0x200个字节大小
AREA:AREA是定义一个新的段,段名叫HEAP,NOINIT表示不初始化这个段,READWRITE表示该段可读可写,ALIGN=3表示该段是2^3(8字节对齐)。
__heap_base:__heap_base标号表示堆的起始地址
Heap_Mem:表示申请一段内存,大小为Heap_Size。
__heap_limit:__heap_limit标号表示堆的结束地址。
AREA:AREA是定义一个新的段,段名叫RESET,DATA该段为数据段,READONLY表示该段只读。
__Vectors:表示中断向量表的起始地址。
__Vectors_End:表示中断向量表的结束地址。
__Vectors_Size:表示中断向量表的大小。
EXPORT:表示标号可以导出给其他文件使用。
在中断向量表中,前16个中断是系统中断,无论哪款Crotex-M4芯片都是固定不变,具体可以在《Crotex-M4权威指南》里面可以查看有关系统中断的概念。
这里的DCD意思是给每一个中断都分配4个字节的大小,也就是一个指针的大小。
不同的MCU厂家都有自己的外设中断,所以外设中断都是不固定的,下面是STM32F4X的外设中断
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
__Vectors_Size :中断向量表大小只需将中断向量表的结束地址减去起始地址就可以获取。
当系统上电或者复位时,会先进入到Reset_Handler这个函数里面,在STM32F4的启动文件中Reset_Handler主要做了以下两个步骤的操作,先进入SystemInit函数里面初始化时钟,然后跳转到C库的__main函数执行用户堆栈的初始化,最后再跳转到用户的main函数执行。
IMPORT:相当于C语言的extern,可以调用外部的函数。
WEAK:弱类型,表示该函数可以在其他文件被重新定义,如果没有定义也不会出错。也就是说如果用户需要的话,可以重新编写Reset_Handler函数。
STM32F4已经帮我们写好了中断服务函数的实现,当然我们也可以自己在别的地方重新实现中断服务函数的业务逻辑。
如果我们定义了__MICROLIB这个宏,就给__initial_sp,__heap_base,__heap_limit这三个标号赋予全局属性,供其他文件使用。__MICROLIB可以在keil里面进行配置。具体的配置方法如下,配置完之后就由C库实现用户堆栈初始化工作。
如果没有定义__MICROLIB,就需要用户自己实现堆栈初始化工作。