Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >零代码玩转OTA升级

零代码玩转OTA升级

作者头像
AIoT-KK
发布于 2020-07-13 08:57:50
发布于 2020-07-13 08:57:50
1.8K00
代码可运行
举报
运行总次数:0
代码可运行

前言: 前边讲过stm32通用bootloader的实现方法,没有看过的,可以参考这一篇文章:STM32通用Bootloader——FOTA,这次将在上篇bootloader的基础上,介绍app如何通过多种固件下载器实现OTA升级。

先看下演示视频,此视频演示了四种升级方式,分别是:

  1. 阿里云物联网平台OTA
  2. HTTP OTA
  3. Ymodem OTA
  4. 不用app,使用Bootloader中的Ymodem OTA

http://mpvideo.qpic.cn/0bf2kqaamaaaeyagvopme5pfavgdazkaabqa.f10002.mp4?dis_k=4e2ee09b44f51d627de5bf0b01b98a48&dis_t=1594630606

此项目硬件使用的是STM32F429开发板,代码全部使用RT-Thread Studio搭积木的方式实现,仅仅改动了几行代码,开发效率非常高。此项目的地址:https://gitee.com/Aladdin-Wang/RT-FOTA-STM32L431.git

使用到的软件包和组件:

在这里插入图片描述

1.准备工作

1.1 新建工程

由于此项目使用的esp8266需要一个串口,我使用的是uart2,所以需要还需要配置uart2:

增加uart接收缓冲区大小:

1.2 打开fal和at device软件包

配置fal软件包

配置sfud组件

配置SPI

配置fal_cfg.h

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#ifndef _FAL_CFG_H_
#define _FAL_CFG_H_

#include <rtconfig.h>
#include <board.h>

#define FLASH_SIZE_GRANULARITY_16K   (4 * 16 * 1024)
#define FLASH_SIZE_GRANULARITY_64K   (64 * 1024)
#define FLASH_SIZE_GRANULARITY_128K  (7 * 128 * 1024)

#define STM32_FLASH_START_ADRESS_16K  STM32_FLASH_START_ADRESS
#define STM32_FLASH_START_ADRESS_64K  (STM32_FLASH_START_ADRESS_16K + FLASH_SIZE_GRANULARITY_16K)
#define STM32_FLASH_START_ADRESS_128K (STM32_FLASH_START_ADRESS_64K + FLASH_SIZE_GRANULARITY_64K)
/* ===================== Flash device Configuration ========================= */
extern const struct fal_flash_dev stm32_onchip_flash_16k;
extern const struct fal_flash_dev stm32_onchip_flash_64k;
extern const struct fal_flash_dev stm32_onchip_flash_128k;
extern struct fal_flash_dev nor_flash0;

/* flash device table */
#define FAL_FLASH_DEV_TABLE                                          \
{                                                                    \
    &stm32_onchip_flash_16k,                                         \
    &stm32_onchip_flash_64k,                                         \
    &stm32_onchip_flash_128k,                                        \
    &nor_flash0,                                                     \
}
/* ====================== Partition Configuration ========================== */
#ifdef FAL_PART_HAS_TABLE_CFG
/* partition table */
#define FAL_PART_TABLE                                                               \
{                                                                                    \
    {FAL_PART_MAGIC_WROD, "bootloader", "onchip_flash_16k",  0 , FLASH_SIZE_GRANULARITY_16K , 0}, \
    {FAL_PART_MAGIC_WROD, "param",      "onchip_flash_64k",  0 , FLASH_SIZE_GRANULARITY_64K , 0}, \
    {FAL_PART_MAGIC_WROD, "app",        "onchip_flash_128k", 0 , FLASH_SIZE_GRANULARITY_128K, 0}, \
    {FAL_PART_MAGIC_WROD, "ef",         "W25Q128",           0 , 1024 * 1024, 0}, \
    {FAL_PART_MAGIC_WROD, "download",   "W25Q128",          1024 * 1024 , 512 * 1024, 0}, \
    {FAL_PART_MAGIC_WROD, "factory",    "W25Q128",          (1024 + 512) * 1024 , 512 * 1024, 0}, \
}
#endif /* FAL_PART_HAS_TABLE_CFG */

