diff --git a/.project b/.project index 840cda7..5dbf2d0 100644 --- a/.project +++ b/.project @@ -1,6 +1,6 @@ - BLV_C1P_20251107 + RCU_C1P_Module diff --git a/.settings/language.settings.xml b/.settings/language.settings.xml index 1a4b8e6..5446086 100644 --- a/.settings/language.settings.xml +++ b/.settings/language.settings.xml @@ -5,7 +5,7 @@ - + diff --git a/BLV_485_Driver/blv_bus_dev_c5iofun.c b/BLV_485_Driver/blv_bus_dev_c5iofun.c index ebfbb3c..71a5773 100644 --- a/BLV_485_Driver/blv_bus_dev_c5iofun.c +++ b/BLV_485_Driver/blv_bus_dev_c5iofun.c @@ -341,7 +341,7 @@ __attribute__((section(".non_0_wait"))) uint8_t BLV_BUS_C5IO_Cycle_Call(uint32_t } /*判定CSIO 时间处于有效期*/ -uint8_t BLV_CSIO_RTC_TimeValid(uint8_t *date) +__attribute__((section(".non_0_wait"))) uint8_t BLV_CSIO_RTC_TimeValid(uint8_t *date) { /*判断年限:2024~2050年*/ if( (RTC_TimeDate_Correct_Figure(date[0]) == 0x00) && ((date[0] >= 0x24) && (date[0] <= 0x50)) ){ diff --git a/BLV_485_Driver/pc_devicetest_fun.c b/BLV_485_Driver/pc_devicetest_fun.c index 8d47c07..ad6a5a9 100644 --- a/BLV_485_Driver/pc_devicetest_fun.c +++ b/BLV_485_Driver/pc_devicetest_fun.c @@ -1144,14 +1144,14 @@ __attribute__((section(".non_0_wait"))) uint8_t BLV_PC_SET_MCU_Revision_Data_Rep { write_addr = data_addr+PKT2_PARA+1; SRAM_DMA_Read_Buff(send_buff,64,write_addr); - Flash_Write(send_buff,64,FLASH_MCU_Model_Revision_ADDRESS); + Flash_Write(send_buff,64,SPIFLASH_MCU_Model_Revision_ADDRESS); } if((temp_data & 0x02) != 0x00) { write_addr = data_addr+PKT2_PARA+65; SRAM_DMA_Read_Buff(send_buff,64,write_addr); - Flash_Write(send_buff,64,FLASH_MCU_Control_Revision_ADDRESS); + Flash_Write(send_buff,64,SPIFLASH_MCU_Control_Revision_ADDRESS); } temp_data = 0x01; @@ -1208,9 +1208,9 @@ __attribute__((section(".non_0_wait"))) uint8_t BLV_PC_READ_MCU_Revision_Data_Re /*数据处理*/ - Flash_Read(&send_buff[PKT2_PARA],64,FLASH_MCU_Model_Revision_ADDRESS); + Flash_Read(&send_buff[PKT2_PARA],64,SPIFLASH_MCU_Model_Revision_ADDRESS); - Flash_Read(&send_buff[PKT2_PARA+64],64,FLASH_MCU_Control_Revision_ADDRESS); + Flash_Read(&send_buff[PKT2_PARA+64],64,SPIFLASH_MCU_Control_Revision_ADDRESS); /*数据处理回复*/ Dbg_Println(DBG_OPT_DEVICE_STATUS,"%s",__func__); diff --git a/Ld/Link.ld b/Ld/Link.ld index c2c835c..23d2f97 100644 --- a/Ld/Link.ld +++ b/Ld/Link.ld @@ -90,6 +90,7 @@ SECTIONS PROVIDE( __cache_end = .); *(.non_0_wait); *(.non_0_wait.*); + . = ALIGN(4); } >FLASH1 AT>FLASH1 diff --git a/MCU_Driver/blv_netcomm_function.c b/MCU_Driver/blv_netcomm_function.c index 5530695..a44d4f7 100644 --- a/MCU_Driver/blv_netcomm_function.c +++ b/MCU_Driver/blv_netcomm_function.c @@ -605,8 +605,8 @@ __attribute__((section(".non_0_wait"))) uint8_t Udp_Internal_Read_MCU_System_Sen SRAM_DMA_Read_Buff(&Global_Large_Buff[BLV_UDP_HEAD_LEN+121],4,SRAM_Register_Start_ADDRESS + Register_MandateUTC_OFFSET); SRAM_DMA_Read_Buff(&Global_Large_Buff[BLV_UDP_HEAD_LEN+125],4,SRAM_Register_Start_ADDRESS + Register_MandateExpiresTime_OFFSET); SRAM_DMA_Read_Buff(&Global_Large_Buff[BLV_UDP_HEAD_LEN+129],128,SRAM_Register_Start_ADDRESS + Register_RoomNumNote_OFFSET); - Flash_Read(&Global_Large_Buff[BLV_UDP_HEAD_LEN+257],64,FLASH_MCU_Model_Revision_ADDRESS); - Flash_Read(&Global_Large_Buff[BLV_UDP_HEAD_LEN+321],64,FLASH_MCU_Control_Revision_ADDRESS); + Flash_Read(&Global_Large_Buff[BLV_UDP_HEAD_LEN+257],64,SPIFLASH_MCU_Model_Revision_ADDRESS); + Flash_Read(&Global_Large_Buff[BLV_UDP_HEAD_LEN+321],64,SPIFLASH_MCU_Control_Revision_ADDRESS); //temp_rev = Read_LogicFile_Information(0x04,(uint8_t *)&temp_data); //查询LOGIC文件中的酒店别名 - 32Byte if(temp_rev == 0x00) @@ -1162,7 +1162,6 @@ __attribute__((section(".non_0_wait"))) uint8_t Udp_Internal_SeriaNet_Uploading( NetCRC16(&Global_Large_Buff[0],data_len); WCHNET_SocketUdpSendTo(g_netinfo.SocketId[SocketIdnex_BLVSeriver], &Global_Large_Buff[0], &data_len, pc_ip, pc_port); - return 0x00; } @@ -1189,11 +1188,10 @@ __attribute__((section(".non_0_wait"))) uint8_t Udp_Internal_SeriaNet_Uploading2 if((server_info.frame_no < 0xfffe) && (server_info.frame_no >= 0x8000)) { server_info.frame_no++; - } - else - { + }else{ server_info.frame_no = 0x8000; } + /*读取PC IP地址*/ SRAM_DMA_Read_Buff(pc_ip,4,SRAM_IAP_IP_ADDRESS); pc_port = SRAM_Read_Word(SRAM_IAP_PORT_ADDRESS); @@ -1276,7 +1274,7 @@ __attribute__((section(".non_0_wait"))) void BLV_UDP_Comm_Task(void) { udp_state_tick = SysTick_1ms; - if(server_info.init_flag == 0x00) return ; //DNS解析域名失败直接退出 + if( (WCHNET_Get_PHY_Linked_Status() == 0x01) || (server_info.init_flag == 0x00) ) return ; //DNS解析域名失败直接退出 /*并且不再TFTP任务中*/ // if(IAPVarTypeStruct_Ptr != NULL) diff --git a/MCU_Driver/inc/blv_netcomm_function.h b/MCU_Driver/inc/blv_netcomm_function.h index 2355938..cffee1d 100644 --- a/MCU_Driver/inc/blv_netcomm_function.h +++ b/MCU_Driver/inc/blv_netcomm_function.h @@ -90,4 +90,6 @@ uint8_t Udp_Internal_SeriaNet_Uploading(uint8_t port,uint32_t baud,uint32_t data uint8_t Udp_Internal_SeriaNet_Uploading2(uint8_t port,uint32_t baud,uint8_t* data, uint16_t DataLen); uint8_t Udp_Internal_SeriaNet_Response_Timeout(void); +void BLV_UDP_Comm_Task(void); + #endif /* MCU_DRIVER_INC_BLV_NETCOMM_FUNCTION_H_ */ diff --git a/MCU_Driver/inc/flash_mem_addr.h b/MCU_Driver/inc/flash_mem_addr.h index 78ffae6..691b9f7 100644 --- a/MCU_Driver/inc/flash_mem_addr.h +++ b/MCU_Driver/inc/flash_mem_addr.h @@ -10,6 +10,10 @@ /*APP数据及特征区保存区域 - 开始*/ #define APPFlag_UartUpgrade_Reset 0xBBC1 //APP串口升级标志位 +#define APP_BLOCK_MAX 460 //APP块最大为460,一块 -> 512Byte +#define CONFIG_BLOCK_MAX 850 //配置文件最大块为850,一块 -> 512Byte +#define App_CRC_Size 2048 //App CRC 校验数据大小 + #define SPIFLASH_APP_Start_Addr 0x00000000 @@ -22,14 +26,16 @@ #define SPIFLASH_APP_Data_End_Addr 0x0006FFFF #define SPIFLASH_APP_End_Addr 0x0006FFFF + + /*APP数据及特征区保存区域 - 结束*/ -#define FLASH_Register_Start_ADDRESS 0x00088000 //项目保存寄存器值 - 起始地址 -#define FLASH_Register_End_ADDRESS 0x000887FF //项目保存寄存器值 - 结束地址 +#define SPIFLASH_Register_Start_ADDRESS 0x00088000 //项目保存寄存器值 - 起始地址 +#define SPIFLASH_Register_End_ADDRESS 0x000887FF //项目保存寄存器值 - 结束地址 -#define FLASH_MCU_Model_Revision_ADDRESS 0x0008A000 //MCU版本型号 64Byte -#define FLASH_MCU_Control_Revision_ADDRESS 0x0008A040 //MCU中控版本型号 64Byte +#define SPIFLASH_MCU_Model_Revision_ADDRESS 0x0008A000 //MCU版本型号 64Byte +#define SPIFLASH_MCU_Control_Revision_ADDRESS 0x0008A040 //MCU中控版本型号 64Byte /*配置文件及参数保存区域*/ diff --git a/MCU_Driver/inc/mcu_flash.h b/MCU_Driver/inc/mcu_flash.h new file mode 100644 index 0000000..47c3ee1 --- /dev/null +++ b/MCU_Driver/inc/mcu_flash.h @@ -0,0 +1,121 @@ +/* + * mcu_flash.h + * + * Created on: Dec 8, 2025 + * Author: cc + */ + +#ifndef MCU_DRIVER_INC_MCU_FLASH_H_ +#define MCU_DRIVER_INC_MCU_FLASH_H_ + +#include "ch564.h" +#include + + +#define MCU_APP_Flash_PageSize 0x00001000 //MCU Flash页为4096Byte +#define APP_Flash_WriteNum 0x05 //APP写入次数 + +#define App_Procedure_Ready 0x66 //APP准备就绪标志位 +#define App_Procedure_Not_Ready 0x44 //App未准备就绪标志位 + +//MCU Flash Address range(0x0 -- 0x6FFFF) Size(448K) +#define MCU_APP_Flash_Start_Addr 0x00007000 //MCU Flash中APP的起始地址 +#define MCU_APP_Data_Start_Addr 0x00007000 //MCU Flash APP数据起始地址 +#define MCU_APP_Data_End_Addr 0x00027DFF //MCU Flash APP数据结束地址 +#define MCU_APP_Feature_Addr 0x00027E00 //MCU Flash 特征区数据保存地址 +#define MCU_APP_Flash_End_Addr 0x00027FFF //MCU Flash中APP的结束地址 + +#define MCU_APP_Feature_PageAddr 0x00027000 //MCU APP特征区 所在页的地址 +#define MCU_APP_Feature_PageOffset 0x00000E00 //MCU APP特征区所在页的偏移量 +#define APP_FEATURE_SIZE 0x0200 //512Byte + +//EEPROM Address range(0x70000 -- 0x77FFF) Size(32K) +#define MCU_EEPROM_Start_Addr 0x00070000 +#define MCU_EEPROM_MCUDevInfo_Address 0x00070000 //MCU 设备信息地址固定为0x00070000,大小为4096 此区域不可改动 +#define MCU_EEPROM_End_Addr 0x00078000 + + + +/* EEPROM 保存数据格式: + * FLAG - 1Byte 保存标志位 + * LEN - 2Byte 保存数据长度 + * CHECK - 1Byte 保存数据校验 + * DATA - nByte 保存数据内容 + * + * */ +#define EEPROM_SVAE_FLAG 0xAE +#define EEPROM_DATA_Size_Max 0x40 //目前保存数据内容最长为100Byte +#define EEPROM_PARA_Size 50 +#define EEPROM_DEV_NAME_Size 32 + +#define EEPROM_Offset_SaveFlag 0x00 +#define EEPROM_Offset_Datalen 0x01 +#define EEPROM_Offset_Check 0x03 +#define EEPROM_Offset_Data 0x04 + + +/* 特征区数据结构体 + * 注意:由于risc-v环境,没有字节对齐操作 + * 所以保存至Flash/MCU Flash中的顺序与结构体定义顺序不一致,使用时需注意 + * */ +typedef enum{ + Feature_Check = 0x00, //特征区 512Byte 的CRC校验 - 2Byte + Feature_AppFlag = 0x02, //特征区 - APP标志位 - 1Byte + Feature_AppStart = 0x03, //特征区 - APP起始地址 - 4Byte + Feature_AppEnd = 0x07, //特征区 - APP结束地址 - 4Byte + Feature_AppCrcSize = 0x0B, //特征区 - APP CRC的长度 - 2Byte + Feature_AppCrcLen = 0x0D, //特征区 - APP CRC校验的数据大小 - 2Byte + Feature_AppFlashCrc = 0x0F, //特征区 - APP CRC +}FEATURE_E; + +#define APP_Feature_CRC_Size 497 + +typedef struct{ + uint8_t app_flag; //APP 标志位 + uint8_t app_crc[APP_Feature_CRC_Size]; //APP CRC校验值 + + uint16_t app_crc_size; //APP CRC校验的数据大小 + uint16_t app_crc_len; //APP CRC校验的数据长度 + uint16_t crc_check; //特征区数据CRC值 - 用于校验特征区数据是否合法 + + uint32_t app_start_addr; //APP起始地址 + uint32_t app_end_addr; //APP结束地址 +}G_SYS_FEATURE_T; + +/*该信息存放于MCU EEPROM区域中*/ +typedef struct{ + + uint8_t dev_addr; //设备地址 + uint8_t dev_type; //设备类型 + uint8_t dev_boot_ver; //设备Boot的软件版本号 + uint8_t dev_app_ver; //设备APP的软件版本号 + uint8_t dev_name_len; //设备名称的长度 + uint8_t dev_name[EEPROM_DEV_NAME_Size]; //设备名称 + +}E_MCU_DEV_INFO; + +extern E_MCU_DEV_INFO g_mcu_dev; +extern G_SYS_FEATURE_T g_app_feature; +extern uint8_t g_flash_buff[570]; + +void EEPROM_Init(void); +uint8_t MCU_APP_Flash_Write(uint8_t* pBuffer,uint16_t NumByteToWrite,uint32_t writeAddr); +uint8_t MCU_APP_Flash_Read(uint8_t* pBuffer,uint16_t NumByteToWrite,uint32_t readAddr); +uint8_t MCU_APP_Flash_Erase(uint32_t readAddr,uint16_t NumByteToWrite); +uint8_t MCU_APP_Flash_ALLErase(void); +uint8_t MCU_EEPROM_Write(uint8_t* pBuffer,uint16_t NumByteToWrite,uint32_t writeAddr); +uint8_t MCU_EEPROM_Read(uint8_t* pBuffer,uint16_t NumByteToWrite,uint32_t readAddr); +uint8_t MCU_EEPROM_Erase(uint32_t readAddr,uint16_t NumByteToWrite); +uint8_t MCU_EEPROM_ALLErase(void); + +uint8_t EEPROM_CheckSum(uint8_t *data,uint16_t len); +uint8_t EEPROM_ReadMCUDevInfo(E_MCU_DEV_INFO *info); +uint8_t EEPROM_WriteMCUDevInfo(E_MCU_DEV_INFO *info); +void EEPROM_Default_MCUDevInfo(E_MCU_DEV_INFO *info); +void EEPROM_Validate_MCUDevInfo(E_MCU_DEV_INFO *info); + +uint8_t Read_APP_Feature_Info(uint8_t option,G_SYS_FEATURE_T *feature_info); +uint8_t Write_APP_Feature_Info(uint8_t option,G_SYS_FEATURE_T *feature_info); +void APP_Feature_Info_Printf(G_SYS_FEATURE_T *feature_info); + +#endif /* MCU_DRIVER_INC_MCU_FLASH_H_ */ diff --git a/MCU_Driver/inc/spi_flash.h b/MCU_Driver/inc/spi_flash.h index 1c59336..a41ab03 100644 --- a/MCU_Driver/inc/spi_flash.h +++ b/MCU_Driver/inc/spi_flash.h @@ -61,5 +61,7 @@ void Flash_Write_Page(uint8_t* pBuffer,uint16_t NumByteToWrite,uint32_t writeAdd void Flash_Write_NoCheck(uint8_t* pBuffer,uint16_t NumByteToWrite,uint32_t writeAddr); void Flash_Write(uint8_t* pBuffer,uint16_t NumByteToWrite,uint32_t WriteAddr); +void SPI_FLASH_APP_Data_Erase(void); +void SPI_FLASH_Logic_File_Erase(void); #endif /* MCU_DRIVER_INC_SPI_FLASH_H_ */ diff --git a/MCU_Driver/logic_file_function.c b/MCU_Driver/logic_file_function.c index 891b001..54c2e2b 100644 --- a/MCU_Driver/logic_file_function.c +++ b/MCU_Driver/logic_file_function.c @@ -361,7 +361,7 @@ __attribute__((section(".non_0_wait"))) void Expand_Scene_Get(void) * Description : 设备动作数据初始化 * 为不带延时的的扩展设备进行延时节点赋值,为带延时的场景,进行地址赋值。 为控制场景的设备进行地址得到 *******************************************************************************/ -void Expand_DevDly_Get(void) +__attribute__((section(".non_0_wait"))) void Expand_DevDly_Get(void) { uint8_t KeepFlag = 0x00; uint16_t i = 0,j = 0; diff --git a/MCU_Driver/mcu_flash.c b/MCU_Driver/mcu_flash.c new file mode 100644 index 0000000..294b50b --- /dev/null +++ b/MCU_Driver/mcu_flash.c @@ -0,0 +1,632 @@ +/* + * mcu_flash.c + * + * Created on: Dec 8, 2025 + * Author: cc + */ + +#include "includes.h" +#include + +E_MCU_DEV_INFO g_mcu_dev; +G_SYS_FEATURE_T g_app_feature; //APP特征区 + +uint8_t g_flash_buff[570] = {0}; + +/******************************************************************************* +* Function Name : EEPROM_Init +* Description : EEPROM 初始化函数 +*******************************************************************************/ +__attribute__((section(".non_0_wait"))) void EEPROM_Init(void) +{ + uint8_t rev = 0; + + rev = EEPROM_ReadMCUDevInfo(&g_mcu_dev); + if(rev == 0x00){ + //读取成功,开始校验以下参数 + EEPROM_Validate_MCUDevInfo(&g_mcu_dev); + }else{ + //读取失败,恢复默认参数 + Dbg_Println(DBG_BIT_SYS_STATUS_bit,"EE Use Defalut Para"); + EEPROM_Default_MCUDevInfo(&g_mcu_dev); + + Dbg_Println(DBG_BIT_SYS_STATUS_bit,"EE DevBootVer:%d",g_mcu_dev.dev_boot_ver); + Dbg_Println(DBG_BIT_SYS_STATUS_bit,"EE DevNameLen:%d",g_mcu_dev.dev_name_len); + Dbg_Println(DBG_BIT_SYS_STATUS_bit,"EE DevName:%s",g_mcu_dev.dev_name); + } +} + +/******************************************************************************* +* Function Name : MCU_Flash_Write +* Description : MCU Flash数据写入函数 +* Input : + pBuffer:写入数据 + NumByteToWrite:写入数据长度 -- 写入长度必须为4的倍速 + writeAddr:写入地址 0x00004000 ~ 0x0006FFFF 432KB +*******************************************************************************/ +__attribute__((section(".non_0_wait"))) uint8_t MCU_APP_Flash_Write(uint8_t* pBuffer,uint16_t NumByteToWrite,uint32_t writeAddr) +{ + FLASH_Status sta; + + /* 校验写入地址和长度是否符合条件 - 写入地址及长度是否在APP Flash范围内以及写入长度是否满足4Byte对齐*/ + if( ( writeAddr < MCU_APP_Flash_Start_Addr ) || ( ( writeAddr + NumByteToWrite ) > MCU_EEPROM_Start_Addr ) || ((NumByteToWrite % 4) != 0x00) ) { + Dbg_Println(DBG_BIT_SYS_STATUS_bit,"MCU APP Flash Addr Error:%x - %x\r\n", writeAddr, NumByteToWrite); + return 0x01; + } + + FLASH_Unlock(); + sta = FLASH_ROMA_WRITE(writeAddr, pBuffer, NumByteToWrite); + FLASH_Lock(); + if (sta != FLASH_COMPLETE){ + Dbg_Println(DBG_BIT_SYS_STATUS_bit,"Operation FLASH_ROMA_WRITE failed %#x!! Err Code %x\r\n", writeAddr, sta); + return 0x01; + } + + sta = FLASH_ROMA_VERIFY(writeAddr, pBuffer, NumByteToWrite); + if (sta != FLASH_COMPLETE){ + Dbg_Println(DBG_BIT_SYS_STATUS_bit,"Operation FLASH_ROMA_VERIFY failed %#x!! Err Code %x\r\n", writeAddr, sta); + return 0x01; + } + + return 0x00; +} + +/******************************************************************************* +* Function Name : MCU_Flash_Read +* Description : MCU Flash数据读取函数 +* Input : + pBuffer:写入数据 + NumByteToWrite:写入数据长度 -- 写入长度必须为4的倍速 + readAddr:读取地址 0x00004000 ~ 0x0006FFFF 432KB +*******************************************************************************/ +__attribute__((section(".non_0_wait"))) uint8_t MCU_APP_Flash_Read(uint8_t* pBuffer,uint16_t NumByteToWrite,uint32_t readAddr) +{ + FLASH_Status sta; + + /* 校验读取地址和长度是否符合条件 - 读取地址及长度是否在APP Flash范围内*/ + if( ( readAddr < MCU_APP_Flash_Start_Addr ) || ( ( readAddr + NumByteToWrite ) > MCU_EEPROM_Start_Addr ) ) { + Dbg_Println(DBG_BIT_SYS_STATUS_bit,"MCU APP Flash Addr Error:%x - %x\r\n", readAddr, NumByteToWrite); + return 0x01; + } + + sta = FLASH_ROMA_READ(readAddr, pBuffer, NumByteToWrite); + + if (sta != FLASH_COMPLETE){ + Dbg_Println(DBG_BIT_SYS_STATUS_bit,"Operation FLASH_ROMA_READ failed %x!! Err Code %x\r\n", readAddr, sta); + return 0x01; + } + + return 0x00; +} + +/******************************************************************************* +* Function Name : MCU_APP_Flash_Erase +* Description : MCU Flash数据擦除函数 +* Input : + pBuffer:写入数据 + NumByteToWrite:写入数据长度 -- 写入长度必须为4的倍速 + readAddr:读取地址 0x00004000 ~ 0x0006FFFF 432KB +*******************************************************************************/ +__attribute__((section(".non_0_wait"))) uint8_t MCU_APP_Flash_Erase(uint32_t readAddr,uint16_t NumByteToWrite) +{ + FLASH_Status sta; + + /* 校验读取地址和长度是否符合条件 - 读取地址及长度是否在APP Flash范围内*/ + if( ( readAddr < MCU_APP_Flash_Start_Addr ) || ( ( readAddr + NumByteToWrite ) > MCU_EEPROM_Start_Addr ) ) { + Dbg_Println(DBG_BIT_SYS_STATUS_bit,"MCU EEPROM Addr Error:%x - %x\r\n", readAddr, NumByteToWrite); + return 0x01; + } + + FLASH_Unlock(); + sta = FLASH_ROMA_ERASE(readAddr, NumByteToWrite); + FLASH_Lock(); + + if (sta != FLASH_COMPLETE){ + Dbg_Println(DBG_BIT_SYS_STATUS_bit,"Operation FLASH_ROMA_ERASE failed %x!! Err Code %x\r\n", readAddr, sta); + return 0x01; + } + + return 0x00; +} + +/******************************************************************************* +* Function Name : MCU_APP_Flash_ALLErase +* Description : MCU Flash擦除函数 - APP所有区域(包括APP特征区) +*******************************************************************************/ +__attribute__((section(".non_0_wait"))) uint8_t MCU_APP_Flash_ALLErase(void) +{ + FLASH_Status sta; + + for(uint32_t i=MCU_APP_Flash_Start_Addr;i MCU_EEPROM_End_Addr ) || ((NumByteToWrite % 4) != 0x00)) { + Dbg_Println(DBG_BIT_SYS_STATUS_bit,"MCU EEPROM Addr Error:%x - %x\r\n", writeAddr, NumByteToWrite); + return 0x01; + } + + FLASH_Unlock(); + sta = EEPROM_WRITE(writeAddr, pBuffer, NumByteToWrite); + FLASH_Lock(); + + if (sta != FLASH_COMPLETE){ + Dbg_Println(DBG_BIT_SYS_STATUS_bit,"Operation FLASH_ROMA_WRITE failed %x!! Err Code %x\r\n", writeAddr, sta); + + return 0x01; + } + + return 0x00; +} + +/******************************************************************************* +* Function Name : MCU_EEPROM_Read +* Description : MCU EEPROM数据读取函数 +* Input : + pBuffer:写入数据 + NumByteToWrite:写入数据长度 -- 写入长度必须为4的倍速 + readAddr:读取地址 0x00004000 ~ 0x0006FFFF 432KB +*******************************************************************************/ +__attribute__((section(".non_0_wait"))) uint8_t MCU_EEPROM_Read(uint8_t* pBuffer,uint16_t NumByteToWrite,uint32_t readAddr) +{ + FLASH_Status sta; + + /* 校验读取地址和长度是否符合条件 - 读取地址及长度是否在APP Flash范围内*/ + if( ( readAddr < MCU_EEPROM_Start_Addr ) || ( ( readAddr + NumByteToWrite ) > MCU_EEPROM_End_Addr ) ) { + Dbg_Println(DBG_BIT_SYS_STATUS_bit,"MCU EEPROM Addr Error:%x - %x\r\n", readAddr, NumByteToWrite); + return 0x01; + } + + sta = EEPROM_READ(readAddr, pBuffer, NumByteToWrite); + + if (sta != FLASH_COMPLETE){ + Dbg_Println(DBG_BIT_SYS_STATUS_bit,"Operation FLASH_ROMA_READ failed %x!! Err Code %x\r\n", readAddr, sta); + return 0x01; + } + + return 0x00; +} + +/******************************************************************************* +* Function Name : MCU_EEPROM_Erase +* Description : MCU EEPROM数据擦除函数 +* Input : + eraseAddr:擦除地址 0x70000 -- 0x77FFF + length:只能按照块擦除,块大小为4096 +*******************************************************************************/ +__attribute__((section(".non_0_wait"))) uint8_t MCU_EEPROM_Erase(uint32_t eraseAddr,uint16_t length) +{ + FLASH_Status sta; + + /* 校验读取地址和长度是否符合条件 - 读取地址及长度是否在APP Flash范围内 */ + if( ( eraseAddr < MCU_EEPROM_Start_Addr ) || ( ( eraseAddr + length ) > MCU_EEPROM_End_Addr ) ) { + Dbg_Println(DBG_BIT_SYS_STATUS_bit,"MCU EEPROM Addr Error:%x - %x\r\n", eraseAddr, length); + return 0x01; + } + + FLASH_Unlock(); + sta = EEPROM_ERASE(eraseAddr, length); + FLASH_Lock(); + + if (sta != FLASH_COMPLETE){ + Dbg_Println(DBG_BIT_SYS_STATUS_bit,"Operation MCU_EEPROM_Erase failed %x!! Err Code %x\r\n", eraseAddr, sta); + return 0x01; + } + + return 0x00; +} + +/******************************************************************************* +* Function Name : MCU_EEPROM_ALLErase +* Description : MCU Flash擦除函数 - EEPROM所有区域 +*******************************************************************************/ +__attribute__((section(".non_0_wait"))) uint8_t MCU_EEPROM_ALLErase(void) +{ + FLASH_Status sta; + + for(uint32_t i=MCU_EEPROM_Start_Addr;idev_addr); + Dbg_Println(DBG_BIT_SYS_STATUS_bit,"EE DevType:%d",info->dev_type); + Dbg_Println(DBG_BIT_SYS_STATUS_bit,"EE DevBootVer:%d",info->dev_boot_ver); + Dbg_Println(DBG_BIT_SYS_STATUS_bit,"EE DevAppVer:%d",info->dev_app_ver); + Dbg_Println(DBG_BIT_SYS_STATUS_bit,"EE DevNameLen:%d",info->dev_name_len); + Dbg_Println(DBG_BIT_SYS_STATUS_bit,"EE DevName:%s",info->dev_name); + + return 0x00; + } + } + } + + return 0x01; +} + +/******************************************************************************* +* Function Name : EEPROM_WriteMCUDevInfo +* Description : 将设备信息写入到EEPROM中 +*******************************************************************************/ +__attribute__((section(".non_0_wait"))) uint8_t EEPROM_WriteMCUDevInfo(E_MCU_DEV_INFO *info) +{ + uint8_t save_data[EEPROM_DATA_Size_Max + 6]; + uint16_t save_len = sizeof(E_MCU_DEV_INFO); + + if(save_len >= EEPROM_DATA_Size_Max) save_len = EEPROM_DATA_Size_Max; + + save_data[0] = EEPROM_SVAE_FLAG; + save_data[1] = save_len & 0xFF; + save_data[2] = (save_len >> 8) & 0xFF; + + memcpy(&save_data[4],(uint8_t *)info,save_len); + + save_data[3] = EEPROM_CheckSum(&save_data[4],save_len); + + save_len+=4; + + MCU_EEPROM_Write(save_data,save_len,MCU_EEPROM_MCUDevInfo_Address); + + return 0; +} + +/******************************************************************************* +* Function Name : EEPROM_Default_MCUDevInfo +* Description : EEPROM中参数恢复默认值,且将默认参数保存至EEPROM中 +*******************************************************************************/ +__attribute__((section(".non_0_wait"))) void EEPROM_Default_MCUDevInfo(E_MCU_DEV_INFO *info) +{ +#if (Project_Area == 0x01) + /*Boot 区域*/ + info->dev_addr = 0x00; + info->dev_type = 0x00; + info->dev_app_ver = 0x00; + info->dev_boot_ver = Project_FW_Version; + info->dev_name_len = sizeof(Peoject_Name); + + memset((char *)info->dev_name,0,EEPROM_DEV_NAME_Size); + memcpy((char *)info->dev_name,(char *)Peoject_Name,info->dev_name_len); + + //EEPROM_WriteMCUDevInfo(info); +#elif (Project_Area == 0x02) + /*APP 区域*/ + info->dev_addr = 0x00; + info->dev_type = Project_Type; + info->dev_app_ver = Project_FW_Version; + info->dev_name_len = sizeof(Peoject_Name); + + memset((char *)info->dev_name,0,EEPROM_DEV_NAME_Size); + memcpy((char *)info->dev_name,(char *)Peoject_Name,info->dev_name_len); + + EEPROM_WriteMCUDevInfo(info); +#endif +} + +/******************************************************************************* +* Function Name : EEPROM_Validate_MCUDevInfo +* Description : 校验从EEPROM 中读取的参数是否正确,如果不正确的话,便将当前正确的参数写入 + APP区域中,判断APP参数与EEPROM中记录的是否一致 + Boot区域中,判断Boot参数与EEPROM中记录的是否一致 +*******************************************************************************/ +__attribute__((section(".non_0_wait"))) void EEPROM_Validate_MCUDevInfo(E_MCU_DEV_INFO *info) +{ +#if (Project_Area == 0x01) + /*Boot 区域*/ + uint8_t save_flag = 0; + + if(info->dev_boot_ver != Project_FW_Version) + { + info->dev_boot_ver = Project_FW_Version; + save_flag = 0x01; + } + + if(save_flag == 0x01) + { + EEPROM_WriteMCUDevInfo(info); + } +#elif (Project_Area == 0x02) + /*APP 区域*/ + U8_T save_flag = 0; + + if(info->dev_app_ver != Project_FW_Version) + { + info->dev_app_ver = Project_FW_Version; + save_flag = 0x01; + } + + if(info->dev_type != Project_Type) + { + info->dev_type = Project_Type; + save_flag = 0x01; + } + + if(info->dev_name_len != sizeof(Peoject_Name)) + { + info->dev_name_len = sizeof(Peoject_Name); + save_flag = 0x01; + } + + if(strncmp((char *)info->dev_name,(char *)Peoject_Name,sizeof(Peoject_Name))) + { + memcpy((char *)info->dev_name,(char *)Peoject_Name,info->dev_name_len); + save_flag = 0x01; + } + + if(save_flag == 0x01) + { + EEPROM_WriteMCUDevInfo(info); + } +#endif +} + +/******************************************************************************* +* Function Name : Read_APP_Feature_Info +* Description : 读取APP特征区 +*******************************************************************************/ +__attribute__((section(".non_0_wait"))) uint8_t Read_APP_Feature_Info(uint8_t option,G_SYS_FEATURE_T *feature_info) +{ + uint16_t crc_val = 0,crc_val2 = 0; + uint32_t temp_val = 0; + memset(Temp_Flash_Buff,0,sizeof(Temp_Flash_Buff)); + + if(option == 0x01){ + //读取MCU Flash APP特征区 + MCU_APP_Flash_Read(Temp_Flash_Buff,APP_FEATURE_SIZE,MCU_APP_Feature_Addr); + }else if(option == 0x02){ + //读取外部 Flash APP特征区 + Flash_Read(Temp_Flash_Buff,APP_FEATURE_SIZE,SPIFLASH_APP_FEATURE_Addr); + } + + Dbg_Print_Buff(DBG_BIT_SYS_STATUS_bit,"APP Feature :",Temp_Flash_Buff,APP_FEATURE_SIZE); + + crc_val = Temp_Flash_Buff[1]; + crc_val <<= 0x08; + crc_val |= Temp_Flash_Buff[0]; + + crc_val2 = NetCRC16_2(&Temp_Flash_Buff[2],510); + Dbg_Println(DBG_BIT_SYS_STATUS_bit,"%s CRC: %x - %x",__func__,crc_val,crc_val2); + + if(crc_val == crc_val2) + { + /*数据校验通过*/ + feature_info->app_flag = Temp_Flash_Buff[Feature_AppFlag]; + + temp_val = Temp_Flash_Buff[Feature_AppStart + 3]; + temp_val <<= 8; + temp_val |= Temp_Flash_Buff[Feature_AppStart + 2]; + temp_val <<= 8; + temp_val |= Temp_Flash_Buff[Feature_AppStart + 1]; + temp_val <<= 8; + temp_val |= Temp_Flash_Buff[Feature_AppStart]; + feature_info->app_start_addr = temp_val; + + temp_val = Temp_Flash_Buff[Feature_AppEnd + 3]; + temp_val <<= 8; + temp_val |= Temp_Flash_Buff[Feature_AppEnd + 2]; + temp_val <<= 8; + temp_val |= Temp_Flash_Buff[Feature_AppEnd + 1]; + temp_val <<= 8; + temp_val |= Temp_Flash_Buff[Feature_AppEnd]; + feature_info->app_end_addr = temp_val; + + temp_val = Temp_Flash_Buff[Feature_AppCrcSize + 1]; + temp_val <<= 8; + temp_val |= Temp_Flash_Buff[Feature_AppCrcSize]; + feature_info->app_crc_size = temp_val; + + temp_val = Temp_Flash_Buff[Feature_AppCrcLen + 1]; + temp_val <<= 8; + temp_val |= Temp_Flash_Buff[Feature_AppCrcLen]; + feature_info->app_crc_len = temp_val; + + memcpy(feature_info->app_crc,&Temp_Flash_Buff[Feature_AppFlashCrc],APP_Feature_CRC_Size); + + /*校验数据是否处于正常范围*/ + if( ( feature_info->app_start_addr < MCU_APP_Flash_Start_Addr ) || ( feature_info->app_start_addr > MCU_APP_Data_End_Addr ) ){ + Dbg_Println(DBG_BIT_SYS_STATUS_bit,"%s app_start_addr:0x%x Error",__func__, feature_info->app_start_addr); + return 0x02; + } + + if( ( feature_info->app_end_addr > MCU_APP_Data_End_Addr ) || ( feature_info->app_start_addr > feature_info->app_end_addr ) ){ + Dbg_Println(DBG_BIT_SYS_STATUS_bit,"%s app_end_addr:0x%x - 0x%x Error",__func__,feature_info->app_start_addr,feature_info->app_end_addr); + return 0x02; + } + + if( feature_info->app_crc_size != MCU_APP_Flash_PageSize ){ + Dbg_Println(DBG_BIT_SYS_STATUS_bit,"%s app_crc_size:%#x Error",__func__,feature_info->app_crc_size); + return 0x02; + } + + return 0x00; + } + + return 0x01; +} + +/******************************************************************************* +* Function Name : Write_APP_Feature_Info +* Description : 写入APP特征区 +*******************************************************************************/ +__attribute__((section(".non_0_wait"))) uint8_t Write_APP_Feature_Info(uint8_t option,G_SYS_FEATURE_T *feature_info) +{ + uint8_t rev = 0; + + memset(Temp_Flash_Buff,0,sizeof(Temp_Flash_Buff)); + memset(g_flash_buff,0,sizeof(g_flash_buff)); + + g_flash_buff[Feature_AppFlag] = feature_info->app_flag; + + g_flash_buff[Feature_AppStart] = feature_info->app_start_addr & 0xFF; + g_flash_buff[Feature_AppStart + 1] = ( feature_info->app_start_addr >> 8 ) & 0xFF; + g_flash_buff[Feature_AppStart + 2] = ( feature_info->app_start_addr >> 16 ) & 0xFF; + g_flash_buff[Feature_AppStart + 3] = ( feature_info->app_start_addr >> 24 ) & 0xFF; + + g_flash_buff[Feature_AppEnd] = feature_info->app_end_addr & 0xFF; + g_flash_buff[Feature_AppEnd + 1] = ( feature_info->app_end_addr >> 8 ) & 0xFF; + g_flash_buff[Feature_AppEnd + 2] = ( feature_info->app_end_addr >> 16 ) & 0xFF; + g_flash_buff[Feature_AppEnd + 3] = ( feature_info->app_end_addr >> 24 ) & 0xFF; + + g_flash_buff[Feature_AppCrcSize] = feature_info->app_crc_size & 0xFF; + g_flash_buff[Feature_AppCrcSize + 1] = ( feature_info->app_crc_size >> 8 ) & 0xFF; + + g_flash_buff[Feature_AppCrcLen] = feature_info->app_crc_len & 0xFF; + g_flash_buff[Feature_AppCrcLen + 1] = ( feature_info->app_crc_len >> 8 ) & 0xFF; + + memcpy(&g_flash_buff[Feature_AppFlashCrc],feature_info->app_crc,APP_Feature_CRC_Size); + + feature_info->crc_check = NetCRC16_2(&g_flash_buff[2], 510); + + g_flash_buff[Feature_Check] = feature_info->crc_check & 0xFF; + g_flash_buff[Feature_Check + 1] = ( feature_info->crc_check >> 8 ) & 0xFF; + + if(option == 0x01){ + //读取MCU Flash APP特征区 由于特征区大小为512Byte,mcu flash 每次写入都必须块写入以及块擦除 4096byte + /*写特征区 - 1、先读取块数据*/ + + MCU_APP_Flash_Read(Temp_Flash_Buff,MCU_APP_Flash_PageSize,MCU_APP_Feature_PageAddr); + + memcpy(&Temp_Flash_Buff[MCU_APP_Feature_PageOffset],g_flash_buff,512); + + /*写特征区 - 2、擦除块内容*/ + rev = MCU_APP_Flash_Erase(MCU_APP_Feature_PageAddr,MCU_APP_Flash_PageSize); + + if(rev != 0x00) { + Dbg_Println(DBG_BIT_SYS_STATUS_bit,"MCU_APP_Flash_Erase Fail:%d %x - %x",rev,MCU_APP_Feature_PageAddr,MCU_APP_Flash_PageSize); + return 0x01; + } + + /*写特征区 - 3、写入块内容*/ + rev = MCU_APP_Flash_Write(Temp_Flash_Buff,MCU_APP_Flash_PageSize,MCU_APP_Feature_PageAddr); + + if(rev != 0x00) { + Dbg_Println(DBG_BIT_SYS_STATUS_bit,"MCU_APP_Flash_Write Fail:%d %#x - %#x",rev,MCU_APP_Feature_PageAddr,MCU_APP_Flash_PageSize); + return 0x02; + } + + /*写特征区 - 4、校验写入块内容*/ + rev = FLASH_ROMA_VERIFY(MCU_APP_Feature_PageAddr,Temp_Flash_Buff,MCU_APP_Flash_PageSize); + if(rev != 0x00) { + Dbg_Println(DBG_BIT_SYS_STATUS_bit,"FLASH_ROMA_VERIFY Fail:%d %#x - %#x",rev,MCU_APP_Feature_PageAddr,MCU_APP_Flash_PageSize); + return 0x03; + } + + }else if(option == 0x02){ + //读取外部 Flash APP特征区 + Dbg_Print_Buff(DBG_BIT_SYS_STATUS_bit,"SPI Flash Para:",g_flash_buff,APP_FEATURE_SIZE); + + Flash_Write(g_flash_buff,APP_FEATURE_SIZE,SPIFLASH_APP_FEATURE_Addr); + } + + return 0x00; +} + +/******************************************************************************* +* Function Name : APP_Feature_Info_Printf +* Description : APP特征区数据打印 +*******************************************************************************/ +__attribute__((section(".non_0_wait"))) void APP_Feature_Info_Printf(G_SYS_FEATURE_T *feature_info) +{ + Dbg_Println(DBG_BIT_SYS_STATUS_bit,"Feature crc_check: %x \r\n",feature_info->crc_check); + Dbg_Println(DBG_BIT_SYS_STATUS_bit,"Feature app_flag: %x \r\n",feature_info->app_flag); + + Dbg_Println(DBG_BIT_SYS_STATUS_bit,"Feature app_start_addr: %x \r\n",feature_info->app_start_addr); + Dbg_Println(DBG_BIT_SYS_STATUS_bit,"Feature app_end_addr: %x \r\n",feature_info->app_end_addr); + Dbg_Println(DBG_BIT_SYS_STATUS_bit,"Feature app_crc_len: %d \r\n",feature_info->app_crc_len); + Dbg_Print_Buff(DBG_BIT_SYS_STATUS_bit,"Feature app_crc:",feature_info->app_crc,471); +} + + + diff --git a/MCU_Driver/md5.c b/MCU_Driver/md5.c index 4cb5661..08af457 100644 --- a/MCU_Driver/md5.c +++ b/MCU_Driver/md5.c @@ -55,7 +55,7 @@ static unsigned char PADDING[64] = { #define HH(a, b, c, d, x, s, ac) { (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); (a) = ROTATE_LEFT ((a), (s)); (a) += (b); } #define II(a, b, c, d, x, s, ac) { (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); (a) = ROTATE_LEFT ((a), (s)); (a) += (b); } -void Encode(unsigned char *output, UINT4 *input, unsigned int len) +__attribute__((section(".non_0_wait"))) void Encode(unsigned char *output, UINT4 *input, unsigned int len) { unsigned int i, j; @@ -67,7 +67,7 @@ void Encode(unsigned char *output, UINT4 *input, unsigned int le } } -void MD5Init(MD5_CTX *context) +__attribute__((section(".non_0_wait"))) void MD5Init(MD5_CTX *context) { context->count[0] = context->count[1] = 0; context->state[0] = 0x67452301; @@ -76,7 +76,7 @@ void MD5Init(MD5_CTX *context) context->state[3] = 0x10325476; } -void Decode(UINT4 *output, unsigned char *input, unsigned int len) +__attribute__((section(".non_0_wait"))) void Decode(UINT4 *output, unsigned char *input, unsigned int len) { unsigned int i, j; @@ -86,7 +86,7 @@ void Decode(UINT4 *output, unsigned char *input, unsigned int le } -void MD5Transform (UINT4 state[4], unsigned char block[64]) +__attribute__((section(".non_0_wait"))) void MD5Transform (UINT4 state[4], unsigned char block[64]) { UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16]; Decode (x, block, 64); @@ -161,7 +161,7 @@ void MD5Transform (UINT4 state[4], unsigned char block[64]) memset ((POINTER)x, 0, sizeof (x)); } -void MD5Update(MD5_CTX *context, unsigned char *input, unsigned int inputLen) +__attribute__((section(".non_0_wait"))) void MD5Update(MD5_CTX *context, unsigned char *input, unsigned int inputLen) { unsigned int i, index, partLen; @@ -183,7 +183,7 @@ void MD5Update(MD5_CTX *context, unsigned char *input, unsigned in memcpy((POINTER)&context->buffer[index], (POINTER)&input[i], inputLen-i); } -void MD5_SRAM_Update(MD5_CTX *context, uint32_t add, unsigned int inputLen) +__attribute__((section(".non_0_wait"))) void MD5_SRAM_Update(MD5_CTX *context, uint32_t add, unsigned int inputLen) { unsigned int i, index, partLen; uint32_t addr = add; @@ -215,7 +215,7 @@ void MD5_SRAM_Update(MD5_CTX *context, uint32_t add, unsigned int in SRAM_DMA_Read_Buff((POINTER)&context->buffer[index], inputLen-i, addr); } -void MD5_FLASH_Update(MD5_CTX *context, uint32_t add, unsigned int inputLen) +__attribute__((section(".non_0_wait"))) void MD5_FLASH_Update(MD5_CTX *context, uint32_t add, unsigned int inputLen) { unsigned int i, index, partLen; uint32_t addr = add; @@ -246,7 +246,7 @@ void MD5_FLASH_Update(MD5_CTX *context, uint32_t add, unsigned int inp Flash_Read((POINTER)&context->buffer[index], inputLen-i, addr); } -void MD5Final(unsigned char digest[16], MD5_CTX *context) +__attribute__((section(".non_0_wait"))) void MD5Final(unsigned char digest[16], MD5_CTX *context) { unsigned char bits[8]; unsigned int index, padLen; @@ -260,7 +260,7 @@ void MD5Final(unsigned char digest[16], MD5_CTX *context) memset ((POINTER)context, 0, sizeof (*context)); } -void MD5Digest(char *pszInput, unsigned int nInputSize, char *pszOutPut) +__attribute__((section(".non_0_wait"))) void MD5Digest(char *pszInput, unsigned int nInputSize, char *pszOutPut) { MD5_CTX context; //unsigned int len = strlen (pszInput); @@ -271,7 +271,7 @@ void MD5Digest(char *pszInput, unsigned int nInputSize, char *pszO MD5Final ((unsigned char *)pszOutPut, &context); } -void MD5Digest_SRAM(uint32_t add, unsigned int nInputSize, char *pszOutPut) +__attribute__((section(".non_0_wait"))) void MD5Digest_SRAM(uint32_t add, unsigned int nInputSize, char *pszOutPut) { MD5_CTX context; //unsigned int len = strlen (pszInput); @@ -282,7 +282,7 @@ void MD5Digest_SRAM(uint32_t add, unsigned int nInputSize, char *psz MD5Final((unsigned char *)pszOutPut, &context); } -void MD5Digest_FLASH(uint32_t add, unsigned int nInputSize, char *pszOutPut) +__attribute__((section(".non_0_wait"))) void MD5Digest_FLASH(uint32_t add, unsigned int nInputSize, char *pszOutPut) { MD5_CTX context; unsigned int len = nInputSize; diff --git a/MCU_Driver/rw_logging.c b/MCU_Driver/rw_logging.c index 1c7d970..e8a84e0 100644 --- a/MCU_Driver/rw_logging.c +++ b/MCU_Driver/rw_logging.c @@ -167,7 +167,7 @@ __attribute__((section(".non_0_wait"))) void Retain_Flash_Register_Data(void) memset(Global_Large_Buff,0,Register_OFFSET_LEN); - Flash_Read(Global_Large_Buff,Register_OFFSET_LEN,FLASH_Register_Start_ADDRESS); + Flash_Read(Global_Large_Buff,Register_OFFSET_LEN,SPIFLASH_Register_Start_ADDRESS); for(i = 0;i 10) -// { -// server_info.con_flag = 0x00; -// server_info.con_tick = SysTick_1s; -// server_info.init_flag = 0x00; -// Dbg_Print(DBG_BIT_NET_STATUS_bit,"直连超时,重启网络\n"); -// } -// } + /* -该用于网络直连超时后,重启网络 + * -处于网络直连状态下,PC工具会向主机定期发送查询数据 + * */ + if(server_info.con_flag==0x01) + { + if(SysTick_1s - server_info.con_tick > 10) + { + server_info.con_flag = 0x00; + server_info.con_tick = SysTick_1s; + server_info.init_flag = 0x00; + Dbg_Print(DBG_BIT_NET_STATUS_bit,"直连超时,重启网络\n"); + } + } if(server_info.init_flag == 0x00) //网络需要重新初始化 { @@ -1078,7 +1084,6 @@ __attribute__((section(".non_0_wait"))) void NetWork_Task(void) server_info.wait_cot = SysTick_1ms; server_info.net_sta = NET_WAIT_MAC_RESTART; - /*释放套接字*/ Dbg_Println(DBG_BIT_NET_STATUS_bit,"释放套接字"); WCHNET_SocketClose(g_netinfo.SocketId[SocketIdnex_BLVSeriver],0x00); diff --git a/NetLib/net_function.h b/NetLib/net_function.h index eb61115..bc0a132 100644 --- a/NetLib/net_function.h +++ b/NetLib/net_function.h @@ -21,7 +21,10 @@ #define TFTPSERVER_NAME_DNS "blv-tftp-log.blv-oa.com" //TFTP日志服务器 - 默认使用域名 #define SERVER_COMM_Port 3339 -#define SocketIdnex_BLVSeriver 0x00 //套接字数组存储下标 +//套接字数组存储下标 +#define SocketIdnex_BLVSeriver 0x00 //BLV通讯服务 - 套接字数组存储下标 +#define SocketIdnex_TFTPCMD 0x01 //TFTP命令 - 套接字数组存储下标 +#define SocketIdnex_TFTPDATA 0x02 //TFTP数据 - 套接字数组存储下标 #define Net_DNS_Port 53 //DNS服务器端口 @@ -154,6 +157,8 @@ extern DEVICE_NET_APPINFO server_info; uint8_t WCHNET_LIB_Init(void); void WCHNET_HandleGlobalInt(void); +uint8_t WCHNET_Get_PHY_Linked_Status(void); +void WCHNET_CreateUdpSocket(uint8_t* S, uint16_t SourPort, pSockRecv cb); void NetWork_Task(void); diff --git a/NetLib/tftp_function.c b/NetLib/tftp_function.c new file mode 100644 index 0000000..ef5d197 --- /dev/null +++ b/NetLib/tftp_function.c @@ -0,0 +1,636 @@ +/* + * 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; + } + } + } +} + + + + + + + diff --git a/NetLib/tftp_function.h b/NetLib/tftp_function.h new file mode 100644 index 0000000..c7f170f --- /dev/null +++ b/NetLib/tftp_function.h @@ -0,0 +1,103 @@ +/* + * tftp_function.h + * + * Created on: Dec 6, 2025 + * Author: cc + */ + +#ifndef NETLIB_TFTP_FUNCTION_H_ +#define NETLIB_TFTP_FUNCTION_H_ + +#include "ch564.h" +#include "eth_driver.h" +#include "net_config.h" +#include "debug.h" + +#define TFTP_Destination_Port 69 //TFTP服务端口 +#define TFTP_DTAT_Local_Port 65535 //TFTP 数据传输本地端口 +#define TFTP_LOG_Local_Port 65500 //TFTP LOG传输本地端口 +#define TFTP_DATA_LEN_MAX 517 +#define TFTP_DATA_PKT_HDR_LEN 4 //TFTP数据包头长度 +#define TFTP_ACK_PKT_LEN 4 //TFTP应答数据包长度 + +#define TFTP_IAP_Task_Timeout 30000 //TFTP IAP任务超时时间 + +#define TFTP_File_Name_Size 128 //TFTP传输文件名最大128Byte + +#define TFTP_LOG_Exceed_Size 4096 //日志上报条件1 - 限定大小 +#define TFTP_LOG_Exceed_Time 7200 //日志上报条件2 - 限定时间 + +#define TFTP_IAP_Start 0x01 //TFTP IAP升级开始 +#define TFTP_IAP_Finish 0x02 //TFTP IAP升级完成 +#define TFTP_IAP_Timeout 0x03 //TFTP IAP升级超时 + +#define TFTP_FUNTYPE_LocalIAP 0x01 //本地IAP升级(局域网升级) +#define TFTP_FUNTYPE_CloudIAP 0x02 //云端IAP升级(远程升级) +#define TFTP_FUNTYPE_LogUpload 0x03 //LOG上传 + +#define TFTP_IAP_DataType_APP 0x01 //IAP升级 - APP固件 +#define TFTP_IAP_DataType_CONFIG 0x02 //IAP升级 - 配置文件 + + +typedef enum { + TFTP_RRQ = 1, + TFTP_WRQ = 2, + TFTP_DATA = 3, + TFTP_ACK = 4, + TFTP_ERROR = 5, + TFTP_OPTION = 6, +}TFTP_OPCODE; + +typedef struct +{ + uint8_t IapFileType; //升级文件类型 就两种,0是固件 1是配置 + uint8_t enable; //TFTP 功能使能状态 0X01:使能,0x00:没使能 + uint8_t FunType; //升级类型 0x01:本地IAP升级,0x02:云端IAP升级,0x03:LOG日志上传 + + uint8_t NewIapFlag; //新升级流程标志位 - 2022-01-05 + + uint8_t IapErrFlag; //升级数据传输错误标志 + + uint8_t status; //状态机 + uint8_t IapPercent; //升级占用的百分比 + + uint8_t FtpFileNameLen; //文件名长度 + + uint8_t FtpFileName[TFTP_File_Name_Size]; //文件名 + uint8_t Md5[16]; //MD5值 + + uint16_t TFTP_Port; + + uint16_t BlockSize; //块大小 + uint16_t Write_Block; //写入块号 + + uint32_t FlashWriteAddress; //升级写入的地址 + uint32_t TotalCount; //文件总大小 + uint32_t WriteCount; //文件写入大小 + + uint32_t processing_tick; //处理时间戳 +}IAPVarTypeStruct; + +typedef struct +{ + uint8_t op; /*WRQ */ + + uint8_t data[TFTP_DATA_LEN_MAX]; + + uint8_t to_ip[4]; + uint8_t retry_num; + + uint16_t data_len; + uint16_t to_port; + + uint16_t block; + + uint16_t tot_bytes; + + uint32_t last_time; +}tftp_connection_args; + + +void Internal_TFTP_Task(void); + +#endif /* NETLIB_TFTP_FUNCTION_H_ */ diff --git a/Readme.md b/Readme.md index e69de29..58949f1 100644 --- a/Readme.md +++ b/Readme.md @@ -0,0 +1,8 @@ +#### 2025-12-06 + +1. 鍔ㄤ綔鎵ц鍑芥暟鍒濇瀹炵幇瀹屾瘯 - 寰呮祴璇 +2. 寮濮嬬Щ妞峊FTP鍔熻兘 + 1. TFTP鍗囩骇 + 2. TFTP鏃ュ織鏂囦欢浼犺緭 + +鈥 \ No newline at end of file diff --git a/User/includes.h b/User/includes.h index d573a97..6066622 100644 --- a/User/includes.h +++ b/User/includes.h @@ -26,6 +26,8 @@ #include "check_fun.h" #include "md5.h" #include "watchdog.h" +#include "mcu_flash.h" + #include "blv_authorize.h" #include "blv_rs485_protocol.h" #include "blv_dev_action.h" @@ -35,6 +37,7 @@ #include "eth_driver.h" #include "net_config.h" #include "net_function.h" +#include "tftp_function.h" #include "blv_netcomm_function.h" #include "pc_devicetest_fun.h"