短文标题启动流程上电先取栈顶和复位向量再进main你有没有想过一个问题单片机通电后执行的第一条指令是什么不是main甚至不是Reset_Handler。第一步是取栈顶地址第二步是取复位向量。这是硬件固化的行为不依赖任何代码。上电后硬件自动完成的两件事从地址0x00000000读取栈顶地址 → 写入MSP主栈指针从地址0x00000004读取复位向量Reset_Handler地址→ 跳转执行在STM32中0x08000000被映射到0x00000000。实际烧录地址是0x08000000但CPU通过地址映射访问。没有栈C语言无法运行局部变量、函数调用都需要栈。所以硬件第一步必须设栈。中断向量表的结构向量表存放在Flash起始地址0x08000000栈顶地址必须是RAM的有效地址通常是RAM末尾。如果写错比如指向ROM压栈操作会覆盖代码区立即HardFault。Reset_Handler里面做了什么启动文件中的Reset_Handler汇编assemblyReset_Handler:LDR R0, SystemInitBLX R0 ; 调用SystemInit配置时钟LDR R0, __mainBX R0 ; 跳转到C库入口SystemInit配置Flash等待周期、设置PLL、切换系统时钟。__main不是mainC库入口函数负责初始化.data段全局变量赋初值、清零.bss段未初始化全局变量最后调用main。没有__main全局变量初值不生效。向量表的位置可以挪通过VTOR向量表偏移寄存器可以把向量表重定位到RAMSCB-VTOR 0x20000000; // 向量表搬移到RAM用途运行时动态修改中断处理函数热补丁从RAM执行代码时向量表也在RAMBootloader跳转到APP前必须重设VTOR否则APP的中断向量仍指向Bootloader区常见启动失败原因栈顶地址超出RAM范围 → 压栈破坏代码区HardFault复位向量地址未对齐奇数地址→ 总线错误启动文件中断处理函数弱符号被覆盖但未正确声明 → 链接错误或未定义行为向量表放在错误地址如未考虑Flash偏移→ 上电后取向量失败这个故事的启示main不是CPU执行的第一个函数。栈顶地址和复位向量在main之前就已经被硬件加载。启动文件写错main永远跑不起来。写在最后调试“上电没反应”最先检查中断向量表。查看0x08000000第一个字是不是RAM地址第二个字是不是Reset_Handler地址这两个地址对了单片机才有可能“活”过来。本文灵感源于于振南《新概念ARM32单片机》教程第5.5节“ARM32启动流程与中断控制器配置”。觉得有用点赞、转发让更多人看懂启动文件的底层逻辑。