#endif /* _FAL_CFG_H_ */

初始化spi flash和fal软件包

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include <rtthread.h>
#include "spi_flash.h"
#include "spi_flash_sfud.h"
#include "drv_spi.h"

#if defined(RT_USING_SFUD)
static int rt_hw_spi_flash_init(void)
{
    __HAL_RCC_GPIOF_CLK_ENABLE();
    rt_hw_spi_device_attach("spi5", "spi50", GPIOF, GPIO_PIN_6);

    if (RT_NULL == rt_sfud_flash_probe("W25Q128", "spi50"))
    {
        return -RT_ERROR;
    }

    return RT_EOK;
}
INIT_COMPONENT_EXPORT(rt_hw_spi_flash_init);
#endif
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
int fs_init(void)
{
    /* partition initialized */
    fal_init();
    return 0;
}
INIT_ENV_EXPORT(fs_init);

配置at device软件包

1.3 配置中断重定向
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/**
 * Function    ota_app_vtor_reconfig
 * Description Set Vector Table base location to the start addr of app(RT_APP_PART_ADDR).
*/
static int ota_app_vtor_reconfig(void)
{
    #define NVIC_VTOR_MASK   0x3FFFFF80
    /* Set the Vector Table base location by user application firmware definition */
    SCB->VTOR = 0x8020000 & NVIC_VTOR_MASK;

    return 0;
}
INIT_BOARD_EXPORT(ota_app_vtor_reconfig);

烧录bootloader: bootloader的制作方法请参考官方的教程https://www.rt-thread.org/document/site/application-note/system/rtboot/an0028-rtboot/或者STM32通用Bootloader——FOTA

2.阿里云物联网平台OTA

注册 LinkPlatform 平台

创建产品

产品详情:

添加设备

添加自定义Topic

配置ali iotkit软件包 将刚才新建的阿里云设备信息填写到配置信息里:

将软件包的示例mqtt-example.c和ota_mqtt-example.c拷贝到applications目录备用

配置mbedtls软件包

