简易的fota升级方式,仅供参数。
/******************************************************************************************************************************************
* @file fota.c
* @author jianqiang.xue
* @version v1.0.0
* **************************************************************************/
#include #include #include #include "crc16.h" #include "errorno.h" #include "modules.h" #include "partition.h" #include "atcmd.h" #include "comm_box.h" #include "sys_cmsis.h" #include "bsp_flash.h" #include "bsp_uart.h" #define FOTA_PACK_HEAD_1ST_BYTE 0xA5 #define FOTA_PACK_OPCODE_DATA 0x5A #define FOTA_PACK_OPCODE_ABORT 0xB6 #define FOTA_GET_PACK_ID(BUFF) (BUFF[2]) #define FOTA_GET_DATA_LEN(BUFF) (BUFF[3]) #define FOTA_GET_DATA_HEAD_ADDR(BUFF) (BUFF[4]) #define FOTA_CRC16_INIT_VAL 0xFFFF #define FLASH_PAGE_SIZE 2048 #define RECV_TIMEOUT_MS 3000 #define BUFF_SIZE 256 #define PACK_DATA_LEN 128 #define PACK_MAX_PAGE 16 #define PACK_HEADER_LEN 4 #define PACK_CRC_LEN 2 #define ACTION_CLS_FLAG 0 #define ACTION_CARRY_TO_APP 2 #define FOTA_STR_LEN(str) strlen(str) #define FOTA_RX_EVENT 1 #define ATCMD_RET_CAN_UPGRADED "Can Upgradedrn" #define ATCMD_RET_CANT_UPGRADED "Can't Upgradedrn" static void fota_timer_handle(void const *arg); static void fota_opcode_abort(void); sys_timer_id_t fota_timer_id; SYS_TIMER_DEF(fota_timer, fota_timer_handle); typedef enum { UPGRADE_FREE = 0, UPGRADE_ING, UPGRADE_END } fota_up_stage_t; typedef enum { RX_DATA_ING = 0, RX_DATA_END } fota_rx_stage_t; typedef struct { fota_up_stage_t up_stage; fota_rx_stage_t data_rx_stage; uint8_t pages_num; uint16_t pack_num; uint32_t size_num; } ota_t; ota_t g_ota; static comm_hdr_t hdr; static uint8_t g_rx_buff[BUFF_SIZE]; static uint8_t g_flash_buf[FLASH_PAGE_SIZE]; static char g_msg_head[] = "UP^"; static char g_msg_tail[] = "rn"; static uint8_t ota_region_erased = 0; static uint8_t g_pack_id = 0; static uint8_t g_recv_timeout_flag = 0; static void fota_jump_carry_mode(uint8_t carry_page_num) { //high 8 page num bsp_flash_write_nv((carry_page_num << 8) | ACTION_CARRY_TO_APP); sys_reset(); } static void fota_timer_start(void) { sys_timer_start(fota_timer_id, RECV_TIMEOUT_MS); } static void fota_timer_stop(void) { sys_timer_stop(fota_timer_id); } static void fota_recv_data_timeout(void) { if (g_ota.up_stage == UPGRADE_ING) { memset(g_rx_buff, 0, BUFF_SIZE); fota_opcode_abort(); } } static void fota_send_ack(char* result, char* err, const char* str, uint16_t len) { uint8_t *p_msg_buf; uint16_t msg_len = 0; uint16_t offset = 0; if (len == 0) { return; } msg_len = sizeof(hdr) + strlen(g_msg_head) + strlen(result) + strlen(err) + strlen(",") + len + strlen(g_msg_tail); p_msg_buf = mem_malloc(msg_len); if (!p_msg_buf) { return; } memcpy(p_msg_buf, &hdr, sizeof(hdr)); offset += sizeof(hdr); memcpy(p_msg_buf + offset, g_msg_head, strlen(g_msg_head)); offset += strlen(g_msg_head); memcpy(p_msg_buf + offset, result, strlen(result)); offset += strlen(result); memcpy(p_msg_buf + offset, err, strlen(err)); offset += strlen(err); memcpy(p_msg_buf + offset, ",", strlen(",")); offset += strlen(","); memcpy(p_msg_buf + offset, str, len); offset += len; memcpy(p_msg_buf + offset, g_msg_tail, strlen(g_msg_tail)); offset += strlen(g_msg_tail); comm_box_send_msg(p_msg_buf, msg_len); mem_free(p_msg_buf); } static void fota_opcode_data(uint8_t pack_len) { memcpy(&g_flash_buf[g_ota.pack_num * PACK_DATA_LEN], &FOTA_GET_DATA_HEAD_ADDR(g_rx_buff), FOTA_GET_DATA_LEN(g_rx_buff)); g_ota.size_num += FOTA_GET_DATA_LEN(g_rx_buff); g_ota.pack_num ++; // After receiving 16 times of 2K, write flash once if ((pack_len == (PACK_HEADER_LEN + PACK_CRC_LEN)) && (FOTA_GET_DATA_LEN(g_rx_buff) == 0)) { g_ota.pack_num = 0; g_ota.data_rx_stage = RX_DATA_END; g_ota.up_stage = UPGRADE_END; } else if (g_ota.pack_num >= PACK_MAX_PAGE) { g_ota.pack_num = 0; g_ota.data_rx_stage = RX_DATA_END; g_ota.up_stage = UPGRADE_ING; } } static void fota_opcode_abort(void) { memset(&g_ota, 0, sizeof(ota_t)); g_ota.pages_num = 0; ota_region_erased = 0; g_pack_id = 0; g_recv_timeout_flag = 0; fota_recv_data_timeout(); memset(g_flash_buf, 0, FLASH_PAGE_SIZE); } static void fota_verify_data(bsp_uart_t uart, uint8_t *data, uint16_t len) { int32_t ret = RETVAL(E_OK); uint16_t calc_crc; uint16_t recv_crc; uint8_t pdu_len = 0; // Protocol Data Unit uint8_t pack_len = 0; char pack_id_s[5]; char err_s[5]; (void)uart; g_recv_timeout_flag = 1; memcpy(g_rx_buff, data, len); // Calculate the current packet length if (len > 4) { pdu_len = FOTA_GET_DATA_LEN(g_rx_buff) + PACK_HEADER_LEN; } else { pdu_len = 0; return; } pack_len = pdu_len + PACK_CRC_LEN; if (len != pack_len) { ret = RETVAL(E_INVAL_LEN); } if ((ret == RETVAL(E_OK)) && g_rx_buff[0] == FOTA_PACK_HEAD_1ST_BYTE) { calc_crc = crc16(FOTA_CRC16_INIT_VAL, g_rx_buff, pdu_len); recv_crc = (g_rx_buff[pack_len - 2] << 8) | g_rx_buff[pack_len - 1]; if (calc_crc == recv_crc) { if (g_rx_buff[1] == FOTA_PACK_OPCODE_DATA && (g_ota.data_rx_stage == RX_DATA_ING)) { // Verify that the packet ID is correct if ((FOTA_GET_PACK_ID(g_rx_buff) - g_pack_id == 1) || (g_pack_id - FOTA_GET_PACK_ID(g_rx_buff) == 255)) { fota_opcode_data(pack_len); } // Resend the acknowledge signal else if (FOTA_GET_PACK_ID(g_rx_buff) == g_pack_id) { ret = RETVAL(E_OK); } else { ret = RETVAL(E_MSG); } } else if (g_rx_buff[1] == FOTA_PACK_OPCODE_ABORT)
上一篇:[keil][python][单片机] keil 集成bin文件生成 boot+app合并 dfu生成
下一篇:[单片机] x_strtok,安全分割函数
推荐阅读最新更新时间:2024-11-12 11:18
设计资源 培训 开发板 精华推荐
- 【中山大学校赛】便携式测温系统
- 典型应用显示 SEPIC 配置具有准确的输入电流检测和 A8515 LED 驱动器的 VSENSE 至 GND 保护
- 使用 ON Semiconductor 的 CAT660 的参考设计
- L7805A 光控制器稳压器的典型应用
- MC34071DR2G 二阶低通有源滤波器的典型应用
- LT6656ACS6-5、5V 精密电流和升压电压基准的典型应用
- 使用 Analog Devices 的 LT1183CS 的参考设计
- EVAL-CN0221-EB1Z,基于 USB 的热电偶温度测量系统
- TCR5SB32、200mA、3.2V 输出电压 CMOS 低压降稳压器的典型应用
- 使用 LTC2377HMS-16、16 位、500ksps SAR ADC 的典型应用