123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299 |
- /********************************************************************************
- * 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<j;i++){
- checksum=checksum^buf[i];
- }
- buf[j++]=checksum;
- return j;
- }
- /////////////////////////////////////////////////////////////////
- /*******************************************************************
- 封包,获取新版本文件信息
- |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++]=TCP_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;i<j;i++){
- checksum=checksum^buf[i];
- }
- buf[j++]=checksum;
- return j;
- }
- /******************************************************
- type=0 --- 4G
- type=1 --- WireLan
- ******************************************************/
- M_RESULT FoTaGetFileData(int type)
- {
- unsigned short subLen;
- unsigned char txbuf[35];
- int r;
- subLen=PacketGetFileData(txbuf,sutFotaPara.nextOffset,1024);
- if(type==0){
- r= ModemSendToSocket(0,txbuf,subLen);
- }else{
- r= WiredSendTcpData(txbuf,subLen);
- }
- return r;
- }
- /******************************************************
- type=0 --- 4G
- type=1 --- WireLan
- ******************************************************/
- M_RESULT FoTaGetFileInfo(int type)
- {
- int r,len;
- SlwTrace(DEBUG,">>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(len<length)
- {
- if((length-len)>1024)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;
- }
- }
|