MyFoTa.c 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. /********************************************************************************
  2. * File Name: MyFoTa.c
  3. * Function Describe: 远程升级APP
  4. * Explain:
  5. * Writer: ShiLiangWen
  6. * Date: 2019-2-17
  7. *******************************************************************************/
  8. #include "includes.h"
  9. SUT_FOTA_PARA sutFotaPara;
  10. void MyFoTaInit(void)
  11. {
  12. memset(&sutFotaPara,0,sizeof(SUT_FOTA_PARA));
  13. }
  14. /*******************************************************************
  15. 封包,获取新版本
  16. |Head|Cmd|length(2) | data... | Check|
  17. Head 包头,固定为0xAB
  18. Cmd 命令字
  19. length 后续的数据长度,包括到Check的长度 length=1+data.len
  20. Check 从Head开始按字节异或运算
  21. data:
  22. unsigned long PSN; //终端编号
  23. unsigned char FileName[20]; //文件名 如:RT101_V102.bin
  24. unsigned long offset; //请求数据在文件中的开始位置
  25. unsigned short len; //请求数据的长度,服务器返回的数据可能小于等于此长度
  26. *******************************************************************/
  27. unsigned short PacketGetFileData(unsigned char *buf,unsigned int offset,unsigned short len)
  28. {
  29. unsigned char checksum;
  30. unsigned short i,j;
  31. char FileName[21];
  32. SUTDL dl;
  33. SUTDS ds;
  34. j=0;
  35. memset(buf,0,35);
  36. buf[j++]=TCP_PACKET_HEAD;
  37. buf[j++]=CMD_GET_FILE_DATA;
  38. buf[j++]=0;
  39. buf[j++]=30+1;//数据18字节,1字节checksum
  40. //PSN
  41. dl.Data.ulData=sutProductPara.PSN; //因为协议要求大端模式传输,所以需要转一下
  42. buf[j++]=dl.Data.ucData.b4;
  43. buf[j++]=dl.Data.ucData.b3;
  44. buf[j++]=dl.Data.ucData.b2;
  45. buf[j++]=dl.Data.ucData.b1;
  46. //FileName
  47. snprintf(FileName,sizeof(FileName), "%s_V%d.bin", sutProductPara.ProductName,sutFotaPara.targetVersion);
  48. for(i=0;i<20;i++){
  49. buf[j++]=FileName[i];
  50. }
  51. //offset
  52. dl.Data.ulData=offset; //因为协议要求大端模式传输,所以需要转一下
  53. buf[j++]=dl.Data.ucData.b4;
  54. buf[j++]=dl.Data.ucData.b3;
  55. buf[j++]=dl.Data.ucData.b2;
  56. buf[j++]=dl.Data.ucData.b1;
  57. //len
  58. ds.Data.usData=len;
  59. buf[j++]=ds.Data.ucData.b2;
  60. buf[j++]=ds.Data.ucData.b1;
  61. //校验
  62. checksum=0;
  63. for(i=0;i<j;i++){
  64. checksum=checksum^buf[i];
  65. }
  66. buf[j++]=checksum;
  67. return j;
  68. }
  69. /////////////////////////////////////////////////////////////////
  70. /*******************************************************************
  71. 封包,获取新版本文件信息
  72. |Head|Cmd|length(2) | data... | Check|
  73. Head 包头,固定为0xAB
  74. Cmd 命令字
  75. length 后续的数据长度,包括到Check的长度 length=1+data.len
  76. Check 从Head开始按字节异或运算
  77. data:
  78. unsigned long PSN;//终端编号
  79. char FileName[20];//文件名,不够的在末尾补0
  80. 总长 24+5=29 bytes
  81. *******************************************************************/
  82. unsigned short PacketGetFileInfo(unsigned char *buf)
  83. {
  84. unsigned char checksum;
  85. unsigned short i,j,k;
  86. char FileName[21];
  87. SUTDL dl;
  88. SUTDS ds;
  89. j=0;
  90. memset(buf,0,29);
  91. buf[j++]=TCP_PACKET_HEAD;
  92. buf[j++]=CMD_GET_FILE_INFO;
  93. buf[j++]=0;
  94. buf[j++]=24+1;//数据24字节,1字节checksum
  95. //PSN
  96. dl.Data.ulData=sutProductPara.PSN; //因为协议要求大端模式传输,所以需要转一下
  97. buf[j++]=dl.Data.ucData.b4;
  98. buf[j++]=dl.Data.ucData.b3;
  99. buf[j++]=dl.Data.ucData.b2;
  100. buf[j++]=dl.Data.ucData.b1;
  101. //FileName
  102. snprintf(FileName,sizeof(FileName), "%s_V%d.bin", sutProductPara.ProductName,sutFotaPara.targetVersion);
  103. for(i=0;i<20;i++){
  104. buf[j++]=FileName[i];
  105. }
  106. //校验
  107. checksum=0;
  108. for(i=0;i<j;i++){
  109. checksum=checksum^buf[i];
  110. }
  111. buf[j++]=checksum;
  112. return j;
  113. }
  114. /******************************************************
  115. type=0 --- 4G
  116. type=1 --- WireLan
  117. ******************************************************/
  118. M_RESULT FoTaGetFileData(int type)
  119. {
  120. unsigned short subLen;
  121. unsigned char txbuf[35];
  122. int r;
  123. subLen=PacketGetFileData(txbuf,sutFotaPara.nextOffset,1024);
  124. if(type==0){
  125. r= ModemSendToSocket(0,txbuf,subLen);
  126. }else{
  127. r= WiredSendTcpData(txbuf,subLen);
  128. }
  129. return r;
  130. }
  131. /******************************************************
  132. type=0 --- 4G
  133. type=1 --- WireLan
  134. ******************************************************/
  135. M_RESULT FoTaGetFileInfo(int type)
  136. {
  137. int r,len;
  138. SlwTrace(DEBUG,">>SendGetFileInfo>>\r\n");
  139. len=PacketGetFileInfo(g_ucPropacketBuf);
  140. if(type==0){
  141. r = ModemSendToSocket(0,g_ucPropacketBuf,len);
  142. }else{
  143. r= WiredSendTcpData(g_ucPropacketBuf,len);
  144. }
  145. return r;
  146. }
  147. static char IapCheckFileMD5_SPI_Flash(unsigned int dataAddr,unsigned int length,uint8_t *MD5)
  148. {
  149. MD5_CTX mdContext;
  150. //unsigned char data[1024];
  151. unsigned char *data=g_ucPropacketBuf;//校验的时候不会发TCP数据,因此可以共用
  152. unsigned long len,l;
  153. char tembuf[5];
  154. int i;
  155. MD5Init(&mdContext);
  156. len=0;
  157. while(len<length)
  158. {
  159. if((length-len)>1024)l=1024;
  160. else l=length-len;
  161. SPI_Flash_Read(data,dataAddr+len,l);
  162. MD5Update(&mdContext,data,l);
  163. len+=l;
  164. }
  165. MD5Final(&mdContext);
  166. //check
  167. for(i=0;i<16;i++){
  168. if(MD5[i]!=mdContext.digest[i])break;
  169. }
  170. if(i<16)return 0;
  171. else return 1;
  172. }
  173. /*************************************************************************
  174. FoTaRecvData
  175. *************************************************************************/
  176. void FoTaRecvData(unsigned char *pData,unsigned short DataLen)
  177. {
  178. char buf[50];
  179. unsigned char cmd;
  180. unsigned short Len;
  181. unsigned char check;
  182. int i;
  183. if(DataLen<5 || pData[0]!=0xAB){
  184. SlwTrace(DEBUG,"TcpRecvData error!\r\n");
  185. return;
  186. }
  187. Len=(((unsigned short)pData[2])<<8)+(unsigned short)pData[3];
  188. if(Len+4!=DataLen){
  189. SlwTrace(DEBUG,"TcpRecvData len error!\r\n");
  190. return;
  191. }
  192. check=0;
  193. for(i=0;i<(DataLen-1);i++){
  194. check^=pData[i];
  195. }
  196. if(check!=pData[DataLen-1]){
  197. SlwTrace(DEBUG,"TcpRecvData check error!\r\n");
  198. return;
  199. }
  200. //-----------
  201. cmd=pData[1];
  202. //snprintf(buf,sizeof(buf),"Recv cmd=%02X len=%d\r\n",cmd,DataLen);
  203. //SlwTrace(DEBUG,buf);
  204. switch(cmd){
  205. case CMD_GET_FILE_INFO_ACK:
  206. SlwTrace(DEBUG,"CMD_GET_FILE_INFO_ACK<<\r\n");
  207. SUT_FILE_INFO *pFileInfo;
  208. unsigned short i,realDataLen,thisLen;
  209. SUTDS ds;
  210. SUTDL dl1;
  211. SUTDL dl2;
  212. char info[30];
  213. pFileInfo=(SUT_FILE_INFO *)&pData[4];
  214. snprintf(info,sizeof(info), "%s_V%d.bin", sutProductPara.ProductName,sutFotaPara.targetVersion);
  215. if(0!=strcmp(pFileInfo->FileName, info))
  216. {//文件名和版本号不对,结束升级
  217. SlwTrace(DEBUG, "FNameErr\r\n");
  218. sutFotaPara.fotaStatus=FOTA_END;
  219. return;
  220. }
  221. dl1.Data.ulData=pFileInfo->FileLength;
  222. dl2.Data.ucData.b1=dl1.Data.ucData.b4;
  223. dl2.Data.ucData.b2=dl1.Data.ucData.b3;
  224. dl2.Data.ucData.b3=dl1.Data.ucData.b2;
  225. dl2.Data.ucData.b4=dl1.Data.ucData.b1;
  226. sutFotaPara.fileLength=dl2.Data.ulData;
  227. sutFotaPara.encrypted=pFileInfo->encrypted;
  228. sutFotaPara.key=pFileInfo->key;
  229. memcpy(sutFotaPara.MD5,pFileInfo->MD5,16);
  230. if(sutFotaPara.fileLength==0)
  231. {//服务器没有文件,退出升级
  232. SlwTrace(DEBUG, "NoFileInServer");
  233. sutFotaPara.fotaStatus=FOTA_END;
  234. return;
  235. }
  236. sutFotaPara.lastOffset=-1;
  237. sutFotaPara.nextOffset=0;
  238. sutFotaPara.reSendCt=FOTA_RE_SEND_CT_MAX;
  239. sutFotaPara.fotaStatus=FOTA_GET_FILEDATA;
  240. break;
  241. case CMD_GET_FILE_DATA_ACK:
  242. SlwTrace(DEBUG,"CMD_GET_FILE_DATA_ACK<<\r\n");
  243. unsigned int thisOffset;
  244. //offset
  245. dl1.Data.ucData.b4=pData[4];
  246. dl1.Data.ucData.b3=pData[5];
  247. dl1.Data.ucData.b2=pData[6];
  248. dl1.Data.ucData.b1=pData[7];
  249. thisOffset=dl1.Data.ulData;
  250. //lenght
  251. ds.Data.ucData.b2=pData[8];
  252. ds.Data.ucData.b1=pData[9];
  253. thisLen=ds.Data.usData;
  254. //save
  255. SPI_Flash_Write(pData+10,APP_FILE_DATA_ADDR+thisOffset,thisLen);
  256. //done?
  257. if((thisOffset+thisLen) >= sutFotaPara.fileLength)
  258. {
  259. snprintf(info,sizeof(info), "\r\nHBD=%d\r\nLoad done\r\n",sutFotaPara.fileLength);
  260. SlwTrace(DEBUG, info);
  261. //校验
  262. if(0!=IapCheckFileMD5_SPI_Flash(APP_FILE_DATA_ADDR, sutFotaPara.fileLength, sutFotaPara.MD5))
  263. {//较验成功,准备跳转到IAP前准备
  264. memcpy(sutDeviceConfig.MD5, sutFotaPara.MD5,sizeof(sutDeviceConfig.MD5));
  265. sutDeviceConfig.AppExAddr=APP_FILE_DATA_ADDR;
  266. sutDeviceConfig.AppLen=sutFotaPara.fileLength;
  267. sutDeviceConfig.FoTaMark[0]='F';sutDeviceConfig.FoTaMark[1]='o';sutDeviceConfig.FoTaMark[2]='T';sutDeviceConfig.FoTaMark[3]='a';
  268. SaveDeviceConfigToFlash();
  269. SlwTrace(DEBUG, "GoingUpdate\r\n");
  270. //系统复位
  271. ModemPowerOff();
  272. SystemReboot();
  273. }else{
  274. SlwTrace(INF, "Md5Err");
  275. //重新升级
  276. sutFotaPara.fotaStatus=FOTA_GET_FILEINFO;
  277. }
  278. }else{
  279. sutFotaPara.reSendCt=FOTA_RE_SEND_CT_MAX;
  280. sutFotaPara.lastOffset=sutFotaPara.nextOffset;
  281. sutFotaPara.nextOffset=thisOffset+thisLen;
  282. snprintf(info,sizeof(info), "\r\nHBD=%d\r\n",sutFotaPara.lastOffset);
  283. SlwTrace(DEBUG, info);
  284. }
  285. break;
  286. }
  287. }