单片机启动过程解析
单片机启动过程解析
一、正常程序运行流程

初始化阶段
- MSP初始化:上电后处理器从
0x8000000
地址读取主堆栈指针(MSP)
初始值(占据0x8000000~0x8000003
)。 - PC跳转:从
0x8000004
地址读取复位中断向量值,程序计数器(PC)
跳转至该地址。
- MSP初始化:上电后处理器从
复位中断处理
- 关键操作:
Reset_Handler
依次执行:- 初始化系统时钟(
SystemInit
) - 将
.data
段从Flash
复制到RAM
- 清零
.bss
段 - 调用
__main
(完成C库
初始化)
- 初始化系统时钟(
- 关键操作:
用户程序执行
- 跳转至
main
函数执行用户代码。 - 中断机制:无中断时运行主循环;中断触发时通过中断向量表跳转至对应服务程序,执行后返回断点继续运行。
- 跳转至
二、中断向量表机制
- 地址计算:
中断向量地址 = 0x8000000 + 4 * (IRQn + 16)
- 注:之所以可以找到复位中断程序,是因为中断向量表占据的是从
0x8000000
起始的连续空间,且每个中断占4字节,按固定顺序存放在表中。 - 注:不同芯片厂商可能采用不同偏移规则(如
STM32
复位向量位于第2项),需以具体手册为准。
- 注:之所以可以找到复位中断程序,是因为中断向量表占据的是从
- 异常处理:复位中断
(IRQn=-15)
位于向量表第1项,地址为0x8000004
。
三、加入IAP
后的启动流程

BootLoader
阶段- 上电后执行
IAP
的Reset_Handler
,跳转至IAP
的main
函数。 - 完成固件接收、校验、写入等操作。
- 上电后执行
跳转至应用程序
- 无需复位:
IAP
直接跳转至APP
入口(如0x8003000
)。 - 关键操作:
- 重设
MSP
:从APP
起始地址读取新MSP
值。 - 重映射向量表:
SCB->VTOR = 0x8003000;
- 重设
- 无需复位:
应用程序执行
- 执行
APP
的Reset_Handler
,流程同正常启动。
- 执行
四、关键注意事项
向量表重映射
GD32F330
特性:SystemInit()
默认设置VTOR
,用户需在其后重设:1
2SystemInit(); // 库函数可能覆盖VTOR
SCB->VTOR = APP_ADDR; // 需在SystemInit之后设置低功耗唤醒:部分芯片唤醒后
VTOR
复位,需重新配置。其他芯片:使用任何芯片在设置
VTOR
前都应先查看是否有其他地方已经设置过了!
跨厂商差异
STM32
的复位向量为向量表第2项(地址0x8000004
)。- 需查阅芯片参考手册确认中断向量偏移规则。
IAP
设计要点- 跳转前准备:关闭所有中断,清理外设状态。
- 地址对齐:
APP
起始地址需满足芯片的Flash
扇区对齐要求。 - 示例跳转代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24typedef void (*pFunction)(void);
uint32_t ApplicationAddress = 0x8003000;
/**
* @brief 跳转到用户程序执行
*/
uint8_t Jump_To_User_Program(void)
{
__disable_irq();
if (((*(__IO uint32_t *)ApplicationAddress) & 0x2FFE0000) == 0x20000000)//判断用户是否已经下载程序,防止跑飞
{
//跳转至用户代码
JumpAddress = *(__IO uint32_t *)(ApplicationAddress + 4);
Jump_To_Application = (pFunction)JumpAddress;
//初始化用户程序的堆栈指针
__set_MSP(*(__IO uint32_t *)ApplicationAddress);
Jump_To_Application();
}
else
{
return 1;
}
return 0;
}
五、附录:关键段说明
段名 | 作用 | 存储位置 |
---|---|---|
.data | 存储已初始化的全局变量 | RAM |
.bss | 存储未初始化的全局变量(启动时清零) | RAM |
.text | 存储程序代码和常量 | Flash |
__main | C库初始化(堆栈、静态变量等) | 自动调用 |
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 龙猫知识库!