LPC845如何判定bootloader是从应用跳转启动还是正常上电启动?
通用 BootLoader 启动源区分方案
核心实现思路
基于上电自动重置、软件可读写、不被系统初始化流程自动清空的存储区域传递标识位,不依赖特定单片机的专属寄存器,适配所有支持自定义内存划分的芯片平台。
具体实现步骤
- 首先在项目链接脚本中划分一块独立的保留存储段,仅需4字节大小,设置为 noinit 属性(不被C语言全局变量初始化逻辑自动清0),该段禁止分配给Bootloader或应用的普通变量使用。
- 定义固定的跳转标识值,例如
#define BOOT_FROM_APP_MAGIC 0x12345678,取值避开芯片上电后存储区域的默认值即可,优先选随机碰撞概率极低的32位特殊值。 - 应用端跳转Bootloader前,先往保留存储段写入预设的标识值,再执行跳转指令。
- Bootloader启动的最优先逻辑判断存储段的标识值:
- 若值与预设标识完全匹配,判定为应用跳转触发启动,执行对应特定任务,任务执行完成后立刻清空该标识值,避免后续重启误判
- 若值与预设标识不匹配,判定为正常上电/硬件复位启动,走常规的应用有效性检测、跳转逻辑
跨平台适配注意点
- 存储区域可根据芯片资源灵活选择:优先选用普通用户SRAM,需要支持掉电保留标识的场景可以换用RTC域备份寄存器,逻辑完全通用。
- 若使用SRAM作为存储介质,需避开芯片BootROM、硬件复位逻辑会主动清空的SRAM区间,选择用户可自由访问的SRAM段即可。
- 对安全性要求较高的场景可以把标识长度扩展到8字节,进一步降低随机值碰撞的误判概率。
示例代码片段
// 保留存储段地址,根据自身链接脚本配置调整,此处假设为0x10007FFC #define MAGIC_ADDR (*((volatile uint32_t *)0x10007FFC)) #define BOOT_FROM_APP_MAGIC 0x12345678 // 应用端跳转Bootloader前调用 void jump_to_bootloader(void) { // 写入跳转标识 MAGIC_ADDR = BOOT_FROM_APP_MAGIC; // 关闭所有外设中断、设置主栈指针,执行跳转逻辑 // 此处省略芯片通用跳转实现代码 } // Bootloader启动入口处优先调用 void check_boot_source(void) { if (MAGIC_ADDR == BOOT_FROM_APP_MAGIC) { // 立刻清除标识避免重复触发 MAGIC_ADDR = 0; // 执行应用跳转触发的自定义任务 do_special_task(); } else { // 正常上电启动逻辑,检测应用有效性并跳转 check_app_and_jump(); } }
方案优势
- 无芯片平台依赖,只要有可用RAM/备份寄存器就能实现,可复用至所有单片机
- 逻辑极简,仅需一次32位变量读写,执行效率极高
- 稳定性强,标识值选取得当的前提下误判概率几乎为0
内容的提问来源于stack exchange,提问作者jtro
相关产品推荐
相关产品推荐

