/* * 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; } } } }