当前位置: 首页 > article >正文

国民技术N32G430开发笔记(14)-IAP升级 usart2接收数据

IAP升级 Usart2接收数据

1、之前有一节我们将PA6 PA7复用成了usart2的功能,这一节我们用usart2接收来自树莓派的升级请求,然后完成N32G430的Iap升级。
2、接线
PA9 PA10 接usb转串口模块A,A模块插入电脑。
PA6 PA7 接usb转串口模块B,B模块插入树莓派。
在这里插入图片描述
3、数据协议

串口升级协议如下:
cmd + data_lenght + data0 + …+ datax + checksum
1、获取版本号 0x01 0x02 0x00 0x00 checksum
2、升级
1、进入升级模式 0x02 0x02 0x00 0x00 checksum
2、升级文件大小 0x03 0x04 0x00 0x00 0x00 0x00 checksum
3、数据包发送 0x04 0x80 0x00 0x00 0x00 0x00 … checksum
4、数据包发送完成 0x05 0x02 0x00 0x00 checksum

checksum采用crc16的检验方法。
4、升级流程
1、树莓派发送进入升级模式命令,mcu进入升级模式,此时led1灯由1000ms闪烁一次变为100ms闪烁一次。
2、树莓派发送文件大小命令,mcu接收到文件大小命令,保存,并将download区域擦除。
3、树莓派分包发送升级文件数据,每包数据64个字节,mcu接收到数据后,分包写入download区域。
4、树莓派发送升级完成命令后,mcu将update_flag置为1,并重启mcu。
5、重启后,mcu进入bootloader后,读取update_flag,如果为1,将download区域数据拷贝到App区域,然后跳转到App执行,完成App区域的升级。如果update_flag不为1,不用拷贝,直接跳转APP。
5、Usart2的中断处理函数修改为:
相关逻辑处理放到了handle_uart_message函数里

static uint8_t RxBuffer1[128];//接收数据缓存区
static uint32_t RxCounter1 = 0;//接收数据长度

void USART2_IRQHandler(void)
{
    if (USART_Interrupt_Status_Get(USART2, USART_INT_RXDNE) != RESET)
    {
        /* 读取数据并清除标志 */
        USART_Interrupt_Status_Clear(USART2,USART_INT_RXDNE);
        RxBuffer1[RxCounter1++] = USART_Data_Receive(USART2);
    }
    else if (USART_Interrupt_Status_Get(USART2, USART_INT_IDLEF) != RESET)
    {
        /* 清除IDLE标志*/
        USART_Interrupt_Status_Clear(USART2,USART_INT_IDLEF);
        
        if (RxCounter1 > 0)
        {
            handle_uart_message(RxBuffer1,RxCounter1);
            RxCounter1 = 0;
        }
    }
}

4、Common目录下增加Update目录,并创建update.c update.h,
协议的解析都在update.c中处理。

#include <string.h>
#include "main.h"
#include "update.h"
#include "usart.h"
#include "settings.h"
#include "log.h"
#include "flash.h"
#include "core_cm4.h"

/*串口升级协议如下:
    cmd + data_lenght + data0 + ....+ datax + checksum 
    1、获取版本号             0x01 0x02 0x00 0x00 checksum
    2、升级
        1、进入升级模式        0x02 0x02 0x00 0x00 checksum
        2、升级文件大小        0x03 0x04 0x00 0x00 0x00 0x00 checksum
        3、数据包发送          0x04 0x80 0x00 0x00 0x00 0x00 .....  checksum
        4、数据包发送完成       0x05 0x02 0x00 0x00 checksum
*/

#define UPGRADE_DATA_PACKAGES_LENGHT  0x40

static MI_CHAR version[36] = {0};
static MI_U32 upgrade_file_size = 0;
static MI_U32 w_time = 0;
static MI_U16 packets_numer = 0;
static MI_U16 remain_packets_numer = 0;
static MI_U8 w_buff[UPGRADE_DATA_PACKAGES_LENGHT] = {0};


static void app_soft_reset(void)
{
    __ASM volatile ("cpsid i");
    NVIC_SystemReset();
}

static MI_U16 CRC16(MI_U8 * buf, MI_U16 len)
{
	MI_U16 i;
	MI_U16 crc = 0xffff;
 
	if (len == 0) {
		len = 1;
	}
	while (len--) {
        
		crc ^= *buf;
		for (i = 0; i<8; i++) 
		{            
			if (crc & 1) {               
				crc >>= 1;        
				crc ^= 0xA001;            
			}      
			else {               
				crc >>= 1;            
			}       
		}     
		buf++;
	}
	return(crc);
}

