[MCU] fota dfu upgrade

Publisher:温柔心绪Latest update time:2022-09-19 Source: csdnKeywords:MCU Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

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);

[1] [2]
Keywords:MCU Reference address:[MCU] fota dfu upgrade

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

51 MCU Basics of IoT 08-Timer
Preface In real-time control systems, timing clocks are often needed to achieve precise delay and timing, and counting functions are often needed to count external pulses. In this section, we begin to learn the timer of the 51 single-chip microcomputer, and then start a timer to achieve a level flip once every 1S to c
[Microcontroller]
51 MCU Basics of IoT 08-Timer
PIC microcontroller ad sampling and display on LCD
/* Main.c file generated by New Project wizard * * Created: Tuesday April 10, 2018 * Processor: PIC18F452 * Compiler: MPLAB C18 */ #include p18f452.h #define RW PORTBbits.RB5 #define RS PORTBbits.RB6 #define EN PORTBbits.RB7 #define P0 PORTD #define ADGO ADCON0bits.GO void tmr(void); void KeyInterrupt1 (void); //Int
[Microcontroller]
51 MCU Learning (II) 74HC595 Module to Realize Dot Matrix Screen
introduction: 74HC595 is a chip that realizes the function of serial to parallel conversion. This is also the first chip that we come into contact with when learning 51 single-chip microcomputers to complete data input and output by controlling the timing line. We will encounter many such chips in the future, such a
[Microcontroller]
51 MCU Learning (II) 74HC595 Module to Realize Dot Matrix Screen
AT89S51 microcontroller realizes the design of timepiece display on 6-digit LED digital tube
This is a microcontroller electronic clock/timer learning board designed by us. It uses a 6-digit LED digital tube to display hours, minutes, and seconds in 24-hour timing. Functions such as hour and minute adjustment, stopwatch/clock function conversion, power saving (turning off the display), etc. can be realized th
[Microcontroller]
AT89S51 microcontroller realizes the design of timepiece display on 6-digit LED digital tube
51 MCU UART serial communication [Method 1] implementation
1 51 serial port structure The UART serial communication of the 51 single-chip microcomputer is based on the programmable hardware structure of its serial port. As long as the correct program code is used to initialize the serial hardware structure by initializing the corresponding register of the serial port, and the
[Microcontroller]
51 MCU UART serial communication [Method 1] implementation
Smart meter design based on LPC1114 microcontroller and ATT7053 chip
ATT7053AU is a single-phase multi-function metering chip (EMU) with SPI. The working range of the chip is 3.0 ~ 3.6V. The crystal oscillator used is 5.5296MHz. 1.att7053 circuit diagram 2.att7053  PCB diagram 3. Finished finished board 4.LPC1114 microcontroller and ATT7053 use SPI communication method. The sof
[Microcontroller]
Smart meter design based on LPC1114 microcontroller and ATT7053 chip
MCS-51 MCU Memory Expansion
Main content: Part 8 MCS-51 MCU memory expansion (1) 1. Overview 2. System bus and bus structure 3. Read/write control, address space allocation and external address latch 4. Program memory EPROM expansion Key points: System bus and bus structure Memory address space allocation External address latch 74LS373 Typical
[Microcontroller]
How to deal with the relationship between microcontroller and latch? Why use serial port to expand I/O?
When expanding the output port through P0 port, how to deal with the relationship between the microcontroller and the latch? Answer: When the output port of the microcontroller is expanded through the P0 port, the latch can be regarded as an external RAM unit, and the output signal is WR. Why use serial port to ex
[Microcontroller]
Latest Microcontroller Articles
  • Download from the Internet--ARM Getting Started Notes
    A brief introduction: From today on, the ARM notebook of the rookie is open, and it can be regarded as a place to store these notes. Why publish it? Maybe you are interested in it. In fact, the reason for these notes is ...
  • Learn ARM development(22)
    Turning off and on interrupts Interrupts are an efficient dialogue mechanism, but sometimes you don't want to interrupt the program while it is running. For example, when you are printing something, the program suddenly interrupts and another ...
  • Learn ARM development(21)
    First, declare the task pointer, because it will be used later. Task pointer volatile TASK_TCB* volatile g_pCurrentTask = NULL;volatile TASK_TCB* vol ...
  • Learn ARM development(20)
    With the previous Tick interrupt, the basic task switching conditions are ready. However, this "easterly" is also difficult to understand. Only through continuous practice can we understand it. ...
  • Learn ARM development(19)
    After many days of hard work, I finally got the interrupt working. But in order to allow RTOS to use timer interrupts, what kind of interrupts can be implemented in S3C44B0? There are two methods in S3C44B0. ...
  • Learn ARM development(14)
  • Learn ARM development(15)
  • Learn ARM development(16)
  • Learn ARM development(17)
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号