单片机通用Bootloader框架

2023-11-14


最近搞了Bootloader,春节没准备回家所以带了硬件,当时有些问题,嗑了两袋瓜子处理了,目前在STM32H743和STM32F407、STM32F103ZET6上测试完毕,具有较高的移植性。
整个Bootloader依赖开源FAL和LetterShell无其他依赖, 移植方法参考之前的博文,对片内Flash使用FAL分区管理,形成统一接口。目前已实现Ymodem协议的文件传输,并留有自定义传输协议接口。

终端控制台预览

这里示范了:引导倒计时,固件下载,上传,app程序未写入升级成功标识时的Bootloader自动从factory恢复固件。
在这里插入图片描述

flash分区

         _       _   _    _____          _   _______                 _     
        (_)     | | (_)  / ____|        (_) |__   __|               | |    
  __ _   _    __| |  _  | (___     ___   _     | |      ___    ___  | |__  
 / _` | | |  / _` | | |  \___ \   / __| | |    | |     / _ \  / __| | '_ \ 
| (_| | | | | (_| | | |  ____) | | (__  | |    | |    |  __/ | (__  | | | |
 \__,_| |_|  \__,_| |_| |_____/   \___| |_|    |_|     \___|  \___| |_| |_|

Build:       Feb 14 2021 01:32:15
Version:     3.0.6
Copyright:   (c) 2021 aidiSciTech
/*在终端输入任意键停止引导倒计时,一开始没有输入的情况下3s倒计时时间,每输入时重置为30s倒计时*/
aidi:/$ Please press any key to stop bootloader, when 1 S later app jump.

/*倒计时时间到,读取当前使用的固件信息,检测为Wait Update时,说明固件已烧录APP分区,等待跳转,若成功跳转执行则APP程序修改flag为更新完成状态,否则每次bootloader会记录Wait Update的次数,超过设定出错次数,说明固件存在问题,自动使用factory分区固件进行恢复*/
firmware name: aidi_app.bin, size : 115840 Bytes, update flag:00AD6666 Wait Update.
                                                                
erase flag partition ...
[I/FAL] first erase page:14
[I/FAL] end erase page:15
[I/FAL] erase page:0x06,PAGES:2,BANK:2
[I/FAL] erase size:262144
write flag partition ok.

/*执行跳转APP分区阶段*/                                                                
read top address of stack : 24018C70
check stack in:24000000

/*以下为APP分区执行,输出*/                                                                
APP Ver:V1.0,stack addr:0x24018C70.
                                                                
[D/FAL] (fal_flash_init:63) Flash device |             stm32_onchip | addr: 0x08000000 | len: 0x00200000 | blk_size: 0x00020000 |initialized finish.
[I/FAL] ==================== FAL partition table ====================
[I/FAL] | name     | flash_dev    |   offset   |    length  |
[I/FAL] -------------------------------------------------------------
[I/FAL] | bl       | stm32_onchip | 0x00000000 | 0x00020000 |
[I/FAL] | app      | stm32_onchip | 0x00020000 | 0x00080000 |
[I/FAL] | download | stm32_onchip | 0x000a0000 | 0x00060000 |
[I/FAL] | factory  | stm32_onchip | 0x00100000 | 0x00080000 |
[I/FAL] | kv       | stm32_onchip | 0x00180000 | 0x00040000 |
[I/FAL] | flag     | stm32_onchip | 0x001c0000 | 0x00040000 |
[I/FAL] =============================================================
[I/FAL] Flash Abstraction Layer (V0.5.0) initialize success.
  • bl:bootloader分区
  • app:运行分区
  • download:新固件下载区
  • factory:出厂固件分区,当新固件运行存在问题,开机启动长按恢复按键,恢复至出厂固件
  • kv:key-value键值对参数存储分区
  • flag:升级标志存储区

APP分区固件制作

设置中断向量表

在main入口加入以下代码

/**
  ******************************************************************
  * @brief   中断向量表设置
  * @param   [in]None
  * @return  None.
  * @author  aron566
  * @version V1.0
  * @date    2021-01-18
  ******************************************************************
  */
void User_InterruptVectorTable_Move(void)
{
  /* 设置中断向量表*/
  SCB->VTOR = FLASH_BANK1_BASE+(128*1024);
}

设置flash起始地址

在这里插入图片描述

加入升级成功标识写入

在其他必须的初始化完成后,加入以下代码

#include "Flash_Port.h"

/*升级标识*/
typedef enum
{
  UPDATE_SUCESSFUL  = 0xAD8888,         /**< 更新成功*/
  UPDATE_WAITTING   = 0xAD6666,         /**< 等待更新*/
  DOWNLOAD_COMPLETE = 0xAD5555,         /**< 下载完成*/
}FRIMWARE_UPDATE_FLAG_Typedef_t;

/*固件信息*/
typedef struct
{
  char FrimwareName[64];                /**< 固件名称*/
  uint32_t FrimwareSize;                /**< 固件大小*/
  FRIMWARE_UPDATE_FLAG_Typedef_t Flag;  /**< 升级标识*/
  uint32_t Retry_Cnt;                   /**< 等待更新次数累计*/
}FRIMWARE_INFO_Typedef_t;

#define FRIMWARE_FLAG_PARTITION_NAME        "flag"    /**< 升级标识分区名*/

FRIMWARE_INFO_Typedef_t Frimware_Info;
/**
  ******************************************************************
  * @brief   获取固件信息
  * @param   [out]Frimware_Info 信息存储区.
  * @return  None.
  * @author  aron566
  * @version v1.0
  * @date    2021/2/11
  ******************************************************************
  */
static void Get_Frimware_Info(FRIMWARE_INFO_Typedef_t *Frimware_Info)
{
  int ret = Flash_Port_Read_Partition_Data(FRIMWARE_FLAG_PARTITION_NAME, 
                              (uint8_t *)Frimware_Info, 0, sizeof(FRIMWARE_INFO_Typedef_t));
  if(ret < 0)
  {
    printf("get frimware info faild.\r\n");
  }
  printf("\r\nfirmware name: %s, size : %u Bytes, update flag:%08X ", Frimware_Info->FrimwareName
        ,Frimware_Info->FrimwareSize, Frimware_Info->Flag);
  switch(Frimware_Info->Flag)
  {
    /*更新成功*/
    case UPDATE_SUCESSFUL:
      printf("App Frimware Ok.\r\n");
      break;
    /*等待更新*/
    case UPDATE_WAITTING:
      printf("Update Frimware Ok.\r\n");
      Frimware_Info->Flag = UPDATE_SUCESSFUL;
      Write_Frimware_Info(Frimware_Info);
      break;
    default:
      printf("Unknow flag.\r\n");
      break;
  }
}

/**
  ******************************************************************
  * @brief   写入固件信息
  * @param   [in]Frimware_Info 固件信息.
  * @return  None.
  * @author  aron566
  * @version v1.0
  * @date    2021/2/12
  ******************************************************************
  */
static void Write_Frimware_Info(FRIMWARE_INFO_Typedef_t *Frimware_Info)
{
  /*擦除信息*/
  printf("erase flag partition ...\r\n");
  Flash_Port_Erase_Partition(FRIMWARE_FLAG_PARTITION_NAME);
  Flash_Port_Write_Partition_Data(FRIMWARE_FLAG_PARTITION_NAME,
                              (uint8_t *)Frimware_Info, 0, sizeof(FRIMWARE_INFO_Typedef_t));
  printf("write flag partition ok.\r\n");
}

生成可烧写bin文件

键入以下命令

fromelf --bin !L --output App_V1.0.bin

在这里插入图片描述

固件升级与上载

支持协议:YMODEM,其他自定义,支持ymodem协议传输的软件:SecureCRT

更新固件

#启动接收命令格式:upgrade 协议 分区名
upgrade ymodem download
upgrade ymodem factory

使用固件更新命令将固件下载至指定分区,当下载成功转到下一步将已下载固件更新至app分区(只有将固件更新到download分区才会执行固件更新

当成功迁移新固件到app分区,则转到下一步跳转app分区执行,app分区跳转成功,应当将flag置为0xAD8888更新成功标识。否则再次重启Bootloader将检测更新成功标识,进行累计,超过指定次数,执行固件恢复(从factory分区恢复固件到app分区)。

所以app分区的软件应当做好升级成功的标识写入

上载固件

#上载固件到本地命令格式:upload 协议
upload ymodem

升级方式

  • 成品阶段:通过手机蓝牙连接发送固件升级指令
  • 出厂阶段:默认串口连接设备,烧录并注册设备(软件加密)

工程下载

前往下载

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

单片机通用Bootloader框架 的相关文章

  • 物联网网关

    物联网网关是 连接物联网设备和互联网的重要桥梁 它负责将物联网设备采集到的数据进行处理 存储和转发 使其能够与云端或其它设备进行通信 物联网网关的作用是实现物联网设备与云端的无缝连接和数据交互 物联网网关功能 数据采集 物联网网关可以从物联
  • STM32F103概要

    The STM32F103x4 STM32F103x6 STM32F103xC STM32F103xD and STM32F103xE are a drop in replacement for STM32F103x8 B medium d
  • [MM32硬件]搭建灵动微MM32G0001A6T的简易开发环境

    作为学习单片机的经典 自然是通过GPIO点亮LED 或者是响应按钮的外部中断例程 这我们看看SOP8封装的芯片MM32G0001A6T得引脚 除了VDD和GND固定外 我们可以使用PA14 PA1 PA13 PA15 PA2 PA3这六个G
  • 硬件基础-电容

    电容 本质 电容两端电压不能激变 所以可以起到稳定电压作用 充放电 电容量的大小 想使电容容量大 使用介电常数高的介质 增大极板间的面积 减小极板间的距离 品牌 国外 村田 muRata 松下 PANASONIC 三星 SAMSUNG 太诱
  • 跟着野火学FreeRTOS:第一段(任务定义,切换以及临界段)

    在裸机系统中 系统的主体就是 C P U CPU CP U 按照预先设定的程序逻辑在 m a i n
  • 中断 0x15 函数 0x86(BIOS WAIT)在真实硬件上的运行速度比在虚拟机上慢得多?

    我一直在汇编 游戏 中编写引导加载程序 引导加载程序使用 BIOS WAIT 函数 int 0x15 ah 0x86 来实现帧之间的延迟 我正在使用 BOCHS 进行调试 一切都运行良好 时机非常完美 我还制作了一个可启动的isoisoge
  • 最终启动顺序错误 - STM32L476 的 Eclipse System Workbench 调试

    我正在尝试调试和运行 STM32L476 的简单汇编代码 我已经设置了 Eclipse Oxygen 在 Eclipse 中安装了最新版本的 System Workbench 插件并安装了 ST Link 驱动程序 IDE 成功构建了程序
  • NASM 模块将十六进制转换为字符串并打印出来。已组装但未按预期工作

    我正在尝试编写一个简单的汇编代码以将十六进制值输出到屏幕上 有两个文件print screen asm它正在与其他模块一起工作 我认为问题出在我尝试将十六进制转换为字符串时的逻辑中 我的代码是 org 0x7c00 xor dx dx xo
  • 与 CMPSB 指令混淆

    我一直在看这段代码 我对代表 cmpsb line LOOP push cx mov cx 0x000B eleven character name mov si ImageName image name to find push di r
  • for循环延时时间计算

    提示 文章写完后 目录可以自动生成 如何生成可参考右边的帮助文档 文章目录 前言 一 pandas是什么 二 使用步骤 1 引入库 2 读入数据 总结 前言 之前做led点亮的实验 好像是被delay函数影响了 因为delay参数设置的不对
  • NASM:磁盘读取超时

    尝试从磁盘 从同一文件 读取数据 将另外 2 个 512 字节扇区加载到内存中 磁盘读取功能如下 read DH sectors to ES BX from drive DL disk read push dx push bx Tried
  • 特殊寄存器

    特殊寄存器 文章目录 前言 一 背景 二 2 1 2 2 总结 前言 前期疑问 STM32特殊寄存器到底是什么 特殊寄存器怎么查看和调试代码 本文目标 记录和理解特殊寄存器 一 背景 最近在看ucosIII文章是 里面提到特殊寄存器 这就进
  • STM32 Nucleo 上的上升沿中断多次触发

    我正在使用 STM32 NUCLEO F401RE 微控制器板 我有一个扬声器 经过编程 当向上 向下推操纵杆时 可以按设定的量改变频率 我的问题是 有时 通常 当向上 向下推动操纵杆时 频率会增加 减少多次 这意味着 ISR 正在执行多次
  • 从没有中断引脚并且在测量准备好之前需要一些时间的传感器读取数据的最佳方法

    我正在尝试将压力传感器 MS5803 14BA 与我的板 NUCLEO STM32L073RZ 连接 根据 第 3 页 压力传感器需要几毫秒才能准备好读取测量值 对于我的项目 我对需要大约 10 毫秒来转换原始数据的最高分辨率感兴趣 不幸的
  • 引导扇区编程中的无限跳转有什么用

    我正在读一本关于如何构建操作系统的书 我浏览了这段代码 所有代码所做的就是打印 hello 但我想了解更多关于无限跳转的信息 mov ah 0x0e mov al H int 0x10 mov al e int 0x10 mov al l
  • PWM DMA 到整个 GPIO

    我有一个 STM32F4 我想对一个已与掩码进行 或 运算的 GPIO 端口进行 PWM 处理 所以 也许我们想要 PWM0b00100010一段时间为 200khz 但随后 10khz 后 我们现在想要 PWM0b00010001 然后
  • STM32F0、ST-link v2、OpenOCD 0.9.0:打开失败

    我在用着发射台 http www ti com ww en launchpad about htmlgcc arm none eabi 4 9 2015q2 为 STM32F0 进行编译 现在我想使用该集合中的 arm none eabi
  • 使用 STM32F0 ADC 单独读取不同的输入

    STM32F072CBU 微控制器 我有多个 ADC 输入 并且希望单独读取它们 STMcubeMX 生成样板代码 假设我希望按顺序读取所有输入 但我无法弄清楚如何纠正这个问题 这篇博文 http blog koepi info 2015
  • 哪些变量类型/大小在 STM32 微控制器上是原子的?

    以下是 STM32 微控制器上的数据类型 http www keil com support man docs armcc armcc chr1359125009502 htm http www keil com support man d
  • stm32l0: 执行MI命令失败。使用 vFlashErase 数据包擦除闪存时出错

    我正在使用 Nucleo STM32L031 和 AC6 STM32 工作台 eclipse 我编写应用程序并进入调试模式 一切正常 直到我在应用程序中添加另一个功能 我注意到当我删除 评论 新函数 软件可以再次进入调试模式 但是当我添加

随机推荐