static MI_BOOL calculate_checksum_and_length(MI_U8 * buf, MI_U16 len)
{
    MI_U16 crc16 = CRC16(buf,len-2);
    if ((crc16 & 0x00ff) == buf[len-2] && ((crc16 >> 8) & 0x00ff) == buf[len-1])
    {
        if (buf[UART_CMD_LENGTH] == (len-2-2))
        {
            return MI_TRUE;
        }
        else
        {
            max_print("crc16 right ,but cmd error\r\n"); 
            return MI_FALSE; 
        }
    }
    else
    {
        max_print("crc16 error and right crc16 = %x\r\n",crc16);  
        return MI_FALSE; 
    }
}

MI_BOOL handle_uart_message(MI_U8 *p_buff,MI_U32 len)
{
    switch (p_buff[UART_CMD_INDEX])
    {
    case UART_GET_SYSTEM_VERSION_CMD/* constant-expression */:
        /* 获取系统版本号 */
        if (calculate_checksum_and_length(p_buff,len) == MI_TRUE)
        {
            system_info_get_app_version(version);
            Usart_SendString(USART2,(char *)version,strlen(version));
        }
        break;
    case UART_ENTER_SYSTEM_UPDATE_MODE_CMD:
        /* 进入升级模式命令 指示灯变为100ms闪烁一次*/
        if (calculate_checksum_and_length(p_buff,len) == MI_TRUE)
        {
            led_freq = LED_TOGGLE_100_MS;
            w_time = 0;
            packets_numer = 0;
            upgrade_file_size = 0;
            remain_packets_numer = 0;
            isRunningUpdate = 1;
            max_print("Mcu Receive Update Command and Wait Receive Data Packets \r\n");
            max_print("Now to Erase Download Pages \r\n");
            n32_flash_erase(DOWNLOAD_START_ADDRESS,DOWNLOAD_END_ADDRESS);
            Usart_SendString(USART2,(char *)p_buff,len);
        }
        break; 
    case UART_GET_SYSTEM_FILE_SIZE_CMD:

        max_print("Erase Download Pages \r\n");
        if (calculate_checksum_and_length(p_buff,len) == MI_TRUE)
        {
            int a = (int)p_buff[2];
            int b = (int)p_buff[3];
            int c = (int)p_buff[4];
            int d = (int)p_buff[5];
            upgrade_file_size = (a<<24) | (b<<16) | (c<<8) | (d);

            if (upgrade_file_size % UPGRADE_DATA_PACKAGES_LENGHT == 0)  //如果整除64
            {
                packets_numer = upgrade_file_size/UPGRADE_DATA_PACKAGES_LENGHT;
            }
            else
            {
                packets_numer = ((upgrade_file_size/UPGRADE_DATA_PACKAGES_LENGHT) + 1);
            }
            max_print("End Erase Download Pages Down\r\n");
            max_print("\r\n");

            max_print("receive upgrade file size %d\r\n",upgrade_file_size);
            max_print("data packets number  %d\r\n",packets_numer);
            max_print("\r\n");
            Usart_SendString(USART2,(char *)p_buff,len);
        }
        break; 
    case UART_RECEIVE_SYSTEM_UPDATE_CMD:
        if (calculate_checksum_and_length(p_buff,len) == MI_TRUE)
        {
            max_print("receive packets........................%d [100] \r\n",(((w_time + 1) * 100) / packets_numer));
            memset(w_buff,0,sizeof(w_buff));
            memcpy(w_buff,&p_buff[2],sizeof(w_buff));

            n32_flash_write(DOWNLOAD_START_ADDRESS+(w_time * UPGRADE_DATA_PACKAGES_LENGHT),w_buff,sizeof(w_buff));

            if (w_time + 1 == packets_numer)
            {
                led_freq = LED_TOGGLE_1000_MS;
                max_print("receive packets........................ done!\r\n");
            }
            w_time ++;
            Usart_SendString(USART2,(char *)p_buff,20);
        }
        break;  
    case UART_COMPLETE_SYSTEM_UPDATE_CMD:
        if (calculate_checksum_and_length(p_buff,len) == MI_TRUE)
        {
            Usart_SendString(USART2,(char *)p_buff,len);
            system_info_set_update_flag(1);

            int flag;
            system_info_get_update_flag(&flag);
            
            max_print("Now Reboot %d!\r\n",flag);
            app_soft_reset();
        }
        break;                 
    default:
        break;    
    }
    return MI_TRUE;
}

update.h

#ifndef __UPDATE_H__
#define __UPDATE_H__

#define UART_CMD_INDEX      0x00
#define UART_CMD_LENGTH     0x01

#define I2C_CMD_INDEX       0x00
#define I2C_CMD_LENGTH      0x01

#define UART_GET_SYSTEM_VERSION_CMD_LENGTH   0x02

