#include "otaEvent.h" #include "usart.h" #include "systick.h" #include "w25q32.h" #include "main.h" #include "ec800m.h" #include #include "string.h" #define APPBLOCKNB 2 //下载的程序位于block的第3块中 #define OTA_EVENT_BLOCKNB 1 //OTA事件完成标志存储的位置位于第2块中 #define SOH 0x01 // XMOD协议帧头 #define ACK 0X06 // 应答标志 #define NAK 0x15 // 非应答标志 #define EOT 0x04 // 结束标志 int8_t xmodem(uint16_t timeout); OTA_T ota_data; uint16_t Xmodem_CRC16(uint8_t *data, uint16_t datalen); static OTA_MESSAGE ota_message; #if 0 //测试用的 int WaitForReadData(uint8_t* data,int timeout,int datalen) { uint32_t len = 0; bool timeoutFlag = false; if (timeout >= 0) { timeoutFlag = true; } while (1) { delay_1ms(50); if (UART0_RX_STAT > 0) { UART0_RX_STAT = 0; char *p = strstr((char *)&UART0_RX_BUF, "CONNECT "); if (p) { p += 8; sscanf(p, "%u\r", &len); // 读取长度 if(len == datalen) { p = strchr(p, '\n') + 1; // 跳过换行 memcpy(data,p,datalen); Clear_DMA_Buffer(); return datalen; } else { Clear_DMA_Buffer(); return len; } } } timeout -= 50; if (timeoutFlag == true && timeout <= 0) { Clear_DMA_Buffer(); return -1; } } } static uint8_t app_programmer[1024]; void read_ota_DATA(uint32_t app_byte) { /* 打开UFS:otaDATA.txt */ EC800MSendCmd(CLOSE_otaDATA_FILE,strlen(CLOSE_otaDATA_FILE)); WaitResponse("QFCLOSE",1000); EC800MSendCmd(OPEN_otaDATA_FILE,strlen(OPEN_otaDATA_FILE)); if(WaitResponse("QFOPEN:", 2000) == 0) return; for(uint8_t i=0;i= 0) { timeoutFlag = true; } while (1) { delay_1ms(50); if (UART0_RX_STAT > 0) { UART0_RX_STAT = 0; char *p = strstr((char *)&UART0_RX_BUF, ": ") + 2; if (p) { uint8_t ret = 0; ret = strtol(p, &p, 10); Clear_DMA_Buffer(); return ret; } } timeout -= 50; if (timeoutFlag == true && timeout <= 0) { Clear_DMA_Buffer(); return 0; } }; } int8_t xmodem(uint16_t timeout) { int startTime = gettick(); ota_data.done=0; OTA_flag data_flag; data_flag.flag=0; data_flag.xmodemNB=0; while(1) { task_fwdgt_reload(); //喂狗 if(gettick()-startTime>timeout*1000)return 0; //如果一直得不到上位机的xmode数据相应,超时则跳出本函数 usart_data_transmit(COM_232, 'C'); //向上位机发送'C',表明请求xmodem数据 delay_1ms(1000); if(ota_data.done==1) { //打开otaData.txt文件 EC800MSendCmd(CLOSE_otaDATA_FILE,strlen(CLOSE_otaDATA_FILE)); WaitResponse("QFCLOSE",1000); EC800MSendCmd(OPEN_otaDATA_FILE,strlen(OPEN_otaDATA_FILE)); if(WaitResponse("QFOPEN:", 2000) == 0) return 0; break; //如果上位机响应请求则跳出循环等待 } } // 判断数据帧头是否符合标准 while (gettick() - startTime < timeout * 1000) { if (ota_data.done == 1) { task_fwdgt_reload(); //喂狗 if (ota_data.data[0] == SOH && ota_data.data_cnt == 133) //如果xmodem数据包是满的128个字节 { uint16_t XCRC = Xmodem_CRC16(ota_data.data + 3, 128); if (XCRC == ota_data.data[131] * 256 + ota_data.data[132]) // 经过校验的数据一致时将进行数据处理 { data_flag.xmodemNB++; //xmodem数据包计数 // W25Q32_PageWrite(w25q32_data,APPBLOCKNB*256+(data_flag.xmodemNB-1)/2); uint8_t sed_flg = 0; while(sed_flg < 2) { EC800MSendCmd(WRITE_otaDATA_FILE,strlen(WRITE_otaDATA_FILE)); if(WaitResponse("CONNECT", 2000) == 0) { sed_flg++; } else { sed_flg = 0; break; } } while(sed_flg < 2) { EC800MSendCmd(ota_data.data + 3,128); // EC800MSendCmd(TEST_DATA,128); int x = WaitResponse_value(2000); if(x != 128) { sed_flg++; char* QFSEEK_CMD; sprintf(QFSEEK_CMD,"AT+QFSEEK=1,%d,2\r\n",x); EC800MSendCmd(QFSEEK_CMD,strlen(QFSEEK_CMD)); //出错的话文件指针向左偏移x个字节 } else { sed_flg = 0; break; } } ota_data.data_cnt = 0; memset(ota_data.data, 0, 133); ota_data.done = 0; usart_data_transmit(COM_232, ACK); } else { ota_data.data_cnt = 0; memset(ota_data.data, 0, 133); ota_data.done = 0; usart_data_transmit(COM_232, NAK); } } //进入结束的包处理 else if (ota_data.data[0] == EOT && ota_data.data_cnt == 1) { // if(data_flag.xmodemNB%2!=0) //将可能为奇数的数据写入进去 // { // W25Q32_PageWrite(w25q32_data,APPBLOCKNB*256+(data_flag.xmodemNB-1)/2); // } // 保存UFS文件 uint8_t sed_flg = 0; while(sed_flg < 2) { EC800MSendCmd(CLOSE_otaDATA_FILE,strlen(CLOSE_otaDATA_FILE)); if(WaitResponse("OK", 2000) == 0) { sed_flg++; } else { sed_flg = 0; break; } } usart_data_transmit(COM_232, ACK); //完成xmodem协议的交互将完成的标志存储到内存中 ota_message.Completion_flag=1U; ota_message.XmodemByte=data_flag.xmodemNB*128;//后续补齐的0x1A还需要进一步考虑 while(sed_flg < 2) { EC800MSendCmd(CLOSE_otaDATA_FILE,strlen(CLOSE_otaDATA_FILE)); WaitResponse("QFCLOSE",1000); EC800MSendCmd(OPEN_otaMSG_FILE,strlen(OPEN_otaMSG_FILE)); if(WaitResponse("QFOPEN:", 2000) == 0) { sed_flg++; } else { sed_flg = 0; break; } } while(sed_flg < 2) { EC800MSendCmd(WRITE_otaMSG_FILE,strlen(WRITE_otaMSG_FILE)); if(WaitResponse("CONNECT", 2000) == 0) { sed_flg++; } else { sed_flg = 0; break; } } while(sed_flg < 2) { EC800MSendCmd((uint8_t *)&ota_message,sizeof(OTA_MESSAGE)); // delay_1ms(3000); int x = WaitResponse_value(2000); if(x != sizeof(OTA_MESSAGE)) { sed_flg++; char* QFSEEK_CMD; sprintf(QFSEEK_CMD,"AT+QFSEEK=1,%d,2",x); EC800MSendCmd(QFSEEK_CMD,strlen(QFSEEK_CMD)); //出错的话文件指针向左偏移x个字节 } else { sed_flg = 0; break; } } while(sed_flg < 2) { EC800MSendCmd(CLOSE_otaMSG_FILE,strlen(CLOSE_otaMSG_FILE)); if(WaitResponse("OK", 2000)) { sed_flg++; } else { sed_flg = 0; break; } } // W25Q32_Erase64K(OTA_EVENT_BLOCKNB);//擦除原先的数据 // W25Q32_PageWrite((uint8_t *)&ota_message,OTA_EVENT_BLOCKNB*256); ota_data.data_cnt = 0; memset(ota_data.data, 0, 133); ota_data.done = 0; delay_1ms(50); // 写入事件完成标志后重启设备,其他状态页无需回滚,写入完成会执行重启指令 return 1; } else { ota_data.data_cnt = 0; memset(ota_data.data, 0, 133); ota_data.done = 0; usart_data_transmit(COM_232, NAK); } } delay_1ms(1); } return 0; } /*-------------------------------------------------*/ /*函数名:Xmodem_CRC16校验 */ /*参 数:data:数据指针 datalen:数据长度 */ /*返回值:校验后的数据 */ /*-------------------------------------------------*/ uint16_t Xmodem_CRC16(uint8_t *data, uint16_t datalen) { uint8_t i; // 用于for循环 uint16_t Crcinit = 0x0000; // Xmdoem CRC校验的初始值,必须是0x0000 uint16_t Crcipoly = 0x1021; // Xmdoem CRC校验的多项式,必须是0x1021 while (datalen--) { // 根据datalen大小,有多少字节循环多少次 Crcinit = (*data << 8) ^ Crcinit; // 先将带校验的字节,挪到高8位 for (i = 0; i < 8; i++) { // 每个字节8个二进制位,循环8次 if (Crcinit & 0x8000) // 判断BIT15是1还是0,是1的话,进入if Crcinit = (Crcinit << 1) ^ Crcipoly; // 是1的话,先左移,再异或多项式 else // 判断BIT15是1还是0,是0的话,进入else Crcinit = (Crcinit << 1); // 是0的话,只左移 } data++; // 下移,计算一个字节数据 } return Crcinit; // 返回校验后的数据 }