#include "includes.h" SUT_FOTA_PARA sutFotaPara; static void IapGetUpdateVersion(void); static void IapGetUpdateData(uint32_t offset,uint16_t len); static char IapCheckFileMD5_SPI_Flash(unsigned int dataAddr,unsigned int length,uint8_t *MD5); void FotaDataInit(void) { memset((unsigned char *)&sutFotaPara, 0, sizeof(sutFotaPara)); sutFotaPara.fotaFlag=FOTA_OFF; } void TriggerFotaOption(FOTA_TYPE fotaStatus) { char buf[20]; sutFotaPara.fotaFlag=fotaStatus; if(FOTA_ON==fotaStatus) return; if(sutFotaPara.init_tcpStatus!=0) { snprintf(buf,sizeof(buf), "AT+ZIPCLOSE=%c", FOTA_SOCKET); ModemSendAT(buf); sutFotaPara.init_tcpStatus=0; } sutFotaPara.fotaStatus=LOAD_GET_FILEINFO; } void FotaHandle(void) { char buf[40]; if(sutFotaPara.fotaFlag == FOTA_OFF) return; if(sutSysStatus.init_tcpStatus!=0) { snprintf(buf,sizeof(buf), "AT+ZIPCLOSE=%c", DATA_SOCKET); ModemSendAT(buf); sutSysStatus.init_tcpStatus=0; } if(sutFotaPara.init_tcpStatus==0) { sutFotaPara.time_10ms_cnt=os_time; return; } switch(sutFotaPara.fotaStatus) { case LOAD_GET_FILEINFO://获取文件信息 //最多尝试三次 if(os_time > sutFotaPara.time_10ms_cnt) { sutFotaPara.time_10ms_cnt=os_time+TIMEOUT_10MS_FILE;//5秒进行一次文件信息获取 if(++sutFotaPara.retryTime > MAX_TIME_GET_FILE) {//三次获取文件不成功 SlwTrace(INF, "ReqFileFailed",1); sutFotaPara.fotaStatus=LOAD_DONE; }else{ SlwTrace(INF, "FotaVersion_req",1); IapGetUpdateVersion(); } } break; case LOAD_GET_FILEDATA://拉取文件内容 //最多重新发起五次文件数据重传 if(os_time > sutFotaPara.time_10ms_cnt) { sutFotaPara.time_10ms_cnt=os_time+TIMEOUT_10MS_DATA;//3秒后没有数据应答,重新发起请求 if(++sutFotaPara.retryTime > MAX_TIME_GET_DATA) {//5次重传都不成功 SlwTrace(INF, "ReqDataFailed",1); sutFotaPara.fotaStatus=LOAD_DONE; }else{ SlwTrace(INF, "FotaData_req",1); IapGetUpdateData(sutFotaPara.lastOffset,DATA_DRAT_SIZE_PER_TIME); } } break; case LOAD_FILE_CHECK://较验文件MD5 if(0!=IapCheckFileMD5_SPI_Flash(APP_FILE_DATA_ADDR, sutFotaPara.fileLength, sutFotaPara.MD5)) {//较验成功,准备跳转到IAP前准备 memcpy(sutProductPara.MD5, sutFotaPara.MD5,sizeof(sutProductPara.MD5)); sutProductPara.ExAddr=APP_FILE_DATA_ADDR; sutProductPara.AppLen=sutFotaPara.fileLength; memcpy(sutProductPara.FoTaMark, "FoTa", 4); SaveParaToInterFlash(); SlwTrace(INF, "GoingUpdate",1); WdgsFeed(); while(1); }else{ SlwTrace(INF, "Md5Err",1); sutFotaPara.fotaStatus=LOAD_DONE; } break; case LOAD_DONE://完成操作 SlwTrace(INF, "FotaQuit",1); TriggerFotaOption(FOTA_OFF); break; } } void HGS_FotaHandle(unsigned char *data, unsigned short len) { unsigned char *p=data; unsigned short i,realDataLen,thisLen; unsigned char sum; unsigned int thisOffset; char info[30]; SUT_FILE_INFO *pFileInfo; SUTDS ds; SUTDL dl1; SUTDL dl2; //判断包头标识 if(PACKET_HEAD != p[0]) { SlwTrace(INF, "HeaderErr",1); return; } //检测长度 ds.Data.ucData.b2=p[2]; ds.Data.ucData.b1=p[3]; realDataLen=ds.Data.usData; if(len != (realDataLen+4)) { SlwTrace(INF, "LenghtErr",1); return; } //检测校验和 sum=0; for(i=0;iFileName, info)) { SlwTrace(INF, "FNameErr",1); return; } dl1.Data.ulData=pFileInfo->FileLength; dl2.Data.ucData.b1=dl1.Data.ucData.b4; dl2.Data.ucData.b2=dl1.Data.ucData.b3; dl2.Data.ucData.b3=dl1.Data.ucData.b2; dl2.Data.ucData.b4=dl1.Data.ucData.b1; sutFotaPara.fileLength=dl2.Data.ulData; sutFotaPara.encrypted=pFileInfo->encrypted; sutFotaPara.key=pFileInfo->key; memcpy(sutFotaPara.MD5,pFileInfo->MD5,16); if(sutFotaPara.fileLength==0) {//服务器没有文件,退出升级 SlwTrace(INF, "NoFileInServer",1); sutFotaPara.fotaStatus=LOAD_DONE; return; } sutFotaPara.fotaStatus=LOAD_GET_FILEDATA; sutFotaPara.lastOffset=0; sutFotaPara.time_10ms_cnt=os_time+TIMEOUT_10MS_DATA; IapGetUpdateData(sutFotaPara.lastOffset,DATA_DRAT_SIZE_PER_TIME); break; case CMD_GET_FILE_DATA_ACK: //offset dl1.Data.ucData.b4=p[4]; dl1.Data.ucData.b3=p[5]; dl1.Data.ucData.b2=p[6]; dl1.Data.ucData.b1=p[7]; thisOffset=dl1.Data.ulData; //lenght ds.Data.ucData.b2=p[8]; ds.Data.ucData.b1=p[9]; thisLen=ds.Data.usData; //save sFlash_Write(p+10,APP_FILE_DATA_ADDR+thisOffset,thisLen); //done? if((thisOffset+thisLen) >= sutFotaPara.fileLength) { snprintf(info,sizeof(info), "\r\nHBD=%d\r\nLoad done",sutFotaPara.fileLength); SlwTrace(INF, info, 1); sutFotaPara.fotaStatus=LOAD_FILE_CHECK; }else{ sutFotaPara.time_10ms_cnt=os_time+TIMEOUT_10MS_DATA; sutFotaPara.lastOffset=thisOffset+thisLen; snprintf(info,sizeof(info), "\r\nHBD=%d",sutFotaPara.lastOffset); SlwTrace(INF, info, 1); IapGetUpdateData(sutFotaPara.lastOffset, DATA_DRAT_SIZE_PER_TIME); } break; default: snprintf(info,sizeof(info), "SkipCmd:0x%02x",p[1]); SlwTrace(INF, info,1); break; } } ///////////////////////////////////////////////////////////////// /******************************************************************* 封包,获取新版本文件信息 |Head|Cmd|length(2) | data... | Check| Head 包头,固定为0xAB Cmd 命令字 length 后续的数据长度,包括到Check的长度 length=1+data.len Check 从Head开始按字节异或运算 data: unsigned long PSN;//终端编号 char FileName[20];//文件名,不够的在末尾补0 总长 24+5=29 bytes *******************************************************************/ unsigned short PacketGetFileInfo(unsigned char *buf) { unsigned char checksum; unsigned short i,j,k; char FileName[21]; SUTDL dl; SUTDS ds; j=0; memset(buf,0,29); buf[j++]=PACKET_HEAD; buf[j++]=CMD_GET_FILE_INFO; buf[j++]=0; buf[j++]=24+1;//数据24字节,1字节checksum //PSN dl.Data.ulData=sutProductPara.PSN; //因为协议要求大端模式传输,所以需要转一下 buf[j++]=dl.Data.ucData.b4; buf[j++]=dl.Data.ucData.b3; buf[j++]=dl.Data.ucData.b2; buf[j++]=dl.Data.ucData.b1; //FileName snprintf(FileName,sizeof(FileName), "%s_V%d.bin", sutProductPara.ProductName,sutFotaPara.targetVersion); for(i=0;i<20;i++){ buf[j++]=FileName[i]; } //校验 checksum=0; for(i=0;i1024)l=1024; else l=length-len; sFlash_Read(data,dataAddr+len,l); MD5Update(&mdContext,data,l); len+=l; } MD5Final(&mdContext); //check for(i=0;i<16;i++){ if(MD5[i]!=mdContext.digest[i])break; } if(i<16)return 0; else return 1; } void FotaTest(void) { #if(FOTA_DEBUG==1) //测试空中升级用 static unsigned char flag=0; static unsigned char tick=0; char info[30]; if(flag!=0) return; if(++tick > 60) { SlwTrace(INF, "Test FotaOn",1); sutFotaPara.targetVersion=3000; flag=1; TriggerFotaOption(FOTA_ON); }else{ snprintf(info,sizeof(info), "Tick:%d",tick); SlwTrace(INF, info, 1); } #endif }