当前位置: 首页 > news >正文

单片机bootloader(APP的自我复制)

文章目录

  • Bootloader 中 APP 的自我复制与启动机制解析
    • 一、为什么要进行自我复制?
    • 二、程序整体结构概述
    • 三、汇编启动代码分析
      • 重点解释:
    • 四、C 语言部分分析
      • 核心功能:
    • 五、start\_app 函数:手动启动指定 APP
    • 六、总结
    • 七、适用场景



Bootloader 中 APP 的自我复制与启动机制解析

在嵌入式系统中,我们常常会使用 Bootloader 作为程序的引导入口,它负责初始化系统资源、判断是否需要升级程序,并最终跳转至应用程序(APP)运行。本文将讲解一种特殊但实用的技巧:Bootloader 在启动后将自身复制到 RAM 中运行,并在复制完成后,从 RAM 重新启动整个程序。


一、为什么要进行自我复制?

Flash 中执行程序是常规做法,那为何还需要将程序复制到 RAM 呢?主要原因有以下几点:

  1. 加快执行速度
    Flash 的访问速度相较 RAM 要慢,而将代码复制到 RAM 后运行,能显著提升程序执行效率。

  2. 实现代码完整重定位(Position-independent)
    某些平台在运行时对代码地址有特殊要求,比如要求代码在 RAM 的某一位置执行。

  3. 为程序热升级或 OTA 预留空间
    通过 RAM 运行,可以在 Flash 中擦除/替换当前正在执行的程序,为系统升级打下基础。


二、程序整体结构概述

这段代码主要由两部分构成:

  1. 启动入口(Reset Handler)
  2. 自我复制函数与主函数(mymain)

三、汇编启动代码分析

__Vectors       DCD     0x20010000         ; 启动时设置的初始栈地址DCD     0x08040009         ; Reset_Handler 的地址(带 Thumb 标志)Reset_Handler   PROCEXPORT  Reset_HandlerIMPORT  mymainIMPORT  copy_myselfIMPORT |Image$$ER_IROM1$$Length|adr     r0, Reset_Handler     ; 获取 Reset_Handler 当前地址bic     r0, r0, #0xFF         ; 取整对齐到 Flash 起始地址ldr     r1, =__Vectors        ; RAM 中目标地址(0x20010000)ldr     r2, =|Image$$ER_IROM1$$Length| ; 段长度(从链接脚本中获取)BL      copy_myself           ; 执行复制操作ldr     pc, =mymain           ; 跳转到 RAM 中的主函数执行ENDP

重点解释:

  • adr r0, Reset_Handler:获取当前代码的实际地址(此时仍在 Flash)。
  • bic r0, r0, #0xFF:对地址按 256 字节对齐,作为复制源起始地址。
  • ldr r1, =__Vectors:复制目标是 RAM 的某段地址,比如 0x20010000。
  • copy_myself:这是用户编写的复制函数,将当前程序代码整体复制到 RAM。
  • ldr pc, =mymain:复制完成后,直接跳转至 RAM 中的入口函数。

四、C 语言部分分析

void copy_myself(int *from, int *to, int len)
{for (int i = 0; i < len / 4 + 1; i++){to[i] = from[i];}
}int mymain()
{char c = 'A';int (*fp)(char) = putchar;putstr("www.100ask.net");while (1){fp(c++);putchar(c++);delay(1000000);if (c == 'Z') c = 'A';}
}

核心功能:

  • copy_myself:按字节复制程序代码到 RAM。
  • mymain:RAM 中的入口函数,简单测试输出字符,验证程序是否正常工作。

五、start_app 函数:手动启动指定 APP

在另一个文件中,还定义了如下函数,用于启动任意地址的应用程序:

start_app   PROCEXPORT  start_appldr r3, =0xE000ED08     ; VTOR 寄存器地址str r0, [r3]            ; 设置中断向量基地址(如 0x08040000)ldr sp, [r0]            ; 初始化栈指针ldr r1, [r0, #4]        ; 获取复位向量地址BX  r1                  ; 跳转到 APP 启动ENDP

这个函数常用于从 Bootloader 跳转到真正的应用程序。


六、总结

整个流程可总结如下:

  1. MCU 上电后执行 Bootloader。
  2. Bootloader 将自身从 Flash 复制到 RAM。
  3. 跳转到 RAM 中的主函数运行,实现从 RAM 启动。
  4. (可选)通过 start_app 跳转到其他 APP 地址运行,实现多段代码管理。

七、适用场景

  • RAM 空间充足,希望提升执行速度;
  • 程序需动态更新或热加载;
  • Flash 中只保留一段主程序,但需要运行时自迁移机制。


相关文章:

  • Cursor 使用分享
  • ​小学五年级的语言来解释符号​
  • 鸿蒙Next仓颉语言开发实战教程:店铺详情页
  • 快速使用 Flutter 的 Dialog 和 AlertDialog
  • SpringBoot请求限流(RateLimiter)
  • Python开发基础手语识别(基础框架版)
  • 什么是Ansible Jinja2
  • Ansible+Zabbix-agent2快速实现对多主机监控
  • 关于YOLOV5—Mosaic数据增强
  • Java解析前端传来的Unix时间戳
  • Element-Plus:popconfirm与tooltip一起使用不生效?
  • 机器学习笔记【Week8】
  • C++11作用域枚举(Scoped Enums):从入门到精通
  • LeetCode Hot100刷题——三数之和
  • 直曲联合!【连续测量】让CAD多线段长度测量精准与效率双升级
  • C/C++ 面试复习笔记(5)
  • Vite 插件使用全攻略(含自动导入)
  • Codeforces Round 1029 (Div. 3)
  • QT 仿网易云项目
  • SQL-labs通关(23-38)
  • 网站制作2007/地推网推平台
  • dreamwear做网站步骤/mac923水蜜桃923色号
  • 上海做网站报价/怎么申请域名建网站
  • 网站建设助手 西部数码/营销方式方案案例
  • 建站平台塔山双喜/最好的免费信息发布平台
  • 仪器仪表行业网站建设/冯耀宗seo课程