## 为什么需要向量表重映射? STM32的向量表(Vector Table)默认位于Flash起始地址(如0x08000000),存放着复位、中断服务函数(ISR)的入口地址。当Bootloader跳转到App时,App的代码通常位于偏移地址(如0x08010000)。若向量表仍指向Bootloader区域,中断触发时CPU会从错误地址取指,导致程序崩溃。因此,跳转前必须将向量表重映射到App的起始地址。 ## 向量表重映射的两种方式 ### 1. 修改VTOR寄存器(Cortex-M3/M4/M7) 对于Cortex-M3及以上内核(如STM32F1/F2/F3/F4/F7/H7),可通过设置系统控制块中的VTOR(Vector Table Offset Register)寄存器实现重映射。 ```c #define APP_ADDRESS 0x08010000 void jump_to_app(void) { // 设置向量表偏移 SCB->VTOR = APP_ADDRESS; // 后续跳转代码... } ``` ### 2. 使用SYSCFG_MEMRMP寄存器(Cortex-M0/M0+) 对于Cortex-M0/M0+内核(如STM32F0/L0),没有VTOR寄存器,需通过SYSCFG配置内存映射,将Flash的起始地址重映射到App区域。 ```c void jump_to_app(void) { // 使能SYSCFG时钟 RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN; // 重映射Flash到0x08010000 SYSCFG->CFGR1 |= SYSCFG_CFGR1_MEM_MODE_0; // 根据实际芯片调整 } ``` ## 跳转前的关键步骤 ### 1. 关闭全局中断 跳转过程中,任何中断都可能导致不可预知行为。必须确保所有中断关闭,并清除挂起标志。 ```c __disable_irq(); // 关闭所有外设中断(示例:关闭SysTick) SysTick->CTRL = 0; ``` ### 2. 设置主栈指针(MSP) App的起始地址前4字节存放初始栈顶地址,需将其加载到MSP。 ```c typedef void (*pFunction)(void); uint32_t app_stack = *(volatile uint32_t*)APP_ADDRESS; __set_MSP(app_stack); ``` ### 3. 获取App复位向量并跳转 App起始地址后4字节为复位向量,即App的入口函数地址。 ```c pFunction app_entry = (pFunction)(*(volatile uint32_t*)(APP_ADDRESS + 4)); app_entry(); ``` ### 4. 完整跳转函数示例 ```c #define APP_ADDRESS 0x08010000 void jump_to_app(void) { // 1. 关闭全局中断 __disable_irq(); // 2. 关闭SysTick SysTick->CTRL = 0; // 3. 设置向量表偏移(Cortex-M3/M4) SCB->VTOR = APP_ADDRESS; // 4. 设置主栈指针 uint32_t app_stack = *(volatile uint32_t*)APP_ADDRESS; __set_MSP(app_stack); // 5. 跳转 pFunction app_entry = (pFunction)(*(volatile uint32_t*)(APP_ADDRESS + 4)); app_entry(); // 6. 不应返回 while(1); } ``` ## App端的配合设置 ### 1. 链接脚本修改 App工程需将Flash起始地址和中断向量表偏移到APP_ADDRESS。以GCC为例: ```c /* Linker script */ FLASH (rx) : ORIGIN = 0x08010000, LENGTH = 128K ``` ### 2. 启动文件中的向量表重映射 在App的SystemInit函数或启动文件中,需再次设置VTOR: ```c void SystemInit(void) { SCB->VTOR = 0x08010000; // 其他初始化... } ``` ### 3. 中断服务函数注意 App中所有中断服务函数必须正确声明,且向量表偏移已生效,否则中断无法响应。 ## 常见问题与调试技巧 - **跳转后死机**:检查栈指针是否正确,确认App的链接脚本偏移无误。 - **中断不工作**:确认VTOR设置成功,且App的SystemInit已执行。 - **时钟配置冲突**:Bootloader和App可能使用不同时钟,跳转前无需重置时钟,但App应重新初始化所有外设。 - **使用调试器**:在跳转函数处设置断点,单步执行,观察寄存器值。 - **检查Flash写入**:确保App已正确烧录到目标地址,可通过读取内存验证。 ## 总结 向量表重映射是Bootloader跳转的核心,理解其原理可避免诸多隐患。本文通过代码示例演示了Cortex-M3/M4的VTOR方法,并提及M0的替代方案。实际开发中,还需结合具体芯片手册,确保配置正确。掌握此技术,可为IAP(在应用编程)打下坚实基础。