STM32 OTA Bootloader部分 demo流程学习

这篇具有很好参考价值的文章主要介绍了STM32 OTA Bootloader部分 demo流程学习。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

学习依据的源文链接:STM32 OTA应用开发——自制BootLoader

前言

什么是OTA?

OTA是“Over-the-Air”(空中升级)的缩写,指的是通过无线通信网络(如Wi-Fi、蓝牙、LoRa等)对嵌入式系统进行远程升级或更新。

在嵌入式系统中,OTA技术可以用于更新固件、软件或配置文件等。通过OTA技术,用户可以在不需要物理接触设备的情况下,对其进行升级和更新,从而提高系统的可靠性、安全性和灵活性。

----------我的理解:

所谓的OTA其实就是通过一些无线通信协议的方式,向嵌入式系统发送应用程序(以下简称APP)和升级指令,再由单片机设备上的BootLoader完成:接收新APP---擦除旧APP---写入新APP---跳转到新APP执行 的过程;

这个demo的实际上是通过USB的连接实现上述的APP升级过程,虽然有线连接不能严格称做OTA,但是二者的差异实际上只是不同(有线与无线)的通信传输过程,主要是学习程序升级的流程,故下文也将USB升级过程视为OTA升级;

什么是BootLoader?

BootLoader是一段程序,通常位于嵌入式系统的非易失性存储器(如Flash)中,用于在系统启动时加载和运行操作系统或其他应用程序。

在嵌入式系统中,BootLoader通常是一个小型的程序,主要负责以下几个方面的工作:

  1. 初始化硬件环境:BootLoader需要初始化硬件环境,包括CPU、存储器、外设、时钟等,以便系统能够正常运行。
  2. 加载操作系统或应用程序:BootLoader需要从存储器中加载操作系统或应用程序,并将控制权转交给操作系统或应用程序。
  3. 检查和修复系统错误:BootLoader需要检查系统的状态和完整性,以确保系统能够正常运行。如果发现系统错误,BootLoader需要尝试修复或恢复系统。
  4. 提供调试和测试功能:BootLoader可以提供调试和测试功能,例如单步执行、断点调试、查看寄存器状态等,以方便开发人员进行调试和测试。

而这个demo是通过自制bootloader,实现加载应用程序和OTA的功能;

BootLoader的OTA功能工作原理

MCU要实现OTA离不开Bootloader,它是一段引导程序,在OTA过程中,MCU启动时会先运行BootLoader,Bootloader会去判断是否需要升级,如果不需要升级就跳转到APP分区运行用户代码,如果需要升级则先通过一些硬件接口接收和搬运要升级的新固件,然后再跳转到APP分区运行新固件,从而实现OTA升级。

stm32 ota,stm32,学习,嵌入式硬件

 

BootLoader的OTA功能常见分区介绍

在没有加入Bootloader之前,MCU内部的flash可以看作一整块分区,我们运行的整个裸机程序都在其中:

stm32 ota,stm32,学习,嵌入式硬件

第一种分区方式——加入BootLoader,那么原本的Flash分区就可以划分为两个区域,Bootloader和Application,这种分区方式的好处在于既可以OTA升级,App又可以分到较大的空间,缺点是没有存放新固件的区域,需要从外部导入进来,而且一旦传输的过程被异常打断,那么原有的App代码也无法正常运行了:

stm32 ota,stm32,学习,嵌入式硬件

第二种分区方式——在第一种分区方式的基础上,将原本独属于APP的Flash空间中再分出一块作为Download分区来存放新的APP(同下文的固件),这种方式的优点是新固件是先存放到Download区的,哪怕搬运的过程中出现异常中断的情况,也不会“变砖”,缺点是需要单独划分一块内存跟APP区差不多的区域用来存放新固件,变相的减少了APP区的空间,对于内存较小的单片机来说内存压力会比较大:

stm32 ota,stm32,学习,嵌入式硬件

 第三种分区方式——这种方式其实与第二种分区方式一样,只是它把原本存放新APP的空间用来存放OTA升级前的旧APP,相当于在升级之前先将旧APP备份到Application2区域,再通过外部导入新APP覆盖写入Application1区域,优点在于升级了新固件以后,还保留了原来的旧版固件,必要的时候还可以进行版本的回退:

stm32 ota,stm32,学习,嵌入式硬件

 第四种分区方式——这种方式基本上与第二种分区方式一样,只不过增加了一个区域用来存放OTA相关的一下参数和用户配置:

stm32 ota,stm32,学习,嵌入式硬件

BootLoader的制作

