[单片机框架][DFU] Dfu升级例子 带crc校验+超时机制+led指示灯+芯片加锁+芯片自擦

发布者:科技创造者最新更新时间:2022-09-15 来源: csdn关键字:crc校验  led指示灯 手机看文章 扫描二维码
随时随地手机看文章

自动检测剩余空间是否支持备份升级,防止升级失败变砖。


/********************************************************************************

* @file    main.c

* @author  jianqiang.xue

* @Version V1.0.0

* @Date    2021-04-03

* @brief   NULL

********************************************************************************/


/* Includes ------------------------------------------------------------------*/

#include

#include

#include

#include


#include "RTE_Components.h"

#include CMSIS_device_header


#include "bsp_system_clock.h"

#include "bsp_gpio.h"

#include "bsp_uart.h"

#include "bsp_flash.h"

#include "sys_api.h"


#include "crc16.h"

#include "check_uid.h"

#include "errorno.h"

#include "str_hex.h"

#include "x_strtok.h"

#include "kv_sys.h"

/* Private Includes ----------------------------------------------------------*/

#include "business_gpio.h"

#include "business_function.h"

#include "dfu.h"

#include "main.h"

/* Private Define ------------------------------------------------------------*/

#define LOG(...)           

    do                     

    {                     

        bsp_uart_send_nbyte(BSP_UART_0, NULL, sprintf((char *)bsp_uart_get_txbuff(BSP_UART_0), __VA_ARGS__));

    } while (0U)


/* Private Typedef -----------------------------------------------------------*/

/* Private Define ------------------------------------------------------------*/

#define CRC_LEN                       2

#define PACK_HEAD_LEN                 2

#define CRC16_INIT_VAL                0xFFFF


/* Private Macro -------------------------------------------------------------*/

/* Private Variables ---------------------------------------------------------*/

uint32_t g_write_flash_addr   = 0;

// DFU 超时机制 15s没有数据达到,则判断app是否存在,如果存在则跳转至app

static dfu_file_info_t dfu_file_info = {0};

uint32_t g_dfu_tickstart      = 0;

uint16_t g_dfu_timeout_ms     = 15000;

bool g_dfu_timeout_flag       = 0; // 0 -- 未检测  1--检测完成


/* Private Function Prototypes -----------------------------------------------*/


static void dfu_file_info_data(uint8_t *data, uint16_t len)

{

    char *token_r;

    char *argv[2];

    char *arg;

    uint8_t argc    = 0;

    uint8_t crc[2]  = {0, 0};

    uint8_t crc_len = 0;

    uint16_t crc16  = 0;

    // LOG("data:%s, len:%drn", data, len);

    arg = x_strtok_s((char*)data, ",", &token_r);

    while (arg != NULL)

    {

        argv[argc++] = arg;

        arg = x_strtok_s(NULL, ",", &token_r);

    }


    if (argc == 2)

    {

        crc_len = str_to_hex(argv[0], crc);

        if (crc_len == CRC_LEN)

        {

            crc16 = (crc[0] << 8) | crc[1];

        }

        else

        {

            goto end;

        }


        memset(&dfu_file_info, 0, sizeof(dfu_file_info_t));

        dfu_file_info.file_crc16 = crc16;

        dfu_file_info.file_size = atoi(argv[1]);

        // LOG("UP^OK,0,crc:%x, size:%drn", crc16, atoi(argv[1]));

        LOG("UP^OK,0,%drn", BS_UART0_CACHE_SIZE);

    }

    else

    {

end:

        LOG("UP^FAIL,%drn", E_INVAL_PARM);

    }

}


static void dfu_file_data(uint8_t *data, uint16_t len)

