Clion开发STM32之OTA升级模块(三)

上一篇

Clion开发STM32之OTA升级模块(二)

本篇概述

  1. OTA升级协议层编写

自定义OTA协议约定

OTA大致发起的流程图

OTA大致发起的流程图### 协议约定

包类型
  1. 起始包(0x01)
  2. 数据包(0x02)
  3. 结束包(0x03)

起始包格式
在这里插入图片描述
数据包格式

在这里插入图片描述

结束包格式

在这里插入图片描述

OTA代码
OTA工具类

头文件(ota_upgrade_utils.h)

#ifndef STM32F103VET6_PROJECT_OTA_UPGRADE_UTILS_H
#define STM32F103VET6_PROJECT_OTA_UPGRADE_UTILS_H

#include "sys_core.h"


int ota_version_compare(const uint8_t *v1, const uint8_t *v2, uint8_t len);

int ota_convert_u8_to_str(char *dst, const uint8_t *data, uint16_t data_len, char *fmt);

int ota_convert_to_hex_str(char *dst, const uint8_t *data, uint16_t len);

#endif //STM32F103VET6_PROJECT_OTA_UPGRADE_UTILS_H

源文件

#include "ota_upgrade_utils.h"

/**
 * ota 版本比较
 * @param v1 版本1
 * @param v2 版本2
 * @param len 版本长度
 * @return 1: v1>v2; 0: v1=v2; -1: v1<v2
 */
int ota_version_compare(const uint8_t *v1, const uint8_t *v2, uint8_t len) {
    for (int i = 0; i < len; ++i) {
        if (v1[i] > v2[i]) {
            return 1;
        } else if (v1[i] < v2[i]) {
            return -1;
        }
    }
    return 0;
}

int ota_convert_u8_to_str(char *dst, const uint8_t *data, uint16_t data_len, char *fmt) {
    int pos = 0;
    int cpy_len;
    for (int i = 0; i < data_len; ++i) {
        cpy_len = sprintf(dst + pos, fmt, data[i]);
        pos += cpy_len;
    }
    return pos;
}

int ota_convert_to_hex_str(char *dst, const uint8_t *data, uint16_t len) {
    return ota_convert_u8_to_str(dst, data, len, "%02X ");
}
OTA驱动flash

头文件(ota_boot_info.h)

#ifndef STM32F103VET6_PROJECT_OTA_BOOT_INFO_H
#define STM32F103VET6_PROJECT_OTA_BOOT_INFO_H

#include "sys_core.h"

#define CLOSE_ALL_INT()  __set_PRIMASK(1)    //关闭所有中断
#define OPEN_ALL_INT()   __set_PRIMASK(0)
#define OTA_UPGRADE_FLAG (0x1389)
typedef struct {
    uint8_t app_version[6]; // 应用版本
    uint32_t app_new_version_flag; // 应用新版本标志位
//    uint32_t app_run_addr; // 应用运行地址
//    uint32_t app_upgrade_data_addr; // 应用升级数据地址
    uint32_t app_upgrade_data_size; // 应用升级数据大小
} APP_Info_t;

void Load_App_Info(APP_Info_t *info);

void Update_App_Info(APP_Info_t *info);

void Jump_To_App(uint32_t run_addr);

void Jump_To_BootLoader(void);

#endif //STM32F103VET6_PROJECT_OTA_BOOT_INFO_H

源文件

#include "ota_boot_info.h"
#include "bsp_flash.h"
#include "app_flash_conf.h"

typedef void (*pFunction)(void);

/**
 * 加载APP信息
 * @param dst
 */
void Load_App_Info(APP_Info_t *info) {
    STMFLASH_Read_Base(BOOT_INF_ADDR, info, sizeof(APP_Info_t));
}

/**
 * 更新APP信息
 * @param dst
 */
void Update_App_Info(APP_Info_t *info) {
    STMFLASH_Write_Base(BOOT_INF_ADDR, info, sizeof(APP_Info_t));
}

void Jump_To_BootLoader(void) {
    __disable_irq();
    uint32_t JumpAddress;
    pFunction Jump_To_Application;
    JumpAddress = *(volatile uint32_t *) (0x00000004);
    Jump_To_Application = (pFunction) JumpAddress;
    __set_MSP(*(volatile uint32_t *) JumpAddress);
    __set_PSP(*(volatile uint32_t *) JumpAddress);
    Jump_To_Application();
}

void Jump_To_App(uint32_t run_addr) {
    __disable_irq();
    pFunction jump_app;
    jump_app = (pFunction) (*(volatile uint32_t *) (run_addr + 0x04));
    __set_MSP(*(volatile uint32_t *) run_addr);
    jump_app();
}
OTA核心文件

