Bootloader 跳转到 RT-Thread 或 FreeRTOS(基于 STM32)
Bootloader 跳转到 RT-Thread 或 FreeRTOS(基于 STM32) 作者:猾蚁 QQ:7376220
一、Bootloader 程序
1. 准备好升级程序项目,可以使用 STM32CubeMX 来自动生成代码,然后自己编
写代码实现升级策略。
2. 跳转代码实现

/* BOOTLOADER */ #define BOOT_LOADER_Address 0x08000000 #define BOOT_LOADER_SIZE (200*1024) //0x32000(200KB) #define BOOT_OS_Address (BOOT_LOADER_Address+BOOT_LOADER_SIZE) typedef void (*pFunction)(void); pFunction Jump_To_Application; uint32_t JumpAddress; static void jump_to_os(void); //重定向 printf intfputc(intch,FILE*f) { while((USART1->SR&0X40)==0); USART1->DR=(uint8_t)ch; return ch; } int main(void) { HAL_Init(); SystemClock_Config(); MX_USART1_UART_Init(); //在这里实现升级策略 printf("user_init()\r\n"); //升级完成后程序跳转到 RT-Thread jump_to_os(); } static void jump_to_os(void) { if(((*__IOuint32_t*)BOOT_OS_Address)&0x2FFE0000)==0x20000000) { /*Jump to user application*/ printf("jump_to_os\r\n"); __disable_irq();//关闭总中断 HAL_DeInit(); JumpAddress=*(__IOuint32_t*)(BOOT_OS_Address+4); Jump_To_Application=(pFunction)JumpAddress; /*Initializeuserapplication'sStackPointer*/ __set_MSP(*(__IOuint32_t*)BOOT_OS_Address); Jump_To_Application(); } else { printf("BOOT_OS_Address:%08X\rn",*__IOuint32_t*)BOOT_OS_Address); } }
3. Keil 设置
上面的 IROM1 的 Size 设置与前面宏定义 BOOT_LOADER_SIZE 值相同,值为十六
进制
这里的 Start、size 和前面的 IROM1 设置相同
编译后下载,因为前面未选择 ResetandRun,下载完成后程序不会运行。
二、RT-Thread 程序
1. 准备好 RT-Thread 项目,确认项目可成功编译运行。
2. 重定义中断向量表地址
找 到 stmtem_stm32fnxx.c 文 件 中 的 SystemInit 函 数 , 找 到 SCB->VTOR =
FLASH_BASE | VECT_TAB_OFFSET 这一句,转到 VECT_TAB_OFFSET 的宏定义,修
改值为前面 BOOT_LOADER_SIZE 的值:#defineVECT_TAB_OFFSET 0x32000
3. 启用 SystemInit 函数,使上面中断向量表重定义生效
SystemInit 函数没有被任何 C 代码调用,它在启动汇编代码中被导入调用。启用
startup_stm32fnnnxx.s 文件中 SystemInit 被调用的相关代码(去掉分号注释即
可) ,启用后如下图:
4. Keil 设置
IROM1的Start设置为前面BOOT_OS_Address定义的值, size设置为MCU的Flash
总大小减去 BOOT_LOADER_SIZE 后剩余的大小。
这里的 Start、size 和前面的 IROM1 设置相同
编译后下载,如果上面选择了 ResetandRun,下载完成后程序会从 Bootloader
开始运行,实现程序升级过程后跳转到 RT-Thread 运行,如下图
引申:中断向量表重定向,注意2点:偏移值要是0x200的整数倍;只所以偏移值与0x1ffffff8进行位与是因为寄存器的7~28位是用来存储偏移值的,
其它参考:
https://www.pianshen.com/article/72501341311/
https://www.cnblogs.com/michaelHeaven/p/3418705.html
https://blog.csdn.net/m0_37738150/article/details/79498220
http://www.eeworld.com.cn/mcu/2018/ic-news081940856.html
http://www.eeworld.com.cn/mcu/2018/ic-news081940854.html
https://wenku.baidu.com/view/6748673201f69e3143329496.html 振南的znFAT
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
2016-02-25 变量的条件编译
2015-02-25 路由器的设置