/******************************************************************************** * File Name: MyFoTa.c * Function Describe: 远程升级APP * Explain: * Writer: ShiLiangWen * Date: 2019-2-17 *******************************************************************************/ #include "includes.h" SUT_FOTA_PARA sutFotaPara; void MyFoTaInit(void) { memset(&sutFotaPara,0,sizeof(SUT_FOTA_PARA)); } /******************************************************************* 封包,获取新版本 |Head|Cmd|length(2) | data... | Check| Head 包头,固定为0xAB Cmd 命令字 length 后续的数据长度,包括到Check的长度 length=1+data.len Check 从Head开始按字节异或运算 data: unsigned long PSN; //终端编号 unsigned char FileName[20]; //文件名 如:RT101_V102.bin unsigned long offset; //请求数据在文件中的开始位置 unsigned short len; //请求数据的长度,服务器返回的数据可能小于等于此长度 *******************************************************************/ unsigned short PacketGetFileData(unsigned char *buf,unsigned int offset,unsigned short len) { unsigned char checksum; unsigned short i,j; char FileName[21]; SUTDL dl; SUTDS ds; j=0; memset(buf,0,35); buf[j++]=TCP_PACKET_HEAD; buf[j++]=CMD_GET_FILE_DATA; buf[j++]=0; buf[j++]=30+1;//数据18字节,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]; } //offset dl.Data.ulData=offset; //因为协议要求大端模式传输,所以需要转一下 buf[j++]=dl.Data.ucData.b4; buf[j++]=dl.Data.ucData.b3; buf[j++]=dl.Data.ucData.b2; buf[j++]=dl.Data.ucData.b1; //len ds.Data.usData=len; buf[j++]=ds.Data.ucData.b2; buf[j++]=ds.Data.ucData.b1; //校验 checksum=0; for(i=0;i>SendGetFileInfo>>\r\n"); len=PacketGetFileInfo(g_ucPropacketBuf); if(type==0){ r = ModemSendToSocket(0,g_ucPropacketBuf,len); }else{ r= WiredSendTcpData(g_ucPropacketBuf,len); } return r; } static char IapCheckFileMD5_SPI_Flash(unsigned int dataAddr,unsigned int length,uint8_t *MD5) { MD5_CTX mdContext; //unsigned char data[1024]; unsigned char *data=g_ucPropacketBuf;//校验的时候不会发TCP数据,因此可以共用 unsigned long len,l; char tembuf[5]; int i; MD5Init(&mdContext); len=0; while(len1024)l=1024; else l=length-len; SPI_Flash_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; } /************************************************************************* FoTaRecvData *************************************************************************/ void FoTaRecvData(unsigned char *pData,unsigned short DataLen) { char buf[50]; unsigned char cmd; unsigned short Len; unsigned char check; int i; if(DataLen<5 || pData[0]!=0xAB){ SlwTrace(DEBUG,"TcpRecvData error!\r\n"); return; } Len=(((unsigned short)pData[2])<<8)+(unsigned short)pData[3]; if(Len+4!=DataLen){ SlwTrace(DEBUG,"TcpRecvData len error!\r\n"); return; } check=0; for(i=0;i<(DataLen-1);i++){ check^=pData[i]; } if(check!=pData[DataLen-1]){ SlwTrace(DEBUG,"TcpRecvData check error!\r\n"); return; } //----------- cmd=pData[1]; //snprintf(buf,sizeof(buf),"Recv cmd=%02X len=%d\r\n",cmd,DataLen); //SlwTrace(DEBUG,buf); switch(cmd){ case CMD_GET_FILE_INFO_ACK: SlwTrace(DEBUG,"CMD_GET_FILE_INFO_ACK<<\r\n"); SUT_FILE_INFO *pFileInfo; unsigned short i,realDataLen,thisLen; SUTDS ds; SUTDL dl1; SUTDL dl2; char info[30]; pFileInfo=(SUT_FILE_INFO *)&pData[4]; snprintf(info,sizeof(info), "%s_V%d.bin", sutProductPara.ProductName,sutFotaPara.targetVersion); if(0!=strcmp(pFileInfo->FileName, info)) {//文件名和版本号不对,结束升级 SlwTrace(DEBUG, "FNameErr\r\n"); sutFotaPara.fotaStatus=FOTA_END; 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(DEBUG, "NoFileInServer"); sutFotaPara.fotaStatus=FOTA_END; return; } sutFotaPara.lastOffset=-1; sutFotaPara.nextOffset=0; sutFotaPara.reSendCt=FOTA_RE_SEND_CT_MAX; sutFotaPara.fotaStatus=FOTA_GET_FILEDATA; break; case CMD_GET_FILE_DATA_ACK: SlwTrace(DEBUG,"CMD_GET_FILE_DATA_ACK<<\r\n"); unsigned int thisOffset; //offset dl1.Data.ucData.b4=pData[4]; dl1.Data.ucData.b3=pData[5]; dl1.Data.ucData.b2=pData[6]; dl1.Data.ucData.b1=pData[7]; thisOffset=dl1.Data.ulData; //lenght ds.Data.ucData.b2=pData[8]; ds.Data.ucData.b1=pData[9]; thisLen=ds.Data.usData; //save SPI_Flash_Write(pData+10,APP_FILE_DATA_ADDR+thisOffset,thisLen); //done? if((thisOffset+thisLen) >= sutFotaPara.fileLength) { snprintf(info,sizeof(info), "\r\nHBD=%d\r\nLoad done\r\n",sutFotaPara.fileLength); SlwTrace(DEBUG, info); //校验 if(0!=IapCheckFileMD5_SPI_Flash(APP_FILE_DATA_ADDR, sutFotaPara.fileLength, sutFotaPara.MD5)) {//较验成功,准备跳转到IAP前准备 memcpy(sutDeviceConfig.MD5, sutFotaPara.MD5,sizeof(sutDeviceConfig.MD5)); sutDeviceConfig.AppExAddr=APP_FILE_DATA_ADDR; sutDeviceConfig.AppLen=sutFotaPara.fileLength; sutDeviceConfig.FoTaMark[0]='F';sutDeviceConfig.FoTaMark[1]='o';sutDeviceConfig.FoTaMark[2]='T';sutDeviceConfig.FoTaMark[3]='a'; SaveDeviceConfigToFlash(); SlwTrace(DEBUG, "GoingUpdate\r\n"); //系统复位 ModemPowerOff(); SystemReboot(); }else{ SlwTrace(INF, "Md5Err"); //重新升级 sutFotaPara.fotaStatus=FOTA_GET_FILEINFO; } }else{ sutFotaPara.reSendCt=FOTA_RE_SEND_CT_MAX; sutFotaPara.lastOffset=sutFotaPara.nextOffset; sutFotaPara.nextOffset=thisOffset+thisLen; snprintf(info,sizeof(info), "\r\nHBD=%d\r\n",sutFotaPara.lastOffset); SlwTrace(DEBUG, info); } break; } }