头文件(ota_upgrade.h)

#ifndef STM32F103VET6_PROJECT_OTA_UPGRADE_H
#define STM32F103VET6_PROJECT_OTA_UPGRADE_H

#include "sys_core.h"
#include "ota_upgrade_utils.h"
#include "ota_boot_info.h"
#include "app_flash_conf.h"

#define OTA_UPGRADE_VERSION_LIN (6) // 升级版本长度
#define OTA_UPGRADE_DATA_FRAME_SIZE (SIZE_1K) // 升级数据帧大小(1KB)
#define OTA_UPGRADE_DEVICE_TYPE  (1) // 升级设备类型
enum {
    SOH_FRAME = 0x01, // 开始包
    STX_FRAME = 0x02, // 数据包
    EOT_FRAME = 0x04, // 结束包
};

typedef struct {
    uint8_t packet_type;  // 包类型
    uint8_t device_type; // 设备类型
    uint8_t upgrade_version[OTA_UPGRADE_VERSION_LIN]; // 升级版本
    uint32_t upgrade_packet_size;  // 升级包大小(总)
    uint8_t current_packet_no;   // 当前包号
    uint8_t total_packet_num; // 总包数
    uint8_t *upgrade_data;        // 升级数据
    uint16_t upgrade_data_size; // 升级数据大小(一帧升级数据大小)
} OTA_Packet_t;
typedef enum {
    OTA_OK = 0x00,
    OTA_UPGRADE_DEVICE_ERR = 0x1,
    OTA_PARAM_ERR = 0x02,
    OTA_FUNC_CODE_ERR = 0x03,
    OTA_DATA_LEN_ERR = 0x04,
    OTA_NOT_INIT_ERR = 0x05,
    OTA_UPGRADE_VERSION_LOW = 0x6,
    OTA_UPGRADE_WRITE_ERR = 0x7,
    OTA_UPGRADE_PACKET_NO_ERR = 0x8,
    OTA_UPGRADE_PACKET_NO_COMPLETE = 0x9, // 升级包不完整
} OTA_Status_t;

/**
 * OTA 响应数据
 * @param data
 * @param len
 */
__weak void OTA_Resp(void *data, uint16_t len);
/**
 * OTA 版本比较
 * @param cur_ver 当前版本
 * @param upgrade_ver 升级版本
 * @param len
 * @return 1:cur_ver>upgrade_ver; 0: cur_ver=upgrade_ver;-1:cur_ver<upgrade_ver
 */
__weak int OTA_Version_Compare(uint8_t *cur_ver, uint8_t *upgrade_ver, uint8_t len);
/**
 * 获取当前版本
 * @return
 */
__weak uint8_t *OTA_GetCur_Version(void);
/**
 * 写入bin数据
 * @param addr
 * @param data
 * @param len
 * @return
 */
__weak bool OTA_Write_Bin_Data(uint32_t addr, uint8_t *data, uint16_t len);
/**
 * 通知升级完成
 * @param info 更新boot信息
 */
__weak void OTA_Notify_Upgrade_Finished(APP_Info_t *info);

void OTA_Upgrade_Handle(uint8_t *data, uint16_t len);

#endif //STM32F103VET6_PROJECT_OTA_UPGRADE_H

源文件

#include "ota_upgrade.h"
#include "sys_core_log.h"


APP_Info_t GB_App_Info = {
//        .app_run_addr=APP_START_ADDR,
//        .app_upgrade_data_addr = APP_UPGRADE_START_ADDR,
};
static OTA_Packet_t ota_pkt;
static bool ota_init_flag = false;
static u8 ota_cur_packet_no = 1;     // 当前升级包号
static volatile u32 ota_cur_rec_data_size = 0; // 当前接收升级数据大小
static u32 ota_upgrade_total_data_size = 0; // 升级总数据大小

static OTA_Status_t OTA_Packet_Parse(OTA_Packet_t *pkt, uint8_t *data, uint16_t len);

static OTA_Status_t OTA_Func_Exec(OTA_Packet_t *pkt);

static void OTA_Rsp_Status(uint8_t code) {
    OTA_Resp(&code, 1);
}

static void ota_status_flag_init(void);

/**
 * OTA 升级处理
 * @param data
 * @param len
 */
void OTA_Upgrade_Handle(uint8_t *data, uint16_t len) {
    os_ps("ota rec len:%d\r\n", len);
    OTA_Status_t status = OTA_Packet_Parse(&ota_pkt, data, len);

    if (status == OTA_OK) {
        status = OTA_Func_Exec(&ota_pkt);

    }
    OTA_Rsp_Status(status);
}

