news 2026/4/18 12:39:36

stm32FXX系列MCU汇编启动文件分析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
stm32FXX系列MCU汇编启动文件分析

汇编代码

;********************(C)COPYRIGHT2011STMicroelectronics********************;文件名:startup_stm32f10x_md.s;作用:STM32F10x 中等容量(MD)器件启动文件(Keil MDK-ARM);功能:;1.定义初始堆栈(SP);2.定义中断向量表(Vector Table);3.提供默认的中断/异常处理函数(弱定义);4.复位后调用SystemInit()完成系统时钟初始化;5.跳转到 C 运行库 __main,最终进入main();*******************************************************************************;------------------------------------------------------------------------------;栈大小配置(单位:字节);------------------------------------------------------------------------------Stack_Size EQU0x00000800;栈大小=2KB,可根据应用调整 AREA STACK,NOINIT,READWRITE,ALIGN=3Stack_Mem SPACE Stack_Size;在 RAM 中为栈分配空间 __initial_sp;栈顶地址(MSP 初始值);------------------------------------------------------------------------------;堆大小配置(单位:字节);------------------------------------------------------------------------------Heap_Size EQU0x00000400;堆大小=1KB AREA HEAP,NOINIT,READWRITE,ALIGN=3__heap_base;堆起始地址 Heap_Mem SPACE Heap_Size;在 RAM 中为堆分配空间 __heap_limit;堆结束地址 PRESERVE8;保证8字节对齐(ARM ABI 要求) THUMB;使用 Thumb 指令集;------------------------------------------------------------------------------;中断向量表(复位后映射到地址0x00000000;------------------------------------------------------------------------------AREA RESET,DATA,READONLY EXPORT __Vectors EXPORT __Vectors_End EXPORT __Vectors_Size __Vectors DCD __initial_sp;0x00:初始主栈指针 MSP DCD Reset_Handler;0x04:复位中断入口 DCD NMI_Handler;0x08:NMI DCD HardFault_Handler;0x0C:硬件错误 DCD MemManage_Handler;0x10:MPU 错误 DCD BusFault_Handler;0x14:总线错误 DCD UsageFault_Handler;0x18:用法错误 DCD0;保留 DCD0;保留 DCD0;保留 DCD0;保留 DCD SVC_Handler;SVCall(系统调用) DCD DebugMon_Handler;调试监控 DCD0;保留 DCD PendSV_Handler;PendSV(RTOS 上下文切换) DCD SysTick_Handler;SysTick 定时器;------------------外部中断向量------------------DCD WWDG_IRQHandler DCD PVD_IRQHandler DCD TAMPER_IRQHandler DCD RTC_IRQHandler DCD FLASH_IRQHandler DCD RCC_IRQHandler DCD EXTI0_IRQHandler DCD EXTI1_IRQHandler DCD EXTI2_IRQHandler DCD EXTI3_IRQHandler DCD EXTI4_IRQHandler DCD DMA1_Channel1_IRQHandler DCD DMA1_Channel2_IRQHandler DCD DMA1_Channel3_IRQHandler DCD DMA1_Channel4_IRQHandler DCD DMA1_Channel5_IRQHandler DCD DMA1_Channel6_IRQHandler DCD DMA1_Channel7_IRQHandler DCD ADC1_2_IRQHandler DCD USB_HP_CAN1_TX_IRQHandler DCD USB_LP_CAN1_RX0_IRQHandler DCD CAN1_RX1_IRQHandler DCD CAN1_SCE_IRQHandler DCD EXTI9_5_IRQHandler DCD TIM1_BRK_IRQHandler DCD TIM1_UP_IRQHandler DCD TIM1_TRG_COM_IRQHandler DCD TIM1_CC_IRQHandler DCD TIM2_IRQHandler DCD TIM3_IRQHandler DCD TIM4_IRQHandler DCD I2C1_EV_IRQHandler DCD I2C1_ER_IRQHandler DCD I2C2_EV_IRQHandler DCD I2C2_ER_IRQHandler DCD SPI1_IRQHandler DCD SPI2_IRQHandler DCD USART1_IRQHandler DCD USART2_IRQHandler DCD USART3_IRQHandler DCD EXTI15_10_IRQHandler DCD RTCAlarm_IRQHandler DCD USBWakeUp_IRQHandler __Vectors_End __Vectors_Size EQU __Vectors_End-__Vectors;向量表大小;------------------------------------------------------------------------------;代码段;------------------------------------------------------------------------------AREA|.text|,CODE,READONLY;------------------------------------------------------------------------------;复位中断处理函数;------------------------------------------------------------------------------Reset_Handler PROC EXPORT Reset_Handler[WEAK]IMPORT __main IMPORT SystemInit;调用系统初始化(时钟、PLL、Flash 等) LDR R0,=SystemInit BLX R0;跳转到 C 运行库入口 __main LDR R0,=__main BX R0 ENDP;------------------------------------------------------------------------------;Cortex-M 内核异常默认处理函数(死循环);------------------------------------------------------------------------------NMI_Handler PROC EXPORT NMI_Handler[WEAK]B.ENDP HardFault_Handler PROC EXPORT HardFault_Handler[WEAK]B.ENDP MemManage_Handler PROC EXPORT MemManage_Handler[WEAK]B.ENDP BusFault_Handler PROC EXPORT BusFault_Handler[WEAK]B.ENDP UsageFault_Handler PROC EXPORT UsageFault_Handler[WEAK]B.ENDP SVC_Handler PROC EXPORT SVC_Handler[WEAK]B.ENDP DebugMon_Handler PROC EXPORT DebugMon_Handler[WEAK]B.ENDP PendSV_Handler PROC EXPORT PendSV_Handler[WEAK]B.ENDP SysTick_Handler PROC EXPORT SysTick_Handler[WEAK]B.ENDP;------------------------------------------------------------------------------;外设中断默认处理函数(统一跳转到死循环);------------------------------------------------------------------------------Default_Handler PROC EXPORT WWDG_IRQHandler[WEAK]EXPORT PVD_IRQHandler[WEAK]EXPORT TAMPER_IRQHandler[WEAK]EXPORT RTC_IRQHandler[WEAK]EXPORT FLASH_IRQHandler[WEAK]EXPORT RCC_IRQHandler[WEAK]EXPORT EXTI0_IRQHandler[WEAK]EXPORT EXTI1_IRQHandler[WEAK]EXPORT EXTI2_IRQHandler[WEAK]EXPORT EXTI3_IRQHandler[WEAK]EXPORT EXTI4_IRQHandler[WEAK]EXPORT DMA1_Channel1_IRQHandler[WEAK]EXPORT DMA1_Channel2_IRQHandler[WEAK]EXPORT DMA1_Channel3_IRQHandler[WEAK]EXPORT DMA1_Channel4_IRQHandler[WEAK]EXPORT DMA1_Channel5_IRQHandler[WEAK]EXPORT DMA1_Channel6_IRQHandler[WEAK]EXPORT DMA1_Channel7_IRQHandler[WEAK]EXPORT ADC1_2_IRQHandler[WEAK]EXPORT USB_HP_CAN1_TX_IRQHandler[WEAK]EXPORT USB_LP_CAN1_RX0_IRQHandler[WEAK]EXPORT CAN1_RX1_IRQHandler[WEAK]EXPORT CAN1_SCE_IRQHandler[WEAK]EXPORT EXTI9_5_IRQHandler[WEAK]EXPORT TIM1_BRK_IRQHandler[WEAK]EXPORT TIM1_UP_IRQHandler[WEAK]EXPORT TIM1_TRG_COM_IRQHandler[WEAK]EXPORT TIM1_CC_IRQHandler[WEAK]EXPORT TIM2_IRQHandler[WEAK]EXPORT TIM3_IRQHandler[WEAK]EXPORT TIM4_IRQHandler[WEAK]EXPORT I2C1_EV_IRQHandler[WEAK]EXPORT I2C1_ER_IRQHandler[WEAK]EXPORT I2C2_EV_IRQHandler[WEAK]EXPORT I2C2_ER_IRQHandler[WEAK]EXPORT SPI1_IRQHandler[WEAK]EXPORT SPI2_IRQHandler[WEAK]EXPORT USART1_IRQHandler[WEAK]EXPORT USART2_IRQHandler[WEAK]EXPORT USART3_IRQHandler[WEAK]EXPORT EXTI15_10_IRQHandler[WEAK]EXPORT RTCAlarm_IRQHandler[WEAK]EXPORT USBWakeUp_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 B.;所有未实现中断进入死循环 ENDP ALIGN;------------------------------------------------------------------------------;用户栈和堆初始化(供 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;R0=堆起始地址;R1=栈结束地址;R2=堆结束地址;R3=栈起始地址 LDR R0,=Heap_Mem LDR R1,=(Stack_Mem+Stack_Size)LDR R2,=(Heap_Mem+Heap_Size)LDR R3,=Stack_Mem BX LR ALIGN ENDIF END



这是STM32F10x(Cortex-M3)在 Keil MDK-ARM 下的启动文件(startup),它的作用可以一句话概括:

在 CPU 上电 / 复位后,用最少的汇编代码把系统“拉起来”,再把控制权交给 C 运行库,最终进入main()

下面我按模块 + 按时间顺序给你系统性解读一遍,偏“嵌入式软件工程师视角”。


一、这个文件在系统里的“地位”

在 STM32 工程中:

上电 / 复位 ↓ startup_stm32f10x_md.s ←【你贴的这个】 ↓ SystemInit() ← system_stm32f10x.c ↓ C 运行库 (__main) ↓ main()

👉这是 MCU 启动链路的第 1 个软件节点


二、整体工作流程(先给你一张“脑图”)

完整启动流程:

  1. CPU 复位

  2. Flash 0x08000000取:

    • MSP(主堆栈指针)
    • Reset_Handler 地址
  3. 跳转执行Reset_Handler

  4. Reset_Handler

    • 调用SystemInit()(时钟 / Flash / PLL)
    • 跳转到__main
  5. __main

    • 初始化.data / .bss
    • 初始化堆 / 栈
    • 调用main()
  6. 进入用户程序


三、Stack / Heap 定义(内存布局基础)

1️⃣ 栈(Stack)

Stack_Size EQU 0x00000800 ; 2KB AREA STACK, NOINIT, READWRITE, ALIGN=3 Stack_Mem SPACE Stack_Size __initial_sp

关键点

  • 栈向下生长
  • __initial_sp= 栈顶地址
  • 上电后MSP = __initial_sp
  • 中断 / 异常 / main 都用它(除非你切 PSP)

👉 这是中断安全 + RTOS 能跑的基础


2️⃣ 堆(Heap)

Heap_Size EQU 0x00000400 ; 1KB AREA HEAP, NOINIT, READWRITE, ALIGN=3 __heap_base Heap_Mem SPACE Heap_Size __heap_limit

作用

  • malloc / free / new
  • 不用 C 动态内存时可以设为 0

四、向量表(Vector Table)——最核心的部分

AREA RESET, DATA, READONLY EXPORT __Vectors __Vectors DCD __initial_sp DCD Reset_Handler DCD NMI_Handler DCD HardFault_Handler ...

1️⃣ 向量表本质

表项含义
第 0 项MSP 初始值
第 1 项Reset_Handler
后面各种异常 / 中断 ISR

📌Cortex-M 硬件强制规定的格式


2️⃣ 外设中断向量

DCD USART1_IRQHandler DCD USART2_IRQHandler DCD USART3_IRQHandler

这些名字必须和 ST 标准库 / HAL / LL 对应
否则 NVIC 触发了也找不到函数


3️⃣__Vectors_Size

__Vectors_Size EQU __Vectors_End - __Vectors

调试器 / 链接器使用,没业务逻辑


五、Reset_Handler —— 启动核心

Reset_Handler PROC IMPORT __main IMPORT SystemInit LDR R0, =SystemInit BLX R0 LDR R0, =__main BX R0 ENDP

1️⃣ 这段代码“刻意很短”

原因:

  • 此时堆栈刚建立
  • 不适合复杂逻辑
  • 所有初始化交给 C 层

2️⃣ SystemInit() 干啥?

system_stm32f10x.c

  • 时钟源切换(HSI / HSE)
  • PLL 配置
  • Flash 等待周期
  • 向量表偏移(SCB->VTOR)

👉“裸机能不能跑、跑多快”全在这


3️⃣__main是谁?

不是你写的,是ARM C Runtime

负责:

  • .data拷贝(Flash → SRAM)
  • .bss清零
  • 堆 / 栈初始化
  • 调用main()

六、异常 / 中断处理机制

1️⃣ WEAK 定义的意义

EXPORT USART1_IRQHandler [WEAK]

含义:

  • 你在 C 文件里写同名函数,会自动覆盖
  • 否则走默认死循环

👉 这就是“中断函数不用手动注册”的原理


2️⃣ 默认中断行为

USART1_IRQHandler USART2_IRQHandler ... B .
  • 无限死循环
  • 防止“中断乱飞”
  • 调试时一进来就卡住,方便定位

3️⃣ HardFault / UsageFault 等

HardFault_Handler B .

你以后如果做HardFault 调试
就是在这里改成C 函数 + 寄存器打印


七、Microlib / 非 Microlib 的区别

1️⃣ Microlib(精简库)

IF :DEF:__MICROLIB EXPORT __initial_sp EXPORT __heap_base EXPORT __heap_limit
  • Keil 精简运行库
  • 省空间
  • 启动更简单

2️⃣ 非 Microlib(完整库)

__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

👉 这是告诉 C 运行库:

  • 堆从哪到哪
  • 栈从哪到哪

八、从“工程实践”角度的总结

这个 startup 文件做了什么?

✔ 定义栈 / 堆
✔ 建立中断向量表
✔ 提供默认中断实现(弱符号)
✔ 调用SystemInit()
✔ 跳转到__main → main()


你可以改 / 常改的地方

位置场景
Stack_SizeRTOS / 中断多
Heap_Sizemalloc / LVGL
HardFault_Handler崩溃定位
向量表Bootloader / APP 跳转

一句话终极总结

startup 文件 = MCU 从“硅片”进入“C 世界”的桥梁

如果你愿意,下一步我可以帮你:

  • ✅ 画一张“复位到 main 的时序图”
  • ✅ 结合RT-Thread / FreeRTOS讲 PendSV / SVC
  • ✅ 拆解Bootloader → APP 跳转时这个文件如何配合

你想往哪个方向继续?

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/18 0:26:49

BetterNCM Installer:小白也能轻松上手的网易云音乐增强神器

BetterNCM Installer:小白也能轻松上手的网易云音乐增强神器 【免费下载链接】BetterNCM-Installer 一键安装 Better 系软件 项目地址: https://gitcode.com/gh_mirrors/be/BetterNCM-Installer 厌倦了网易云音乐单调的界面和有限的功能?想要更丰…

作者头像 李华
网站建设 2026/4/18 2:04:40

Kotaemon与向量数据库的高效集成方案

Kotaemon与向量数据库的高效集成方案 在企业智能对话系统日益复杂的今天,一个核心挑战始终存在:如何让AI既“知道得准”,又“答得有据”?大模型本身虽博学,却容易“胡说八道”;传统客服机器人虽稳定&#x…

作者头像 李华
网站建设 2026/4/18 1:53:52

Kotaemon框架的日志监控与运维建议

Kotaemon框架的日志监控与运维建议 在企业级智能对话系统日益复杂的今天,一个看似简单的用户提问背后,可能涉及知识检索、工具调用、多轮状态维护和生成模型推理等多个环节。当系统突然出现响应延迟或无响应时,如果没有清晰的运行轨迹记录&am…

作者头像 李华
网站建设 2026/4/18 2:01:13

23、深入探索SAMBA文件共享与网络打印管理

深入探索SAMBA文件共享与网络打印管理 1. SAMBA文件共享管理 在VMware配置的 smb.conf 文件中,有两个部分控制着客户端对文件系统的访问,分别是 [homes] 和 [HostFS] 。 [homes] 部分 :用于控制对用户主目录的访问,其配置示例如下: [homes]comment = Home dir…

作者头像 李华
网站建设 2026/4/18 2:04:35

静态住宅IP防封的原理

静态住宅IP被视为普通家庭用户的真实IP地址,其流量特征与正常用户行为一致。相较于数据中心IP或动态IP,静态住宅IP更难被平台识别为爬虫或自动化工具,从而降低被封禁的风险。低检测优先级 平台对住宅IP的检测优先级较低。住宅IP通常用于日常上…

作者头像 李华
网站建设 2026/4/18 2:00:00

2、拉格朗日插值法在量子电路参数偏移规则中的应用

拉格朗日插值法在量子电路参数偏移规则中的应用 1. 拉格朗日插值与参数偏移规则基础 在量子计算中,拉格朗日插值法可用于推导参数偏移规则。首先,有如下方程组: [ \begin{cases} d_1 \sin(\frac{\alpha_1}{2}) + d_2 \sin(\frac{\alpha_2}{2}) = \frac{1}{4}\ d_1 \si…

作者头像 李华