rt-thread物联网开发板用qboot实现固件ota升级

使用qboot软件包制作bootloader

  1. 为了使bootloader尽量小,对内核及其组件进行了如下配置
    在这里插入图片描述线程间通信只用选择这两个:
    在这里插入图片描述为了方便调试,下面这项配置成这样:
    在这里插入图片描述组件中除了这两项其他都不选:
    在这里插入图片描述在这里插入图片描述在这里插入图片描述这个msh shell其实占用rom挺多的。我们用console打印调试信息,但是可以不用shell, shell只是一些命令集
    在这里插入图片描述在这里插入图片描述网络组件全部不用,这些子菜单点进去,确认都没有选上!

  2. 配置qboot
    在这里插入图片描述在这里插入图片描述开发板上红色灯是E7,低电平点亮,所以这里running status led pin设置为71,led on level设置为0。
    在这里插入图片描述必须要开启片内flash

  3. 下载软件包并编译
    运行pkgs --update后,会自动下载qboot及其依赖包
    下载完成后,在board/ports/fal目录下,添加如下源文件(把其他文件删掉,只保留SConscript)
    在这里插入图片描述fal_cfg.h:

#ifndef _FAL_CFG_H_
#define _FAL_CFG_H_

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

#include <stdlib.h>

#define RT_APP_PART_ADDR            (0x08000000 + 64 * 1024)  // app partition begin address

#define NOR_FLASH_DEV_NAME          FAL_USING_NOR_FLASH_DEV_NAME//"norflash0"

/* ===================== Flash device Configuration ========================= */
extern const struct fal_flash_dev stm32_onchip_flash;
//extern struct fal_flash_dev nor_flash0;

/* flash device table */
#define FAL_FLASH_DEV_TABLE                                          \
{                                                                    \
    &stm32_onchip_flash,                                             \
    /*&nor_flash0,*/                                                 \
}
/* ====================== Partition Configuration ========================== */
#ifdef FAL_PART_HAS_TABLE_CFG
/* partition table */
#define FAL_PART_TABLE                                                                      \
{                                                                                           \
    /*{FAL_PART_MAGIC_WORD,   "bl",           "onchip_flash",     0,          32*1024,  0},*/  \
    {FAL_PART_MAGIC_WORD,   "app",          "onchip_flash",     64*1024,   128*1024,  0},  \
    {FAL_PART_MAGIC_WORD,   "factory",      "onchip_flash",     192*1024,  128*1024,  0},  \
    {FAL_PART_MAGIC_WORD,   "download",     "onchip_flash",     320*1024,  128*1024,  0},  \
    /*{FAL_PART_MAGIC_WORD,   "param",        "onchip_flash",     252*1024,  4*1024,  0},*/  \
    /*{FAL_PART_MAGIC_WORD,   "filesys",      NOR_FLASH_DEV_NAME, 0,          8*1024*1024,  0},*/ \
}
#endif /* FAL_PART_HAS_TABLE_CFG */

#endif /* _FAL_CFG_H_ */

注意RT_APP_PART_ADDR这个宏,这是app跳转地址。这里分了64k给bootloader
drv_fal_init.c:

#include <rtthread.h>

#ifdef PKG_USING_FAL

#include <fal.h>
extern int fal_init(void);
INIT_COMPONENT_EXPORT(fal_init);

#endif

修改main.c

int main(void)
{
    /* set LED0 pin mode to output */
    return RT_EOK;
}

把编译优化级别设置为Os,修改rtconfig.py文件:
在这里插入图片描述

运行scons编译,我这编译完了之后,有36kb。

  1. 运行效果
    因为app区 download区 和factory区都没有固件,所以一直重启(等待时间是默认的5秒):
    在这里插入图片描述

制作带ota升级功能的app

  • 使能ymodem和fal
    在这里插入图片描述在这里插入图片描述
  • board/ports/fal目录中的所有源文件内容保持和bootloader中的一样。
  • app的地址偏移是64k,必须保证以下两点才能跳转成功
  1. 修改链接脚本
    在这里插入图片描述
  2. 重新设置中断向量表地址
    main.c中添加如下代码段:
/* 将中断向量表起始地址重新设置为 app 分区的起始地址 */
static int ota_app_vtor_reconfig(void)
{
    #define NVIC_VTOR_MASK 0x3FFFFF80
    #define RT_APP_PART_ADDR 0x08010000
    /* 根据应用设置向量表 */
    SCB->VTOR = RT_APP_PART_ADDR & NVIC_VTOR_MASK;

    return 0;
}
INIT_BOARD_EXPORT(ota_app_vtor_reconfig);
  • 为了使用ymodem传输固件,还需要在applications目录添加如下源文件
    ymodem_update.c:
