在使用 STM32CubeMX 开发 STM32 时,往往会看到一个.s 的文件,这个文件就是 STM32 的启动文件,里面包含多个功能,例如堆栈大小配置、STM32 复位后初始化和建立中断服务入口地址等功能。
下面是一个 STM32 启动文件的实例,在 STM32CubeIDE 开发环境下打开的.s 文件,如图 1 所示。
在文件描述的地方其实也说明了该文件的作用:
This module performs:
– Set the initial SP
– Set the initial PC == Reset_Handler,
– Set the vector table entries with the exceptions ISR address
– Branches to main in the C library (which eventually calls main()).
即.s 启动文件有如下功能:
1. 初始化栈指针和必要的程序
/** * @brief This is the code that gets called when the processor first * starts execution following a reset event. Only the absolutely * necessary set is performed, after which the application * supplied main() routine is called. * @param None * @retval : None */ .section .text.Reset_Handler .weak Reset_Handler .type Reset_Handler, %function Reset_Handler: ldr sp, =_estack /* set stack pointer */
注意:STM32CubeIDE 下的堆栈大小默认在.ld 文件中设置。其他开发环境,如 MDK 下的堆栈大小默认在.s 文件下设置。
2. 从 systeminit()函数进入到 main()函数
对于 stm32 我们定义系统时钟的时候直接在 system_stm3210x.c 文件里修改宏定义即可,而事实上到底是从哪开始执行的呢?
system_stm3210x.c 文件里有个 SystemInit()函数,就是对时钟的设置。
而这个 SystemInit()在哪调用的呢,就是启动文件先调用了,然后才进入到 mian()函数。
在启动文件 .s 中有以下一段话可以解释。
/* Call the clock system intitialization function.*/ bl SystemInit /* Call static constructors */ bl __libc_init_array /* Call the application's entry point.*/ bl main bx lr
3. 建立中断服务入口地址
这个功能其实就是把中断向量与中断服务函数链接起来。
我们知道在串口 NVIC 配置中我们只定义了:
NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
也就是中断服务向量,再然后我们在 stm32f10x_it.c 文件的 void USART2_IRQHandler(void){} 函数里添加串口的服务程序。
但是 mcu 怎么知道中断向量 USART2_IRQn 对应的是 USART2_IRQHandler(){}呢,这个就是启动文件所起的作用。
在启动文件.s 中以 g_pfnVectors:开头的定义即是建立中断服务入口地址。
另外,某些系列的 STM32 根据不同的使用场景和 FLASH 大小,启动文件.s 又有 cl、vl、xl、ld、md、hd 的区分,例如 STM32F10x 系列 MCU,其 cl、vl、xl、ld、md、hd 的含义如下:
- cl:互联型产品,stm32f105/107 系列
- vl:超值型产品,stm32f100 系列
- xl:超高密度产品,stm32f101/103 系列
- ld:低密度产品,FLASH 小于 64K
- md:中等密度产品,FLASH=64 or 128
- hd:高密度产品,FLASH 大于 128
扫码关注尚为网微信公众号
原创文章,作者:sunev,如若转载,请注明出处:https://www.sunev.cn/embedded/953.html