零代码玩转OTA升级

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

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

  1. 阿里云物联网平台OTA

  2. HTTP OTA

  3. Ymodem OTA

  4. 不用app,使用Bootloader中的Ymodem OTA

此项目硬件使用的是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

 1#ifndef _FAL_CFG_H_
 2#define _FAL_CFG_H_
 3
 4#include <rtconfig.h>
 5#include <board.h>
 6
 7#define FLASH_SIZE_GRANULARITY_16K   (4 * 16 * 1024)
 8#define FLASH_SIZE_GRANULARITY_64K   (64 * 1024)
 9#define FLASH_SIZE_GRANULARITY_128K  (7 * 128 * 1024)
10
11#define STM32_FLASH_START_ADRESS_16K  STM32_FLASH_START_ADRESS
12#define STM32_FLASH_START_ADRESS_64K  (STM32_FLASH_START_ADRESS_16K + FLASH_SIZE_GRANULARITY_16K)
13#define STM32_FLASH_START_ADRESS_128K (STM32_FLASH_START_ADRESS_64K + FLASH_SIZE_GRANULARITY_64K)
14/* ===================== Flash device Configuration ========================= */
15extern const struct fal_flash_dev stm32_onchip_flash_16k;
16extern const struct fal_flash_dev stm32_onchip_flash_64k;
17extern const struct fal_flash_dev stm32_onchip_flash_128k;
18extern struct fal_flash_dev nor_flash0;
19
20/* flash device table */
21#define FAL_FLASH_DEV_TABLE                                          \
22{                                                                    \
23    &stm32_onchip_flash_16k,                                         \
24    &stm32_onchip_flash_64k,                                         \
25    &stm32_onchip_flash_128k,                                        \
26    &nor_flash0,                                                     \
27}
28/* ====================== Partition Configuration ========================== */
29#ifdef FAL_PART_HAS_TABLE_CFG
30/* partition table */
31#define FAL_PART_TABLE                                                               \
32{                                                                                    \
33    {FAL_PART_MAGIC_WROD, "bootloader", "onchip_flash_16k",  0 , FLASH_SIZE_GRANULARITY_16K , 0}, \
34    {FAL_PART_MAGIC_WROD, "param",      "onchip_flash_64k",  0 , FLASH_SIZE_GRANULARITY_64K , 0}, \
35    {FAL_PART_MAGIC_WROD, "app",        "onchip_flash_128k", 0 , FLASH_SIZE_GRANULARITY_128K, 0}, \
36    {FAL_PART_MAGIC_WROD, "ef",         "W25Q128",           0 , 1024 * 1024, 0}, \
37    {FAL_PART_MAGIC_WROD, "download",   "W25Q128",          1024 * 1024 , 512 * 1024, 0}, \
38    {FAL_PART_MAGIC_WROD, "factory",    "W25Q128",          (1024 + 512) * 1024 , 512 * 1024, 0}, \
39}
40#endif /* FAL_PART_HAS_TABLE_CFG */
41
42#endif /* _FAL_CFG_H_ */

初始化spi flash和fal软件包

 1#include <rtthread.h>
 2#include "spi_flash.h"
 3#include "spi_flash_sfud.h"
 4#include "drv_spi.h"
 5
 6#if defined(RT_USING_SFUD)
 7static int rt_hw_spi_flash_init(void)
 8{
 9    __HAL_RCC_GPIOF_CLK_ENABLE();
10    rt_hw_spi_device_attach("spi5", "spi50", GPIOF, GPIO_PIN_6);
11
12    if (RT_NULL == rt_sfud_flash_probe("W25Q128", "spi50"))
13    {
14        return -RT_ERROR;
15    }
16
17    return RT_EOK;
18}
19INIT_COMPONENT_EXPORT(rt_hw_spi_flash_init);
20#endif
1int fs_init(void)
2{
3    /* partition initialized */
4    fal_init();
5    return 0;
6}
7INIT_ENV_EXPORT(fs_init);

配置at device软件包

