打印
[应用相关]

STM32三方库 - 固件升级/OTA

[复制链接]
18|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
晓伍|  楼主 | 2025-3-10 18:11 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式



一、Bootloader
1、Bootloader生成
官方网站:http://iot.rt-thread.com

官方文档:https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/application-note/system/rtboot/an0028-rtboot

新建产品->固件升级->生成Bootloader:








将会生成bin固件发送到邮箱并下载:



2、Bootloader烧录
配置工程、Target->Production Programming(JLINK方式):



由于此时app分区还没有对应的app程序,所以会卡住:



二、Application
1、链接文件修改
修改程序链接脚本中ROM的起始地址和大小:



2、中断向量表地址偏移
由于App分区的起始地址为0x08020000(根据实际情况),需要修改链接脚本和中断向量的跳转地址;

注意:rt-thread/src/components.c->rtthread_startup为初始化函数,初始化完毕进入main。

修改中断向量表位置(board.c):

RT_WEAK void rt_hw_board_init()

{

// 中断向量表偏移

SCB->VTOR = ((uint32_t)0x8020000);

... ...

3、添加固件版本信息
在 main 函数中添加版本信息(用于区别APP分区):

#define APP_VERSION "1.0.0"

int main(void)

{

rt_kprintf("/* ---------Application--------- */\n");

rt_kprintf("The current version of APP firmware is %s\n", APP_VERSION);

    ... ...

4、FLASH及分区配置
SFUD(全称 Serial Flash Universal Driver)是一款开源的串行 SPI Flash 通用驱动库;

FAL:Flash 抽象层。      

使能组件:



修改board.h:

#define BSP_USING_ON_CHIP_FLASH

#define BSP_USING_SPI2

添加fal_config:



// 修改fal_cfg.h:

/*******************************************

* File: fal_cfg.h

* Describe: FAL_FLASH分区表

* Author: Xiangfu DING

* Time: 2025-02-10

*******************************************/

#ifndef _FAL_CFG_H_

#define _FAL_CFG_H_

#include <rtconfig.h>

#include <board.h>

#ifndef FAL_USING_NOR_FLASH_DEV_NAME

#define NOR_FLASH_DEV_NAME             "norflash0"

#else

#define NOR_FLASH_DEV_NAME              FAL_USING_NOR_FLASH_DEV_NAME

#endif

// STM32F407VGT6 - 内部 Flash 大小为 1024KB(分为 4 个 16KB 扇区、1 个 64KB 扇区、7 个 128KB 扇区)

#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;

/* ===================== Flash device Configuration ========================= */

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,        "app",     "onchip_flash",      0 * 1024,       512 * 1024, 0}, \

    {FAL_PART_MAGIC_WROD,   "download", NOR_FLASH_DEV_NAME,      0 * 1024,       512 * 1024, 0}, \

}

#endif /* FAL_PART_HAS_TABLE_CFG */

#endif /* _FAL_CFG_H_ */

// 初始化

#include "fal.h"

int main(void)

{

// 初始化W25Q64

    rt_hw_spi_device_attach("spi2", "spi20", GPIOB, GPIO_PIN_12);

    //flash名称要正确

    if (RT_NULL == rt_sfud_flash_probe("W25Q64", "spi20")) {

     rt_kprintf("rt_sfud_flash_probe failed!\n");

    }

// 初始化FAL

fal_init();

    ... ...



5、执行OTA升级
制作固件包
https://codeload.github.com/RT-Thread-packages/ota_downloader/zip/refs/tags/1.0.0

打开资源所在目录:



打包固件:



注意:OTA只会增量升级,固件版本必须大于当前app分区版本号才可以触发。

SD卡升级
/*******************************************

* File: sdota.c

* Describe: SD卡固件升级

* Author: Xiangfu DING

* Time: 2025-02-07

*******************************************/

#include "sdota.h"

#include "core.h"

#include <rtdevice.h>

#include <drv_common.h>

#include <rtdbg.h>

#include <finsh.h>

#include <fal.h>

#include <dfs_fs.h>

static void print_progress(size_t cur_size, size_t total_size)

{

    uint8_t progress = cur_size * 100 / total_size;

    if (progress > 100) {

        progress = 100;

    }

    rt_kprintf("Download progress: %d%\n", progress);

}

int sdOtaDownload(const char* uri)

{

    const struct fal_partition *dl_part = RT_NULL;

    int begin_offset = 0;

    int file_size = 0;

    int fd;

    struct stat fileStat;

    uint8_t buffer[1024];

    int ret = RT_EOK;

    rt_kprintf("sdOtaDownload uri: %s\n", uri);

    // 打开并检查固件是否存在

    fd = open(uri, O_RDONLY);

    if (fd < 0) {

        rt_kprintf("Firmware does not exist!\n");

        goto __exit;

    }

    // 获取固件大小

    if (stat(uri, &fileStat) == 0) {

        file_size =  fileStat.st_size;

        rt_kprintf("Firmware size: %d\n", file_size);

    } else {

        rt_kprintf("Failed to get file size for %s\n", uri);

        goto __exit;

    }

    // 获取下载分区信息并擦除下载分区数据

    if ((dl_part = fal_partition_find("download")) == RT_NULL) {

        rt_kprintf("Firmware download failed! Partition (%s) find error!\n", "download");

        ret = -RT_ERROR;

        goto __exit;

    }

    // 擦除Download分区

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

    if (fal_partition_erase(dl_part, 0, file_size) < 0) {

        rt_kprintf("Firmware download failed! Partition (%s) erase error!\n", dl_part->name);

        ret = -RT_ERROR;

        goto __exit;

    }

    rt_kprintf("Erase flash (%s) partition success!\n", dl_part->name);

    // 拷贝固件到Download分区

    while (begin_offset < file_size) {

        // 读取文件到缓冲区

        int length = read(fd, buffer, sizeof(buffer));

        if (length < 0) {

            rt_kprintf("Read file error!\n");

            ret = -RT_ERROR;

            goto __exit;

        }

        // 写入闪存分区

        if (fal_partition_write(dl_part, begin_offset, buffer, length) < 0) {

            rt_kprintf("Firmware download failed! Partition (%s) write data error!\n", dl_part->name);

            ret = -RT_ERROR;

            goto __exit;

        }

        // 更新下载的偏移量

        begin_offset += length;

        // 打印下载进度

        print_progress(begin_offset, file_size);

    }

    // 重启升级固件

    if (ret == RT_EOK) {

        rt_kprintf("Download firmware to flash success.\n");

        rt_kprintf("System now will restart...\n");

        rt_thread_delay(rt_tick_from_millisecond(5));

        // Reset the device, Start new firmware

        extern void rt_hw_cpu_reset(void);

        rt_hw_cpu_reset();

    } else {

        rt_kprintf("Download firmware failed!\n");

    }

__exit:

    close(fd);

    return ret;

}

void sdota(int argc, char **argv)

{

    sdOtaDownload(FIRMWARE_PATH);

}

MSH_CMD_EXPORT(sdota, "The sd card firmware is upgraded");

HTTP升级
该软件包会自动勾选webclient软件包:



HTTP升级源码位置:



使用示例:

http_ota http://192.168.0.108:8080/download/rtthread.rbl
————————————————

                            版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

原文链接:https://blog.csdn.net/dxf1971738522/article/details/145996813

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

74

主题

4217

帖子

1

粉丝