01-跳转
2026/5/20大约 2 分钟
01-跳转
基础信息
stm32f103c8t6的flash大小64kb,sram大小为20kb
新建一个APP
配置Debug

配置时钟


配置LED

其他


代码

写好后直接烧录,看看能不能正常运行: 每秒闪一次led, 同时向串口1发送app is running,正常运行后下一步
代码并没有写完,要看到最后!!!
创建Boot工程
配置
配置与上面的app相同,只是多了个按钮
修改优化
开发boot阶段优化务必改成-O0,后面搞好了再改成-O3或者其他!!!
获取二进制文件
使用fromelf --bin -o "$L@L.bin" "#L,每次编译后会在编译文件夹生成二进制文件夹
代码
#define APP_ADDRESS 0x08005000U // 指向等会要跳转到地方
void JumpToApplication(void) {
uint32_t app_sp = *(__IO uint32_t*)APP_ADDRESS; // 到指定位置查看sp指针正不正常
uint32_t app_pc = *(__IO uint32_t*)(APP_ADDRESS + 4); // 到指定位置查看pc指针正不正常
// 将它们打印出来
char data[50]="";
HAL_UART_Transmit(&huart1,(uint8_t*)"boot start run!\r\n",sizeof("boot start run!\r\n"),1000);
sprintf(data,"SP:0x%08X,PC:0x%08X\r\n",app_sp,app_pc);
HAL_UART_Transmit(&huart1,(uint8_t*)data,strlen(data),1000);
// 判断堆栈指针正不正常
if((app_sp & 0x2FFE0000) == 0x20000000) {
// 1. 彻底“缴械”所有外设,清除一切潜在的中断源
HAL_RCC_DeInit();
HAL_DeInit();
SysTick->CTRL = 0;
SysTick->LOAD = 0;
SysTick->VAL = 0;
// 2. 清除 NVIC 挂起标志,确保战场绝对干净
for (uint32_t i = 0; i < 8; i++) {
NVIC->ICER[i] = 0xFFFFFFFF;
NVIC->ICPR[i] = 0xFFFFFFFF;
}
// 3. 重定向中断向量表
SCB->VTOR = APP_ADDRESS;
// 4. 开启全局中断(因为外设已被彻底缴械,此时开门绝对安全,且能拯救 App 的 HAL_Delay)
__enable_irq();
// 5. 危险区:切换栈指针并直接跳转(拒绝使用局部变量)
__set_MSP(*(__IO uint32_t*)APP_ADDRESS);
((void (*)(void)) (*(__IO uint32_t*)(APP_ADDRESS + 4)))();
} else {
HAL_UART_Transmit(&huart1,(uint8_t*)"[BOOT] ERROR: SP Validation FAILED!\r\n",sizeof("ERROR: SP Validation FAILED!\r\n"),1000);
}
}