上一篇
本篇概述
- OTA升级协议层编写
自定义OTA协议约定
OTA大致发起的流程图
### 协议约定
包类型
- 起始包(0x01)
- 数据包(0x02)
- 结束包(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;
}
下篇概述
- OTA实际通讯驱动编写(暂定串口+DMA+中断)