【STM32】启动流程

1、.s启动文件解析

STM32的启动文件(一般是.s汇编文件,如startup_stm32f407xx.s)是STM32上电后执行的第一段代码,承担着"系统初始化化引导员"的角色。

它的主要作用是设置初始化栈指针(SP)、程序计数器(PC)、定义向量表、跳转到C库中__main函数,最终调用用户main函数。

1.1、栈和堆的初始化配置

定义栈和堆的大小,并指定分配内存空间。

c 复制代码
Stack_Size		EQU     0x400

                AREA    STACK, NOINIT, READWRITE, ALIGN=3
Stack_Mem       SPACE   Stack_Size
__initial_sp

Heap_Size      EQU     0x200

                AREA    HEAP, NOINIT, READWRITE, ALIGN=3
__heap_base
Heap_Mem        SPACE   Heap_Size
__heap_limit

1.2、向量表

定义储存中断服务程序地址的数组,即中断向量表。

c 复制代码
__Vectors       DCD     __initial_sp               ; Top of Stack
                DCD     Reset_Handler              ; Reset Handler
                DCD     NMI_Handler                ; NMI Handler
                ...

1.3、复位处理程序

Reset_Handler是复位处理程序,当MCU复位时,程序会跳转到这里执行。其中主要包括SystemInit函数和__main函数。

c 复制代码
Reset_Handler    PROC
                 EXPORT  Reset_Handler             [WEAK]
        IMPORT  SystemInit
        IMPORT  __main

                 LDR     R0, =SystemInit
                 BLX     R0
                 LDR     R0, =__main
                 BX      R0
                 ENDP

1.4、其它中断处理程序

这里都是默认的异常处理程序,如非屏蔽中断(NMI)、硬故障(HardFault)等。可以在用户程序中重新定义这些中断处理程序,例如,在main.c中定义void SysTick_Handler(void)会覆盖启动文件中的弱定义。

1.5、用户栈和堆初始化

如果使用 MicroLIB,则导出栈顶指针、堆基地址和堆限制地址。否则,导入 __use_two_region_memory 符号,并定义__user_initial_stackheap函数,用于初始化用户栈和堆。

这里是用于初始化栈和堆的内存布局,并根据不同的工具链和库配置提供相应的接口。

c 复制代码
                 IF      :DEF:__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
  • 1、MicroLIB分支
    • 适用于Flash/RAM较小的场景(如F1系列)。
    • 减小代码体积。
    • 直接通过全局变量管理堆和栈,无需函数调用开销。
  • 2、标准库
    • 适用于需要完整的C库功能的场景(如malloc()printf())。
    • 通过__user_initial_stackheap函数动态配置堆和栈,支持更灵活的内存管理。
    • 双区域模型避免栈和堆的冲突(如栈溢出导致覆盖堆数据)

2、STM32启动流程

  • 1、复位:当 STM32 微控制器复位时,处理器从地址 0 处读取栈顶指针(SP)的值,并将其加载到 SP 寄存器中。
  • 2、跳转到复位处理程序 :接着从地址 4 处读取复位处理程序的地址,并将其加载到程序计数器(PC)中,程序跳转到 Reset_Handler 执行。
  • 3、系统初始化 :在 Reset_Handler 中,首先调用 SystemInit 函数进行系统时钟等硬件配置的初始化。
  • 4、进入 C 库启动函数 :然后调用 __main 函数,__main 函数会完成一些初始化工作,如全局变量的初始化等,最终调用用户的 main 函数。
  • 5、用户程序执行 :程序进入用户的 main 函数,开始执行用户编写的代码。
  • 6、异常处理:当发生异常或中断时,处理器会根据向量表中的地址跳转到相应的异常处理程序执行。

3、常见使用技巧

  • 1、增大栈内存,解决栈溢出问题
  • 2、重映射中断向量表(IAP升级或双程序)
  • 3、裁剪启动流程,适配应用场景。
相关推荐
亿道电子Emdoor2 小时前
【ARM】MDK Debug模式下Disassembly窗口介绍
stm32·单片机·嵌入式硬件
点灯小铭2 小时前
基于STM32单片机的无线鼠标设计
stm32·单片机·计算机外设·毕业设计·课程设计
嵌入式小李7 小时前
stm32项目(24)——基于STM32的汽车CAN通信系统
stm32·嵌入式硬件·汽车
我怕是好20 小时前
STM32 输入捕获,串口打印,定时器,中断综合运用
stm32·单片机·嵌入式硬件
点灯小铭1 天前
基于STM32单片机的OneNet物联网环境检测系统
stm32·单片机·物联网·毕业设计·课程设计
滴啦嘟啦哒1 天前
【从0到1制作一块STM32开发板】5. 整体布局
stm32·单片机·嵌入式硬件
普中科技1 天前
【普中STM32精灵开发攻略】--第 11 章 SysTick系统定时器
stm32·单片机·嵌入式硬件·物联网·arm·普中科技
Hello_Embed1 天前
STM32HAL 快速入门(二):用 CubeMX 配置点灯程序 —— 从工程生成到 LED 闪烁
笔记·stm32·单片机·学习·嵌入式软件
JasmineX-11 天前
STM32的SPI通信(软件读写W25Q64)
c语言·stm32·单片机·嵌入式硬件
小杨爱搞嵌入式2 天前
【STM32】GPIO的输入输出
c语言·笔记·stm32·单片机·学习