BootLoader的程序是从源文找到的参考的demo,下面的内容一方面整理Bootloader的编写过程,一方面也会去详细解析Bootloader的源代码执行流程

以上述的第四种分区方式去编写Bootloader,参考demo使用的设备是STM32F103,内存128K,其内存分区表如下:

name offset size
Bootloader 0x08000000 0x00003000
Setting 0x08003000 0x00001000
Application 0x08004000 0x0000E000
Download 0x08012000 0x0000E000

其中0x08000000是内存起始地址,那么128K大小的内存空间的结束地址为0x0801FFFF,最后Download分区为0x08012000+0x0000E000 - 0x1 =0x0801FFFF,这四个部分将128K的内存空间全部分配完成;

这里记录一下地址空间与大小的计算过程:0x0801FFFF - 0x08000000 + 0x1 = 0x00020000,即0x20000个byte的空间,转换成十进制就是131072 bytes,而 128 * 1024 = 131072,所以是128K内存空间;

BootLoader功能简述:
  1. Bootloader启动;
  2. 从Setting中读取参数,确定是否需要升级;
    • 需要升级——把Download分区固件搬运到Application分区;
    • 不需要升级——直接跳转到Application分区;

新固件的下载传输过程,在App里面去处理,这里不做拓展;

源码解析

主要针对demo中的main.c、bootloader.c、bootloader.h中的内容进行流程解析,源码中涉及到的flash、uart等原本ST驱动中带有的外设控制接口只做简要说明;

main.c

#include "hardware.h"
#include "bootloader.h"
#include "flash.h"
#include "type.h"

void print_boot_message(void)
{
    printf("---------- Enter BootLoader ----------\r\n");
    printf("\r\n");
    printf("======== flash pration table =========\r\n");
    printf("| name     | offset     | size       |\r\n");
    printf("--------------------------------------\r\n");
    printf("| boot     | 0x08000000 | 0x00003000 |\r\n");
    printf("| setting  | 0x08003000 | 0x00001000 |\r\n");
    printf("| app      | 0x08004000 | 0x0000E000 |\r\n");
    printf("| download | 0x08012000 | 0x0000E000 |\r\n");
    printf("======================================\r\n");
}

int main() 
{
    process_status process;
    uint16_t i;
    uint8_t boot_state;
    uint8_t down_buf[128];
    uint32_t down_addr;
    uint32_t app_addr;

    uart1_init();
    print_boot_message();

    boot_parameter.process = read_setting_boot_state();
    boot_parameter.addr = APP_SECTOR_ADDR;

    while (1) 
    {
        process = get_boot_state();
        switch (process) 
        {
            case START_PROGRAM:
                printf("start app...\r\n");
                delay_ms(50);
                if (!jump_app(boot_parameter.addr)) 
                {
                    printf("no program\r\n");
                    delay_ms(1000);
                }
                printf("start app failed\r\n");
                break;
            case UPDATE_PROGRAM:
                printf("update app program...\r\n");
                app_addr = APP_SECTOR_ADDR;
                down_addr = DOWNLOAD_SECTOR_ADDR;

                printf("app addr: 0x%08X \r\n", app_addr);
                printf("down addr: 0x%08X \r\n", down_addr);

                printf("erase mcu flash...\r\n");
                mcu_flash_erase(app_addr, APP_ERASE_SECTORS);  
                printf("mcu flash erase success\r\n");
            
                printf("write mcu flash...\r\n");
                // memset(down_buf, 0, sizeof(down_buf));
                for (i = 0; i < APP_ERASE_SECTORS * 8; i++)
                {
                    mcu_flash_read(down_addr, &down_buf[0], 128);
                    delay_ms(5);
                    mcu_flash_write(app_addr, &down_buf[0], 128);
                    delay_ms(5);
                    down_addr += 128;
                    app_addr += 128;
                    // printf("mcu_flash_write: %d\r\n", i);
                }
                printf("mcu flash write success\r\n");

                set_boot_state(UPDATE_SUCCESS);
                break;
            case UPDATE_SUCCESS:
                printf("update success\r\n");
                boot_state = UPDATE_SUCCESS_STATE;
                write_setting_boot_state(boot_state);
                set_boot_state(START_PROGRAM);
                break;
            default:
                break;
        }
    }
}
  1. 在bootloader的主函数中,首先初始化了uart串口方便输出log信息,再调用print_boot_message()输出分区信息表(main.c line29~30);
  2. 之后调用read_setting_boot_state()(bootloader.c line32~48)将0x08003000也就是Setting地址空间中存放的状态值读取赋值给boot_parameter.process,再把APP首地址0x08004000赋值给boot_parameter.addr作为后面跳转到APP程序的准备(main.c line32~33),而boot_parameter是bootloader.c定义的全局变量(bootloader.c line3),用于存放bootloader的相关参数与状态;
  3. 进入到while(1)的流程当中,针对boot_parameter.process的三种状态:START_PROGRAM、UPDATE_PROGRAM、 UPDATE_SUCCESS执行对应逻辑,也就是启动APP、升级APP、升级成功;
  4. 启动APP的case(main.c line40~49)当中,除开log信息,主要是调用jump_app()接口(bootloader.c line5~16)跳转到APP程序,而传入的参数就是APP程序的起始地址0x08004000;如果APP起始地址无程序,才会继续执行下面的log输出,不然就直接跳转到APP的程序当中,bootloader执行就结束了;
  5. 升级APP的case(main.c line50~77)当中,先按页擦除flash中APP地址区块(main.c line59)将旧APP清除,然后再从Download地址区块开始每128byte读取数据再写到APP地址区块中(main.c line64~73),最后把bootloader的状态置为UPDATE_SUCCESS,下次循环进入UPDATE_SUCCESS的case执行;
  6. 升级成功的case(main.c line78~83)当中,调用write_setting_boot_state()接口(bootloader.c line 50~64)将升级成功的标志UPDATE_SUCCESS_STATE写入到地址0x08003000也就是Setting地址空间,下一次循环就会在步骤2中走到步骤4的流程,从而启动APP;

