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