更改ota_mqtt-example.c中的部分代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
static int _ota_mqtt_client(void)
{
#define OTA_BUF_LEN        (16385)
#define DEFAULT_DOWNLOAD_PART "download"
    int rc = 0, ota_over = 0;
    void *pclient = NULL, *h_ota = NULL;
    iotx_conn_info_pt pconn_info;
    iotx_mqtt_param_t mqtt_params;

    // FILE *fp;
    static char buf_ota[OTA_BUF_LEN];
    const struct fal_partition * dl_part = RT_NULL;

    // if (NULL == (fp = fopen("ota.bin", "wb+"))) {
    //     EXAMPLE_TRACE("open file failed");
    //     goto do_exit;
    // }

    /**< get device info*/
    HAL_GetProductKey(g_product_key);
    HAL_GetDeviceName(g_device_name);
    HAL_GetDeviceSecret(g_device_secret);
    /**< end*/

    /* Device AUTH */
    if (0 != IOT_SetupConnInfo(g_product_key, g_device_name, g_device_secret, (void **)&pconn_info)) {
        EXAMPLE_TRACE("AUTH request failed!");
        rc = -1;
        goto do_exit;
    }

    /* Initialize MQTT parameter */
    memset(&mqtt_params, 0x0, sizeof(mqtt_params));

    mqtt_params.port = pconn_info->port;
    mqtt_params.host = pconn_info->host_name;
    mqtt_params.client_id = pconn_info->client_id;
    mqtt_params.username = pconn_info->username;
    mqtt_params.password = pconn_info->password;
    mqtt_params.pub_key = pconn_info->pub_key;

    mqtt_params.request_timeout_ms = 2000;
    mqtt_params.clean_session = 0;
    mqtt_params.keepalive_interval_ms = 60000;
    mqtt_params.read_buf_size = OTA_MQTT_MSGLEN;
    mqtt_params.write_buf_size = OTA_MQTT_MSGLEN;

    mqtt_params.handle_event.h_fp = event_handle;
    mqtt_params.handle_event.pcontext = NULL;

    /* Construct a MQTT client with specify parameter */
    pclient = IOT_MQTT_Construct(&mqtt_params);
    if (NULL == pclient) {
        EXAMPLE_TRACE("MQTT construct failed");
        rc = -1;
        goto do_exit;
    }
    h_ota = IOT_OTA_Init(g_product_key, g_device_name, pclient);
    if (NULL == h_ota) {
        rc = -1;
        EXAMPLE_TRACE("initialize OTA failed");
        goto do_exit;
    }


        do {
            uint32_t firmware_valid;

            EXAMPLE_TRACE("wait ota upgrade command....");

            /* handle the MQTT packet received from TCP or SSL connection */
            IOT_MQTT_Yield(pclient, 200);

            if (IOT_OTA_IsFetching(h_ota)) {
                uint32_t last_percent = 0, percent = 0;
                char md5sum[33];
                char version[128] = {0};
                uint32_t len, size_downloaded, size_file;
                IOT_OTA_Ioctl(h_ota, IOT_OTAG_FILE_SIZE, &size_file, 4);
                /* Get download partition information and erase download partition data */
                if ((dl_part = fal_partition_find(DEFAULT_DOWNLOAD_PART)) == RT_NULL)
                {
                    LOG_E("Firmware download failed! Partition (%s) find error!", "download");
                    rc = -1;
                    goto do_exit;
                }

                LOG_I("Start erase flash (%s) partition!", dl_part->name);

                if (fal_partition_erase(dl_part, 0, size_file) < 0)
                {
                    LOG_E("Firmware download failed! Partition (%s) erase error!", dl_part->name);
                    rc = -1;
                    goto do_exit;
                }
                LOG_I("Erase flash (%s) partition success!", dl_part->name);

                rt_uint32_t content_pos = 0, content_write_sz;

                do {

                    len = IOT_OTA_FetchYield(h_ota, buf_ota, OTA_BUF_LEN, 1);
                    if (len > 0) {
                        content_write_sz = fal_partition_write(dl_part, content_pos, (uint8_t *)buf_ota, len);
                        if (content_write_sz !=  len)
                        {
                            LOG_I("Write OTA data to file failed");

                            IOT_OTA_ReportProgress(h_ota, IOT_OTAP_BURN_FAILED, RT_NULL);

                            goto do_exit;
                        }
                        else
                        {
                            content_pos = content_pos + len;
                            LOG_I("receive %d bytes, total recieve: %d bytes", content_pos, size_file);
                        }
                    } else {
                        IOT_OTA_ReportProgress(h_ota, IOT_OTAP_FETCH_FAILED, NULL);
                        EXAMPLE_TRACE("ota fetch fail");
                    }

                    /* get OTA information */
                    IOT_OTA_Ioctl(h_ota, IOT_OTAG_FETCHED_SIZE, &size_downloaded, 4);
                    IOT_OTA_Ioctl(h_ota, IOT_OTAG_FILE_SIZE, &size_file, 4);

                    last_percent = percent;
                    percent = (size_downloaded * 100) / size_file;
                    if (percent - last_percent > 0) {
                        IOT_OTA_ReportProgress(h_ota, percent, NULL);
                    }
                    IOT_MQTT_Yield(pclient, 100);
                } while (!IOT_OTA_IsFetchFinish(h_ota));

                IOT_OTA_Ioctl(h_ota, IOT_OTAG_MD5SUM, md5sum, 33);
                IOT_OTA_Ioctl(h_ota, IOT_OTAG_VERSION, version, 128);
                IOT_OTA_Ioctl(h_ota, IOT_OTAG_CHECK_FIRMWARE, &firmware_valid, 4);
                if (0 == firmware_valid) {
                    EXAMPLE_TRACE("The firmware is invalid");
                } else {
                    EXAMPLE_TRACE("The firmware is valid");
                    IOT_OTA_ReportVersion(h_ota, version);

                    LOG_I("Download firmware to flash success.");
                    LOG_I("System now will restart...");

                    HAL_SleepMs(1000);

                    /* Reset the device, Start new firmware */
                    extern void rt_hw_cpu_reset(void);
                    rt_hw_cpu_reset();
                }

                ota_over = 1;
            }
            HAL_SleepMs(2000);
        } while (!ota_over);

    HAL_SleepMs(1000);

do_exit:

    if (NULL != h_ota) {
        IOT_OTA_Deinit(h_ota);
    }

    if (NULL != pclient) {
        IOT_MQTT_Destroy(&pclient);
    }

    return rc;
}

