当前位置:   article > 正文

单片机通用Bootloader框架_单片机bootloader

单片机bootloader


最近搞了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.
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 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);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

设置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");
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79

生成可烧写bin文件

键入以下命令

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

在这里插入图片描述

固件升级与上载

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

更新固件

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

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

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

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

上载固件

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

升级方式

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

工程下载

前往下载

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/691628
推荐阅读
相关标签
  

闽ICP备14008679号