fota.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369
  1. #include "includes.h"
  2. SUT_FOTA_PARA sutFotaPara;
  3. static void IapGetUpdateVersion(void);
  4. static void IapGetUpdateData(uint32_t offset,uint16_t len);
  5. static char IapCheckFileMD5_SPI_Flash(unsigned int dataAddr,unsigned int length,uint8_t *MD5);
  6. void FotaDataInit(void)
  7. {
  8. memset((unsigned char *)&sutFotaPara, 0, sizeof(sutFotaPara));
  9. sutFotaPara.fotaFlag=FOTA_OFF;
  10. }
  11. void TriggerFotaOption(FOTA_TYPE fotaStatus)
  12. {
  13. char buf[20];
  14. sutFotaPara.fotaFlag=fotaStatus;
  15. if(FOTA_ON==fotaStatus) return;
  16. if(sutFotaPara.init_tcpStatus!=0)
  17. {
  18. snprintf(buf,sizeof(buf), "AT+ZIPCLOSE=%c", FOTA_SOCKET);
  19. ModemSendAT(buf);
  20. sutFotaPara.init_tcpStatus=0;
  21. }
  22. sutFotaPara.fotaStatus=LOAD_GET_FILEINFO;
  23. }
  24. void FotaHandle(void)
  25. {
  26. char buf[40];
  27. if(sutFotaPara.fotaFlag == FOTA_OFF) return;
  28. if(sutSysStatus.init_tcpStatus!=0)
  29. {
  30. snprintf(buf,sizeof(buf), "AT+ZIPCLOSE=%c", DATA_SOCKET);
  31. ModemSendAT(buf);
  32. sutSysStatus.init_tcpStatus=0;
  33. }
  34. if(sutFotaPara.init_tcpStatus==0)
  35. {
  36. sutFotaPara.time_10ms_cnt=os_time;
  37. return;
  38. }
  39. switch(sutFotaPara.fotaStatus)
  40. {
  41. case LOAD_GET_FILEINFO://获取文件信息
  42. //最多尝试三次
  43. if(os_time > sutFotaPara.time_10ms_cnt)
  44. {
  45. sutFotaPara.time_10ms_cnt=os_time+TIMEOUT_10MS_FILE;//5秒进行一次文件信息获取
  46. if(++sutFotaPara.retryTime > MAX_TIME_GET_FILE)
  47. {//三次获取文件不成功
  48. SlwTrace(INF, "ReqFileFailed",1);
  49. sutFotaPara.fotaStatus=LOAD_DONE;
  50. }else{
  51. SlwTrace(INF, "FotaVersion_req",1);
  52. IapGetUpdateVersion();
  53. }
  54. }
  55. break;
  56. case LOAD_GET_FILEDATA://拉取文件内容
  57. //最多重新发起五次文件数据重传
  58. if(os_time > sutFotaPara.time_10ms_cnt)
  59. {
  60. sutFotaPara.time_10ms_cnt=os_time+TIMEOUT_10MS_DATA;//3秒后没有数据应答,重新发起请求
  61. if(++sutFotaPara.retryTime > MAX_TIME_GET_DATA)
  62. {//5次重传都不成功
  63. SlwTrace(INF, "ReqDataFailed",1);
  64. sutFotaPara.fotaStatus=LOAD_DONE;
  65. }else{
  66. SlwTrace(INF, "FotaData_req",1);
  67. IapGetUpdateData(sutFotaPara.lastOffset,DATA_DRAT_SIZE_PER_TIME);
  68. }
  69. }
  70. break;
  71. case LOAD_FILE_CHECK://较验文件MD5
  72. if(0!=IapCheckFileMD5_SPI_Flash(APP_FILE_DATA_ADDR, sutFotaPara.fileLength, sutFotaPara.MD5))
  73. {//较验成功,准备跳转到IAP前准备
  74. memcpy(sutProductPara.MD5, sutFotaPara.MD5,sizeof(sutProductPara.MD5));
  75. sutProductPara.ExAddr=APP_FILE_DATA_ADDR;
  76. sutProductPara.AppLen=sutFotaPara.fileLength;
  77. memcpy(sutProductPara.FoTaMark, "FoTa", 4);
  78. SaveParaToInterFlash();
  79. SlwTrace(INF, "GoingUpdate",1);
  80. WdgsFeed();
  81. while(1);
  82. }else{
  83. SlwTrace(INF, "Md5Err",1);
  84. sutFotaPara.fotaStatus=LOAD_DONE;
  85. }
  86. break;
  87. case LOAD_DONE://完成操作
  88. SlwTrace(INF, "FotaQuit",1);
  89. TriggerFotaOption(FOTA_OFF);
  90. break;
  91. }
  92. }
  93. void HGS_FotaHandle(unsigned char *data, unsigned short len)
  94. {
  95. unsigned char *p=data;
  96. unsigned short i,realDataLen,thisLen;
  97. unsigned char sum;
  98. unsigned int thisOffset;
  99. char info[30];
  100. SUT_FILE_INFO *pFileInfo;
  101. SUTDS ds;
  102. SUTDL dl1;
  103. SUTDL dl2;
  104. //判断包头标识
  105. if(PACKET_HEAD != p[0])
  106. {
  107. SlwTrace(INF, "HeaderErr",1);
  108. return;
  109. }
  110. //检测长度
  111. ds.Data.ucData.b2=p[2];
  112. ds.Data.ucData.b1=p[3];
  113. realDataLen=ds.Data.usData;
  114. if(len != (realDataLen+4))
  115. {
  116. SlwTrace(INF, "LenghtErr",1);
  117. return;
  118. }
  119. //检测校验和
  120. sum=0;
  121. for(i=0;i<len-1;i++) sum ^= p[i];
  122. if(sum != p[len-1])
  123. {
  124. SlwTrace(INF, "SumErr",1);
  125. return;
  126. }
  127. //包正常,处理数据
  128. switch(p[1])//cmd type
  129. {
  130. case CMD_GET_FILE_INFO_ACK:
  131. pFileInfo=(SUT_FILE_INFO *)&p[4];
  132. snprintf(info,sizeof(info), "%s_V%d.bin", sutProductPara.ProductName,sutFotaPara.targetVersion);
  133. if(0!=strcmp(pFileInfo->FileName, info))
  134. {
  135. SlwTrace(INF, "FNameErr",1);
  136. return;
  137. }
  138. dl1.Data.ulData=pFileInfo->FileLength;
  139. dl2.Data.ucData.b1=dl1.Data.ucData.b4;
  140. dl2.Data.ucData.b2=dl1.Data.ucData.b3;
  141. dl2.Data.ucData.b3=dl1.Data.ucData.b2;
  142. dl2.Data.ucData.b4=dl1.Data.ucData.b1;
  143. sutFotaPara.fileLength=dl2.Data.ulData;
  144. sutFotaPara.encrypted=pFileInfo->encrypted;
  145. sutFotaPara.key=pFileInfo->key;
  146. memcpy(sutFotaPara.MD5,pFileInfo->MD5,16);
  147. if(sutFotaPara.fileLength==0)
  148. {//服务器没有文件,退出升级
  149. SlwTrace(INF, "NoFileInServer",1);
  150. sutFotaPara.fotaStatus=LOAD_DONE;
  151. return;
  152. }
  153. sutFotaPara.fotaStatus=LOAD_GET_FILEDATA;
  154. sutFotaPara.lastOffset=0;
  155. sutFotaPara.time_10ms_cnt=os_time+TIMEOUT_10MS_DATA;
  156. IapGetUpdateData(sutFotaPara.lastOffset,DATA_DRAT_SIZE_PER_TIME);
  157. break;
  158. case CMD_GET_FILE_DATA_ACK:
  159. //offset
  160. dl1.Data.ucData.b4=p[4];
  161. dl1.Data.ucData.b3=p[5];
  162. dl1.Data.ucData.b2=p[6];
  163. dl1.Data.ucData.b1=p[7];
  164. thisOffset=dl1.Data.ulData;
  165. //lenght
  166. ds.Data.ucData.b2=p[8];
  167. ds.Data.ucData.b1=p[9];
  168. thisLen=ds.Data.usData;
  169. //save
  170. sFlash_Write(p+10,APP_FILE_DATA_ADDR+thisOffset,thisLen);
  171. //done?
  172. if((thisOffset+thisLen) >= sutFotaPara.fileLength)
  173. {
  174. snprintf(info,sizeof(info), "\r\nHBD=%d\r\nLoad done",sutFotaPara.fileLength);
  175. SlwTrace(INF, info, 1);
  176. sutFotaPara.fotaStatus=LOAD_FILE_CHECK;
  177. }else{
  178. sutFotaPara.time_10ms_cnt=os_time+TIMEOUT_10MS_DATA;
  179. sutFotaPara.lastOffset=thisOffset+thisLen;
  180. snprintf(info,sizeof(info), "\r\nHBD=%d",sutFotaPara.lastOffset);
  181. SlwTrace(INF, info, 1);
  182. IapGetUpdateData(sutFotaPara.lastOffset, DATA_DRAT_SIZE_PER_TIME);
  183. }
  184. break;
  185. default:
  186. snprintf(info,sizeof(info), "SkipCmd:0x%02x",p[1]);
  187. SlwTrace(INF, info,1);
  188. break;
  189. }
  190. }
  191. /////////////////////////////////////////////////////////////////
  192. /*******************************************************************
  193. 封包,获取新版本文件信息
  194. |Head|Cmd|length(2) | data... | Check|
  195. Head 包头,固定为0xAB
  196. Cmd 命令字
  197. length 后续的数据长度,包括到Check的长度 length=1+data.len
  198. Check 从Head开始按字节异或运算
  199. data:
  200. unsigned long PSN;//终端编号
  201. char FileName[20];//文件名,不够的在末尾补0
  202. 总长 24+5=29 bytes
  203. *******************************************************************/
  204. unsigned short PacketGetFileInfo(unsigned char *buf)
  205. {
  206. unsigned char checksum;
  207. unsigned short i,j,k;
  208. char FileName[21];
  209. SUTDL dl;
  210. SUTDS ds;
  211. j=0;
  212. memset(buf,0,29);
  213. buf[j++]=PACKET_HEAD;
  214. buf[j++]=CMD_GET_FILE_INFO;
  215. buf[j++]=0;
  216. buf[j++]=24+1;//数据24字节,1字节checksum
  217. //PSN
  218. dl.Data.ulData=sutProductPara.PSN; //因为协议要求大端模式传输,所以需要转一下
  219. buf[j++]=dl.Data.ucData.b4;
  220. buf[j++]=dl.Data.ucData.b3;
  221. buf[j++]=dl.Data.ucData.b2;
  222. buf[j++]=dl.Data.ucData.b1;
  223. //FileName
  224. snprintf(FileName,sizeof(FileName), "%s_V%d.bin", sutProductPara.ProductName,sutFotaPara.targetVersion);
  225. for(i=0;i<20;i++){
  226. buf[j++]=FileName[i];
  227. }
  228. //校验
  229. checksum=0;
  230. for(i=0;i<j;i++){
  231. checksum=checksum^buf[i];
  232. }
  233. buf[j++]=checksum;
  234. return j;
  235. }
  236. static void IapGetUpdateVersion(void)
  237. {
  238. unsigned short len;
  239. unsigned char txbuf[29];
  240. len=PacketGetFileInfo(txbuf);
  241. ModemSendData(FOTA_SOCKET,txbuf,len);
  242. }
  243. /*******************************************************************
  244. 封包,获取新版本
  245. |Head|Cmd|length(2) | data... | Check|
  246. Head 包头,固定为0xAB
  247. Cmd 命令字
  248. length 后续的数据长度,包括到Check的长度 length=1+data.len
  249. Check 从Head开始按字节异或运算
  250. data:
  251. unsigned long PSN; //终端编号
  252. unsigned char FileName[20]; //文件名 如:RT101_V102.bin
  253. unsigned long offset; //请求数据在文件中的开始位置
  254. unsigned short len; //请求数据的长度,服务器返回的数据可能小于等于此长度
  255. *******************************************************************/
  256. unsigned short PacketGetFileData(unsigned char *buf,unsigned int offset,unsigned short len)
  257. {
  258. unsigned char checksum;
  259. unsigned short i,j;
  260. char FileName[21];
  261. SUTDL dl;
  262. SUTDS ds;
  263. j=0;
  264. memset(buf,0,35);
  265. buf[j++]=PACKET_HEAD;
  266. buf[j++]=CMD_GET_FILE_DATA;
  267. buf[j++]=0;
  268. buf[j++]=30+1;//数据18字节,1字节checksum
  269. //PSN
  270. dl.Data.ulData=sutProductPara.PSN; //因为协议要求大端模式传输,所以需要转一下
  271. buf[j++]=dl.Data.ucData.b4;
  272. buf[j++]=dl.Data.ucData.b3;
  273. buf[j++]=dl.Data.ucData.b2;
  274. buf[j++]=dl.Data.ucData.b1;
  275. //FileName
  276. snprintf(FileName,sizeof(FileName), "%s_V%d.bin", sutProductPara.ProductName,sutFotaPara.targetVersion);
  277. for(i=0;i<20;i++){
  278. buf[j++]=FileName[i];
  279. }
  280. //offset
  281. dl.Data.ulData=offset; //因为协议要求大端模式传输,所以需要转一下
  282. buf[j++]=dl.Data.ucData.b4;
  283. buf[j++]=dl.Data.ucData.b3;
  284. buf[j++]=dl.Data.ucData.b2;
  285. buf[j++]=dl.Data.ucData.b1;
  286. //len
  287. ds.Data.usData=len;
  288. buf[j++]=ds.Data.ucData.b2;
  289. buf[j++]=ds.Data.ucData.b1;
  290. //校验
  291. checksum=0;
  292. for(i=0;i<j;i++){
  293. checksum=checksum^buf[i];
  294. }
  295. buf[j++]=checksum;
  296. return j;
  297. }
  298. static void IapGetUpdateData(uint32_t offset,uint16_t len)
  299. {
  300. unsigned short subLen;
  301. unsigned char txbuf[35];
  302. subLen=PacketGetFileData(txbuf,offset,len);
  303. ModemSendData(FOTA_SOCKET,txbuf,subLen);
  304. }
  305. static char IapCheckFileMD5_SPI_Flash(unsigned int dataAddr,unsigned int length,uint8_t *MD5)
  306. {
  307. MD5_CTX mdContext;
  308. unsigned char data[1024];
  309. unsigned long len,l;
  310. char tembuf[5];
  311. int i;
  312. MD5Init(&mdContext);
  313. len=0;
  314. while(len<length)
  315. {
  316. if((length-len)>1024)l=1024;
  317. else l=length-len;
  318. sFlash_Read(data,dataAddr+len,l);
  319. MD5Update(&mdContext,data,l);
  320. len+=l;
  321. }
  322. MD5Final(&mdContext);
  323. //check
  324. for(i=0;i<16;i++){
  325. if(MD5[i]!=mdContext.digest[i])break;
  326. }
  327. if(i<16)return 0;
  328. else return 1;
  329. }
  330. void FotaTest(void)
  331. {
  332. #if(FOTA_DEBUG==1) //测试空中升级用
  333. static unsigned char flag=0;
  334. static unsigned char tick=0;
  335. char info[30];
  336. if(flag!=0) return;
  337. if(++tick > 60)
  338. {
  339. SlwTrace(INF, "Test FotaOn",1);
  340. sutFotaPara.targetVersion=3000;
  341. flag=1;
  342. TriggerFotaOption(FOTA_ON);
  343. }else{
  344. snprintf(info,sizeof(info), "Tick:%d",tick);
  345. SlwTrace(INF, info, 1);
  346. }
  347. #endif
  348. }