编译工程,将bin文件上传到阿里云: 阿里云不支持rbl格式的文件,直接将rt_ota_packaging_tool生成的rbl文件后缀改为bin,上传即可。

最后使用ali_ota_sample命令升级:

3.HTTP OTA和Ymodem OTA

配置ota_downloader软件包

如果暂时没有自己的服务器,可以使用MyWebServer进行测试:

配置完MyWebServer,可以打开浏览器输入IP地址查看:

使用http_ota命令进行http_ota升级:

使用ymodem_ota命令进行ymodem_ota升级:

4.不使用APP进行升级

rt-fota集成了ymodem_ota,上电短按恢复出厂设置按钮即可进入rt-fota命令行模式,通过ymodem_ota命令即可进行升级:

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-06-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 AIoT开源项目分享 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
STM32通用Bootloader——FOTA
固件升级,通常称为 OTA(Over the Air)升级或者 FOTA(Firmware Over-The-Air)升级,即固件通过空中下载进行升级的技术。
AIoT-KK
2020/07/13
6.8K0
STM32通用Bootloader——FOTA
STM32通用FLASH管理软件包——SFUD/FAL
本次介绍的两个软件包SFUD/FAL都与FLASH有关,并且都可以独立使用或者结合在一起使用,两个软件包都对操作系统无依赖,可以使用裸机移植,也很方便移植到各种系统。
AIoT-KK
2020/07/13
2.2K0
STM32通用FLASH管理软件包——SFUD/FAL
STM32在线升级OTA,看这一篇就够啦~
本文主要讲解在线升级(OTA)的基础知识, 主要是针对IAP OTA从原理分析, 分区划分, 到代码编写和实验验证等过程阐述这一过程. 帮助大家加深对OTA的认识.
Mculover666
2020/07/16
12.6K5
STM32在线升级OTA,看这一篇就够啦~
适用于MCU的轻量级远程升级组件mOTA
在物联网快速发展的今天,很多终端产品都需要OTA的功能。今天为大家分享一款开源的,专为单片机开发的轻量级 OTA 组件:mOTA。
单片机点灯小能手
2024/05/28
7220
适用于MCU的轻量级远程升级组件mOTA
详解STM32在线IAP升级
最近一些朋友在玩在线升级,所以这里bug菌挑选了一篇原理与实践结合的技术文章,在stm32上实现还是比较详细的,以前bug也跟大家介绍过这一块的设计方案:
杨源鑫
2021/09/17
2.3K0
干货 | 详解 stm32 在线 IAP 升级
本文主要讲解在线升级IAP的基础知识, 主要是针对IAP从原理分析, 分区划分, 到代码编写和实验验证等过程阐述这一过程. 帮助大家加深对在线升级的认识。
混说Linux
2023/02/24
2.3K0
干货 | 详解 stm32 在线 IAP 升级
【DIY数字仪表】STM32F429移植TouchGFX到RT-Thread系统(1)
硬件: 野火挑战者STM32F429 V1开发版,5寸屏 软件:最新版本的STM32CubeF4固件库,TouchGFXDesigner v4.13和 STM32CubeMX v5.6.1,开发环境MDK v5.29
AIoT-KK
2020/07/13
1.5K0
【DIY数字仪表】STM32F429移植TouchGFX到RT-Thread系统(1)
从零编写STM32H7的MDK SPI FLASH下载算法
当我们要下载编译好的镜像到Flash时,首先要做的一步就是选择合适的Flash下载算法,而这个算法本身就是一个FLM文件:
AIoT-KK
2023/03/01
1.4K0
从零编写STM32H7的MDK SPI FLASH下载算法
06-STM32+ESP8266+AIR202远程升级方案-移植STM32+ESP8266实现利用http或https远程更新STM32程序到自己的项目(定时访问升级,备份升级)
<p><iframe name="ifd" src="https://mnifdv.cn/resource/cnblogs/ESA2GJK1DH1K_B/" frameborder="0" scrolling="auto" width="100%" height="1500"></iframe></p>
杨奉武
2020/08/19
9750
06-STM32+ESP8266+AIR202远程升级方案-移植STM32+ESP8266实现利用http或https远程更新STM32程序到自己的项目(定时访问升级,备份升级)
利用MDK的FLM文件制作通用flash驱动
在进行Flash操作时,一般我们需要设计一套Flash抽象层,至少要包括flash的init,read、write、erase这些操作。但每更换一个单片机或者flash器件就要额外去编写flash驱动去适配init,read、write、erase。尽管有会者不难的属性加持,但适配所有的单片机或者flash器件,工作量也可想而知。
AIoT-KK
2023/03/01
2.4K1
利用MDK的FLM文件制作通用flash驱动
MCU 通过 UART 实现 OTA 在线升级流程
空中下载技术OTA(Over-the-Air Technology)是用户自己的程序在运行过程中对User Flash的部分区域进行烧写,目的是为了在产品发布后可以方便地通过预留的通信口,对产品中的固件程序进行更新升级。通常实现OTA功能时,即用户程序运行中作自身的更新操作,需要在设计固件程序时编写两个项目代码,第一个项目程序为Bootloader区域,第二个项目程序App代码为真正的功能代码,执行应用和升级。这两部分项目代码同时烧录在User Flash中。
混说Linux
2022/11/18
1.6K0
MCU 通过 UART 实现 OTA 在线升级流程
【DIY数字仪表】RT-Thread移植touchgfx使用sd卡升级固件和图片资源(4)
1.固件升级演示: 固件升级在第三个界面,已经提前把待升级的固件和图片bin文件放在了SD卡里,升级前软件版本为V1,升级后软件版本为V2,并且更改了表盘,升级完成后,会记录升级的时间,详细请看视频演示:
AIoT-KK
2020/08/07
1.8K0
EasyFlash 移植说明
[点击此链接](https://github.com/armink/EasyFlash/archive/master.zip)即可直接下载位于Github上的源码。
心跳包
2020/08/31
1.8K0
RT-Thread进阶之文件系统
在早期的嵌入式系统中,需要存储的数据比较少,数据类型也比较单一,往往使用直接在存储设备中的指定地址写入数据的方法来存储数据。然而随着嵌入式设备功能的发展,需要存储的数据越来越多,也越来越复杂,这时仍使用旧方法来存储并管理数据就变得非常繁琐困难。因此我们需要新的数据管理方式来简化存储数据的组织形式,这就是文件系统的由来。
AIoT-KK
2020/07/13
2.4K0
RT-Thread进阶之文件系统
还不会OTA升级?手把手教你基于STM32的BootLoader的OTA远程升级
上次发过SD卡的Bootloader离线升级后,应大家的要求,这次就讲一下STM32的OTA远程升级。 OTA又叫空中下载技术,是通过移动通信的空中接口实现对移动终端设备数据进行远程管理的技术,还能提供移动化的新业务下载功能。 要实现OTA功能,至少需要两块设备,分别是服务器与客户端。服务器只有一个,客户端可有多个。服务器通过串口与PC机连接,需要下载的镜像文件存放于PC机,命令执行器给服务器发命令及镜像文件。首先命令执行器控制服务器广播当前可用的镜像文件信息,客户端收到信息后进行对比,若有与自身相匹配的镜像,则向服务器请求数据。服务器收到请求后向命令执行器索取固定大小的块,再点对点传送给客户端。镜像传输完毕后,客户端进行校验,完成后发送终止信号。 一. 升级方式的对比
MCU起航
2021/09/03
3.4K0
还不会OTA升级?手把手教你基于STM32的BootLoader的OTA远程升级
【IoT应用创新大赛】基于腾讯云的智能停车平台
都说科技改变生活,今天来聊的这个作品可以真实的改变生活相信有车的朋友最头疼的莫过于停车问题,其他小城市还好,像深圳这样的大城市,停车问题一直困扰着有车一族:- 不知道哪里有车位可以停- 好不容易找到停车场因为方向错误或者技术不好车位被别人占了- 随意停路边容易吃罚单对于其他地方,停车场多于车辆的,停车场主面临收入问题:- 怎么让更多的车停到我这里增加收入- 我的停车场到底收入如何,如何简化做账流程- 我新建了一个停车场怎么让别人知道呢...基于以上几个痛点本人设计了一款基于腾讯云以及TencentOS Tiny实时系统打造的智能停车平台,依靠智能车位锁,智能抬杆,以及平台的管理能力,解决以上几个生活中的问题,并具有一定及广阔的商业价值
物联风景
2020/04/20
3.5K0
【IoT应用创新大赛】基于腾讯云的智能停车平台
【IoT迷你赛】环境监测小Demo
很幸运有这一次的Tencent Tiny OS的内测机会,体验了一把腾讯自主研发的物联网操作系统。在7月尾我参加了腾讯举办的物联网分享大会,在那一次的技术交流会上,腾讯的IOT云端技术大佬就讲解了腾讯开发的物联网操作系统Tiny OS。简单来说,该操作系统简洁、实用,系统拥有线程管理与信号量处理等满足物联网需求的基础功能,专门为物联网的打造,所以具备有CoAP、MQTT等应用层的协议架构。该操作系统为腾讯云自主研发,所以在连接腾讯云的物联网平台已经提供最佳参考。
Aitcon
2019/08/28
1K0
【IoT迷你赛】环境监测小Demo
【STM32H7教程】第68章 STM32H7的系统bootloader之USB DFU方式固件升级
完整教程下载地址:http://www.armbbs.cn/forum.php?mod=viewthread&tid=86980 第68章       STM32H7的系统bootloader之USB
Simon223
2020/03/06
2K0
04-STM32+W5500+AIR202远程升级篇
STM32控制W5500使用http获取云端info.txt文件,从文件里面获取远端固件版本,固件下载地址等信息
杨奉武
2020/08/03
1.4K0
1-STM32+W5500远程升级篇(自建物联网平台)-STM32通过W5500使用http下载程序文件,升级程序(单片机程序轮训检查更新)
说明 这节测试一下STM32通过W5500使用http远程下载升级单片机程序 我已经把固件文件放在了自己的服务器上 默认使用本人提供的下载路径测试 文件路径:  网站根目录->ota->hardware->STM32W5500BK user_crc.bin: 是固件程序文件. 该固件程序文件并不是直接可以运行的文件 里面的数据每隔128字节后面增加2位CRC校验位 单片机下载以后每隔130字节校验一下数据,然后把前128字节写入Flash. 加入CRC校验让升级变的稳定可靠. info.txt文件内容:
杨奉武
2022/04/29
2.8K0
1-STM32+W5500远程升级篇(自建物联网平台)-STM32通过W5500使用http下载程序文件,升级程序(单片机程序轮训检查更新)
推荐阅读
相关推荐
STM32通用Bootloader——FOTA
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验