STM32启动过程
STM32 的启动过程是指从芯片上电 / 复位到执行用户main()函数前的一系列硬件和软件初始化操作,核心由硬件复位逻辑和启动文件(汇编代码) 共同完成。整个过程可分为以下几个关键阶段:
一、硬件复位阶段(芯片上电 / 复位瞬间)
当 STM32 上电、外部复位引脚(NRST)触发或软件复位时,硬件会自动执行以下操作:
- 初始化核心寄存器:CPU(Cortex-M 内核)的关键寄存器被重置,例如程序计数器(PC)、栈指针(SP)等。
- 确定启动方式:根据 BOOT0 和 BOOT1 引脚的电平状态(硬件配置),选择程序的加载源(启动介质),常见的启动方式有:
- 从 Flash 启动(默认,BOOT0=0):程序存储在片内 Flash,适合正常运行。
- 从 RAM 启动(BOOT0=1,BOOT1=1):程序加载到 RAM 中运行,适合调试。
- 从系统存储器启动(BOOT0=1,BOOT1=0):执行芯片内部固化的 BootLoader(如 ISP 下载程序)。
- 映射中断向量表:根据启动方式,将中断向量表(存放中断服务程序入口地址的表格)映射到对应介质的起始地址(例如 Flash 起始地址 0x08000000)。
二、启动文件执行阶段(汇编代码)
硬件复位完成后,CPU 会从中断向量表的第 0 项获取栈顶地址(SP),从第 1 项获取复位中断服务程序的入口地址(PC),然后跳转到复位中断服务程序执行。这部分逻辑由芯片厂商提供的启动文件(如startup_stm32f103xe.s)实现,核心任务是初始化系统环境,为main()函数运行做准备。
启动文件的主要操作包括:
- 初始化栈(SP)和堆(Heap):
- 栈(Stack):用于函数调用、局部变量存储,启动文件会定义栈的大小(如Stack_Size EQU 0x400),并将 SP初始化为栈顶地址(中断向量表第 0 项的值)。
- 堆(Heap):用于动态内存分配(如malloc()),启动文件会定义堆的大小和起始地址,初始化堆管理结构。
- 初始化数据段(.data)和清零 BSS 段(.bss):
- .data 段:存放初始化的全局变量(如int a = 10;)。这些变量在 Flash 中存储初始值,启动时需要从 Flash
复制到 RAM 中(因为 RAM 断电丢失数据,而 Flash 可持久化)。 - .bss 段:存放未初始化的全局变量或初始值为 0 的变量(如int b;或int c = 0;)。启动时需要将这部分 RAM
区域清零。
- 配置系统时钟(SystemInit):
启动文件会调用SystemInit()函数(在system_stm32fxxx.c中实现),完成系统时钟的初始化。例如:
- 复位后默认使用内部低速时钟(HSI,8MHz),SystemInit()会切换到外部高速时钟(HSE)或PLL,将系统主频提升到额定值(如 STM32F103 最高 72MHz)。
- 配置 AHB、APB 等外设总线的分频,确保外设时钟正确。
- 跳转到用户main()函数:
完成上述初始化后,启动文件通过bl main(分支跳转指令)跳转到用户编写的main()函数,至此启动过程结束,程序进入用户逻辑。
三、关键补充:中断向量表的作用
中断向量表是启动过程的 “导航图”,位于启动介质的起始地址(如 Flash 的 0x08000000),其结构为:
- 第 0 项:栈顶地址(SP 的初始值)。
- 第 1 项:复位中断服务程序入口地址(CPU 复位后执行的第一个程序)。
- 第 2 项及以后:其他中断(如定时器、UART、GPIO 等)的服务程序入口地址。
当发生中断时,CPU 会根据中断号查找向量表,跳转到对应的服务程序执行。启动文件中会定义默认的中断服务程序(多数为死循环,需用户根据需求重写)。
总结:
上电/复位后从地址0x00000000处取出主堆栈指针MSP的初始值,从0x00000004处取出程序计数器PC的初始值,PC指向复位向量,芯片厂商会把这两个地址映射到其他地址。用户通过设置boot0和boot1引脚选择启动位置,一般是从内部flash启动0x08000000。启动代码位于startup_stm32f10XX.s,具体内容如下:
1.定义栈和堆(
通过汇编指令定义栈和堆的大小及起始地址。
)
2. 定义中断向量表(
STM32 有数十个中断源(如定时器中断、I2C 中断、外部中断等),中断向量表是一个按固定顺序排列的中断服务程序(ISR)入口地址表。当硬件中断发生时,CPU 会根据中断号在向量表中找到对应的 ISR 地址并跳转执行。
向量表第 0 项固定为栈顶地址(复位后 CPU 会将其加载到 SP 寄存器,初始化栈)。
第 1 项为复位中断服务程序(Reset_Handler),是系统上电 / 复位后执行的第一个函数。
)
3.复位中断服务程序(
调用 SystemInit:初始化系统时钟
跳转至 __main:这是 C 库函数(非用户 main),负责:
初始化数据段(.data):将 Flash 中存储的初始化全局变量复制到 RAM。
清零 BSS 段(.bss):将未初始化的全局变量 / 静态变量清零。
最终调用用户编写的 main() 函数,程序进入用户逻辑。
)
4. 中断服务程序的默认实现(
对于用户未自定义的中断,启动文件会提供默认处理函数(通常为无限循环,防止程序跑飞
)
补充
栈:用于函数调用、局部变量存储、函数参数传递等,由编译器自动管理。
堆:用于动态内存分配(如 malloc),需用户手动管理。
更多推荐


所有评论(0)