至此,bootloader的OTA过程状态机形成闭环

bootloader.c文章来源地址https://www.toymoban.com/news/detail-763504.html

#include "bootloader.h"

boot_t boot_parameter = {START_PROGRAM, 0, 0, 0};

uint8_t jump_app(uint32_t app_addr) 
{
    uint32_t jump_addr;
    jump_callback cb;
    if (((*(__IO uint32_t*)app_addr) & 0x2FFE0000 ) == 0x20000000) {  
        jump_addr = *(__IO uint32_t*) (app_addr + 4);  
        cb = (jump_callback)jump_addr;  
        __set_MSP(*(__IO uint32_t*)app_addr);  
        cb();
        return 1;
    } 
    return 0;
}

void set_boot_state(process_status process) 
{
    boot_parameter.process = process;
}

process_status get_boot_state(void) 
{
    process_status process;
    process = boot_parameter.process;

    return process;
}

process_status read_setting_boot_state(void)
{
	process_status process;
	uint8_t boot_state;
    mcu_flash_read(SETTING_BOOT_STATE, &boot_state, 1);
    // printf("boot_state: %d \r\n", boot_state);
 
    if(boot_state != UPDATE_PROGRAM_STATE)
    {
       process = START_PROGRAM;
    }
    else
    {
       process = UPDATE_PROGRAM;
    }
	return process;
}

uint8_t write_setting_boot_state(uint8_t boot_state)
{
	uint8_t result;
	result = mcu_flash_erase(SETTING_BOOT_STATE, 1);
	if(result)
	{
		result = mcu_flash_write(SETTING_BOOT_STATE, &boot_state, 1);
		if(result != 1)
		{
			return result;
		}
	}
    
	return result;
}

