Files
RCU_C1P_Launcher/MCU_Driver/bootload_fun.c
caocong 094fd76a72 新增:首次提交
首次提交,上传Launcher工程
2026-01-05 09:40:42 +08:00

1150 lines
43 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* launcher_fun.c
* Code Flash总空间 0x00000000 ~ 0x00070000 448KB
* Launcher区域 0x00000000 ~ 0x00003FFF 16KB
* APP区域 0x00004000 ~ 0x0006FFFF 432KB
* Data Flash总空间 0x00070000 ~ 0x00077FFF 32KB
*
* Created on: Jul 28, 2025
* Author: cc
*/
#include "includes.h"
#include <string.h>
G_SYS_FEATURE_T g_app_feature;
G_SYS_FEATURE_T g_mcu_app_feature;
UPDATE_RECORD_T g_update_recode; //升级信息
uint8_t g_jump_flag = 0; //跳转标志位
uint32_t g_Boot_Tick = 0; //Boot时间戳 单位ms
uint32_t g_Boot_Time= 0; //Boot时间 单位ms
/*******************************************************************************
* Function Name : Boot_Time_Refresh
* Description : Boot时间戳更新
*******************************************************************************/
void Boot_Time_Refresh(void)
{
g_Boot_Tick = SysTick_1ms;
}
/*******************************************************************************
* Function Name : Boot_Timeout_Task
* Description : Boot超时任务
*******************************************************************************/
void Boot_Timeout_Task(void)
{
if(SysTick_1ms - g_Boot_Tick >= g_Boot_Time)
{
while(1); //执行看门狗复位
}
}
/*********************************************************************
* @fn Jump_APP
* @brief 跳转至APP程序
* @param addr - APP起始地址
* @return none
*/
void Jump_APP(uint32_t addr)
{
// __asm volatile("jr %0": :"r"(addr));
__asm("li a6, 0x0E000");
__asm("jr a6");
while(1);
}
/*******************************************************************************
* Function Name : SPI_FLASH_APP_Data_Erase
* Description : 外部Flash APP空间擦除
* APP空间大小 Size: 0x00070000 地址范围0x00000000 ~ 0x0006FFFF
*******************************************************************************/
void SPI_FLASH_APP_Data_Erase(void)
{
for(uint8_t i = 0;i < 7;i++)
{
Flash_Erase_Block(i);
}
}
/*******************************************************************************
* Function Name : SPI_FLASH_Logic_File_Erase
* Description : 外部Flash 配置文件空间擦除
* APP空间大小 Size: 0x00090000 地址范围0x00070000 ~ 0x000FFFFF
*******************************************************************************/
void SPI_FLASH_Logic_File_Erase(void)
{
for(uint8_t i = 7;i < 16;i++)
{
Flash_Erase_Block(i);
}
}
/*******************************************************************************
* Function Name : CRC16_Check
* Description : CRC16校验算法
*******************************************************************************/
uint16_t CRC16_Check(uint8_t * aStr, uint16_t len)
{
uint16_t xda , xdapoly ;
uint16_t i, j, xdabit ;
xda = 0xFFFF ;
xdapoly = 0xA001 ; // (X**16 + X**15 + X**2 + 1)
for (i = 0; i < len; i++)
{
xda ^= aStr[i] ;
for (j = 0; j < 8; j++)
{
xdabit = (unsigned char)(xda & 0x01) ;
xda >>= 1 ;
if ( xdabit ) xda ^= xdapoly ;
}
}
return xda;
}
/*******************************************************************************
* Function Name : Boot_Comm_FillReplyPack
* Description : Boot通讯协议回复数据打包函数
*******************************************************************************/
void Boot_Comm_FillReplyPack(UART_t *g_rev)
{
uint16_t data_len = g_rev->ackLen + BCOMM_FMT_PARAM;
g_rev->ackBuffer[BCOMM_FMT_TXAddr] = g_mcu_dev.dev_addr;
g_rev->ackBuffer[BCOMM_FMT_SN] = g_rev->sn;
g_rev->ackBuffer[BCOMM_FMT_TYPE] = g_mcu_dev.dev_type;
g_rev->ackBuffer[BCOMM_FMT_RXAddr] = g_rev->pc_addr;
g_rev->ackBuffer[BCOMM_FMT_CMD] = g_rev->cmd;
g_rev->ackBuffer[BCOMM_FMT_LEN_L] = data_len & 0xFF;
g_rev->ackBuffer[BCOMM_FMT_LEN_H] = (data_len >> 8) & 0xFF;
g_rev->ackBuffer[BCOMM_FMT_CKS] = 0;
g_rev->ackBuffer[BCOMM_FMT_CKS] = Data_CheckSum(g_rev->ackBuffer, data_len);
#if DBG_LOG_EN
Dbg_Print_Buff(DBG_BIT_SYS_STATUS,"ACKBuff ",g_rev->ackBuffer,data_len);
#endif
g_rev->send_data_cf(g_rev->ackBuffer,data_len);
// memset(g_rev->ackBuffer,0,USART_BUFFER_SIZE);
// g_rev->ackLen = 0x00;
}
uint8_t Launcher_Uart_Upgrade_Process(UART_t *g_rev)
{
uint8_t deal_flag = 0,group_flag = 0,reply_flag = 0;
uint16_t crcNumIndex = 0,crcResultFlag = 0;
uint32_t temp_val = 0,temp_val_2 = 0;
/*拷贝串口缓冲区中的数据内容 */
__disable_irq();
memcpy(g_rev->deal_buff,g_rev->RecvBuffer,g_rev->RecvLen);
g_rev->deal_len = g_rev->RecvLen;
g_rev->RecvLen = 0;
memset(g_rev->RecvBuffer,0,USART_BUFFER_SIZE);
g_rev->Receiving = 0x00; //接收结束
g_rev->CommBusy &= ~(UART_COMMBUSY_RECV_Flag); //清除接收标志位
__enable_irq();
DBG_SYS_Printf("Len %d \r\n",g_rev->deal_len);
Dbg_Print_Buff(DBG_BIT_SYS_STATUS,"UARTx_Buff:",g_rev->deal_buff,g_rev->deal_len);
temp_val = g_rev->deal_buff[BCOMM_FMT_LEN_H];
temp_val <<= 8;
temp_val |= g_rev->deal_buff[BCOMM_FMT_LEN_L];
if(temp_val != g_rev->deal_len)
{
DBG_SYS_Printf("Len Fail \r\n");
return 0x01;
}
if(Data_CheckSum(g_rev->deal_buff,g_rev->deal_len) != 0) {
DBG_SYS_Printf("Boot_Comm_CheckSum Fail:%x ",Data_CheckSum(g_rev->deal_buff,g_rev->deal_len));
return 0x02;
}
if( (g_rev->deal_buff[BCOMM_FMT_SN] & 0x80) == 0x80){
//群发标志位
group_flag = 0x01;
if( (g_rev->deal_buff[BCOMM_FMT_SN] & 0x0F) != g_rev->sn){
deal_flag = 0x01;
DBG_SYS_Printf("Group Data SN Disaffinity,Processing Data");
}else {
deal_flag = 0x00;
DBG_SYS_Printf("Group Data SN The Same,No Processing Data");
}
}else {
//单发标志位
group_flag = 0x00;
if( (g_rev->deal_buff[BCOMM_FMT_SN] & 0x0F) != g_rev->sn){
//包序号不太相同,需要处理
DBG_SYS_Printf("Single Data SN Disaffinity,Processing Data");
deal_flag = 0x01;
reply_flag = 0x01;
}else if( (g_rev->deal_buff[BCOMM_FMT_SN] & 0x40) == 0x40 ){
//包序号相同,重发标志位置位,不处理,但是需要回复数据
deal_flag = 0x00;
reply_flag = 0x01;
DBG_SYS_Printf("Single Data SN The Same,No Processing Data");
}
}
/*判断类型是否相同,且不是广播类型*/
if( (g_rev->deal_buff[BCOMM_FMT_TYPE] != g_mcu_dev.dev_type) && (g_rev->deal_buff[BCOMM_FMT_TYPE] != 0xFF) ){
DBG_SYS_Printf("Boot_Comm_RecvType %d - %d ",g_mcu_dev.dev_type,g_rev->deal_buff[BCOMM_FMT_TYPE]);
return 0x03;
}
/*判断是否广播类型与广播地址*/
if( (g_rev->deal_buff[BCOMM_FMT_RXAddr] != g_mcu_dev.dev_addr) && (g_rev->deal_buff[BCOMM_FMT_RXAddr] != 0xFF) ){
DBG_SYS_Printf("Boot_Comm_RecvAddr %d - %d ",g_mcu_dev.dev_addr,g_rev->deal_buff[BCOMM_FMT_RXAddr]);
return 0x04;
}
Boot_Time_Refresh();
g_rev->pc_addr = g_rev->deal_buff[BCOMM_FMT_TXAddr];
g_rev->sn = g_rev->deal_buff[BCOMM_FMT_SN] & 0x0F;
g_rev->cmd = g_rev->deal_buff[BCOMM_FMT_CMD];
switch(g_rev->cmd)
{
case BCOMM_CMD_Handshake:
if( ( deal_flag == 0x01 ) && ( g_rev->deal_len >= ( BCOMM_FMT_PARAM + 4 ) ) ) {
/*设置Boot 超时时间 单位S*/
temp_val = g_rev->deal_buff[BCOMM_FMT_PARAM + 1];
temp_val <<= 8;
temp_val |= g_rev->deal_buff[BCOMM_FMT_PARAM];
if(temp_val != g_Boot_Time)
{
g_Boot_Time = temp_val;
if(g_Boot_Time < 10) g_Boot_Time = 10;
g_Boot_Time = g_Boot_Time * 1000;
}
/*回复数据的有效期*/
temp_val = g_rev->deal_buff[BCOMM_FMT_PARAM + 3];
temp_val <<= 8;
temp_val |= g_rev->deal_buff[BCOMM_FMT_PARAM + 2];
g_rev->ackValidity = temp_val;
}
//握手命令 - 需要回复的数据,正常回复
if(reply_flag != 0x01) break; //不回复,直接退出
g_rev->ackBuffer[BCOMM_FMT_PARAM] = Project_Area; //当前处于Bootload区域 0x01Boot;0x02APP
g_rev->ackBuffer[BCOMM_FMT_PARAM + 1] = g_mcu_dev.dev_boot_ver; //Boot 软件版本号
g_rev->ackBuffer[BCOMM_FMT_PARAM + 2] = g_mcu_dev.dev_app_ver; //APP 软件版本号
//MCU UID
g_rev->ackBuffer[BCOMM_FMT_PARAM + 3] = 0x06; //CH564 以MAC地址作为唯一ID 长度6Byte
GetMACAddress(&g_rev->ackBuffer[BCOMM_FMT_PARAM + 4]);
//机型编号 - 32Byte
g_rev->ackBuffer[BCOMM_FMT_PARAM + 10] = g_mcu_dev.dev_name_len;
g_rev->ackLen = 11;
for(uint8_t i=0;i<g_mcu_dev.dev_name_len;i++){
g_rev->ackBuffer[BCOMM_FMT_PARAM + i + 11] = g_mcu_dev.dev_name[i];
g_rev->ackLen++;
}
break;
case BCOMM_CMD_Jump: //跳转命令
if(deal_flag != 0x01) break; //不处理直接退出
if(g_rev->deal_buff[BCOMM_FMT_PARAM] == 0x02){
/*跳转至APP区域*/
g_Boot_Time = 200; //在Boot超时中跳转
g_Boot_Tick = SysTick_1ms;
g_rev->ackBuffer[BCOMM_FMT_PARAM] = BCOMM_CMD_ReplySUCC;
}else {
/*参数错误*/
DBG_SYS_Printf("ERR:Jump_boot");
g_rev->ackBuffer[BCOMM_FMT_PARAM] = BCOMM_CMD_ReplyFAIL;
}
g_rev->ackLen = 1;
break;
case BCOMM_CMD_SetInfo: //设置参数
if(deal_flag != 0x01) break; //不处理直接退出
if(g_rev->deal_len < (BCOMM_FMT_PARAM + 4) ) {
DBG_SYS_Printf("BCOMM_CMD_SetInfo Para Error ");
break;
}
DBG_SYS_Printf("BCOMM_CMD_SetInfo Proecessing ");
/*设置波特率参数*/
temp_val = g_rev->deal_buff[BCOMM_FMT_PARAM + 1];
temp_val <<= 8;
temp_val |= g_rev->deal_buff[BCOMM_FMT_PARAM];
temp_val *= 100;
/*设置Boot 超时时间*/
g_Boot_Time = g_rev->deal_buff[BCOMM_FMT_PARAM + 3];
g_Boot_Time <<= 8;
g_Boot_Time |= g_rev->deal_buff[BCOMM_FMT_PARAM + 2];
if(g_Boot_Time < 10) g_Boot_Time = 10;
g_Boot_Time = g_Boot_Time * 1000;
DBG_SYS_Printf("BaudSet: %d",temp_val);
DBG_SYS_Printf("bootTimeout: %d",g_Boot_Time);
g_rev->ChangeBaudFlag = 0x01;
g_rev->CommBaud = temp_val;
g_rev->ackBuffer[BCOMM_FMT_PARAM] = BCOMM_CMD_ReplySUCC;
g_rev->ackLen = 1;
break;
case BCOMM_CMD_WriteFlash: //写Flash
if(deal_flag != 0x01) break; //不处理直接退出
if( g_rev->deal_len < (BCOMM_FMT_PARAM + 6) ) {
DBG_SYS_Printf("BCOMM_CMD_WriteFlash Para Error ");
break;
}
DBG_SYS_Printf("BCOMM_CMD_WriteFlash Proecessing ");
/*写入Flash地址 */
temp_val = g_rev->deal_buff[BCOMM_FMT_PARAM + 3];
temp_val <<= 8;
temp_val |= g_rev->deal_buff[BCOMM_FMT_PARAM + 2];
temp_val <<= 8;
temp_val |= g_rev->deal_buff[BCOMM_FMT_PARAM + 1];
temp_val <<= 8;
temp_val |= g_rev->deal_buff[BCOMM_FMT_PARAM];
/*写入Flash长度 */
temp_val_2 = g_rev->deal_buff[BCOMM_FMT_PARAM + 5];
temp_val_2 <<= 8;
temp_val_2 |= g_rev->deal_buff[BCOMM_FMT_PARAM + 4];
DBG_SYS_Printf("WAddr: 0x%x Len:%d",temp_val,temp_val_2);
if (temp_val_2 == ( g_rev->deal_len - BCOMM_FMT_PARAM - 6 )){
/*Flash 数据写入*/
//g_rev->ackBuffer[BCOMM_FMT_PARAM] = MCU_APP_Flash_Write(&g_rev->deal_buff[BCOMM_FMT_PARAM + 6],temp_val_2,temp_val);
Flash_Write_NoCheck(&g_rev->deal_buff[BCOMM_FMT_PARAM + 6],temp_val_2,temp_val);
Flash_Read(g_read_buff, temp_val_2,temp_val);
Dbg_Print_Buff(DBG_BIT_SYS_STATUS,"App CRC BUFF:",g_read_buff,temp_val_2);
g_rev->ackBuffer[BCOMM_FMT_PARAM] = BCOMM_CMD_ReplySUCC;
}else {
/*写入Flash 不在地址范围内 */
g_rev->ackBuffer[BCOMM_FMT_PARAM] = BCOMM_CMD_ReplyFAIL;
}
g_rev->ackLen = 1;
break;
case BCOMM_CMD_ReadFlash: //读取Flash
if(deal_flag != 0x01) break; //不处理直接退出
if( g_rev->deal_len < (BCOMM_FMT_PARAM + 6) ) {
DBG_SYS_Printf("BCOMM_CMD_ReadFlash Para Error ");
break;
}
DBG_SYS_Printf("BCOMM_CMD_ReadFlash Proecessing ");
/*读取Flash地址 */
temp_val = g_rev->deal_buff[BCOMM_FMT_PARAM + 3];
temp_val <<= 8;
temp_val |= g_rev->deal_buff[BCOMM_FMT_PARAM + 2];
temp_val <<= 8;
temp_val |= g_rev->deal_buff[BCOMM_FMT_PARAM + 1];
temp_val <<= 8;
temp_val |= g_rev->deal_buff[BCOMM_FMT_PARAM];
/*读取Flash长度 */
temp_val_2 = g_rev->deal_buff[BCOMM_FMT_PARAM + 5];
temp_val_2 <<= 8;
temp_val_2 |= g_rev->deal_buff[BCOMM_FMT_PARAM + 4];
if(temp_val_2 > BCOMM_ParaSize) temp_val_2 = BCOMM_ParaSize; //参数最长不能超过ACK BUFF大小
g_rev->ackBuffer[BCOMM_FMT_PARAM] = MCU_APP_Flash_Read(&g_rev->ackBuffer[BCOMM_FMT_PARAM + 1],temp_val_2,temp_val);
if(g_rev->ackBuffer[BCOMM_FMT_PARAM] == BCOMM_CMD_ReplySUCC)
{
g_rev->ackLen = temp_val_2 + 1;
}else {
g_rev->ackLen = 1;
}
break;
case BCOMM_CMD_EraseFlash: //擦除Flash
if(deal_flag != 0x01) break; //不处理直接退出
if( g_rev->deal_len < (BCOMM_FMT_PARAM + 1) ) {
DBG_SYS_Printf("BCOMM_CMD_ReadFlash Para Error ");
break;
}
DBG_SYS_Printf("BCOMM_CMD_EraseFlash Proecessing ");
if(g_rev->deal_buff[BCOMM_FMT_PARAM] == 0x01){
/*擦除APP Flash 指定区域*/
if( g_rev->deal_len < (BCOMM_FMT_PARAM + 7) ) {
DBG_SYS_Printf("BCOMM_CMD_EraseFlash Para Error ");
break;
}
/*擦除Flash地址 */
temp_val = g_rev->deal_buff[BCOMM_FMT_PARAM + 4];
temp_val <<= 8;
temp_val |= g_rev->deal_buff[BCOMM_FMT_PARAM + 3];
temp_val <<= 8;
temp_val |= g_rev->deal_buff[BCOMM_FMT_PARAM + 2];
temp_val <<= 8;
temp_val |= g_rev->deal_buff[BCOMM_FMT_PARAM + 1];
/*擦除Flash 长度*/
temp_val_2 = g_rev->deal_buff[BCOMM_FMT_PARAM + 6];
temp_val_2 <<= 8;
temp_val_2 |= g_rev->deal_buff[BCOMM_FMT_PARAM + 5];
if( (MCU_APP_Flash_Start_Addr <= temp_val) && ( (temp_val + temp_val_2) < MCU_APP_Flash_End_Addr ) ){
DBG_SYS_Printf("EraseFlash Addr:%x Len:%d ",temp_val,temp_val_2);
temp_val = temp_val - (temp_val % MCU_APP_Flash_PageSize);
for(uint32_t i = temp_val;i<(temp_val + temp_val_2) ;i+=MCU_APP_Flash_PageSize){
DBG_SYS_Printf("PageErase Addr:%x ",i);
//FLASH_ROMA_ERASE(i,MCU_APP_Flash_PageSize);
//Flash_Erase_Sector(i);
}
g_rev->ackBuffer[BCOMM_FMT_PARAM] = BCOMM_CMD_ReplySUCC;
g_rev->ackLen = 1;
}else {
/*写入Flash 不在地址范围内 */
g_rev->ackBuffer[BCOMM_FMT_PARAM] = BCOMM_CMD_ReplyFAIL;
g_rev->ackLen = 1;
}
}else if(g_rev->deal_buff[BCOMM_FMT_PARAM] == 0x02){
/*擦除全部APP Flash 同时也有APP 特征区*/
SPI_FLASH_APP_Data_Erase();
g_rev->ackBuffer[BCOMM_FMT_PARAM] = BCOMM_CMD_ReplySUCC;
g_rev->ackLen = 1;
}else {
g_rev->ackBuffer[BCOMM_FMT_PARAM] = BCOMM_CMD_ReplyFAIL;
g_rev->ackLen = 1;
}
break;
case BCOMM_CMD_WriteEEPROM: //写EEPROM
if(deal_flag != 0x01) break; //不处理直接退出
if( g_rev->deal_len < (BCOMM_FMT_PARAM + 6) ) {
DBG_SYS_Printf("BCOMM_CMD_WriteEEPROM Para Error ");
break;
}
DBG_SYS_Printf("BCOMM_CMD_WriteEEPROM Proecessing ");
/*写入Flash地址 */
temp_val = g_rev->deal_buff[BCOMM_FMT_PARAM + 3];
temp_val <<= 8;
temp_val |= g_rev->deal_buff[BCOMM_FMT_PARAM + 2];
temp_val <<= 8;
temp_val |= g_rev->deal_buff[BCOMM_FMT_PARAM + 1];
temp_val <<= 8;
temp_val |= g_rev->deal_buff[BCOMM_FMT_PARAM];
/*写入Flash长度 */
temp_val_2 = g_rev->deal_buff[BCOMM_FMT_PARAM + 5];
temp_val_2 <<= 8;
temp_val_2 |= g_rev->deal_buff[BCOMM_FMT_PARAM + 4];
DBG_SYS_Printf("WAddr: 0x%x Len:%d",temp_val,temp_val_2);
if (temp_val_2 == ( g_rev->deal_len - BCOMM_FMT_PARAM - 6 )){
/*Flash 数据写入*/
g_rev->ackBuffer[BCOMM_FMT_PARAM] = MCU_EEPROM_Write(&g_rev->deal_buff[BCOMM_FMT_PARAM + 6],temp_val_2,temp_val);
}else {
/*写入Flash 不在地址范围内 */
g_rev->ackBuffer[BCOMM_FMT_PARAM] = BCOMM_CMD_ReplyFAIL;
}
g_rev->ackLen = 1;
break;
case BCOMM_CMD_ReadEEPROM: //写EEPROM
if(deal_flag != 0x01) break; //不处理直接退出
if( g_rev->deal_len < (BCOMM_FMT_PARAM + 6) ) {
DBG_SYS_Printf("BCOMM_CMD_ReadFlash Para Error ");
break;
}
DBG_SYS_Printf("BCOMM_CMD_ReadFlash Proecessing ");
/*读取Flash地址 */
temp_val = g_rev->deal_buff[BCOMM_FMT_PARAM + 3];
temp_val <<= 8;
temp_val |= g_rev->deal_buff[BCOMM_FMT_PARAM + 2];
temp_val <<= 8;
temp_val |= g_rev->deal_buff[BCOMM_FMT_PARAM + 1];
temp_val <<= 8;
temp_val |= g_rev->deal_buff[BCOMM_FMT_PARAM];
/*读取Flash长度 */
temp_val_2 = g_rev->deal_buff[BCOMM_FMT_PARAM + 5];
temp_val_2 <<= 8;
temp_val_2 |= g_rev->deal_buff[BCOMM_FMT_PARAM + 4];
if(temp_val_2 > BCOMM_ParaSize) temp_val_2 = BCOMM_ParaSize; //参数最长不能超过ACK BUFF大小
g_rev->ackBuffer[BCOMM_FMT_PARAM] = MCU_APP_Flash_Read(&g_rev->ackBuffer[BCOMM_FMT_PARAM + 1],temp_val_2,temp_val);
if(g_rev->ackBuffer[BCOMM_FMT_PARAM] == BCOMM_CMD_ReplySUCC)
{
g_rev->ackLen = temp_val_2 + 1;
}else {
g_rev->ackLen = 1;
}
break;
case BCOMM_CMD_EraseEEPROM: //擦除EEPROM
if(deal_flag != 0x01) break; //不处理直接退出
if( g_rev->deal_len < (BCOMM_FMT_PARAM + 1) ) {
DBG_SYS_Printf("BCOMM_CMD_EraseEEPROM Para Error ");
break;
}
DBG_SYS_Printf("BCOMM_CMD_EraseEEPROM Proecessing ");
if(g_rev->deal_buff[BCOMM_FMT_PARAM] == 0x01){
/*擦除APP Flash 指定区域*/
if( g_rev->deal_len < (BCOMM_FMT_PARAM + 7) ) {
DBG_SYS_Printf("BCOMM_CMD_EraseEEPROM Para Error ");
break;
}
/*擦除Flash地址 */
temp_val = g_rev->deal_buff[BCOMM_FMT_PARAM + 4];
temp_val <<= 8;
temp_val |= g_rev->deal_buff[BCOMM_FMT_PARAM + 3];
temp_val <<= 8;
temp_val |= g_rev->deal_buff[BCOMM_FMT_PARAM + 2];
temp_val <<= 8;
temp_val |= g_rev->deal_buff[BCOMM_FMT_PARAM + 1];
/*擦除Flash 长度*/
temp_val_2 = g_rev->deal_buff[BCOMM_FMT_PARAM + 6];
temp_val_2 <<= 8;
temp_val_2 |= g_rev->deal_buff[BCOMM_FMT_PARAM + 5];
if( (MCU_APP_Flash_Start_Addr <= temp_val) && ( (temp_val + temp_val_2) < MCU_APP_Flash_End_Addr ) ){
DBG_SYS_Printf("EraseFlash Addr:%x Len:%d ",temp_val,temp_val_2);
temp_val = temp_val - (temp_val % MCU_APP_Flash_PageSize);
for(uint32_t i = temp_val;i<(temp_val + temp_val_2) ;i+=MCU_APP_Flash_PageSize){
DBG_SYS_Printf("PageErase Addr:%x ",i);
FLASH_ROMA_ERASE(i,MCU_APP_Flash_PageSize);
}
g_rev->ackBuffer[BCOMM_FMT_PARAM] = BCOMM_CMD_ReplySUCC;
g_rev->ackLen = 1;
}else {
/*写入Flash 不在地址范围内 */
g_rev->ackBuffer[BCOMM_FMT_PARAM] = BCOMM_CMD_ReplyFAIL;
g_rev->ackLen = 1;
}
}else if(g_rev->deal_buff[BCOMM_FMT_PARAM] == 0x02){
/*擦除全部EEPROM*/
MCU_EEPROM_ALLErase();
g_rev->ackBuffer[BCOMM_FMT_PARAM] = BCOMM_CMD_ReplySUCC;
g_rev->ackLen = 1;
}else {
g_rev->ackBuffer[BCOMM_FMT_PARAM] = BCOMM_CMD_ReplyFAIL;
g_rev->ackLen = 1;
}
break;
case BCOMM_CMD_CheckData: //校验
if(deal_flag != 0x01) break; //不处理直接退出
if( g_rev->deal_len < (BCOMM_FMT_PARAM + 10) ) {
DBG_SYS_Printf("BCOMM_CMD_CheckData Para Error ");
break;
}
DBG_SYS_Printf("BCOMM_CMD_CheckData Proecessing ");
memset(&g_app_feature,0,sizeof(G_SYS_FEATURE_T));
/* 校验CRC 起始地址*/
g_app_feature.app_start_addr = g_rev->deal_buff[BCOMM_FMT_PARAM + 3];
g_app_feature.app_start_addr <<= 8;
g_app_feature.app_start_addr |= g_rev->deal_buff[BCOMM_FMT_PARAM + 2];
g_app_feature.app_start_addr <<= 8;
g_app_feature.app_start_addr |= g_rev->deal_buff[BCOMM_FMT_PARAM + 1];
g_app_feature.app_start_addr <<= 8;
g_app_feature.app_start_addr |= g_rev->deal_buff[BCOMM_FMT_PARAM];
/* 校验CRC 结束地址*/
g_app_feature.app_end_addr = g_rev->deal_buff[BCOMM_FMT_PARAM + 7];
g_app_feature.app_end_addr <<= 8;
g_app_feature.app_end_addr |= g_rev->deal_buff[BCOMM_FMT_PARAM + 6];
g_app_feature.app_end_addr <<= 8;
g_app_feature.app_end_addr |= g_rev->deal_buff[BCOMM_FMT_PARAM + 5];
g_app_feature.app_end_addr <<= 8;
g_app_feature.app_end_addr |= g_rev->deal_buff[BCOMM_FMT_PARAM + 4];
/* 校验CRC 大小*/
g_app_feature.app_crc_size = g_rev->deal_buff[BCOMM_FMT_PARAM + 9];
g_app_feature.app_crc_size <<= 8;
g_app_feature.app_crc_size |= g_rev->deal_buff[BCOMM_FMT_PARAM + 8];
DBG_SYS_Printf("App Start_addr :%x ",g_app_feature.app_start_addr);
DBG_SYS_Printf("App End_addr :%x ",g_app_feature.app_end_addr);
DBG_SYS_Printf("App CRC Block_Size :%d ",g_app_feature.app_crc_size);
if( (g_app_feature.app_start_addr >= MCU_APP_Flash_Start_Addr)
&& (g_app_feature.app_end_addr < MCU_APP_Flash_End_Addr)
&& (g_app_feature.app_end_addr > g_app_feature.app_start_addr)
&& (g_app_feature.app_crc_size == MCU_APP_Flash_PageSize) )
{
temp_val = g_app_feature.app_end_addr - g_app_feature.app_start_addr;
DBG_SYS_Printf("App Len :%d ",temp_val);
if( (temp_val % g_app_feature.app_crc_size ) != 0x00 ){
g_app_feature.app_crc_len = ((temp_val / g_app_feature.app_crc_size) + 1) * 2;
}else {
g_app_feature.app_crc_len = (temp_val / g_app_feature.app_crc_size) * 2;
}
DBG_SYS_Printf("App CRC BLock:%d ",g_app_feature.app_crc_len);
/*比对校验的数据包长 对不对 */
if( (BCOMM_FMT_PARAM + 10 + g_app_feature.app_crc_len ) == g_rev->deal_len ){
uint32_t crc_data_len = 0;
crcNumIndex = 0;
memcpy(g_app_feature.app_crc,&g_rev->deal_buff[BCOMM_FMT_PARAM + 10],(g_rev->deal_len - 10 - BCOMM_FMT_PARAM) );
for(uint32_t crc_addr = g_app_feature.app_start_addr; crc_addr < g_app_feature.app_end_addr;crc_addr += g_app_feature.app_crc_size)
{
if( g_app_feature.app_end_addr - crc_addr >= g_app_feature.app_crc_size) {
crc_data_len = g_app_feature.app_crc_size;
}else {
crc_data_len = g_app_feature.app_end_addr - crc_addr;
}
memset(g_read_buff,0,sizeof(g_read_buff));
if(crc_data_len > 2048)
{
Flash_Read(g_read_buff,2048,crc_addr);
Flash_Read(&g_read_buff[2048],(crc_data_len - 2048),crc_addr+2048);
}else {
Flash_Read(g_read_buff,crc_data_len,crc_addr);
}
temp_val = CRC16_Check(g_read_buff,crc_data_len);
temp_val_2 = g_app_feature.app_crc[crcNumIndex + 1];
temp_val_2 <<= 8;
temp_val_2 |= g_app_feature.app_crc[crcNumIndex];
//DBG_SYS_Printf("App CRC ADDR:%x %x-%x",crc_addr,temp_val,temp_val_2);
//Dbg_Print_Buff(DBG_BIT_SYS_STATUS,"App CRC BUFF:",g_read_buff,crc_data_len);
if(temp_val != temp_val_2){
/*校验失败 - */
g_rev->ackBuffer[BCOMM_FMT_PARAM ] = BCOMM_CMD_ReplyFAIL;
g_rev->ackBuffer[BCOMM_FMT_PARAM + 5 + crcResultFlag*4] = ((crc_addr >> 24) & 0xFF);
g_rev->ackBuffer[BCOMM_FMT_PARAM + 4 + crcResultFlag*4] = ((crc_addr >> 16) & 0xFF);
g_rev->ackBuffer[BCOMM_FMT_PARAM + 3 + crcResultFlag*4] = ((crc_addr >> 8) & 0xFF);
g_rev->ackBuffer[BCOMM_FMT_PARAM + 2 + crcResultFlag*4] = (crc_addr & 0xFF);
DBG_SYS_Printf("App CRC Fail ADDR:%X %X-%X",crc_addr,temp_val,temp_val_2);
crcResultFlag++;
if(crcResultFlag >= 20) break;
}
crcNumIndex += 2;
}
if(crcResultFlag == 0x00){
/*校验成功 - 写入APP 特征区*/
g_app_feature.app_flag = App_Procedure_Ready;
g_app_feature.crc_check = 0x00;
Write_APP_Feature_Info(0x02,&g_app_feature);
g_rev->ackBuffer[BCOMM_FMT_PARAM] = BCOMM_CMD_ReplySUCC;
}
g_rev->ackBuffer[BCOMM_FMT_PARAM + 1] = crcResultFlag;
g_rev->ackLen = 2 + crcResultFlag*4;
}else {
/*数据包长不对*/
DBG_SYS_Printf("App CRC BLock ERROR:%d %d",temp_val,g_rev->deal_len);
g_rev->ackBuffer[BCOMM_FMT_PARAM] = 0x02;
g_rev->ackLen = 1;
}
}else{
DBG_SYS_Printf("App CRC Para ERROR");
g_rev->ackBuffer[BCOMM_FMT_PARAM] = 0x01;
g_rev->ackLen = 1;
}
break;
}
/*回复通讯数据*/
if( (group_flag == 0x00) && (reply_flag == 0x01) )
{
Boot_Comm_FillReplyPack(g_rev);
}
return 0;
}
/*******************************************************************************
* Function Name : Read_APP_Feature
* Description : 读取APP特征区参数
* Return :
0没问题
1Flash中APP不正确或错误
2MCU APP需要更新
*******************************************************************************/
uint8_t Read_APP_Feature(void)
{
uint8_t rev = 0;
uint8_t crcResultFlag = TRUE;
uint16_t crcNumIndex = 0;
uint16_t crcVal = 0;
uint8_t crcValH = 0, crcValL = 0;
uint32_t crc_data_len = 0;
memset(&g_app_feature,0,sizeof(G_SYS_FEATURE_T));
memset(&g_mcu_app_feature,0,sizeof(G_SYS_FEATURE_T));
/*第一步先读取外部Flash的APP特征区是否有数据同时验证APP的合法性*/
rev = Read_APP_Feature_Info(0x02,&g_app_feature);
if(rev == 0x00)
{
DBG_SYS_Printf("SPIFlash APP Feature Check Succ");
APP_Feature_Info_Printf(&g_app_feature);
/*判断APP 标志位是否成立*/
if(g_app_feature.app_flag == App_Procedure_Ready)
{
/*判断APP 起始地址、结束地址以及CRC校验大小是否在范围内*/
if( ( g_app_feature.app_start_addr < MCU_APP_Flash_Start_Addr ) \
|| ( g_app_feature.app_end_addr > MCU_APP_Flash_End_Addr ) \
|| ( g_app_feature.app_crc_size != MCU_APP_Flash_PageSize ) )
{
DBG_SYS_Printf("SPIFlash Flash APP ADDRESS ERROR!");
LOG_Launcher_APP_Check_Record(0x03);
return 1;
}
/*外部flash 校验APP数据*/
crcNumIndex = 0;
memset(g_read_buff,0,sizeof(g_read_buff));
for(uint32_t i = g_app_feature.app_start_addr; i < g_app_feature.app_end_addr; i += g_app_feature.app_crc_size)
{
if( g_app_feature.app_end_addr - i >= g_app_feature.app_crc_size) {
crc_data_len = g_app_feature.app_crc_size;
}else {
crc_data_len = g_app_feature.app_end_addr - i;
}
memset(g_read_buff,0,sizeof(g_read_buff));
if(crc_data_len > 2048)
{
Flash_Read(g_read_buff,2048,i);
Flash_Read(&g_read_buff[2048],(crc_data_len - 2048),i+2048);
}else {
Flash_Read(g_read_buff,crc_data_len,i);
}
crcVal = CRC16_Check(g_read_buff, crc_data_len);
crcValH = crcVal >> 8;
crcValL = crcVal & 0xFF;
if((g_app_feature.app_crc[crcNumIndex + 1] != crcValH) || (g_app_feature.app_crc[ crcNumIndex] != crcValL))
{
DBG_SYS_Printf("block:%d , app_crc:%x%x , crcVal:%X\r\n",crcNumIndex,g_app_feature.app_crc[crcNumIndex],g_app_feature.app_crc[1 + crcNumIndex],crcVal);
Dbg_Print_Buff(DBG_BIT_SYS_STATUS,"Read Flash:",g_read_buff,MCU_APP_Flash_PageSize);
crcResultFlag = FALSE;
break;
}
crcNumIndex+=2;
}
if(crcResultFlag == FALSE)
{
DBG_SYS_Printf("SPI FLash APP ERROR! - 擦除APP数据\r\n");
//擦除Flash APP特征区数据
Flash_Erase_Pageaddr(SPIFLASH_APP_FEATURE_Addr);
LOG_Launcher_APP_Check_Record(0x04);
return 1; //校验失败
}
}else{
LOG_Launcher_APP_Check_Record(0x05);
return 1; //没APP数据
}
}else {
DBG_SYS_Printf("SPIFlash APP Feature Check Fail \r\n");
LOG_Launcher_APP_Check_Record(0x06);
return 1;
}
/*第二步先读取MCU Flash的APP特征区是否有数据同时验证APP的合法性*/
rev = Read_APP_Feature_Info(0x01,&g_mcu_app_feature);
if(rev == 0x00)
{
DBG_SYS_Printf("MCU Flash APP Feature Check Succ");
APP_Feature_Info_Printf(&g_mcu_app_feature);
/*判断APP 标志位是否成立*/
if(g_mcu_app_feature.app_flag == App_Procedure_Ready)
{
/*判断APP 起始地址、结束地址以及CRC校验大小是否在范围内*/
if( ( g_mcu_app_feature.app_start_addr < MCU_APP_Flash_Start_Addr ) \
|| ( g_mcu_app_feature.app_end_addr > MCU_APP_Flash_End_Addr ) \
|| ( g_mcu_app_feature.app_crc_size != MCU_APP_Flash_PageSize ) )
{
DBG_SYS_Printf("MCU Flash APP ADDRESS ERROR!");
LOG_Launcher_APP_Check_Record(0x03);
return 1;
}
/*外部flash 校验APP数据*/
crcNumIndex = 0;
memset(g_read_buff,0,sizeof(g_read_buff));
for(uint32_t i = g_mcu_app_feature.app_start_addr; i < g_mcu_app_feature.app_end_addr; i += g_mcu_app_feature.app_crc_size)
{
if( g_app_feature.app_end_addr - i >= g_app_feature.app_crc_size) {
crc_data_len = g_app_feature.app_crc_size;
}else {
crc_data_len = g_app_feature.app_end_addr - i;
}
memset(g_read_buff,0,sizeof(g_read_buff));
MCU_APP_Flash_Read(g_read_buff ,crc_data_len,i);
crcVal = CRC16_Check(g_read_buff, crc_data_len);
crcValH = crcVal >> 8;
crcValL = crcVal & 0xFF;
if((g_mcu_app_feature.app_crc[crcNumIndex + 1] != crcValH) || (g_mcu_app_feature.app_crc[crcNumIndex] != crcValL))
{
DBG_SYS_Printf("block:%d , app_crc:%x%x , crcVal:%X\r\n",crcNumIndex,g_mcu_app_feature.app_crc[crcNumIndex],g_mcu_app_feature.app_crc[1 + crcNumIndex],crcVal);
Dbg_Print_Buff(DBG_BIT_SYS_STATUS,"Read Flash:",g_read_buff,MCU_APP_Flash_PageSize);
crcResultFlag = FALSE;
break;
}
crcNumIndex+=2;
}
if(crcResultFlag == FALSE)
{
DBG_SYS_Printf("APP ERROR! \r\n");
LOG_Launcher_APP_Check_Record(0x07);
return 2; //校验失败
}
}else{
LOG_Launcher_APP_Check_Record(0x08);
return 2;
}
}else {
DBG_SYS_Printf("MCU Feature ERROR! \r\n");
LOG_Launcher_APP_Check_Record(0x09);
return 2;
}
/*判断MCU Flash中的特征区内容是否与外部SPI Flash中的特征区内容是否一致*/
if(g_app_feature.app_crc_len != g_mcu_app_feature.app_crc_len) {
DBG_SYS_Printf("app_crc_len different!\r\n");
LOG_Launcher_APP_Check_Record(0x02);
return 2;
}
if(g_app_feature.app_start_addr != g_mcu_app_feature.app_start_addr) {
DBG_SYS_Printf("app_start_addr different!\r\n");
LOG_Launcher_APP_Check_Record(0x02);
return 2;
}
if(g_app_feature.app_end_addr != g_mcu_app_feature.app_end_addr) {
DBG_SYS_Printf("app_end_addr different!\r\n");
LOG_Launcher_APP_Check_Record(0x02);
return 2;
}
for(uint16_t j = 0;j<g_app_feature.app_crc_len;j++)
{
if(g_mcu_app_feature.app_crc[j] != g_app_feature.app_crc[j])
{
LOG_Launcher_APP_Check_Record(0x02);
return 2;
}
}
/*没问题了 准备 跳转APP*/
LOG_Launcher_APP_Check_Record(0x00);
return 0x00;
}
/*******************************************************************************
* Function Name : MCU_APP_Write
* Description : MCU Flash APP区数据写入函数
* Input :
*******************************************************************************/
uint8_t MCU_APP_Write(void)
{
uint8_t rev = 0;
uint8_t crcValH = 0, crcValL = 0;
uint16_t crcVal = 0,crcNumIndex = 0;
uint32_t crc_data_len = 0;
DBG_SYS_Printf("MCU Flash 擦除APP程序");
rev = MCU_APP_Flash_ALLErase(); //先擦除 全部APP程序
if(rev != 0) {
DBG_SYS_Printf("MCU Flash 擦除APP程序 失败");
return 0x01;
}
if( ( g_app_feature.app_start_addr < MCU_APP_Flash_Start_Addr ) || ( g_app_feature.app_start_addr > MCU_APP_Data_End_Addr ) ){
DBG_SYS_Printf("MCU Flash app_start_addr:0x%x Error",g_app_feature.app_start_addr);
return 0x01;
}
if( ( g_app_feature.app_end_addr > MCU_APP_Data_End_Addr ) || ( g_app_feature.app_start_addr > g_app_feature.app_end_addr ) ){
DBG_SYS_Printf("MCU Flash app_end_addr:0x%x - 0x%x Error",g_app_feature.app_start_addr,g_app_feature.app_end_addr);
return 0x01;
}
if( g_app_feature.app_crc_size != MCU_APP_Flash_PageSize ){
DBG_SYS_Printf("MCU Flash app_crc_size:%x Error",g_app_feature.app_crc_size);
return 0x01;
}
/*1、写入APP Flash数据 - 按照块大小写入APP Flash数据内容*/
for(uint32_t i = g_app_feature.app_start_addr;i < g_app_feature.app_end_addr;i += MCU_APP_Flash_PageSize )
{
if( g_app_feature.app_end_addr - i >= g_app_feature.app_crc_size) {
crc_data_len = g_app_feature.app_crc_size;
}else {
crc_data_len = g_app_feature.app_end_addr - i;
}
memset(g_read_buff,0,sizeof(g_read_buff));
if(crc_data_len > 2048)
{
Flash_Read(g_read_buff,2048,i);
Flash_Read(&g_read_buff[2048],(crc_data_len - 2048),i+2048);
}else {
Flash_Read(g_read_buff,crc_data_len,i);
}
DBG_SYS_Printf("MCU Write APP Addr:%x",i);
rev = MCU_APP_Flash_Write(g_read_buff,crc_data_len,i);
if(rev != 0x00){
DBG_SYS_Printf("MCU Flash Write:%x Error",i);
return 0x01;
}
}
/*2、写入APP 特征区数据*/
g_mcu_app_feature.app_flag = g_app_feature.app_flag;
g_mcu_app_feature.app_start_addr = g_app_feature.app_start_addr;
g_mcu_app_feature.app_end_addr = g_app_feature.app_end_addr;
g_mcu_app_feature.app_crc_size = g_app_feature.app_crc_size;
g_mcu_app_feature.app_crc_len = g_app_feature.app_crc_len;
g_mcu_app_feature.crc_check = g_app_feature.crc_check;
memcpy(g_mcu_app_feature.app_crc,g_app_feature.app_crc,APP_Feature_CRC_Size);
rev = Write_APP_Feature_Info(0x01,&g_mcu_app_feature);
if(rev != 0x00){
DBG_SYS_Printf("MCU Write APP Feature_Info Error");
return 0x01;
}
/*3、读取APP特征区数据且对APP Flash数据进行CRC校验*/
rev = Read_APP_Feature_Info(0x01,&g_mcu_app_feature);
if(rev != 0x00){
DBG_SYS_Printf("MCU Read APP Feature_Info Error");
return 0x01;
}
for(uint32_t i = g_mcu_app_feature.app_start_addr; i < g_mcu_app_feature.app_end_addr; i += MCU_APP_Flash_PageSize)
{
if( g_app_feature.app_end_addr - i >= g_app_feature.app_crc_size) {
crc_data_len = g_app_feature.app_crc_size;
}else {
crc_data_len = g_app_feature.app_end_addr - i;
}
memset(g_read_buff,0,sizeof(g_read_buff));
rev = MCU_APP_Flash_Read(g_read_buff,crc_data_len,i);
Dbg_Print_Buff(DBG_BIT_SYS_STATUS, "MCU Flash:", g_read_buff, crc_data_len);
crcVal = CRC16_Check(g_read_buff, crc_data_len);
crcValH = crcVal >> 8;
crcValL = crcVal & 0xFF;
DBG_SYS_Printf("MCU Write APP Addr:%x - CRC:%x",i,crcVal);
if( ( g_mcu_app_feature.app_crc[crcNumIndex + 1] != crcValH ) || ( g_mcu_app_feature.app_crc[crcNumIndex] != crcValL ) )
{
DBG_SYS_Printf("Addr:%x app_crc:%x%x crcVal:%x ",i,g_mcu_app_feature.app_crc[crcNumIndex],g_mcu_app_feature.app_crc[1 + crcNumIndex],crcVal);
Dbg_Print_Buff(DBG_BIT_SYS_STATUS, "MCU Flash:", g_read_buff, crc_data_len);
if(crc_data_len > 2048)
{
Flash_Read(g_read_buff,2048,i);
Flash_Read(&g_read_buff[2048],(crc_data_len - 2048),i+2048);
}else {
Flash_Read(g_read_buff,crc_data_len,i);
}
Dbg_Print_Buff(DBG_BIT_SYS_STATUS, "SPI Flash:", g_flash_buff, MCU_APP_Flash_PageSize);
for(uint32_t t_addr = 0;t_addr < crc_data_len;t_addr++ )
{
if(g_read_buff[t_addr] != g_flash_buff[t_addr])
{
DBG_SYS_Printf("Different Addr:%x %x - %x",i+t_addr,g_read_buff[t_addr],g_flash_buff[t_addr]);
}
}
return 0x01;
}
crcNumIndex += 2;
}
/*4、校验成功*/
DBG_SYS_Printf("MCU APP Update Succ!!");
LOG_Launcher_Read_App_Record(0x00);
return 0x00;
}
/*******************************************************************************
* Function Name : SPIFLASH_Read_Update_Recode
* Description : MCU Flash APP区数据写入函数
* Input :
*******************************************************************************/
uint8_t SPIFLASH_Read_Update_Recode(UPDATE_RECORD_T *info)
{
uint16_t read_len = 0;
memset(g_flash_buff,0,sizeof(g_flash_buff));
Flash_Read(g_flash_buff, APP_FEATURE_SIZE, SPIFLASH_UPDATE_RECORD_Addr);
if(g_flash_buff[EEPROM_Offset_SaveFlag] == EEPROM_SVAE_FLAG)
{
read_len = g_flash_buff[EEPROM_Offset_Datalen + 1];
read_len <<= 8;
read_len |= g_flash_buff[EEPROM_Offset_Datalen];
DBG_SYS_Printf("%s read_len : %d ",__func__,read_len);
if(read_len == UPDATE_RECORD_INFO_Size)
{
if(EEPROM_CheckSum(&g_flash_buff[EEPROM_Offset_Data],read_len) == g_flash_buff[EEPROM_Offset_Check]){
memcpy((uint8_t *)info,&g_flash_buff[EEPROM_Offset_Data],read_len);
DBG_SYS_Printf("spiflash_fw_count:%d",g_mcu_dev.dev_addr);
DBG_SYS_Printf("spiflash_fw_succ:%d",g_mcu_dev.dev_type);
DBG_SYS_Printf("spiflash_fw_fail:%d",g_mcu_dev.dev_boot_ver);
DBG_SYS_Printf("EE DevAppVer:%d",g_mcu_dev.dev_app_ver);
DBG_SYS_Printf("EE DevNameLen:%d",g_mcu_dev.dev_name_len);
DBG_SYS_Printf("EE DevName:%s",g_mcu_dev.dev_name);
return 0x00; //读取成功
}else {
DBG_SYS_Printf("%s Check Error !",__func__);
}
}else {
DBG_SYS_Printf("%s Len Error !",__func__);
}
}else{
DBG_SYS_Printf("%s Flag Error !",__func__);
}
return 0x01; //读取失败
}
uint8_t SPIFLASH_Write_Update_Recode(UPDATE_RECORD_T *info)
{
uint16_t save_len = UPDATE_RECORD_INFO_Size;
memset(g_flash_buff,0,sizeof(g_flash_buff));
g_flash_buff[EEPROM_Offset_SaveFlag] = EEPROM_SVAE_FLAG;
g_flash_buff[EEPROM_Offset_Datalen] = save_len & 0xFF;
g_flash_buff[EEPROM_Offset_Datalen] = (save_len >> 8) & 0xFF;
memcpy(&g_flash_buff[EEPROM_Offset_Data],(uint8_t *)info,save_len);
g_flash_buff[3] = EEPROM_CheckSum(&g_flash_buff[4],save_len);
save_len+=4;
Flash_Write(g_flash_buff, APP_FEATURE_SIZE, SPIFLASH_UPDATE_RECORD_Addr);
return 0x00;
}