static OTA_Status_t OTA_Packet_Parse(OTA_Packet_t *pkt, uint8_t *data, uint16_t len) {
    if (data == NULL) {
        return OTA_PARAM_ERR;
    }
    uint16_t idx = 0;
    switch (data[0]) {
        case SOH_FRAME:
            ASSERT(len == 12, OTA_DATA_LEN_ERR);
            pkt->packet_type = data[idx++];   // 包类型
            pkt->device_type = data[idx++];  // 设备类型
            pkt->upgrade_packet_size = convert_u8_to_u32(data, idx, true);
            idx += 4;
            cpy_data(pkt->upgrade_version, data + idx, OTA_UPGRADE_VERSION_LIN);
            ota_init_flag = true;
            break;
        case STX_FRAME:
            ASSERT(len == OTA_UPGRADE_DATA_FRAME_SIZE + 3, OTA_DATA_LEN_ERR);
            pkt->packet_type = data[idx++];   // 包类型
            pkt->total_packet_num = data[idx++]; // 总包数
            pkt->current_packet_no = data[idx++]; // 当前包号
            pkt->upgrade_data_size = len - idx;
            pkt->upgrade_data = data + idx;
            break;
        case EOT_FRAME:
            ASSERT(len == 6, OTA_DATA_LEN_ERR);
            pkt->packet_type = data[idx++];   // 包类型
            pkt->device_type = data[idx++];  // 设备类型
            pkt->upgrade_packet_size = convert_u8_to_u32(data, idx, true); // 升级大小
            break;
        default:
            return OTA_FUNC_CODE_ERR;
    }
    return OTA_OK;
}

static OTA_Status_t OTA_Func_Exec(OTA_Packet_t *pkt) {
//    ota_init_flag = true; // 测试
//    pkt->device_type = OTA_UPGRADE_DEVICE_ERR;
    switch (pkt->packet_type) {
        case SOH_FRAME: // OTA起始升级帧
        {

            ASSERT(OTA_UPGRADE_DEVICE_TYPE == pkt->device_type, OTA_UPGRADE_DEVICE_ERR);
            ASSERT(OTA_Version_Compare(OTA_GetCur_Version(), ota_pkt.upgrade_version,
                                       OTA_UPGRADE_VERSION_LIN) > 0, OTA_UPGRADE_VERSION_LOW);
            ota_init_flag = true;
            ota_status_flag_init();
            ota_upgrade_total_data_size = pkt->upgrade_packet_size;

            os_ps("ota start packet,size:%d\r\n", pkt->upgrade_packet_size);
        }
            break;
        case STX_FRAME: {
            //
            os_ps("ota data packet,no:%d\r\n", pkt->current_packet_no);

            ASSERT(ota_init_flag, OTA_NOT_INIT_ERR);// 未初始化
            ASSERT(ota_cur_packet_no == pkt->current_packet_no, OTA_UPGRADE_PACKET_NO_ERR); // 升级包序号与当前需要的包序号不对应
            ASSERT(OTA_Write_Bin_Data(APP_UPGRADE_START_ADDR + ota_cur_rec_data_size, ota_pkt.upgrade_data,
                                      pkt->upgrade_data_size), OTA_UPGRADE_WRITE_ERR);
            ota_cur_rec_data_size += pkt->upgrade_data_size; // 升级数据递加
            ota_cur_packet_no += 1;
        }
            break;
        case EOT_FRAME: {
            os_ps("ota end packet,no:%d\r\n", pkt->current_packet_no);
            ota_upgrade_total_data_size = pkt->upgrade_packet_size;
            ASSERT(OTA_UPGRADE_DEVICE_TYPE == pkt->device_type, OTA_UPGRADE_DEVICE_ERR);
            ASSERT(ota_init_flag, OTA_NOT_INIT_ERR);// 未初始化
            ASSERT(pkt->upgrade_packet_size == ota_upgrade_total_data_size, OTA_UPGRADE_PACKET_NO_COMPLETE);
            // 更新boot信息
            cpy_data(GB_App_Info.app_version, pkt->upgrade_version, OTA_UPGRADE_VERSION_LIN);
            GB_App_Info.app_upgrade_data_size = ota_upgrade_total_data_size;
            GB_App_Info.app_new_version_flag = OTA_UPGRADE_FLAG;
            OTA_Notify_Upgrade_Finished(&GB_App_Info);
            // 重置标志位
            ota_status_flag_init();
            ota_init_flag = false;
        }
            break;
    }
    return OTA_OK;
}

/**
 * 状态标志位初始化
 */
static void ota_status_flag_init(void) {
    ota_cur_packet_no = 1;
    ota_cur_rec_data_size = 0;
    ota_upgrade_total_data_size = 0;
}

下篇概述

  1. OTA实际通讯驱动编写(暂定串口+DMA+中断)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

詩不诉卿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值