针对qboot跳转APP卡死的问题,以下是系统性的解决方案:
// 在跳转函数中添加(假设APP起始地址为0x08010000)
SCB->VTOR = 0x08010000; // 设置应用层中断向量表地址
__DSB(); // 数据同步屏障main()开头同步设置 // APP的main()函数首行添加
SCB->VTOR = 0x08010000 | 0x20000000; // 若有RAM偏移需组合地址 void jump_to_app(uint32_t app_addr) {
typedef void (*pFunction)(void);
pFunction app_entry;
uint32_t stack_ptr = *(volatile uint32_t*)app_addr; // 获取APP栈顶地址
__set_MSP(stack_ptr); // 设置主堆栈指针
app_entry = (pFunction)(*(volatile uint32_t*)(app_addr + 4)); // 复位函数地址
app_entry(); // 跳转
} RCC->CR |= RCC_CR_HSION; // 开启内部高速时钟
while ((RCC->CR & RCC_CR_HSIRDY) == 0); // 等待就绪
RCC->CFGR = 0x00000000; // 复位时钟配置
RCC->CR &= ~RCC_CR_PLLON; // 关闭PLL RCC->APB1RSTR = 0xFFFFFFFF; // 复位APB1外设
RCC->APB2RSTR = 0xFFFFFFFF; // 复位APB2外设
RCC->AHB1RSTR = 0xFFFFFFFF; // 复位AHB1外设
RCC->APB1RSTR = 0x00000000; // 清除复位
RCC->APB2RSTR = 0x00000000;
RCC->AHB1RSTR = 0x00000000; __disable_irq(); // 关闭全局中断
for (int i = 0; i < 8; i++) {
NVIC->ICER[i] = 0xFFFFFFFF; // 禁用中断
NVIC->ICPR[i] = 0xFFFFFFFF; // 清除挂起标志
}STM32F417ZGTx_FLASH.ld): MEMORY {
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K
FLASH (rx) : ORIGIN = 0x08010000, LENGTH = 896K // 偏移64K给Bootloader
}启动文件.s中添加HardFault捕获函数0x08008000readelf -a bootloader.elf查看实际大小__attribute__((naked))防止栈破坏 __attribute__((naked)) void jump_to_app(uint32_t addr) {
__asm volatile(
"ldr r1, [r0, #0x00] n" // 加载栈指针
"msr msp, r1 n"
"ldr r1, [r0, #0x04] n" // 加载复位地址
"bx r1 n"
);
}void firmware_jump(uint32_t addr) {
// 1. 关闭所有外设时钟和中断
disable_peripherals();
// 2. 重置时钟
reset_clock_to_default();
// 3. 设置向量表偏移
SCB->VTOR = addr;
__DSB();
// 4. 禁用全局中断
__disable_irq();
// 5. 执行跳转
jump_to_app(addr); // 使用前述跳转函数
}
验证顺序:
- 用J-Link读取APP起始地址的内容,确认前8字节包含有效栈顶和复位地址
- 在跳转前暂停调试,手动修改PC到APP复位地址,检查是否运行
- 减小APP复杂度(如仅保留LED闪烁),排除APP自身问题
通过以上步骤系统排查,90%以上的跳转问题可解决。关键点在于中断向量表重定位和彻底清理MCU状态。
举报
更多回帖