STM32F103芯片的启动过程
一、启动概述
STM32F103从上电到运行用户程序经历了一个精确的启动序列,主要包括硬件复位、启动模式选择、堆栈指针初始化、跳转到复位处理程序等步骤。
二、启动模式选择
1. 三种启动模式
STM32F103通过BOOT0和BOOT1引脚的电平状态决定启动模式:
-
主闪存启动 (BOOT1=X, BOOT0=0)
- 从0x08000000地址启动
- 这是最常用的模式,运行用户程序
-
系统存储器启动 (BOOT1=0, BOOT0=1)
- 从0x1FFFF000地址启动
- 运行ST出厂固化的Bootloader
- 用于通过串口等接口下载程序
-
内置SRAM启动 (BOOT1=1, BOOT0=1)
- 从0x20000000地址启动
- 用于调试或运行RAM中的代码
2. 地址映射机制
根据启动模式,0x00000000地址会被映射到不同的物理地址:
- 主闪存模式:0x00000000映射到0x08000000
- 系统存储器模式:0x00000000映射到0x1FFFF000
- SRAM模式:0x00000000映射到0x20000000
三、详细启动流程
1. 上电复位阶段
上电 → POR/PDR复位 → 等待时钟稳定 → 读取BOOT引脚
- 电源监控:POR(Power On Reset)和PDR(Power Down Reset)监控电源电压
- 复位延时:确保电源稳定,典型值约为几毫秒
- HSI启动:默认使用8MHz内部高速时钟(HSI)作为系统时钟
2. 向量表读取
芯片首先从启动地址读取两个重要的32位数据:
地址0x00000000: 初始堆栈指针值(MSP)
地址0x00000004: 复位向量(Reset_Handler地址)
3. 硬件初始化
// CPU自动执行的操作:
1. SP = 读取地址0x00000000的值 // 设置主堆栈指针
2. PC = 读取地址0x00000004的值 // 跳转到Reset_Handler
4. Reset_Handler执行
这是第一个执行的用户代码,通常完成:
Reset_Handler:// 1. 设置向量表偏移寄存器(如果需要)SCB->VTOR = FLASH_BASE;// 2. 初始化数据段(.data)// 从Flash复制初始化数据到RAM// 3. 清零BSS段// 将未初始化的全局变量清零// 4. 调用SystemInit()// 配置时钟系统、PLL等// 5. 调用C库初始化(如果使用)__libc_init_array();// 6. 跳转到main函数main();
5. SystemInit系统初始化
SystemInit()函数主要完成:
-
时钟配置
- 使能HSE(外部高速时钟)
- 配置PLL倍频
- 设置AHB、APB1、APB2分频器
- 切换系统时钟源到PLL
-
Flash访问配置
- 设置Flash预取缓冲
- 配置Flash等待周期
-
中断向量表配置
- 设置向量表偏移地址
四、启动时序示例
时间线:
0ms: 上电,POR复位激活
1-2ms: 电压稳定,读取BOOT引脚
2ms: 从0x08000000读取MSP值
2.1ms: 从0x08000004读取Reset_Handler地址
2.2ms: 跳转执行Reset_Handler
3ms: 执行SystemInit,配置时钟
5ms: 时钟切换完成,进入main函数
五、重要寄存器
1. RCC寄存器
- RCC_CR: 时钟控制寄存器
- RCC_CFGR: 时钟配置寄存器
- RCC_CSR: 控制/状态寄存器(包含复位标志)
2. SCB寄存器
- SCB_VTOR: 向量表偏移寄存器
- SCB_AIRCR: 应用中断和复位控制寄存器
六、启动代码示例
典型的启动文件结构(startup_stm32f103.s):
.section .isr_vector
.word _estack /* 栈顶地址 */
.word Reset_Handler /* 复位处理函数 */
.word NMI_Handler /* NMI处理函数 */
.word HardFault_Handler /* 硬件错误处理 */
/* ... 其他中断向量 ... */Reset_Handler:/* 复制.data段 */ldr r0, =_sdataldr r1, =_edataldr r2, =_sidata/* ... 复制代码 ... *//* 清零.bss段 */ldr r0, =_sbssldr r1, =_ebss/* ... 清零代码 ... *//* 调用系统初始化 */bl SystemInit/* 调用main函数 */bl main
七、注意事项
-
启动时间优化
- 减少全局变量初始化
- 优化时钟配置流程
- 合理设置Flash等待周期
-
调试技巧
- 通过RCC_CSR寄存器判断复位原因
- 使用GPIO翻转监测启动时间
- 检查向量表配置是否正确
-
常见问题
- 晶振不起振导致启动失败
- Flash等待周期设置不当
- 堆栈溢出导致启动异常
这个启动过程确保了STM32F103能够可靠地从复位状态过渡到运行用户应用程序,整个过程通常在几毫秒内完成。