Simple fota upgrade method, only for parameters.
/******************************************************************************************************************************************
* @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) { right = RIGHTVAL(E_OK); } else { ret = RETVAL(E_MSG); } } else if (g_rx_buff[1] == FOTA_PACK_OPCODE_ABORT) { fota_opcode_abort(); fota_timer_stop(); } else { ret = RETVAL(E_MSG); } } else { ret = RETVAL(E_CRC); } } else { ret = RETVAL(E_INVAL_ADDR); } if (ret != RETVAL(E_OK)) { itoa((int)FOTA_GET_PACK_ID(g_rx_buff), pack_id_s, 10); itoa((int)ret, err_s, 10); fota_send_ack("FAIL,", err_s, pack_id_s, FOTA_STR_LEN(pack_id_s)); } else { g_pack_id = FOTA_GET_PACK_ID(g_rx_buff); itoa((int)g_pack_id, pack_id_s, 10); fota_send_ack("OK,", "0", pack_id_s, FOTA_STR_LEN(pack_id_s)); if (g_rx_buff[1] == FOTA_PACK_OPCODE_ABORT) { g_pack_id = 0; } } memset(g_rx_buff, 0x00, sizeof(g_rx_buff)); } static void fota_data_Handle(uint8_t *buff, uint16_t len) { uint8_t offset; int32_t ret = RETVAL(E_OK); uint8_t page_num = 0; uint32_t write_ptr = 0; memcpy(&hdr, buff, sizeof(hdr)); hdr.response = 1; offset = sizeof(hdr); offset += FOTA_STR_LEN(g_msg_head); fota_verify_data(BSP_UART0, (uint8_t *)(buff + offset), len - offset); if (g_ota.data_rx_stage == RX_DATA_END) { write_ptr = FLASH_OTA_REGION_BASE + g_ota.pages_num * FLASH_PAGE_SIZE; sys_irq_disable(); // the whole ota region will be erased if the first dfu pack received if (ota_region_erased == 0) { uint8_t pages = FLASH_APP_REGION_SIZE / FLASH_PAGE_SIZE; uint8_t i; for (i = 0; i < pages; i++) { bsp_flash_erase_page(FLASH_OTA_REGION_BASE + i * FLASH_PAGE_SIZE); } ota_region_erased = 1; fota_timer_start(); } ret = bsp_flash_write_words(write_ptr, (uint32_t *)g_flash_buf, ARRAY_SIZE(g_flash_buf)); sys_irq_enable(); if (ret == RETVAL(E_OK)) { g_ota.pages_num += 1; } g_ota.data_rx_stage = RX_DATA_ING; if (g_ota.up_stage == UPGRADE_END) { g_ota.up_stage = UPGRADE_FREE; page_num = (g_ota.size_num % FLASH_PAGE_SIZE) == 0 ? g_ota.size_num / FLASH_PAGE_SIZE : g_ota.size_num / FLASH_PAGE_SIZE + 1; sys_irq_disable(); fota_jump_carry_mode(page_num); sys_reset(); sys_irq_enable(); } } } static void fota_timer_handle(void const *arg) { if (g_recv_timeout_flag) { g_recv_timeout_flag = 0; } else { fota_recv_data_timeout(); } } static void fota_task_init(void) { comm_box_register_msg_channel("UP^", fota_data_Handle); fota_timer_id = sys_timer_create(SYS_TIMER(fota_timer), SYS_TIMER_PERIODIC, NULL); memset(&g_ota, 0, sizeof(ota_t)); memset(g_rx_buff, 0, BUFF_SIZE); memset(g_flash_buf, 0, FLASH_PAGE_SIZE); } static int32_t check_upgrade_state(char* argv[], int argc) { uint8_t flag = 0; // check state if (flag == 0) { atcmd_send_response(AT_OK, ATCMD_RET_CAN_UPGRADED, strlen(ATCMD_RET_CAN_UPGRADED)); } else { atcmd_send_response(AT_ERROR, ATCMD_RET_CANT_UPGRADED, strlen(ATCMD_RET_CANT_UPGRADED)); } return RETVAL(E_OK); } APP_INITCALL("fota_task", fota_task_init); ATCMD_INIT("AT^CHECKUP?", 0, check_upgrade_state);
Previous article:[keil][python][MCU] keil integrated bin file to generate boot+app merged dfu generation
Next article:[MCU] x_strtok, safe segmentation function
Recommended ReadingLatest update time:2024-11-15 15:55
- Popular Resources
- Popular amplifiers
- Wireless Sensor Network Technology and Applications (Edited by Mou Si, Yin Hong, and Su Xing)
- Modern Electronic Technology Training Course (Edited by Yao Youfeng)
- Modern arc welding power supply and its control
- Small AC Servo Motor Control Circuit Design (by Masaru Ishijima; translated by Xue Liang and Zhu Jianjun, by Masaru Ishijima, Xue Liang, and Zhu Jianjun)
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- LED chemical incompatibility test to see which chemicals LEDs can be used with
- Application of ARM9 hardware coprocessor on WinCE embedded motherboard
- What are the key points for selecting rotor flowmeter?
- LM317 high power charger circuit
- A brief analysis of Embest's application and development of embedded medical devices
- Single-phase RC protection circuit
- stm32 PVD programmable voltage monitor
- Introduction and measurement of edge trigger and level trigger of 51 single chip microcomputer
- Improved design of Linux system software shell protection technology
- What to do if the ABB robot protection device stops
- Huawei's Strategic Department Director Gai Gang: The cumulative installed base of open source Euler operating system exceeds 10 million sets
- Download from the Internet--ARM Getting Started Notes
- Learn ARM development(22)
- Learn ARM development(21)
- Learn ARM development(20)
- Learn ARM development(19)
- Learn ARM development(14)
- Learn ARM development(15)
- Analysis of the application of several common contact parts in high-voltage connectors of new energy vehicles
- Wiring harness durability test and contact voltage drop test method
- How to use the standard library time_t time(time_t *seconds)? Is there a difference between the value obtained by the parameter and the return value?
- Techniques for PCB board array vias
- EEWORLD University ---- Razavi Analog Integrated Circuit Tutorial (English)
- How to interconnect DSP5509A and ARM
- 【Industrial Production Process PDA】Material Unboxing Post- DISCOVERY KIT WITH STM32F7508-DK
- Will 3D Touch be popular in the future?
- Car maintenance oscilloscope detection Volvo S80 fan does not rotate
- The reason why the temperature coefficient of resistance is expressed in positive and negative
- Submit your IoT application ideas and win multimeters, Bluetooth headsets, Xiaomi power strips, JD.com cards and other gifts!
- [Evaluation of Anxinke Bluetooth Development Board PB-02-Kit] First Look