otaEvent.c 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. #include "otaEvent.h"
  2. #include "usart.h"
  3. #include "systick.h"
  4. #include "w25q32.h"
  5. #include "main.h"
  6. #include "ec800m.h"
  7. #include <stdio.h>
  8. #include "string.h"
  9. #define APPBLOCKNB 2 //下载的程序位于block的第3块中
  10. #define OTA_EVENT_BLOCKNB 1 //OTA事件完成标志存储的位置位于第2块中
  11. #define SOH 0x01 // XMOD协议帧头
  12. #define ACK 0X06 // 应答标志
  13. #define NAK 0x15 // 非应答标志
  14. #define EOT 0x04 // 结束标志
  15. int8_t xmodem(uint16_t timeout);
  16. OTA_T ota_data;
  17. uint16_t Xmodem_CRC16(uint8_t *data, uint16_t datalen);
  18. /*
  19. * 函数名:uint8_t check_ota_event()
  20. * 输入参数:无
  21. * 输出参数:无
  22. * 返回值:无
  23. * 函数作用:判断ota事件是否产生是否要进入更新部分
  24. */
  25. int8_t check_ota_event()
  26. {
  27. //关闭看门狗
  28. // 当标志位为1时证明ota事件产生,将进入ota升级路线
  29. if (ota_data.ota_flag == 1)
  30. {
  31. // W25Q32_Erase64K(APPBLOCKNB); //程序文件在第三block以后
  32. EC800MSendCmd(DEL_otaDATA_FILE, strlen(DEL_otaDATA_FILE)); //清空OTA数据文件
  33. int8_t recvSta = xmodem(1000); //在1000秒内解决OTA更新
  34. if (recvSta == 0)
  35. {
  36. return 0;
  37. }
  38. else
  39. {
  40. NVIC_SystemReset();
  41. }
  42. }
  43. else
  44. return 0;
  45. }
  46. uint8_t WaitResponse_value(int timeout)
  47. {
  48. bool timeoutFlag = false;
  49. if (timeout >= 0)
  50. {
  51. timeoutFlag = true;
  52. }
  53. while (1)
  54. {
  55. delay_1ms(50);
  56. if (UART0_RX_STAT > 0)
  57. {
  58. UART0_RX_STAT = 0;
  59. char *p = strstr((char *)&UART0_RX_BUF, ": ") + 2;
  60. if (p)
  61. {
  62. uint8_t ret = 0;
  63. ret = strtol(p, &p, 10);
  64. Clear_DMA_Buffer();
  65. return ret;
  66. }
  67. }
  68. timeout -= 50;
  69. if (timeoutFlag == true && timeout <= 0)
  70. {
  71. Clear_DMA_Buffer();
  72. return 0;
  73. }
  74. };
  75. }
  76. int8_t xmodem(uint16_t timeout)
  77. {
  78. int startTime = gettick();
  79. ota_data.done=0;
  80. OTA_flag data_flag;
  81. data_flag.flag=0;
  82. data_flag.xmodemNB=0;
  83. while(1)
  84. {
  85. task_fwdgt_reload(); //喂狗
  86. if(gettick()-startTime>timeout*1000)return 0; //如果一直得不到上位机的xmode数据相应,超时则跳出本函数
  87. usart_data_transmit(COM_232, 'C'); //向上位机发送'C',表明请求xmodem数据
  88. delay_1ms(1000);
  89. if(ota_data.done==1)
  90. {
  91. //打开otaMSG.txt文件
  92. EC800MSendCmd(OPEN_otaDATA_FILE,strlen(OPEN_otaDATA_FILE));
  93. if(WaitResponse("QFOPEN:", 2000) == 0)
  94. return 0;
  95. break; //如果上位机响应请求则跳出循环等待
  96. }
  97. }
  98. // 判断数据帧头是否符合标准
  99. while (gettick() - startTime < timeout * 1000)
  100. {
  101. if (ota_data.done == 1)
  102. {
  103. task_fwdgt_reload(); //喂狗
  104. if (ota_data.data[0] == SOH && ota_data.data_cnt == 133) //如果xmodem数据包是满的128个字节
  105. {
  106. uint16_t XCRC = Xmodem_CRC16(ota_data.data + 3, 128);
  107. if (XCRC == ota_data.data[131] * 256 + ota_data.data[132]) // 经过校验的数据一致时将进行数据处理
  108. {
  109. data_flag.xmodemNB++; //xmodem数据包计数
  110. // W25Q32_PageWrite(w25q32_data,APPBLOCKNB*256+(data_flag.xmodemNB-1)/2);
  111. uint8_t sed_flg = 0;
  112. while(sed_flg < 2)
  113. {
  114. EC800MSendCmd(WRITE_otaDATA_FILE,strlen(WRITE_otaDATA_FILE));
  115. if(WaitResponse("CONNECT", 2000) == 0)
  116. {
  117. sed_flg++;
  118. }
  119. else
  120. {
  121. sed_flg = 0;
  122. break;
  123. }
  124. }
  125. while(sed_flg < 2)
  126. {
  127. EC800MSendCmd(ota_data.data + 3,128);
  128. int x = WaitResponse_value(2000);
  129. if(x != 128)
  130. {
  131. sed_flg++;
  132. char* QFSEEK_CMD;
  133. sprintf(QFSEEK_CMD,"AT+QFSEEK=1,%d,2",x);
  134. EC800MSendCmd(QFSEEK_CMD,strlen(QFSEEK_CMD)); //出错的话文件指针向左偏移x个字节
  135. }
  136. else
  137. {
  138. sed_flg = 0;
  139. break;
  140. }
  141. }
  142. ota_data.data_cnt = 0;
  143. memset(ota_data.data, 0, 133);
  144. ota_data.done = 0;
  145. usart_data_transmit(COM_232, ACK);
  146. }
  147. else
  148. {
  149. ota_data.data_cnt = 0;
  150. memset(ota_data.data, 0, 133);
  151. ota_data.done = 0;
  152. usart_data_transmit(COM_232, NAK);
  153. }
  154. }
  155. //进入结束的包处理
  156. else if (ota_data.data[0] == EOT && ota_data.data_cnt == 1)
  157. {
  158. // if(data_flag.xmodemNB%2!=0) //将可能为奇数的数据写入进去
  159. // {
  160. // W25Q32_PageWrite(w25q32_data,APPBLOCKNB*256+(data_flag.xmodemNB-1)/2);
  161. // }
  162. // 保存UFS文件
  163. uint8_t sed_flg = 0;
  164. while(sed_flg < 2)
  165. {
  166. EC800MSendCmd(CLOSE_otaDATA_FILE,strlen(CLOSE_otaDATA_FILE));
  167. if(WaitResponse("OK", 2000) == 0)
  168. {
  169. sed_flg++;
  170. }
  171. else
  172. {
  173. sed_flg = 0;
  174. break;
  175. }
  176. }
  177. usart_data_transmit(COM_232, ACK);
  178. //完成xmodem协议的交互将完成的标志存储到内存中
  179. OTA_MESSAGE ota_message;
  180. ota_message.Completion_flag=1U;
  181. ota_message.XmodemByte=data_flag.xmodemNB*128;//后续补齐的0x1A还需要进一步考虑
  182. while(sed_flg < 2)
  183. {
  184. EC800MSendCmd(OPEN_otaMSG_FILE,strlen(OPEN_otaMSG_FILE));
  185. if(WaitResponse("QFOPEN:", 2000) == 0)
  186. {
  187. sed_flg++;
  188. }
  189. else
  190. {
  191. sed_flg = 0;
  192. break;
  193. }
  194. }
  195. while(sed_flg < 2)
  196. {
  197. EC800MSendCmd(WRITE_otaMSG_FILE,strlen(WRITE_otaMSG_FILE));
  198. if(WaitResponse("CONNECT", 2000) == 0)
  199. {
  200. sed_flg++;
  201. }
  202. else
  203. {
  204. sed_flg = 0;
  205. break;
  206. }
  207. }
  208. while(sed_flg < 2)
  209. {
  210. EC800MSendCmd((uint8_t *)&ota_message,sizeof(OTA_MESSAGE));
  211. int x = WaitResponse_value(2000);
  212. if(x != sizeof(OTA_MESSAGE))
  213. {
  214. sed_flg++;
  215. char* QFSEEK_CMD;
  216. sprintf(QFSEEK_CMD,"AT+QFSEEK=1,%d,2",x);
  217. EC800MSendCmd(QFSEEK_CMD,strlen(QFSEEK_CMD)); //出错的话文件指针向左偏移x个字节
  218. }
  219. else
  220. {
  221. sed_flg = 0;
  222. break;
  223. }
  224. }
  225. while(sed_flg < 2)
  226. {
  227. EC800MSendCmd(CLOSE_otaMSG_FILE,strlen(CLOSE_otaMSG_FILE));
  228. if(WaitResponse("OK", 2000))
  229. {
  230. sed_flg++;
  231. }
  232. else
  233. {
  234. sed_flg = 0;
  235. break;
  236. }
  237. }
  238. // W25Q32_Erase64K(OTA_EVENT_BLOCKNB);//擦除原先的数据
  239. // W25Q32_PageWrite((uint8_t *)&ota_message,OTA_EVENT_BLOCKNB*256);
  240. delay_1ms(50);
  241. // 写入事件完成标志后重启设备,其他状态页无需回滚,写入完成会执行重启指令
  242. return 1;
  243. }
  244. else
  245. {
  246. ota_data.data_cnt = 0;
  247. memset(ota_data.data, 0, 133);
  248. ota_data.done = 0;
  249. usart_data_transmit(COM_232, NAK);
  250. }
  251. }
  252. delay_1ms(1);
  253. }
  254. return 0;
  255. }
  256. /*-------------------------------------------------*/
  257. /*函数名:Xmodem_CRC16校验 */
  258. /*参 数:data:数据指针 datalen:数据长度 */
  259. /*返回值:校验后的数据 */
  260. /*-------------------------------------------------*/
  261. uint16_t Xmodem_CRC16(uint8_t *data, uint16_t datalen)
  262. {
  263. uint8_t i; // 用于for循环
  264. uint16_t Crcinit = 0x0000; // Xmdoem CRC校验的初始值,必须是0x0000
  265. uint16_t Crcipoly = 0x1021; // Xmdoem CRC校验的多项式,必须是0x1021
  266. while (datalen--)
  267. { // 根据datalen大小,有多少字节循环多少次
  268. Crcinit = (*data << 8) ^ Crcinit; // 先将带校验的字节,挪到高8位
  269. for (i = 0; i < 8; i++)
  270. { // 每个字节8个二进制位,循环8次
  271. if (Crcinit & 0x8000) // 判断BIT15是1还是0,是1的话,进入if
  272. Crcinit = (Crcinit << 1) ^ Crcipoly; // 是1的话,先左移,再异或多项式
  273. else // 判断BIT15是1还是0,是0的话,进入else
  274. Crcinit = (Crcinit << 1); // 是0的话,只左移
  275. }
  276. data++; // 下移,计算一个字节数据
  277. }
  278. return Crcinit; // 返回校验后的数据
  279. }