1.3 配置中断重定向
 1/**
 2 * Function    ota_app_vtor_reconfig
 3 * Description Set Vector Table base location to the start addr of app(RT_APP_PART_ADDR).
 4*/
 5static int ota_app_vtor_reconfig(void)
 6{
 7    #define NVIC_VTOR_MASK   0x3FFFFF80
 8    /* Set the Vector Table base location by user application firmware definition */
 9    SCB->VTOR = 0x8020000 & NVIC_VTOR_MASK;
10
11    return 0;
12}
13INIT_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中的部分代码:

  1static int _ota_mqtt_client(void)
  2{
  3#define OTA_BUF_LEN        (16385)
  4#define DEFAULT_DOWNLOAD_PART "download"
  5    int rc = 0, ota_over = 0;
  6    void *pclient = NULL, *h_ota = NULL;
  7    iotx_conn_info_pt pconn_info;
  8    iotx_mqtt_param_t mqtt_params;
  9
 10    // FILE *fp;
 11    static char buf_ota[OTA_BUF_LEN];
 12    const struct fal_partition * dl_part = RT_NULL;
 13
 14    // if (NULL == (fp = fopen("ota.bin", "wb+"))) {
 15    //     EXAMPLE_TRACE("open file failed");
 16    //     goto do_exit;
 17    // }
 18
 19    /**< get device info*/
 20    HAL_GetProductKey(g_product_key);
 21    HAL_GetDeviceName(g_device_name);
 22    HAL_GetDeviceSecret(g_device_secret);
 23    /**< end*/
 24
 25    /* Device AUTH */
 26    if (0 != IOT_SetupConnInfo(g_product_key, g_device_name, g_device_secret, (void **)&pconn_info)) {
 27        EXAMPLE_TRACE("AUTH request failed!");
 28        rc = -1;
 29        goto do_exit;
 30    }
 31
 32    /* Initialize MQTT parameter */
 33    memset(&mqtt_params, 0x0, sizeof(mqtt_params));
 34
 35    mqtt_params.port = pconn_info->port;
 36    mqtt_params.host = pconn_info->host_name;
 37    mqtt_params.client_id = pconn_info->client_id;
 38    mqtt_params.username = pconn_info->username;
 39    mqtt_params.password = pconn_info->password;
 40    mqtt_params.pub_key = pconn_info->pub_key;
 41
 42    mqtt_params.request_timeout_ms = 2000;
 43    mqtt_params.clean_session = 0;
 44    mqtt_params.keepalive_interval_ms = 60000;
 45    mqtt_params.read_buf_size = OTA_MQTT_MSGLEN;
 46    mqtt_params.write_buf_size = OTA_MQTT_MSGLEN;
 47
 48    mqtt_params.handle_event.h_fp = event_handle;
 49    mqtt_params.handle_event.pcontext = NULL;
 50
 51    /* Construct a MQTT client with specify parameter */
 52    pclient = IOT_MQTT_Construct(&mqtt_params);
 53    if (NULL == pclient) {
 54        EXAMPLE_TRACE("MQTT construct failed");
 55        rc = -1;
 56        goto do_exit;
 57    }
 58    h_ota = IOT_OTA_Init(g_product_key, g_device_name, pclient);
 59    if (NULL == h_ota) {
 60        rc = -1;
 61        EXAMPLE_TRACE("initialize OTA failed");
 62        goto do_exit;
 63    }
 64
 65
 66        do {
 67            uint32_t firmware_valid;
 68
 69            EXAMPLE_TRACE("wait ota upgrade command....");
 70
 71            /* handle the MQTT packet received from TCP or SSL connection */
 72            IOT_MQTT_Yield(pclient, 200);
 73
 74            if (IOT_OTA_IsFetching(h_ota)) {
 75                uint32_t last_percent = 0, percent = 0;
 76                char md5sum[33];
 77                char version[128] = {0};
 78                uint32_t len, size_downloaded, size_file;
 79                IOT_OTA_Ioctl(h_ota, IOT_OTAG_FILE_SIZE, &size_file, 4);
 80                /* Get download partition information and erase download partition data */
 81                if ((dl_part = fal_partition_find(DEFAULT_DOWNLOAD_PART)) == RT_NULL)
 82                {
 83                    LOG_E("Firmware download failed! Partition (%s) find error!", "download");
 84                    rc = -1;
 85                    goto do_exit;
 86                }
 87
 88                LOG_I("Start erase flash (%s) partition!", dl_part->name);
 89
 90                if (fal_partition_erase(dl_part, 0, size_file) < 0)
 91                {
 92                    LOG_E("Firmware download failed! Partition (%s) erase error!", dl_part->name);
 93                    rc = -1;
 94                    goto do_exit;
 95                }
 96                LOG_I("Erase flash (%s) partition success!", dl_part->name);
 97
 98                rt_uint32_t content_pos = 0, content_write_sz;
 99
100                do {
101
102                    len = IOT_OTA_FetchYield(h_ota, buf_ota, OTA_BUF_LEN, 1);
103                    if (len > 0) {
104                        content_write_sz = fal_partition_write(dl_part, content_pos, (uint8_t *)buf_ota, len);
105                        if (content_write_sz !=  len)
106                        {
107                            LOG_I("Write OTA data to file failed");
108
109                            IOT_OTA_ReportProgress(h_ota, IOT_OTAP_BURN_FAILED, RT_NULL);
110
111                            goto do_exit;
112                        }
113                        else
114                        {
115                            content_pos = content_pos + len;
116                            LOG_I("receive %d bytes, total recieve: %d bytes", content_pos, size_file);
117                        }
118                    } else {
119                        IOT_OTA_ReportProgress(h_ota, IOT_OTAP_FETCH_FAILED, NULL);
120                        EXAMPLE_TRACE("ota fetch fail");
121                    }
122
123                    /* get OTA information */
124                    IOT_OTA_Ioctl(h_ota, IOT_OTAG_FETCHED_SIZE, &size_downloaded, 4);
125                    IOT_OTA_Ioctl(h_ota, IOT_OTAG_FILE_SIZE, &size_file, 4);
126
127                    last_percent = percent;
128                    percent = (size_downloaded * 100) / size_file;
129                    if (percent - last_percent > 0) {
130                        IOT_OTA_ReportProgress(h_ota, percent, NULL);
131                    }
132                    IOT_MQTT_Yield(pclient, 100);
133                } while (!IOT_OTA_IsFetchFinish(h_ota));
134
135                IOT_OTA_Ioctl(h_ota, IOT_OTAG_MD5SUM, md5sum, 33);
136                IOT_OTA_Ioctl(h_ota, IOT_OTAG_VERSION, version, 128);
137                IOT_OTA_Ioctl(h_ota, IOT_OTAG_CHECK_FIRMWARE, &firmware_valid, 4);
138                if (0 == firmware_valid) {
139                    EXAMPLE_TRACE("The firmware is invalid");
140                } else {
141                    EXAMPLE_TRACE("The firmware is valid");
142                    IOT_OTA_ReportVersion(h_ota, version);
143
144                    LOG_I("Download firmware to flash success.");
145                    LOG_I("System now will restart...");
146
147                    HAL_SleepMs(1000);
148
149                    /* Reset the device, Start new firmware */
150                    extern void rt_hw_cpu_reset(void);
151                    rt_hw_cpu_reset();
152                }
153
154                ota_over = 1;
155            }
156            HAL_SleepMs(2000);
157        } while (!ota_over);
158
159    HAL_SleepMs(1000);
160
161do_exit:
162
163    if (NULL != h_ota) {
164        IOT_OTA_Deinit(h_ota);
165    }
166
167    if (NULL != pclient) {
168        IOT_MQTT_Destroy(&pclient);
169    }
170
171    return rc;
172}

编译工程,将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命令即可进行升级:

你可以添加微信17775982065为好友,注明:公司+姓名,拉进 RT-Thread 官方微信交流群!

RT-Thread


让物联网终端的开发变得简单、快速,芯片的价值得到最大化发挥。Apache2.0协议,可免费在商业产品中使用,不需要公布源码,无潜在商业风险。

长按二维码,关注我们

点击阅读原文,进入RT-Thread 官网

点个“在看”,让知识流行起来

“在看”的小可爱永远十八岁!

“在看”的小可爱永远十八岁!

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值