Files
RCU_C1P_Module/NetLib/tftp_function.c
caocong cc8783e9f8 feat:新增TFTP IAP升级功能
修改事项:
1、新增TFTP IAP升级功能,只是代码移植完毕,没有测试使用
2、代码空间编译优化,零等待区域空间已满,而应用层代码已全部挪移到非零等待区域中,但还是会增加零等待区的空间占用。 待优化
2025-12-10 14:06:45 +08:00

637 lines
28 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.
/*
* 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;
}
}
}
}