{

    uint16_t rx_crc;

    uint16_t cal_crc;

    uint8_t  pack_id;

    uint8_t  pack_len;

    uint8_t *pack_data;

    uint8_t  pdu_len;


    if (len < PACK_HEAD_LEN + CRC_LEN)

    {

        //LOG("UP^FAIL,%drn", E_INVAL_LEN);

        LOG("UP^FAIL,LENrn");

        return;

    }


    pack_len = *(data + 1);

    pdu_len = pack_len + PACK_HEAD_LEN;


    if (len != pdu_len + CRC_LEN)

    {

        //LOG("UP^FAIL,%d,%d,%drn", E_INVAL_DATA, pdu_len + CRC_LEN, len);

        LOG("UP^FAIL,LEN1rn");

        return;

    }


    pack_id   = *(data + 0);

    pack_data = (data + 2);


    // pack的最后两个字节为crc值, 这里的len是按1计算的,所以按数组时,要多减1.

    rx_crc = (*(data + len - 2) << 8) | *(data + len - 1);

    cal_crc = crc16(CRC16_INIT_VAL, pack_data, pack_len);

    // LOG("CRC,rx:%x,cal:%xrn",rx_crc, cal_crc);

    if (rx_crc != cal_crc)

    {

        //LOG("UP^FAIL,%d,R:%x,C:%x,L:%drn", E_CRC, rx_crc, cal_crc, pack_len);

        LOG("UP^FAIL,CRC1rn");

        return;

    }


    // 第一次接到数据,则擦除flash

    if (dfu_file_info.flash_flag == false && dfu_file_info.file_size != 0)

    {

        dfu_file_info.flash_flag = true;

        // 如果固件大小 < APP容量的一半,则使用备份升级

        if (dfu_file_info.file_size < (BS_FLASH_APP_SIZE / 2))

        {

            g_write_flash_addr = BS_FLASH_OTA_ADDR;

            sys_disable_irq();

            bsp_flash_erase_page(g_write_flash_addr, ((BS_FLASH_APP_SIZE / 2) / BS_FLASH_PAGE_SIZE) + 1);

            sys_enable_irq();

        }

        else

        {

            g_write_flash_addr = BS_FLASH_APP_ADDR;

            sys_disable_irq();

            bsp_flash_erase_page(g_write_flash_addr, (BS_FLASH_APP_SIZE / BS_FLASH_PAGE_SIZE) + 1);

            sys_enable_irq();

        }

        return;

    }


    if ((pack_id == dfu_file_info.old_pack_id) ||

        (pack_id < dfu_file_info.old_pack_id) ||

        (pack_id > dfu_file_info.old_pack_id && (pack_id - dfu_file_info.old_pack_id != 1)))

    {

        LOG("UP^FAIL,%d,%d,%drn", E_MSG, dfu_file_info.old_pack_id, pack_id);

        return;

    }


    dfu_file_info.old_pack_id = pack_id;


    if (dfu_file_info.flash_flag == true && dfu_file_info.file_size != 0)

    {

        if (g_write_flash_addr == 0)

        {

            return;

        }

        bsp_flash_write_nbyte_s(g_write_flash_addr + dfu_file_info.current_size, pack_data, pack_len);

        dfu_file_info.current_size += pack_len;

        LOG("UP^OK,%drn", pack_id);

    }

}


static void dfu_check_file(uint8_t *data, uint16_t len)

{

    if (dfu_file_info.flash_flag == false || dfu_file_info.file_size == 0 ||

        dfu_file_info.file_size != dfu_file_info.current_size || g_write_flash_addr == 0)

    {

        LOG("UP^FAIL,FILErn");

        return;

    }


    uint16_t cal_crc;

    cal_crc = crc16(CRC16_INIT_VAL, (uint8_t *)g_write_flash_addr, dfu_file_info.current_size);

    if (cal_crc != dfu_file_info.file_crc16)

    {

        // LOG("UP^FAIL,%x %xrn", cal_crc, dfu_file_info.file_crc16);

        LOG("UP^FAIL,CRCrn");

    }

    else

    {

        LOG("UP^OK,UPrn");

        g_boot_info.app_crc         = dfu_file_info.file_crc16;

        g_boot_info.boot_carry_size = dfu_file_info.current_size;

        if (g_write_flash_addr == BS_FLASH_OTA_ADDR)

        {

            g_boot_info.boot_state      = BOOT_STATE_MOVE_OTA_IN_APP;

            kv_set_env(BS_KV_KEY_BOOT_INFO, (uint8_t *)&g_boot_info, sizeof(boot_info_t));

            delay_ms(5);

        }

        else if (g_boot_info.boot_state < 2)

        {

            g_boot_info.boot_state      = BOOT_STATE_RUN_APP;

            kv_set_env(BS_KV_KEY_BOOT_INFO, (uint8_t *)&g_boot_info, sizeof(boot_info_t));

            delay_ms(5);

        }

        // 跳转启动

        sys_reset();

    }

}


static void dfu_data_analysis(uint8_t *data, uint16_t len)

{

    data[len] = '';

    if (strncmp((const char *)data, "FILE_INFO=", strlen("FILE_INFO=")) == 0)

[1] [2]
关键字:crc校验  led指示灯 引用地址:[单片机框架][DFU] Dfu升级例子 带crc校验+超时机制+led指示灯+芯片加锁+芯片自擦

上一篇:[C语言] sscanf如何实现sscanf_s?
下一篇:[单片机框架] [drivers] [hc4051] 8路模拟分流器

推荐阅读最新更新时间:2024-11-17 13:10

[单片机框架][bsp层][AT32F415][bsp_exti] EXTI配置和使用
7.2.1 主要特性 EXTI 控制器的主要特性如下: ● 每个中断/事件都有独立的触发和屏蔽 ● 每个中断线都有专用的状态位 ● 支持多达 23 个软件的中断/事件请求 ● 检测脉冲宽度低于 APB2 时钟宽度的外部信号。参见数据手册中电气特性部分的相关参数。 7.2.4 功能说明 要产生中断,必须先配置好并使能中断线。根据需要的边沿检测设置 2 个触发寄存器,同时在中断屏蔽寄存器的相应位写’1’允许中断请求。当外部中断线上发生了期待的边沿时,将产生一个中断请求,对应的挂起位也随之被置’1’。在挂起寄存器的对应位写’1’,将清除该中断请求。 如果需要产生事件,必须先配置好并使能事件线。根据需要的边沿检测设置 2 个触发寄存器
[单片机]
[<font color='red'>单片机</font><font color='red'>框架</font>][bsp层][AT32F415][bsp_exti] EXTI配置和使用
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved