/* ****************************************************************************** * @file Bootload.c * @author caocong * @version V1.00 * @date 2025/04/03 * @Description * MCU空间规划 * Boot 0x0000 ~ 0x27FF 10K * APP 0x2800 ~ 0xFEFF 53.8K * APP_FEATURE 0xFF00 ~ 0xFFFF 256Byte * EEPROM空间规划 * APP设备信息 0x10000000 - Size:0x40 - 64Byte * */ #include "includes.h" #include #include #include BOOT_INFO_T g_boot; APP_FEATURE_INFO_T g_app_feature; void Boot_Function_Init(void) { U8_T app_ready = 0; U16_T sys_reset_sta = 0; memset(&g_boot,0,sizeof(BOOT_INFO_T)); memset(&g_app_feature,0,sizeof(APP_FEATURE_INFO_T)); g_boot.ackValidity = 1000; //数据默认有效期为1000ms EEPROM_Init(); /*读取APP 特征区*/ // app_ready = Check_APP_Feature(); //#if DBG_LOG_EN // if(app_ready == 0x00) // { // Dbg_Println(DBG_BIT_SYS_STATUS,"APP Feature SUCC"); // Dbg_Println(DBG_BIT_SYS_STATUS,"APP app_flag:%d",g_app_feature.app_flag); // Dbg_Println(DBG_BIT_SYS_STATUS,"APP app_start_addr:%08x",g_app_feature.app_start_addr); // Dbg_Println(DBG_BIT_SYS_STATUS,"APP app_end_addr:%08x",g_app_feature.app_end_addr); // Dbg_Println(DBG_BIT_SYS_STATUS,"APP app_crc_size:%d",g_app_feature.app_crc_size); // Dbg_Println(DBG_BIT_SYS_STATUS,"APP app_crc_len:%d",g_app_feature.app_crc_len); // Dbg_Print_Buff(DBG_BIT_SYS_STATUS,"APP app_crc:",g_app_feature.app_crc,g_app_feature.app_crc_len); // // }else { // Dbg_Println(DBG_BIT_SYS_STATUS,"APP Feature Fail!"); // // } //#endif sys_reset_sta = SYSCON->UREG3; if(sys_reset_sta == 0x100) //软件复位 -- 升级开始复位源 { g_boot.bootTimeout = 5000; #if DBG_LOG_EN Dbg_Println(DBG_BIT_SYS_STATUS," Boot software reset"); #endif }else if(sys_reset_sta == 0x01) //上电复位RPOR { g_boot.bootTimeout = 500; #if DBG_LOG_EN Dbg_Println(DBG_BIT_SYS_STATUS,"Boot power on reset"); #endif }else if(sys_reset_sta == 0x04) //外部手动复位 { g_boot.bootTimeout = 2000; #if DBG_LOG_EN Dbg_Println(DBG_BIT_SYS_STATUS,"Boot ex-pin reset"); #endif }else if(sys_reset_sta == 0x10) //看门狗超时复位 --升级完成复位源 { g_boot.bootTimeout = 2000; #if DBG_LOG_EN Dbg_Println(DBG_BIT_SYS_STATUS,"Boot wdt reset"); #endif }else if(sys_reset_sta == 0x40) //外部时钟无效复位 { g_boot.bootTimeout = 2000; #if DBG_LOG_EN Dbg_Println(DBG_BIT_SYS_STATUS,"Boot ex clock invalid reset"); #endif }else if(sys_reset_sta == 0x80) //CPU请求复位 - link调试复位 { g_boot.bootTimeout = 2000; #if DBG_LOG_EN Dbg_Println(DBG_BIT_SYS_STATUS,"Boot cpu request reset"); #endif }else { g_boot.bootTimeout = 2000; #if DBG_LOG_EN Dbg_Println(DBG_BIT_SYS_STATUS,"Boot other reset 0x%x",sys_reset_sta); #endif } } U8_T Boot_Comm_CheckSum(U8_T * buffer, U16_T len) { U8_T sum = 0; U16_T i=0; while(len--) { sum += buffer[i]; i++; } return (~sum); } U16_T NetCRC16(U8_T * aStr, U16_T len) { U16_T xda , xdapoly ; U16_T i, j, xdabit ; xda = 0xFFFF ; xdapoly = 0xA001 ; // (X**16 + X**15 + X**2 + 1) for (i = 0; i < len; i++) { xda ^= aStr[i] ; for (j = 0; j < 8; j++) { xdabit = (unsigned char)(xda & 0x01) ; xda >>= 1 ; if ( xdabit ) xda ^= xdapoly ; } } return xda; } void Boot_Comm_FillReplyPack(BOOT_INFO_T *ack_uart) { U16_T data_len = ack_uart->ackLen + BCOMM_FMT_PARAM; ack_uart->ackBuffer[BCOMM_FMT_TXAddr] = g_mcu_dev.dev_addr; ack_uart->ackBuffer[BCOMM_FMT_SN] = ack_uart->sn; ack_uart->ackBuffer[BCOMM_FMT_TYPE] = g_mcu_dev.dev_type; ack_uart->ackBuffer[BCOMM_FMT_RXAddr] = g_boot.pc_addr; ack_uart->ackBuffer[BCOMM_FMT_CMD] = ack_uart->cmd; ack_uart->ackBuffer[BCOMM_FMT_LEN_L] = data_len & 0xFF; ack_uart->ackBuffer[BCOMM_FMT_LEN_H] = (data_len >> 8) & 0xFF; ack_uart->ackBuffer[BCOMM_FMT_CKS] = 0; ack_uart->ackBuffer[BCOMM_FMT_CKS] = Boot_Comm_CheckSum(ack_uart->ackBuffer, data_len); #if DBG_LOG_EN Dbg_Print_Buff(DBG_BIT_SYS_STATUS,"ACKBuff ",ack_uart->ackBuffer,data_len); #endif //MCU485_SendData(ack_uart->ackBuffer, data_len); Set_GroupSend(ack_uart->ackBuffer,data_len,0x01,ack_uart->ackValidity,100); //ack_uart->ackLen = 0x00; } /******************************************************************************* * Function Name : APP_Flash_AllEase * Description : 擦除APP Flash空间 *******************************************************************************/ void APP_Flash_AllEase(void) { for(U32_T index = APP_Flash_StartAddr; index < APP_Flash_EndAddr;index+=APP_Flash_PageSize){ SYSCON_IWDCNT_Reload(); PageErase(index); } } /******************************************************************************* * Function Name : MCU_EEPROM_AllEase * Description : 擦除EEPROM 空间 *******************************************************************************/ void MCU_EEPROM_AllEase(void) { for(U32_T index = MCU_EEPROM_StartAddr; index < MCU_EEPROM_EndAddr;index+=MCU_EEPROM_PageSize){ SYSCON_IWDCNT_Reload(); PageErase(index); } } /******************************************************************************* * Function Name : APP_FEATURE_Flash_Ease * Description : 擦除APP特征区 Flash空间 *******************************************************************************/ void APP_FEATURE_Flash_Ease(void) { PageErase(APP_FEATURE_Flash_Addr); } /******************************************************************************* * Function Name : Boot_Comm_UpgradeProcess * Description : Boot通讯数据处理函数 *******************************************************************************/ U8_T Boot_Comm_UpgradeProcess(U8_T *data,U16_T len) { U8_T deal_flag = 0,group_flag = 0,reply_flag = 0,setinfo_flag = 0,crcResultFlag = 0; U16_T data_len = 0,crcNumIndex = 0; U32_T temp_data = 0,temp_data_2 = 0; data_len = data[BCOMM_FMT_LEN_H]; data_len <<= 8; data_len |= data[BCOMM_FMT_LEN_L]; if(len != data_len) { #if DBG_LOG_EN Dbg_Println(DBG_BIT_SYS_STATUS,"Len Fail "); #endif return 0x01; } if(Boot_Comm_CheckSum(data,len) != 0) { #if DBG_LOG_EN Dbg_Println(DBG_BIT_SYS_STATUS,"Boot_Comm_CheckSum Fail "); #endif return 0x02; } if( (data[BCOMM_FMT_SN] & 0x80) == 0x80){ //群发标志位 group_flag = 0x01; if( (data[BCOMM_FMT_SN] & 0x0F) != g_boot.sn){ deal_flag = 0x01; #if DBG_LOG_EN Dbg_Println(DBG_BIT_SYS_STATUS,"Group Data SN Disaffinity,Processing Data"); #endif }else { deal_flag = 0x00; #if DBG_LOG_EN Dbg_Println(DBG_BIT_SYS_STATUS,"Group Data SN The Same,No Processing Data"); #endif } }else { //单发标志位 group_flag = 0x00; if( (data[BCOMM_FMT_SN] & 0x0F) != g_boot.sn){ //包序号不太相同,需要处理 #if DBG_LOG_EN Dbg_Println(DBG_BIT_SYS_STATUS,"Single Data SN Disaffinity,Processing Data"); #endif deal_flag = 0x01; reply_flag = 0x01; }else if( (data[BCOMM_FMT_SN] & 0x40) == 0x40 ){ //包序号相同,重发标志位置位,不处理,但是需要回复数据,回复上次的数据内容 deal_flag = 0x00; /*重发数据包命令与上一次的命令相同的话,直接回复上一次的数据内容*/ if(data[BCOMM_FMT_CMD] == g_boot.ackBuffer[BCOMM_FMT_CMD] ){ reply_flag = 0x01; } #if DBG_LOG_EN Dbg_Println(DBG_BIT_SYS_STATUS,"Single Data SN The Same,No Processing Data"); #endif } } /*判断类型是否相同,且不是广播类型*/ if( (data[BCOMM_FMT_TYPE] != g_mcu_dev.dev_type) && (data[BCOMM_FMT_TYPE] != 0xFF) ){ #if DBG_LOG_EN Dbg_Println(DBG_BIT_SYS_STATUS,"Boot_Comm_RecvType %d - %d ",g_mcu_dev.dev_type,data[BCOMM_FMT_TYPE]); #endif return 0x03; } /*判断是否广播类型与广播地址*/ if( (data[BCOMM_FMT_RXAddr] != g_mcu_dev.dev_addr) && (data[BCOMM_FMT_RXAddr] != 0xFF) ){ #if DBG_LOG_EN Dbg_Println(DBG_BIT_SYS_STATUS,"Boot_Comm_RecvAddr %d - %d ",g_mcu_dev.dev_addr,data[BCOMM_FMT_RXAddr]); #endif return 0x04; } Boot_Time_Refresh(); g_boot.pc_addr = data[BCOMM_FMT_TXAddr]; g_boot.sn = data[BCOMM_FMT_SN] & 0x0F; g_boot.cmd = data[BCOMM_FMT_CMD]; switch(g_boot.cmd){ case BCOMM_CMD_Handshake: //握手命令 if( (deal_flag == 0x01) && (data_len >= (BCOMM_FMT_PARAM + 4) ) ){ #if DBG_LOG_EN Dbg_Println(DBG_BIT_SYS_STATUS,"BCOMM_CMD_Handshake Proecessing "); #endif /*设置Boot 超时时间*/ temp_data = data[BCOMM_FMT_PARAM + 1]; temp_data <<= 8; temp_data |= data[BCOMM_FMT_PARAM]; if(temp_data != g_boot.bootTimeout){ g_boot.bootTimeout = temp_data; if(g_boot.bootTimeout < 10) g_boot.bootTimeout = 10; g_boot.bootTimeout = g_boot.bootTimeout * 1000; } /*回复数据的有效期*/ temp_data = data[BCOMM_FMT_PARAM + 3]; temp_data <<= 8; temp_data |= data[BCOMM_FMT_PARAM + 2]; g_boot.ackValidity = temp_data; } //握手命令 - 需要回复的数据,正常回复 if(reply_flag != 0x01) break; //不回复,直接退出 g_boot.ackBuffer[BCOMM_FMT_PARAM] = Project_Area; //当前处于Bootload区域 0x01:Boot;0x02:APP g_boot.ackBuffer[BCOMM_FMT_PARAM + 1] = g_mcu_dev.dev_boot_ver; //Boot 软件版本号 g_boot.ackBuffer[BCOMM_FMT_PARAM + 2] = g_mcu_dev.dev_app_ver; //APP 软件版本号 //MCU UID g_boot.ackBuffer[BCOMM_FMT_PARAM + 3] = 0x03; //UUID 长度 MD203 UID 3Byte g_boot.ackBuffer[BCOMM_FMT_PARAM + 4] = SYSCON->UID0; g_boot.ackBuffer[BCOMM_FMT_PARAM + 5] = SYSCON->UID1; g_boot.ackBuffer[BCOMM_FMT_PARAM + 6] = SYSCON->UID2; //机型编号 - 32Byte 最长32Byte if(g_mcu_dev.dev_name_len > EEPROM_DEV_NAME_Size) g_mcu_dev.dev_name_len = EEPROM_DEV_NAME_Size; g_boot.ackBuffer[BCOMM_FMT_PARAM + 7] = g_mcu_dev.dev_name_len; for(U8_T i=0;i= g_boot.bootTimeout) { while(1); //执行看门狗复位 } } void Jump_To_APP(void) { volatile U32_T EIPaddr = g_app_feature.app_start_addr + 0x010C; asm("mov r0,%0\n"::"r"(EIPaddr):); // APP入口地址 __start label的值 asm(" jmp r0 "); } U8_T Check_APP_Feature(void) { U8_T temp_buff[530]; U16_T crcNumIndex = 0,temp_data = 0,temp_data_2 = 0; U32_T crc_data_len = 0,crc_feature_len = 0; /*读取APP 特征区*/ ReadDataArry_U8(APP_FEATURE_Flash_Addr,sizeof(APP_FEATURE_INFO_T),temp_buff); #if DBG_LOG_EN Dbg_Println(DBG_BIT_SYS_STATUS,"App Feature Size:%d",sizeof(APP_FEATURE_INFO_T)); Dbg_Print_Buff(DBG_BIT_SYS_STATUS,"App Feature Buff:",temp_buff,sizeof(APP_FEATURE_INFO_T)); #endif crc_data_len = temp_buff[1]; crc_data_len <<= 8; crc_data_len |= temp_buff[0]; temp_buff[0] = 0x00; temp_buff[1] = 0x00; if( NetCRC16((U8_T *)temp_buff,sizeof(APP_FEATURE_INFO_T)) != crc_data_len ) { #if DBG_LOG_EN Dbg_Println(DBG_BIT_SYS_STATUS,"App Feature CRC ERROR"); #endif return 0x01; } memcpy(&g_app_feature,temp_buff,sizeof(APP_FEATURE_INFO_T)); g_app_feature.crcL_check = crc_data_len & 0xFF; g_app_feature.crcH_check = (crc_data_len >> 8) & 0xFF; if(g_app_feature.app_flag != App_Procedure_Ready) { #if DBG_LOG_EN Dbg_Println(DBG_BIT_SYS_STATUS,"App Feature Flag ERROR"); #endif return 0x02; //没有APP标志位 } if( (g_app_feature.app_start_addr >= APP_Flash_StartAddr) && (g_app_feature.app_end_addr < APP_Flash_EndAddr) && (g_app_feature.app_end_addr > g_app_feature.app_start_addr) && (g_app_feature.app_crc_size == 512) ) { crc_data_len = g_app_feature.app_end_addr - g_app_feature.app_start_addr; #if DBG_LOG_EN Dbg_Println(DBG_BIT_SYS_STATUS,"App Len :%d ",crc_data_len); #endif if( (crc_data_len % g_app_feature.app_crc_size ) != 0x00 ){ crc_feature_len = ((crc_data_len / g_app_feature.app_crc_size) + 1) * 2; }else { crc_feature_len = (crc_data_len / g_app_feature.app_crc_size) * 2; } if(g_app_feature.app_crc_len != crc_feature_len) { #if DBG_LOG_EN Dbg_Println(DBG_BIT_SYS_STATUS,"App CRC Len :%d - %d",crc_feature_len,g_app_feature.app_crc_len); #endif return 0x03; //APP CRC长度不对 } for(U32_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) { SYSCON_IWDCNT_Reload(); 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; } ReadDataArry_U8(crc_addr,crc_data_len,temp_buff); temp_data = NetCRC16(temp_buff,crc_data_len); temp_data_2 = g_app_feature.app_crc[crcNumIndex + 1]; temp_data_2 <<= 8; temp_data_2 |= g_app_feature.app_crc[crcNumIndex]; #if DBG_LOG_EN Dbg_Println(DBG_BIT_SYS_STATUS,"App CRC ADDR:%08x %04x-%04x",crc_addr,temp_data,temp_data_2); #endif if(temp_data != temp_data_2){ /*校验失败 - */ #if DBG_LOG_EN Dbg_Println(DBG_BIT_SYS_STATUS,"App CRC Fail ADDR:%08X %04X-%04X",crc_addr,temp_data,temp_data_2); #endif return 0x04; //校验失败 } crcNumIndex += 2; } }else { #if DBG_LOG_EN Dbg_Println(DBG_BIT_SYS_STATUS,"App Feature StartAddr ERROR"); Dbg_Println(DBG_BIT_SYS_STATUS,"APP app_start_addr:%08x",g_app_feature.app_start_addr); Dbg_Println(DBG_BIT_SYS_STATUS,"APP app_end_addr:%08x",g_app_feature.app_end_addr); Dbg_Println(DBG_BIT_SYS_STATUS,"APP app_crc_len:%d",g_app_feature.app_crc_len); #endif return 0x05; //起始地址不正确 } return 0x00; }