修改事项: 1、新增TFTP IAP升级功能,只是代码移植完毕,没有测试使用 2、代码空间编译优化,零等待区域空间已满,而应用层代码已全部挪移到非零等待区域中,但还是会增加零等待区的空间占用。 待优化
637 lines
28 KiB
C
637 lines
28 KiB
C
/*
|
||
* tftp_function.c
|
||
*
|
||
* Created on: Dec 6, 2025
|
||
* Author: cc
|
||
*/
|
||
#include "tftp_function.h"
|
||
#include "net_function.h"
|
||
#include "sram_mem_addr.h"
|
||
#include "flash_mem_addr.h"
|
||
#include "spi_flash.h"
|
||
#include "spi_sram.h"
|
||
#include "mcu_flash.h"
|
||
#include "check_fun.h"
|
||
#include "log_api.h"
|
||
#include "watchdog.h"
|
||
#include "md5.h"
|
||
#include "debug.h"
|
||
|
||
IAPVarTypeStruct IAPVarTypeStruct_Ptr; //与局域网升级通讯相关的数据
|
||
tftp_connection_args tftp_args; //TFTP相关的数据
|
||
|
||
__attribute__((section(".non_0_wait"))) uint8_t bytes_cmp(uint8_t *src,uint8_t *dat,uint32_t len)
|
||
{
|
||
for(uint32_t i = 0; i < len; i++ )
|
||
{
|
||
if( src[i] != dat[i] )
|
||
{
|
||
return 0x01;
|
||
}
|
||
}
|
||
return 0x00;
|
||
}
|
||
|
||
/*******************************************************************************
|
||
* Function Name : TFTP_Get_Decode_op
|
||
* Description : TFTP 获取TFTP数据宝中的功能码
|
||
* Input :
|
||
* buf - TFTP数据包
|
||
*******************************************************************************/
|
||
__attribute__((section(".non_0_wait"))) uint8_t TFTP_Pack_Get_Opcode(uint8_t *buf)
|
||
{
|
||
return buf[1];
|
||
}
|
||
|
||
/*******************************************************************************
|
||
* Function Name : TFTP_Pack_Get_Block
|
||
* Description : TFTP 获取TFTP数据宝中的块号
|
||
* Input :
|
||
* buf - TFTP数据包
|
||
*******************************************************************************/
|
||
__attribute__((section(".non_0_wait"))) uint16_t TFTP_Pack_Get_Block(uint8_t *buf)
|
||
{
|
||
uint16_t temp = 0x00;
|
||
|
||
temp = buf[3];
|
||
temp <<= 8;
|
||
temp |= buf[4];
|
||
|
||
return temp;
|
||
}
|
||
|
||
/*******************************************************************************
|
||
* Function Name : TFTP_Pack_Set_Opcode
|
||
* Description : TFTP 获取TFTP数据宝中的功能码
|
||
* Input :
|
||
* buf - TFTP数据包
|
||
*******************************************************************************/
|
||
__attribute__((section(".non_0_wait"))) void TFTP_Pack_Set_Opcode(uint8_t *buffer, uint8_t opcode)
|
||
{
|
||
buffer[0] = 0;
|
||
buffer[1] = opcode;
|
||
}
|
||
|
||
/*******************************************************************************
|
||
* Function Name : TFTP_Pack_Set_Opcode
|
||
* Description : TFTP 设置TFTP数据宝中的块号
|
||
* Input :
|
||
* buf - TFTP数据包
|
||
*******************************************************************************/
|
||
__attribute__((section(".non_0_wait"))) void TFTP_Pack_Set_Block(uint8_t* packet, uint16_t block)
|
||
{
|
||
packet[2] = (block >> 8) & 0xFF;
|
||
packet[3] = block & 0xFF;
|
||
}
|
||
|
||
/*******************************************************************************
|
||
* Function Name : TFTP_send_ack_packet
|
||
* Description : 发送TFTP 应答数据
|
||
* Input : None
|
||
* Return : 返回发送状态
|
||
*******************************************************************************/
|
||
__attribute__((section(".non_0_wait"))) uint8_t TFTP_send_ack_packet(uint8_t s, uint8_t *to_ip, int to_port, int block)
|
||
{
|
||
uint8_t err = 0;
|
||
uint32_t sendlen = TFTP_ACK_PKT_LEN;
|
||
char packet[TFTP_ACK_PKT_LEN];
|
||
|
||
/* define the first two bytes of the packet */
|
||
if(1 == IAPVarTypeStruct_Ptr.IapErrFlag) TFTP_Pack_Set_Opcode(packet,TFTP_ERROR);
|
||
else TFTP_Pack_Set_Opcode(packet, TFTP_ACK);
|
||
|
||
TFTP_Pack_Set_Block(packet, block);
|
||
|
||
Dbg_Println(DBG_BIT_NET_STATUS_bit,"TFTP ACK packet -- SocketId:%d , port:%d ,block:%ld len:%ld , IP:%d.%d.%d.%d",s,to_port,block,sendlen,to_ip[0],to_ip[1],to_ip[2],to_ip[3]);
|
||
err = WCHNET_SocketUdpSendTo(s, (uint8_t *)&packet[0], &sendlen, to_ip, to_port);
|
||
|
||
return err;
|
||
}
|
||
|
||
/*******************************************************************************
|
||
* Function Name : IAP_tftp_process_write
|
||
* Description : IAP TFTP 写命令处理函数
|
||
* Input :
|
||
s : 套接字ID号
|
||
to_ip : 接收的IP
|
||
to_port :接收的端口
|
||
* Return : None
|
||
*******************************************************************************/
|
||
__attribute__((section(".non_0_wait"))) uint8_t IAP_tftp_process_write(uint8_t s, uint8_t* to_ip, int to_port)
|
||
{
|
||
tftp_args.op = TFTP_WRQ;
|
||
memcpy(&tftp_args.to_ip[0],to_ip,4);
|
||
tftp_args.to_port = to_port;
|
||
|
||
tftp_args.block = 0;
|
||
tftp_args.tot_bytes = 0;
|
||
|
||
IAPVarTypeStruct_Ptr.TotalCount =0;
|
||
IAPVarTypeStruct_Ptr.IapErrFlag = 0;
|
||
|
||
/*BLV_C1 -- 擦除Flash数据,还是在验证完数据之后,再擦除同时将SRAM中的数据写入flash中*/
|
||
if(IAPVarTypeStruct_Ptr.IapFileType == TFTP_IAP_DataType_APP)
|
||
{
|
||
Dbg_Println(DBG_BIT_NET_STATUS_bit,"设置升级文件写入地址");
|
||
IAPVarTypeStruct_Ptr.FlashWriteAddress = SRAM_IAP_APP_FILE_ADDRESS; //设置写地址 - 数据先保存在SRAM中
|
||
}
|
||
else if(IAPVarTypeStruct_Ptr.IapFileType == TFTP_IAP_DataType_CONFIG)
|
||
{
|
||
Dbg_Println(DBG_BIT_NET_STATUS_bit,"设置逻辑配置写入地址");
|
||
IAPVarTypeStruct_Ptr.FlashWriteAddress = SRAM_IAP_LOGIC_DataStart_ADDRESS; //设置写地址 - 数据先保存在SRAM中
|
||
}
|
||
else
|
||
{
|
||
return 0x01;
|
||
}
|
||
|
||
TFTP_send_ack_packet(s, to_ip, to_port, tftp_args.block);
|
||
return 0x00;
|
||
}
|
||
|
||
/*******************************************************************************
|
||
* Function Name : TFTP_IAP_Data_Processing
|
||
* Description : TFTP IAP数据处理函数 - 主要是处理IAP过程中数据包内容
|
||
* Input :
|
||
* s - 套接字ID
|
||
* pkt_buf - 数据包
|
||
* pkt_buf_len - 数据包长度
|
||
* ip_addr - 数据包的IP
|
||
* Port - 数据包的端口号
|
||
*******************************************************************************/
|
||
__attribute__((section(".non_0_wait"))) void TFTP_IAP_Data_Processing(uint8_t s, uint8_t *pkt_buf,uint16_t pkt_buf_len,uint8_t *ip_addr, uint16_t Port)
|
||
{
|
||
uint8_t data_buffer[TFTP_DATA_LEN_MAX];
|
||
uint32_t temp_val = 0,crcNumIndex = 0;
|
||
|
||
IAPVarTypeStruct_Ptr.IapPercent++;
|
||
IAPVarTypeStruct_Ptr.processing_tick = SysTick_1ms;
|
||
|
||
if( (pkt_buf_len > TFTP_DATA_PKT_HDR_LEN) && (TFTP_Pack_Get_Block(pkt_buf) == (IAPVarTypeStruct_Ptr.Write_Block + 1) ) )
|
||
{
|
||
pkt_buf_len = pkt_buf_len - TFTP_DATA_PKT_HDR_LEN;
|
||
memset(data_buffer,0,TFTP_DATA_LEN_MAX);
|
||
|
||
for(uint32_t i = 0;i < pkt_buf_len;i++)
|
||
{
|
||
data_buffer[i] = pkt_buf[TFTP_DATA_PKT_HDR_LEN+i];
|
||
}
|
||
|
||
IAPVarTypeStruct_Ptr.TotalCount += pkt_buf_len;
|
||
Dbg_Println(DBG_BIT_NET_STATUS_bit,"IapFileType:%d",IAPVarTypeStruct_Ptr.IapFileType);
|
||
switch(IAPVarTypeStruct_Ptr.IapFileType)
|
||
{
|
||
case TFTP_IAP_DataType_APP:
|
||
if( IAPVarTypeStruct_Ptr.Write_Block == 0x00 )
|
||
{
|
||
temp_val = data_buffer[0] + (data_buffer[1]<<8) + (data_buffer[2]<<16) + (data_buffer[3]<<24);
|
||
Dbg_Println(DBG_BIT_NET_STATUS_bit,"temp_var : %08X ,block :%d",temp_val,IAPVarTypeStruct_Ptr.Write_Block);
|
||
if( (temp_val & 0x2FFE0000) != 0x20000000 )
|
||
{
|
||
Dbg_Println(DBG_BIT_NET_STATUS_bit,"内存分配的地址不是有效的");
|
||
|
||
Dbg_Print_Buff(DBG_BIT_NET_STATUS_bit,"pkt_buf:",pkt_buf,pkt_buf_len);
|
||
Dbg_Print_Buff(DBG_BIT_NET_STATUS_bit,"data:",data_buffer,pkt_buf_len-TFTP_DATA_PKT_HDR_LEN);
|
||
}
|
||
|
||
// switch(IAPVarTypeStruct_Ptr.IapType)
|
||
// {
|
||
// case IAPTFTPWRITE: //升级文件错误
|
||
// IAP_AckState(IAP_Error_File,(uint8_t *)ip,(uint16_t)port);
|
||
// break;
|
||
// case IAPTFTPREAD:
|
||
// CLOUD_IAP_AckState(CLOUD_IAP_Cmd, IAP_Error_File, (uint8_t *)ip, (uint16_t)port, DATATYPE_IAP);
|
||
// break;
|
||
// }
|
||
|
||
IAPVarTypeStruct_Ptr.IapErrFlag = 1; //升级错误标志置一
|
||
Dbg_Println(DBG_BIT_NET_STATUS_bit,"升级失败,地址错误 data_buffer[0] & 0x2FFE0000 = %X; data_buffer[1]=%X\n", (data_buffer[0] & 0x2FFE0000), data_buffer[1]);
|
||
|
||
}else if( IAPVarTypeStruct_Ptr.Write_Block > APP_BLOCK_MAX ){
|
||
|
||
// switch(IAPVarTypeStruct_Ptr->IapType)
|
||
// {
|
||
// case IAPTFTPWRITE: //回复升级块错误
|
||
// IAP_AckState(IAP_Error_Block, (uint8_t *)ip, (uint16_t)port);
|
||
// break;
|
||
// case IAPTFTPREAD:
|
||
// CLOUD_IAP_AckState(CLOUD_IAP_Cmd, IAP_Error_Block, (uint8_t *)ip, (uint16_t)port, DATATYPE_IAP);
|
||
// break;
|
||
// }
|
||
IAPVarTypeStruct_Ptr.IapErrFlag = 1; //升级错误标志置一
|
||
Dbg_Println(DBG_BIT_NET_STATUS_bit,"升级失败,超出最大块数\n");
|
||
}
|
||
break;
|
||
case TFTP_IAP_DataType_CONFIG:
|
||
if( IAPVarTypeStruct_Ptr.Write_Block >= CONFIG_BLOCK_MAX)
|
||
{
|
||
// switch(IAPVarTypeStruct_Ptr->IapType)
|
||
// {
|
||
// case IAPTFTPWRITE: //回复升级块错误
|
||
// LOGIC_Config_AckState(IAP_Error_Block, (uint8_t *)ip, (uint16_t)port);
|
||
// break;
|
||
// case IAPTFTPREAD:
|
||
// CLOUD_IAP_AckState(CLOUD_IAP_Cmd, IAP_Error_Block, (uint8_t *)ip, (uint16_t)port, DATATYPE_CONFIG);
|
||
// break;
|
||
// }
|
||
|
||
IAPVarTypeStruct_Ptr.IapErrFlag = 1;
|
||
Dbg_Println(DBG_BIT_NET_STATUS_bit,"升级配置失败,超出最大块数\n");
|
||
}
|
||
break;
|
||
default:
|
||
IAPVarTypeStruct_Ptr.IapErrFlag = 1;
|
||
Dbg_Println(DBG_BIT_NET_STATUS_bit,"升级文件类型不对");
|
||
break;
|
||
}
|
||
|
||
if(IAPVarTypeStruct_Ptr.IapErrFlag == 0x00)
|
||
{
|
||
IAPVarTypeStruct_Ptr.Write_Block++;
|
||
SRAM_DMA_Write_Buff(data_buffer,pkt_buf_len,IAPVarTypeStruct_Ptr.FlashWriteAddress); //写入SRAM缓冲区中
|
||
Dbg_Println(DBG_BIT_NET_STATUS_bit,"写入地址:%08X,写入数据: byte:%d", IAPVarTypeStruct_Ptr.FlashWriteAddress, pkt_buf_len);
|
||
|
||
/*对长度进行4Byte对齐 ,用于地址偏移使用 这需不需要字节对齐,好像不太需要*/
|
||
// pkt_buf_len = (pkt_buf_len + 3) / 4;
|
||
// pkt_buf_len = pkt_buf_len * 4;
|
||
IAPVarTypeStruct_Ptr.FlashWriteAddress += pkt_buf_len;
|
||
}
|
||
|
||
}else if( TFTP_Pack_Get_Block((char *)pkt_buf) == (IAPVarTypeStruct_Ptr.Write_Block + 1) )
|
||
{
|
||
IAPVarTypeStruct_Ptr.Write_Block++;
|
||
}
|
||
|
||
TFTP_send_ack_packet(s, ip_addr, Port, IAPVarTypeStruct_Ptr.Write_Block); //对每次传数据包的回复,传套接字 地址 端口和块号
|
||
|
||
if( IAPVarTypeStruct_Ptr.Write_Block == IAPVarTypeStruct_Ptr.BlockSize )
|
||
{
|
||
uint8_t md5[16] = {0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0};
|
||
uint16_t crc_data_len = 0;
|
||
|
||
switch(IAPVarTypeStruct_Ptr.IapFileType)
|
||
{
|
||
case TFTP_IAP_DataType_APP:
|
||
MD5Digest_SRAM(SRAM_IAP_APP_FILE_ADDRESS, IAPVarTypeStruct_Ptr.TotalCount,(char *)&md5[0]);
|
||
Dbg_Println(DBG_BIT_NET_STATUS_bit,"falsh写入总长度:%dByte", IAPVarTypeStruct_Ptr.TotalCount );
|
||
|
||
if( bytes_cmp(md5,IAPVarTypeStruct_Ptr.Md5,16) == 0x00 )
|
||
{
|
||
//文件MD5校验成功
|
||
Dbg_Println(DBG_BIT_NET_STATUS_bit,"升级成功,Md5正确");
|
||
//为啥本地与云端回复的数据内容需要不一样
|
||
// switch(IAPVarTypeStruct_Ptr->IapType)
|
||
// {
|
||
// case IAPTFTPWRITE: //本地网络升级状态为完成,保存参数
|
||
// Dbg_Println(DBG_BIT_NET_STATUS_bit,"记录局域网升级成功状态..");
|
||
// SRAM_Write_Byte(IAP_STATE_COMPLETE, SRAM_IAP_NET_UPGRADE_Flag_ADDRESS);
|
||
// LOG_LogicInfo_DebugRecord("记录局域网升级成功状态..");
|
||
// break;
|
||
// case IAPTFTPREAD: //云端网络升级
|
||
// Dbg_Println(DBG_BIT_NET_STATUS_bit,"记录云端升级成功状态..");
|
||
// LOG_LogicInfo_DebugRecord("记录云端升级成功状态..");
|
||
// SRAM_Write_Byte(CLOUD_IAP_TFTP_STATE_COMPLETE, SRAM_IAP_NET_UPGRADE_Flag_ADDRESS);
|
||
// break;
|
||
// }
|
||
Dbg_Println(DBG_BIT_NET_STATUS_bit,"将APP写入Flash中..");
|
||
|
||
//Cloud_IAP_Plan_SendPack(args,IAPVarTypeStruct_Ptr,IAPPlan_State_CheckSucc); //升级传输完成,校验中。。。
|
||
|
||
SPI_FLASH_APP_Data_Erase();
|
||
for(uint32_t i = 0;i < IAPVarTypeStruct_Ptr.BlockSize; i++ )
|
||
{
|
||
WDT_Feed();
|
||
SRAM_DMA_Read_Buff(data_buffer,512,SRAM_IAP_APP_FILE_ADDRESS+i*512);
|
||
Flash_Write(data_buffer,512,SPIFLASH_APP_Data_Start_Addr+i*512);
|
||
}
|
||
|
||
memset(data_buffer,0,TFTP_DATA_LEN_MAX);
|
||
|
||
/* 计算APP的CRC校验值 生成APP特征区数据*/
|
||
g_app_feature.app_flag = App_Procedure_Ready;
|
||
g_app_feature.app_crc_size = MCU_APP_Flash_PageSize;
|
||
g_app_feature.app_start_addr = MCU_APP_Flash_Start_Addr;
|
||
g_app_feature.app_end_addr = MCU_APP_Flash_Start_Addr + IAPVarTypeStruct_Ptr.TotalCount;
|
||
|
||
if( ( IAPVarTypeStruct_Ptr.TotalCount % g_app_feature.app_crc_size ) != 0x00 ){
|
||
g_app_feature.app_crc_len = ( (IAPVarTypeStruct_Ptr.TotalCount / g_app_feature.app_crc_size) + 1) * 2;
|
||
}else {
|
||
g_app_feature.app_crc_len = (IAPVarTypeStruct_Ptr.TotalCount / g_app_feature.app_crc_size) * 2;
|
||
}
|
||
|
||
Dbg_Println(DBG_BIT_NET_STATUS_bit,"App CRC BLock:%d ",g_app_feature.app_crc_len);
|
||
|
||
crcNumIndex = 0x00;
|
||
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(Temp_Flash_Buff,0,sizeof(Temp_Flash_Buff));
|
||
|
||
if(crc_data_len > 2048)
|
||
{
|
||
Flash_Read(Temp_Flash_Buff,2048,crc_addr);
|
||
Flash_Read(&Temp_Flash_Buff[2048],(crc_data_len - 2048),crc_addr+2048);
|
||
}else {
|
||
Flash_Read(Temp_Flash_Buff,crc_data_len,crc_addr);
|
||
}
|
||
|
||
temp_val = NetCRC16_2(Temp_Flash_Buff,crc_data_len);
|
||
|
||
g_app_feature.app_crc[crcNumIndex] = temp_val & 0xFF;
|
||
g_app_feature.app_crc[crcNumIndex + 1] = (temp_val >> 8) & 0xFF;
|
||
crcNumIndex += 2;
|
||
}
|
||
|
||
g_app_feature.crc_check = 0x00;
|
||
Write_APP_Feature_Info(0x02,&g_app_feature); //写入APP特征区
|
||
|
||
WDT_Feed(); //防止看门狗复位
|
||
|
||
Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"固件网络升级复位!");
|
||
//直接看门狗复位
|
||
|
||
}else{
|
||
//MD5校验失败
|
||
// switch(IAPVarTypeStruct_Ptr->IapType)
|
||
// {
|
||
// case IAPTFTPWRITE://IAP_AckState(IAP_Error_MD5, (uint8_t *)ip, (uint16_t)port); break; //回复Md5错误
|
||
// IAP_AckState(IAP_Error_MD5, (uint8_t *)ip_addr, (uint16_t)sever_port); //回复Md5错误
|
||
// break;
|
||
// case IAPTFTPREAD:
|
||
// CLOUD_IAP_AckState(CLOUD_IAP_Cmd, IAP_Error_MD5, (uint8_t *)ip, (uint16_t)port, DATATYPE_IAP);
|
||
// break;
|
||
// }
|
||
|
||
IAPVarTypeStruct_Ptr.IapErrFlag = 1;
|
||
Dbg_Println(DBG_BIT_NET_STATUS_bit,"升级失败,Md5错误:%02X,%02X,%02X,%02X,%02X,%02X,%02X,%02X,%02X,%02X%02X,%02X,%02X,%02X,%02X,%02X", \
|
||
md5[0],md5[1],md5[2],md5[3],md5[4],md5[5],md5[6],md5[7],md5[8],md5[9],md5[10],md5[11],md5[12],md5[13],md5[14],md5[15]);
|
||
Dbg_Println(DBG_BIT_NET_STATUS_bit,"UDP Md5:%02X,%02X,%02X,%02X,%02X,%02X,%02X,%02X,%02X,%02X,%02X,%02X,%02X,%02X,%02X,%02X", \
|
||
IAPVarTypeStruct_Ptr.Md5[0],IAPVarTypeStruct_Ptr.Md5[1], \
|
||
IAPVarTypeStruct_Ptr.Md5[2],IAPVarTypeStruct_Ptr.Md5[3], \
|
||
IAPVarTypeStruct_Ptr.Md5[4],IAPVarTypeStruct_Ptr.Md5[5], \
|
||
IAPVarTypeStruct_Ptr.Md5[6],IAPVarTypeStruct_Ptr.Md5[7], \
|
||
IAPVarTypeStruct_Ptr.Md5[8],IAPVarTypeStruct_Ptr.Md5[9], \
|
||
IAPVarTypeStruct_Ptr.Md5[10],IAPVarTypeStruct_Ptr.Md5[11],\
|
||
IAPVarTypeStruct_Ptr.Md5[12],IAPVarTypeStruct_Ptr.Md5[13],\
|
||
IAPVarTypeStruct_Ptr.Md5[14],IAPVarTypeStruct_Ptr.Md5[15]);
|
||
}
|
||
break;
|
||
case TFTP_IAP_DataType_CONFIG:
|
||
MD5Digest_SRAM(SRAM_IAP_LOGIC_DataStart_ADDRESS, IAPVarTypeStruct_Ptr.TotalCount, (char *)&md5[0]);
|
||
if( bytes_cmp(md5,IAPVarTypeStruct_Ptr.Md5,16) == 0x00 )
|
||
{
|
||
// switch(IAPVarTypeStruct_Ptr->IapType)
|
||
// {
|
||
// case IAPTFTPWRITE: //回复发送完成
|
||
// Dbg_Println(DBG_BIT_NET_STATUS_bit,"记录逻辑文件写入成功状态..");
|
||
// LOGIC_Config_AckState(IAP_Finish, (uint8_t *)ip, (uint16_t)sever_port);
|
||
// break;
|
||
// case IAPTFTPREAD:
|
||
// Dbg_Println(DBG_BIT_NET_STATUS_bit,"记录逻辑文件读取成功状态..");
|
||
// CLOUD_IAP_AckState(CLOUD_IAP_Cmd, IAP_Finish, (uint8_t *)ip, (uint16_t)sever_port, DATATYPE_CONFIG);
|
||
// break;
|
||
// }
|
||
|
||
//Cloud_IAP_Plan_SendPack(args,IAPVarTypeStruct_Ptr,IAPPlan_State_CheckSucc); //升级传输完成,校验中。。。
|
||
|
||
SPI_FLASH_Logic_File_Erase(); //擦除配置全部数据
|
||
|
||
for(uint32_t i = 0; i < IAPVarTypeStruct_Ptr.BlockSize; i++)
|
||
{
|
||
WDT_Feed();
|
||
temp_val = SRAM_IAP_LOGIC_DataStart_ADDRESS+i*512;
|
||
SRAM_DMA_Read_Buff(data_buffer,512,SRAM_IAP_LOGIC_DataStart_ADDRESS+i*512);
|
||
Flash_Write(data_buffer,512,SPIFLASH_LOGIC_DataStart_ADDRESS+i*512);
|
||
}
|
||
|
||
data_buffer[0] = 0x01;
|
||
data_buffer[1] = 0x00;
|
||
data_buffer[2] = 0x06;
|
||
data_buffer[3] = 0xCC;
|
||
|
||
data_buffer[4] = IAPVarTypeStruct_Ptr.TotalCount & 0xFF;
|
||
data_buffer[5] = (IAPVarTypeStruct_Ptr.TotalCount >> 8) & 0xFF;
|
||
data_buffer[6] = (IAPVarTypeStruct_Ptr.TotalCount >> 16) & 0xFF;
|
||
data_buffer[7] = (IAPVarTypeStruct_Ptr.TotalCount >> 24) & 0xFF;
|
||
|
||
memcpy(&data_buffer[8],IAPVarTypeStruct_Ptr.Md5,16);
|
||
Flash_Write(data_buffer,24,SPIFLASH_LOGIC_DataFlag_ADDRESS);
|
||
|
||
Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"配置网络升级完成");
|
||
LOG_LogicInfo_DebugRecord("配置网络升级复位");
|
||
}else{
|
||
// switch(IAPVarTypeStruct_Ptr->IapType)
|
||
// {
|
||
// case IAPTFTPWRITE: //回复发送完成
|
||
// LOGIC_Config_AckState(IAP_Error_MD5, (uint8_t *)ip_addr, (uint16_t)sever_port);
|
||
// break;
|
||
// case IAPTFTPREAD:
|
||
// CLOUD_IAP_AckState(CLOUD_IAP_Cmd, IAP_Error_MD5, (uint8_t *)ip, (uint16_t)sever_port, DATATYPE_CONFIG);
|
||
// break;
|
||
// }
|
||
|
||
IAPVarTypeStruct_Ptr.IapErrFlag = 1;
|
||
Dbg_Println(DBG_BIT_NET_STATUS_bit,"升级配置失败,Md5错误:%02X,%02X,%02X,%02X,%02X,%02X,%02X,%02X,%02X,%02X%02X,%02X,%02X,%02X,%02X,%02X",\
|
||
md5[0],md5[1],md5[2],md5[3],md5[4],md5[5],md5[6],md5[7],md5[8],md5[9],md5[10],md5[11],md5[12],md5[13],md5[14],md5[15]);
|
||
Dbg_Println(DBG_BIT_NET_STATUS_bit,"UDP Md5:%02X,%02X,%02X,%02X,%02X,%02X,%02X,%02X,%02X,%02X,%02X,%02X,%02X,%02X,%02X,%02X",\
|
||
IAPVarTypeStruct_Ptr.Md5[0],IAPVarTypeStruct_Ptr.Md5[1],\
|
||
IAPVarTypeStruct_Ptr.Md5[2],IAPVarTypeStruct_Ptr.Md5[3],\
|
||
IAPVarTypeStruct_Ptr.Md5[4],IAPVarTypeStruct_Ptr.Md5[5],\
|
||
IAPVarTypeStruct_Ptr.Md5[6],IAPVarTypeStruct_Ptr.Md5[7],\
|
||
IAPVarTypeStruct_Ptr.Md5[8],IAPVarTypeStruct_Ptr.Md5[9],\
|
||
IAPVarTypeStruct_Ptr.Md5[10],IAPVarTypeStruct_Ptr.Md5[11],\
|
||
IAPVarTypeStruct_Ptr.Md5[12],IAPVarTypeStruct_Ptr.Md5[13],\
|
||
IAPVarTypeStruct_Ptr.Md5[14],IAPVarTypeStruct_Ptr.Md5[15]);
|
||
}
|
||
break;
|
||
default:
|
||
IAPVarTypeStruct_Ptr.IapErrFlag = 1;
|
||
Dbg_Println(DBG_BIT_NET_STATUS_bit,"升级文件类型不对");
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
/*******************************************************************************
|
||
* Function Name : UDPSocket_TFTP_CMD_AppCallBack
|
||
* Description : TFTP命令套接字 - 数据处理回调函数
|
||
*******************************************************************************/
|
||
__attribute__((section(".non_0_wait"))) void UDPSocket_TFTP_CMD_AppCallBack(struct _SOCK_INF * SocketInf,uint32_t ipaddr,uint16_t port,uint8_t *buff,uint32_t len)
|
||
{
|
||
uint8_t ip_addr[4];
|
||
ip_addr[0] = ipaddr & 0xFF;
|
||
ip_addr[1] = (ipaddr >> 8) & 0xFF ;
|
||
ip_addr[2] = (ipaddr >> 16) & 0xFF ;
|
||
ip_addr[3] = (ipaddr >> 24) & 0xFF ;
|
||
|
||
Dbg_Println(DBG_BIT_NET_STATUS_bit,"%s len:%ld",__func__,len);
|
||
Dbg_Println(DBG_BIT_NET_STATUS_bit,"ip:%d.%d.%d.%d, port:%d",ip_addr[0], ip_addr[1], ip_addr[2], ip_addr[3], port);
|
||
|
||
/*TFTP 命令处理*/
|
||
if( TFTP_Pack_Get_Opcode(buff) == TFTP_WRQ )
|
||
{
|
||
if(IAPVarTypeStruct_Ptr.FunType == TFTP_FUNTYPE_LocalIAP)
|
||
{
|
||
/*如果当前处于TFTP升级状态下,接收到写请求*/
|
||
|
||
Dbg_Print_Buff(DBG_BIT_NET_STATUS_bit, "TFTP写文件指令:", buff, len);
|
||
|
||
IAP_tftp_process_write(g_netinfo.SocketId[SocketIdnex_TFTPCMD], ip_addr, port); //回复升级 写文件指令
|
||
}else{
|
||
|
||
}
|
||
|
||
}else if( TFTP_Pack_Get_Opcode(buff) == TFTP_OPTION )
|
||
{
|
||
/*TFTP处于上传日志任务中,才会接收到该命令*/
|
||
|
||
|
||
}else {
|
||
/*其他命令 - 暂不处理*/
|
||
|
||
}
|
||
}
|
||
|
||
/*******************************************************************************
|
||
* Function Name : UDPSocket_TFTP_DATA_AppCallBack
|
||
* Description : TFTP数据套接字 - 数据处理回调函数
|
||
*******************************************************************************/
|
||
__attribute__((section(".non_0_wait"))) void UDPSocket_TFTP_DATA_AppCallBack(struct _SOCK_INF * SocketInf,uint32_t ipaddr,uint16_t port,uint8_t *buff,uint32_t len)
|
||
{
|
||
uint8_t ip_addr[4];
|
||
ip_addr[0] = ipaddr & 0xFF;
|
||
ip_addr[1] = (ipaddr >> 8) & 0xFF ;
|
||
ip_addr[2] = (ipaddr >> 16) & 0xFF ;
|
||
ip_addr[3] = (ipaddr >> 24) & 0xFF ;
|
||
|
||
Dbg_Println(DBG_BIT_NET_STATUS_bit,"%s len:%ld",__func__,len);
|
||
Dbg_Println(DBG_BIT_NET_STATUS_bit,"ip:%d.%d.%d.%d, port:%d",ip_addr[0], ip_addr[1], ip_addr[2], ip_addr[3], port);
|
||
|
||
if( TFTP_Pack_Get_Opcode(buff) == TFTP_DATA ) //TFTP IAP文件数据
|
||
{
|
||
TFTP_IAP_Data_Processing(g_netinfo.SocketId[SocketIdnex_TFTPDATA],buff, len, ip_addr, port);
|
||
}
|
||
// else if( TFTP_Get_Decode_op(buff) == TFTP_ACK ) //TFTP的ACK,此处是写日志的场景才会出现
|
||
// {
|
||
// //TFTP不在此处处理,请特别注意,TFTP的回调函数是另外一个
|
||
// Dbg_Println(DBG_BIT_NET_STATUS_bit,"TFTP的ACK,此处是写日志");
|
||
// }
|
||
}
|
||
|
||
/*******************************************************************************
|
||
* Function Name : Internal_TFTP_Task
|
||
* Description : TFTP任务函数
|
||
* --主要功能有:1、IAP升级 - 局域网升级;2、IAP升级 - 云端升级;2、日志文件上传
|
||
*******************************************************************************/
|
||
__attribute__((section(".non_0_wait"))) void Internal_TFTP_Task(void)
|
||
{
|
||
//static uint8_t tftp_ack_num = 0;
|
||
|
||
if(IAPVarTypeStruct_Ptr.enable == 0x01)
|
||
{
|
||
if( (IAPVarTypeStruct_Ptr.FunType == TFTP_FUNTYPE_LocalIAP) || (IAPVarTypeStruct_Ptr.FunType == TFTP_FUNTYPE_CloudIAP) )
|
||
{
|
||
if((WCHNET_Get_PHY_Linked_Status() == 0x01) || (server_info.init_flag == 0x00)) {
|
||
//网络连接断开,直接退出 - 同时退出当前网络升级状态
|
||
|
||
return;
|
||
}
|
||
|
||
switch( IAPVarTypeStruct_Ptr.status )
|
||
{
|
||
case STA_INIT:
|
||
|
||
Dbg_Println(DBG_BIT_NET_STATUS_bit,"开始创建TFTP服务套接字...");
|
||
WCHNET_CreateUdpSocket(&g_netinfo.SocketId[SocketIdnex_TFTPCMD], TFTP_Destination_Port, UDPSocket_TFTP_CMD_AppCallBack); //创建套接字,TFTP服务
|
||
Dbg_Println(DBG_BIT_NET_STATUS_bit,"开始创建TFTP文件传输套接字...");
|
||
WCHNET_CreateUdpSocket(&g_netinfo.SocketId[SocketIdnex_TFTPDATA], TFTP_LOG_Local_Port, UDPSocket_TFTP_DATA_AppCallBack); //创建套接字,TFTP文件传输
|
||
|
||
IAPVarTypeStruct_Ptr.status = STA_INIT_WAIT;
|
||
IAPVarTypeStruct_Ptr.processing_tick = SysTick_1ms;
|
||
break;
|
||
case STA_INIT_WAIT:
|
||
if( SysTick_1ms - IAPVarTypeStruct_Ptr.processing_tick > 50 )
|
||
{
|
||
IAPVarTypeStruct_Ptr.processing_tick = SysTick_1ms;
|
||
IAPVarTypeStruct_Ptr.status = STA_INIT_IDLE;
|
||
}
|
||
break;
|
||
case STA_INIT_IDLE:
|
||
//向云端发送读取文件请求
|
||
|
||
if( SysTick_1ms - IAPVarTypeStruct_Ptr.processing_tick > TFTP_IAP_Timeout) //升级超时,释放套接字
|
||
{
|
||
//Cloud_IAP_Plan_SendPack(tftp_args,IAPVarTypeStruct_Ptr,IAPPlan_State_IAPTimeout); //发送IAP升级结果 - 升级超时
|
||
|
||
Dbg_Println(DBG_BIT_NET_STATUS_bit,"TFTP 升级超时");
|
||
IAPVarTypeStruct_Ptr.status = STA_END;
|
||
}
|
||
|
||
if(IAPVarTypeStruct_Ptr.IapErrFlag == 0x01)
|
||
{
|
||
Dbg_Println(DBG_BIT_NET_STATUS_bit,"TFTP 升级错误");
|
||
IAPVarTypeStruct_Ptr.status = STA_END;
|
||
}
|
||
break;
|
||
case STA_END: //任务结束 - 释放套接字
|
||
WCHNET_SocketClose(g_netinfo.SocketId[SocketIdnex_TFTPCMD], TCP_CLOSE_NORMAL); //释放套接字
|
||
WCHNET_SocketClose(g_netinfo.SocketId[SocketIdnex_TFTPDATA], TCP_CLOSE_NORMAL); //释放套接字
|
||
IAPVarTypeStruct_Ptr.status = STA_INIT; //将升级服务状态置为需要初始化
|
||
|
||
IAPVarTypeStruct_Ptr.IapErrFlag = 0;
|
||
IAPVarTypeStruct_Ptr.enable = 0x00;
|
||
break;
|
||
default:
|
||
IAPVarTypeStruct_Ptr.status = STA_END; //释放套接字
|
||
break;
|
||
}
|
||
|
||
}else if(IAPVarTypeStruct_Ptr.FunType == TFTP_FUNTYPE_LogUpload)
|
||
{
|
||
if((WCHNET_Get_PHY_Linked_Status() == 0x01) || (server_info.init_flag == 0x00)) {
|
||
//网络连接断开,直接退出 - 同时退出当前TFTP 上传日志
|
||
|
||
return;
|
||
}
|
||
|
||
/*- TFTP 日志上传方式需要修改一下,
|
||
*- 由于主动上传日志,服务器压力过大,
|
||
*- 因此需修改为有需要的时候,通过服务器下发命令进行数据读取*/
|
||
switch(IAPVarTypeStruct_Ptr.status)
|
||
{
|
||
case STA_INIT:
|
||
/*TFTP文件主动传输 - 一个套接字搞定*/
|
||
Dbg_Println(DBG_BIT_NET_STATUS_bit,"开始创建TFTP服务套接字...");
|
||
//WCHNET_CreateUdpSocket(&g_netinfo.SocketId[SocketIdnex_TFTPCMD], TFTP_LOG_Local_Port, TFTP_LOG_CallBack); //创建套接字,TFTP服务
|
||
|
||
//tftp_ack_num = 0x00;
|
||
IAPVarTypeStruct_Ptr.status = STA_INIT_WAIT;
|
||
IAPVarTypeStruct_Ptr.processing_tick = SysTick_1ms;
|
||
break;
|
||
case STA_INIT_WAIT:
|
||
if( SysTick_1ms - IAPVarTypeStruct_Ptr.processing_tick > 50 )
|
||
{
|
||
IAPVarTypeStruct_Ptr.processing_tick = SysTick_1ms;
|
||
|
||
IAPVarTypeStruct_Ptr.status = STA_INIT_CONNECT;
|
||
}
|
||
break;
|
||
case STA_INIT_CONNECT: //
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|