基于rtthread studio的STM32F407OTA升级(http篇)

基于rtthread studio的STM32F407OTA升级(http篇)

0、前提

0.1、已经完成联网配置

STM32F407VG联网笔记(基于rtthread studio)_LangLang_2020的博客-优快云博客

0.2、已经完成ymodem_OTA升级

基于rtthread studio的STM32F407OTA升级(ymodem篇)_LangLang_2020的博客-优快云博客

1、相关配置

image-20211106170412362

image-20211106170549419

image-20211106171141091

2、更改http_ota.c的文件内容

image-20211106172332952

将原文件中的内容替换为以下内容,具体细节可自行分析源码。


#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <rtthread.h>
#include <finsh.h>

#include "webclient.h"
#include <fal.h>

#define DBG_ENABLE
#define DBG_SECTION_NAME          "http_ota"
#ifdef OTA_DOWNLOADER_DEBUG
#define DBG_LEVEL                 DBG_LOG
#else
#define DBG_LEVEL                 DBG_INFO
#endif
#define DBG_COLOR
#include <rtdbg.h>

#ifdef PKG_USING_HTTP_OTA

#define HTTP_OTA_BUFF_LEN         4096
#define GET_HEADER_BUFSZ          1024
#define GET_RESP_BUFSZ            1024
#define HTTP_OTA_DL_DELAY         (10 * RT_TICK_PER_SECOND)

#define HTTP_OTA_URL              PKG_HTTP_OTA_URL

static void print_progress(size_t cur_size, size_t total_size)
{
    static unsigned char progress_sign[100 + 1];
    uint8_t i, per = cur_size * 100 / total_size;

    if (per > 100)
    {
        per = 100;
    }

    for (i = 0; i < 100; i++)
    {
        if (i < per)
        {
            progress_sign[i] = '=';
        }
        else if (per == i)
        {
            progress_sign[i] = '>';
        }
        else
        {
            progress_sign[i] = ' ';
        }
    }

    progress_sign[sizeof(progress_sign) - 1] = '\0';

    LOG_I("\033[2A");
    LOG_I("Download: [%s] %d%%", progress_sign, per);
}

static int http_ota_fw_download(const char* uri)
{
    int ret = 0, resp_status;
    int file_size = 0, length, total_length = 0;
    rt_uint8_t *buffer_read = RT_NULL;
    struct webclient_session* session = RT_NULL;
    const struct fal_partition * dl_part = RT_NULL;

    /* create webclient session and set header response size */
    session = webclient_session_create(GET_HEADER_BUFSZ);
    if (!session)
    {
        LOG_E("open uri failed.");
        ret = -RT_ERROR;
        goto __exit;
    }

    /* send GET request by default header */
    if ((resp_status = webclient_get(session, uri)) != 200)
    {
        LOG_E("webclient GET request failed, response(%d) error.", resp_status);
        ret = -RT_ERROR;
        goto __exit;
    }

    file_size = webclient_content_length_get(session);
    rt_kprintf("http file_size:%d\n",file_size);

    if (file_size == 0)
    {
        LOG_E("Request file size is 0!");
        ret = -RT_ERROR;
        goto __exit;
    }
    else if (file_size < 0)
    {
        LOG_E("webclient GET request type is chunked.");
        ret = -RT_ERROR;
        goto __exit;
    }

    /* Get download partition information and erase download partition data */
    if ((dl_part = fal_partition_find("download")) == RT_NULL)
    {
        LOG_E("Firmware download failed! Partition (%s) find error!", "download");
        ret = -RT_ERROR;
        goto __exit;
    }

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

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

    buffer_read = web_malloc(HTTP_OTA_BUFF_LEN);
    if (buffer_read == RT_NULL)
    {
        LOG_E("No memory for http ota!");
        ret = -RT_ERROR;
        goto __exit;
    }
    memset(buffer_read, 0x00, HTTP_OTA_BUFF_LEN);

    LOG_I("OTA file size is (%d)", file_size);

    do
    {
        length = webclient_read(session, buffer_read, file_size - total_length > HTTP_OTA_BUFF_LEN ?
                            HTTP_OTA_BUFF_LEN : file_size - total_length);
        if (length > 0)
        {
            /* Write the data to the corresponding partition address */
            if (fal_partition_write(dl_part, total_length, buffer_read, length) < 0)
            {
                LOG_E("Firmware download failed! Partition (%s) write data error!", dl_part->name);
                ret = -RT_ERROR;
                goto __exit;
            }
            total_length += length;

            print_progress(total_length, file_size);
        }
        else
        {
            LOG_E("Exit: server return err (%d)!", length);
            ret = -RT_ERROR;
            goto __exit;
        }

    } while(total_length != file_size);

    ret = RT_EOK;

    if (total_length == file_size)
    {
        if (session != RT_NULL)
        {
            webclient_close(session);
            session = RT_NULL;
        }
        if (buffer_read != RT_NULL)
        {
            web_free(buffer_read);
            buffer_read = RT_NULL;
        }

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

        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();
    }

__exit:
    if (session != RT_NULL)
        webclient_close(session);
    if (buffer_read != RT_NULL)
        web_free(buffer_read);

    return ret;
}

void http_ota(uint8_t argc, char **argv)
{
    if (argc < 2)
    {
        rt_kprintf("using uri: " HTTP_OTA_URL "\n");
        http_ota_fw_download(HTTP_OTA_URL);
    }
    else
    {
        http_ota_fw_download(argv[1]);
    }
}
/**
 * msh />http_ota [url]
*/
MSH_CMD_EXPORT(http_ota, Use HTTP to download the firmware);

#endif

3、打包升级固件

打包生成.rbl文件

image-20211106174824487

4、打开webserver

[下载地址](MyWebServer - Download (softonic.com))

image-20211106175624084

在这里插入图片描述

5、执行http_ota命令

image-20211106175109995

### 将CJSON库移植到RT-Thread Nano操作系统 #### 创建新项目 为了在RT-Thread Nano上使用cJSON库,首先需要创建一个新的RT-Thread Nano工程项目。通过RT-Thread Studio可以选择创建包含Nano版本的操作系统的工程[^1]。 #### 添加cJSON库至项目 一旦建立了基于RT-Thread Nano的新项目,则可以着手准备集成cJSON库。这通常涉及下载cJSON源文件并将其加入到项目的源码目录中。确保所选的cJSON版本兼容于目标平台以及编译器设置。 #### 修改配置文件 对于RT-Thread Nano而言,在`rtconfig.h`或其他相关配置头文件里可能需定义特定宏来适应cJSON的需求。例如,如果cJSON依赖某些标准函数而这些函数不在Nano环境中默认提供的话,就需要额外处理这些问题。 #### 编写适配层代码 有时为了让第三方库能在资源受限环境下正常运作,编写少量中间件或接口转换程序是必要的。比如实现缺少的标准I/O功能或是调整内存管理策略等。这部分工作取决于具体应用场景下的需求分析结果。 #### 测试验证 完成上述步骤之后,应该构建整个应用程序并对其实行全面测试以确认其行为符合预期。利用调试工具检查是否存在任何潜在错误,并优化性能直至满意为止。 ```c // 示例:初始化 cJSON 并解析 JSON 字符串 #include "cjson/cJSON.h" void json_example(void){ const char *input = "{\"name\":\"John\",\"age\":30}"; cJSON *root; root = cJSON_Parse(input); if (root != NULL) { // 解析成功后的操作... cJSON_Delete(root); // 清理分配给 cJSON 的空间 } } ```
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值