/*
 * Copyright (c) 2006-2018, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2018-01-30     armink       the first version
 * 2018-08-27     Murphy       update log
 */

#include <rtthread.h>
#include <stdio.h>
#include <stdbool.h>
#include <finsh.h>
#include <fal.h>
// #include <spi_flash_sfud.h>
#include <ymodem.h>

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

static size_t update_file_total_size, update_file_cur_size;

static const struct fal_partition * dl_part = RT_NULL;

static enum rym_code ymodem_on_begin(struct rym_ctx *ctx, rt_uint8_t *buf, rt_size_t len)
{
    char *file_name, *file_size;    

    /* calculate and store file size */
    file_name = (char *)&buf[0];
    file_size = (char *)&buf[rt_strlen(file_name) + 1];
    update_file_total_size = atol(file_size);

    update_file_cur_size = 0;

    /* 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");
        return RYM_CODE_CAN;
    }

    if (update_file_total_size > dl_part->len)
    {
        LOG_E("Firmware is too large! File size (%d), '%s' partition size (%d)", update_file_total_size, "download", dl_part->len);
        return RYM_CODE_CAN;
    }

    LOG_I("Start erase. Size (%d)", update_file_total_size);

    /* erase DL section */
    if (fal_partition_erase(dl_part, 0, update_file_total_size) < 0)
    {
        LOG_E("Firmware download failed! Partition (%s) erase error!", dl_part->name);
        return RYM_CODE_CAN;
    }

    return RYM_CODE_ACK;
}

static enum rym_code ymodem_on_data(struct rym_ctx *ctx, rt_uint8_t *buf, rt_size_t len)
{
    /* write data of application to DL partition  */
    if (fal_partition_write(dl_part, update_file_cur_size, buf, len) < 0)
    {
        LOG_E("Firmware download failed! Partition (%s) write data error!", dl_part->name);
        return RYM_CODE_CAN;
    }

    update_file_cur_size += len;

    return RYM_CODE_ACK;
}

void update(uint8_t argc, char **argv)
{
    struct rym_ctx rctx;

    rt_kprintf("Waring: Ymodem has started! This operator will not recovery.\n");
    rt_kprintf("Please select the ota firmware file and use Ymodem to send.\n");

    if (!rym_recv_on_device(&rctx, rt_console_get_device(), RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
                            ymodem_on_begin, ymodem_on_data, NULL, RT_TICK_PER_SECOND))
    {
        rt_kprintf("Download firmware to flash success.\n");
        rt_kprintf("System now will restart...\r\n");

        /* wait some time for terminal response finish */
        rt_thread_delay(rt_tick_from_millisecond(200));

        /* Reset the device, Start new firmware */
        extern void rt_hw_cpu_reset(void);
        rt_hw_cpu_reset();
        /* wait some time for terminal response finish */
        rt_thread_delay(rt_tick_from_millisecond(200));        
    }
    else
    {
        /* wait some time for terminal response finish */
        rt_thread_delay(RT_TICK_PER_SECOND);
        rt_kprintf("Update firmware fail.\n");
    }

    return;
}
MSH_CMD_EXPORT_ALIAS(update, ymodem_start, Update user application firmware);

  • main函数中打印标记当前版本:
int main(void)
{   
    /* set LED0 pin mode to output */
    LOG_I("app version is v1.0\n");
    rt_pin_mode(LED0_PIN, PIN_MODE_OUTPUT);
    
    while (1)
    {
        rt_pin_write(LED0_PIN, PIN_HIGH);
        rt_thread_mdelay(500);
        rt_pin_write(LED0_PIN, PIN_LOW);
        rt_thread_mdelay(500);
    }

    return RT_EOK;
}

编译下载到 0x08010000后运行效果:
在这里插入图片描述

试试升级功能

  • 修改一下main.c
int main(void)
{   
    /* set LED0 pin mode to output */
    LOG_I("app version is v2.0\n");
    rt_pin_mode(LED0_PIN, PIN_MODE_OUTPUT);
    
    while (1)
    {
        rt_pin_write(LED0_PIN, PIN_HIGH);
        rt_thread_mdelay(500);
        rt_pin_write(LED0_PIN, PIN_LOW);
        rt_thread_mdelay(500);
    }

    return RT_EOK;
}
  • 编译完了之后 ,用固件打包器打包
    在这里插入图片描述
  • 传输新固件
    1. 输入ymodem_start
    2. 选择.rbl文件
      在这里插入图片描述
      在这里插入图片描述 注意终端工具用的是xshell
      在这里插入图片描述传完了之后自动重启:
      在这里插入图片描述
  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值