typedef enum uart_update_cmd
{
    UART_GET_SYSTEM_VERSION_CMD                 = 0x01,
    UART_ENTER_SYSTEM_UPDATE_MODE_CMD           = 0x02,
    UART_GET_SYSTEM_FILE_SIZE_CMD               = 0x03,
    UART_RECEIVE_SYSTEM_UPDATE_CMD              = 0x04,
    UART_COMPLETE_SYSTEM_UPDATE_CMD             = 0x05,

}MI_UartUpdateCmd;


MI_BOOL handle_uart_message(MI_U8 *p_buff,MI_U32 len);
#endif

5、Bootloader 修改

#include <string.h>
#include "main.h"
#include "bsp_delay.h"
#include "flash.h"
#include "settings.h"
#include "log.h"

typedef void (*pFunction)(void);
pFunction Jump_To_Application;
uint32_t JumpAddress;

void Jump_To_App(uint32_t address)
{
    if (((*(__IO uint32_t*)address) & 0x2FFE0000) == 0x20000000)
    {
        JumpAddress = *(__IO uint32_t*) (address + 4);
		Jump_To_Application = (pFunction) JumpAddress;
        __set_MSP(*(__IO uint32_t*) address);
        Jump_To_Application();
    }
}

int main(void)
{
	MI_U8 update_flag;
	SysTick_Delay_Ms(1000);
	usart1_init();
	system_info_get_update_flag(&update_flag);

	max_print("system_info_get_update_flag == %d\r\n",update_flag);
	max_print("\r\n");

	if (update_flag == 1)
	{

		copy_download_to_app();

    	max_print("\r\n");
    	max_print("update success,and go to Application\r\n");
		system_info_set_update_flag(0);
	}
	SysTick_Delay_Ms(1000);
	Jump_To_App(APP_START_ADDRESS);

	while(1)
	{
		SysTick_Delay_Ms(2000);
	}
}

6、在falsh.c 增加copy_download_to_app()函数

MI_BOOL copy_download_to_app(void)
{
    MI_U8 buffer[1024] = {0};  //每次从download读1K字节,然后写入1K
    MI_U8 w_count = 0;
    MI_U16 w_len = sizeof(buffer);
    MI_U16 app_size = APP_SIZE;

    w_count = app_size / w_len;
    // 将App区域擦除
    n32_flash_erase(APP_START_ADDRESS,APP_END_ADDRESS);
    max_print("w_count == %d\r\n",APP_SIZE);

    max_print("w_count == %d\r\n",w_len);

    max_print("w_count == %d\r\n",w_count);
    for (int i = 0;i < w_count;i++)
    {
        n32_flash_read(DOWNLOAD_START_ADDRESS + (w_len * i),buffer,w_len);
        SysTick_Delay_Ms(50);
        n32_flash_write(APP_START_ADDRESS + (w_len * i),buffer,w_len);
        
        max_print("update.............................%d [100] \r\n",((i+1) * 100 /w_count));
    }

    return MI_TRUE;
}

7、整个升级的视频打印:

屏幕录制2023-05-03 14.16.12


http://www.kler.cn/a/17555.html

相关文章:

  • 【深度学习】LSTM、BiLSTM详解
  • Spring框架之适配器模式 (Adapter Pattern)
  • 物联网(RFID)全景:被装信息化监控应用与挑战
  • Elasticsearch中什么是倒排索引?
  • 移远通信亮相骁龙AI PC生态科技日,以领先的5G及Wi-Fi产品革新PC用户体验
  • [Docker#4] 镜像仓库 | 部分常用命令
  • MySQL知识学习03(三大日志详解 binlog、redo log、undo log)
  • Python3 简介
  • Android 9.0 系统systemui下拉通知栏的通知布局相关源码分析
  • 05.rabbitMQ之搭建的各种坑
  • 基于DSP+FPGA+AD9238的冲击波超压测试系统设计与实现
  • 手搓GPT系列之 - chatgpt + langchain 实现一个书本解读机器人
  • Ajax -- from表单与模板引擎
  • 华为OD机试 - 密室逃生游戏(Python)
  • 提示工程玩转 ChatGPT
  • springboot2
  • 【Python】flask
  • SpringBatch之实际操作
  • Java反射和动态代理
  • java单链表反转
  • 代码评审都评审些什么呢?
  • 一起Talk Android吧(第五百四十二回:无进度值ProgressBar)
  • 【Java开发】Spring Cloud 11:Gateway 配置 ssl 证书(https、http、域名访问)
  • 《C和指针》笔记3:置一和清零
  • 一种用于大坝水库边坡内部振弦式应变计组
  • 【CSS 知识总结】第七篇 - CSS 布局-居中布局-水平居中布局