到了这里,关于STM32 OTA Bootloader部分 demo流程学习的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • STM32-OTA升级-基于STM32CubeMX+STM32F103(一)基础知识

    STM32-OTA升级-基于STM32CubeMX+STM32F103(一)基础知识

    0 引言 对于一个项目而言,往往将远程升级作为程序的最后一步(基本所有功能都开发完成之后再考虑)。但是在我看来,我们在写单片机的程序之前,就要规划好FLASH的使用情况,因为code、全局变量等重要信息都是放在FLASH(常说的闪存)中的,SRAM是程序运行时的存放位置

    2024年02月04日
    浏览(28)
  • 调试笔记-stm32的OTA/IAP 通过485升级固件

    调试笔记-stm32的OTA/IAP 通过485升级固件

    背景:最近需要在stm32上实现通过rs485升级固件功能。经过几天搜索和调试,实现了功能。 目标:使用cubeIDE实现stm32F407VGT6,通过RS485升级固件 调试记录: 步骤1. 在keil环境下的rs485升级固件(含源码):STM32 OTA应用开发——通过串口/RS485实现OTA升级(方式2)_stm32串口升级_柒壹漆

    2024年02月11日
    浏览(14)
  • STM32_通过Ymodem协议进行蓝牙OTA升级固件教程

    STM32_通过Ymodem协议进行蓝牙OTA升级固件教程

    作为单片机进阶能力,IAP升级固件的学习是非常重要的。 想直接看如何操作的从第三条开始看。 蓝牙OTA(Over-The-Air)升级是指通过蓝牙无线技术,对设备中的固件或软件进行远程升级和更新的过程。蓝牙OTA升级在现代物联网和智能设备领域有着重要的应用和意义。 重要性:

    2024年02月04日
    浏览(9)
  • stm32 esp8266 ota升级-qt bin文件处理工具

    stm32 esp8266 ota升级-qt bin文件处理工具

    stm32 esp8266 ota系列文章: stm32 esp8266 ota-快速搭建web服务器之docker安装openresty stm32 esp8266 ota升级-tcp模拟http stm32 esp8266 ota升级-hex合并-烧录-bin生成 stm32 esp8266 ota升级-qt bin文件处理工具 stm32 esp8266 ota升级-自建mqtt和文件服务器动态AB面方式 stm32 esp8266 ota升级-自建mqtt和文件服务器全

    2024年02月05日
    浏览(14)
  • gd32f103vbt6 串口OTA升级5-combin部分

    gd32f103vbt6 串口OTA升级5-combin部分

    本文主要是bin文件的组成进行一些简单介绍,方便理解升级的过程。 2.1 rk3399cpu+gd32f103 2.2 连接方式:串口(115200,8N1)或者iic(本文没有介绍iic) 3.1 单片机端分两个部分:iap(用于升级)和app(自己的应用)部分(这两个部分本文不做介绍)。 3.2 linux端做一个升级的app软件

    2024年02月16日
    浏览(10)
  • gd32f103vbt6 串口OTA升级3-linux端的部分

    gd32f103vbt6 串口OTA升级3-linux端的部分

    本文主要是对linux端升级单片机程序的功能部分做一些介绍,包括一些软件流程。 2.1 rk3399cpu+gd32f103 2.2 连接方式:串口(115200,8N1)或者iic(本文没有介绍iic) 3.4.1  0 ~(0x5c00-1) : iap程序区,用于存放iap程序 3.4.2  0x5c00~(0x6000-1) : 这个1k用于存放一些标志位,以及程序的

    2024年02月17日
    浏览(10)
  • 【RT-Thread】使用RT-Thread Studio 配置BootLoader及App实现OTA功能

    【RT-Thread】使用RT-Thread Studio 配置BootLoader及App实现OTA功能

    由于项目需要实现OTA功能学习了一下具体实现方法,以备后期查看,有问题的地方随时指正修改 1.什么是OTA OTA是“over-the-air”的缩写,是一种无线技术,用于在不需要接触设备的情况下向移动设备或物联网设备提供更新、补丁或新版本的软件。OTA更新通常通过无线网络(如

    2024年02月09日
    浏览(12)
  • ESP32 OTA升级之https ota详解

    ESP32 OTA升级之https ota详解

    本文以 ESP32 官方demo例程 native_ota_example 为例,详细阐述如何采用https实现esp32的ota升级。 第一章节,为本文的前言部分,对文章内容进行大体概述; 第二章节,主要描述了如何在本地将demo例程跑起来,并附带了关于使用demo例程中遇到的相关报错的具体解决措施; 第三章节,

    2024年02月14日
    浏览(12)
  • STM32 usart bootloader 源代码 STM32 usart bootloader 源代码 STM32 usart bootloader 原代源码

    STM32 usart bootloader 源代码 STM32 usart bootloader 源代码 STM32 usart bootloader 原代源码

    STM32 usart bootloader 源代码   STM32 usart bootloader 源代码  STM32 usart bootloader 原代源码,上位机C#,下位机c。 简单修改可以支持stm32全系列芯片。 支持串口升级 该版本为优化过的版本, 1.支持代码段保护; 2.支持烧写失败重置; 3.兼容我公司生产的配套wifi模块和w5500模块远程更新

    2024年01月23日
    浏览(11)
  • STM32duino-bootloader:STM32的开源Bootloader深入解析

    STM32微控制器广泛应用于各种嵌入式系统。一个常见的需求是能够远程更新固件,而这通常是通过Bootloader来实现的。在本文中,我们将深入解析一个叫做STM32duino-bootloader的开源项目,它为STM32微控制器提供了一个USB DFU (Device Firmware Upgrade) bootloader。 STM32duino-bootloader简介 STM32d

    2024年02月11日
    浏览(8)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包