HAL_Project/Project -APP-V1.0/Hardware/OTA/ota.c

258 lines
7.8 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "main.h"
IAP_Stuct IAPStuct;
//[INFO] 串口2本次接收229字节报文数据(*4G模组*)
//[INFO]
//+MSUB: "/iot/data/down/a284c67982b089f9",175 byte,{"id":"1471561db17870ef","header":"iot.ota.upgrade.post","body":{"crc16":"1f8c","ver":1,"url":"http://iot.futureny.cn/ota/pull/f46bf3544fe6ca73.bin","md5":"f46bf3544fe6ca73"}}
//[INFO] 收到OTA升级指令
//[INFO] 版本号后的数据为:1,"url":"http://iot.futureny.cn/ota/pull/f46bf3544fe6ca73.bin","md5":"f46bf3544fe6ca73"}}
//[INFO] 新的版本号是1
//[INFO] id后的数据为:1471561db17870ef","header":"iot.ota.upgrade.post","body":{"crc16":"1f8c","ver":1,"url":"http://iot.futureny.cn/ota/pull/f46bf3544fe6ca73.bin","md5":"f46bf3544fe6ca73"}}
//[INFO] ErrFlag= 0
//[INFO] 更新代码测试
uint8_t checkId(uint8_t *data){
uint8_t i;
char *TempPointer; // 临时指针
uint8_t ErrFlag = 0;
uint16_t Version = 0;
uint8_t Err = 0;
uint8_t verRepeti = 0;
TempPointer = strstr((char *)data, "\"ver\":");
TempPointer += 6;
log_info("版本号后的数据为:%s", TempPointer);
i = 0;
while ((TempPointer[i] >= '0') && (TempPointer[i] <= '9')){
Version = (Version * 10) + (TempPointer[i] - '0');
i++;
}
if (TempPointer[i] != ','){
log_info("版本号解析错误");
Err = 1;
}
if (Version == MqttInfoStr.iapVer){
log_info("版本号重复");
Err = 1;
verRepeti = 1;
}else{ // 无误则存储版本号
MqttInfoStr.iapVer = Version;
log_info("新的版本号是%d", MqttInfoStr.iapVer);
eepromWriteData(0, &MqttInfoStr, MQTT_STRUCT_LEN);//将变化的数据写入eeprom
}
TempPointer = strstr((char *)data, "\"id\":\"");
TempPointer += 6; // 找到id的第一个位置
log_info("id后的数据为:%s", TempPointer);
if(verRepeti == 1){
log_info("****ERR 版本号重复,发送成功指令 ERR****");
CAT1_printf("AT+MPUB=\"/iot/data/up/%s\",0,0,\"{\\22header\\22:\\22iot.ota.progress.post\\22,\\22body\\22:{\\22id\\22:\\22%.16s\\22,\\22progress\\22:10}}\"\r\n",MqttInfoStr.ClientID,TempPointer);
return Err; // 版本号重复或降级退出程序
}
for(i = 0; i < 16; i++){
if (((TempPointer[i] >= '0') && (TempPointer[i] <= '9')) || ((TempPointer[i] >= 'a') && (TempPointer[i] <= 'z'))){ // 检查是否是字符
if (MqttInfoStr.iapid[i] == TempPointer[i]){
ErrFlag++;
}
}
else{ // 不是字符,直接退出
ErrFlag = 16;
log_info("id[%d]不是字符,id=%d", i, TempPointer[i]);
break;
}
}
if (ErrFlag >= 16){ // 如果所有字都相同,直接退出,认为重复发送了升级数据
Err = 1;
}
ErrFlag = 0;
if (Err == 0){ // 无误,准备存储id
for (i = 0; i < 16; i++){ // 存储id值
MqttInfoStr.iapid[i] = TempPointer[i];
eepromWriteData(0, &MqttInfoStr, MQTT_STRUCT_LEN);//将变化的数据写入eeprom
}
}
return Err;
}
#if 0
void otaUpData(void){
uint8_t i;
char NetMessage[512]; // 定义网络数据
if (GetUpgradePara() == 1)
{
i = 0;
while ((Connce2TCP()) && (i < 200))
{
i++;
}
if (i < 200)
{
if (GetUpgradeFile() == 0)
{
Ping_flag = 0; // 要清除Ping_flag标志
Connect_flag = 0;
ConnectPack_flag = 0;
SubcribePack_flag = 0;
printf("代码升级失败 准备重连\r\n");
memset(NetMessage, 0, 512 * sizeof(char)); // 清零消息
sprintf(NetMessage, "AT+MSUB=\"/iot/data/up/%s\",0,0,0,\"{\\\"header\\\":\\\"iot.ota.result.post\\\",\\\"body\\\":{\\\"id\\\":\\\"%.16s\\\",\\\"success\\\":false}}\"\r\n", DEVICEID, IapFlashStuct.iapid); // 构建回复数据
TxDataBuf_Deal((u8 *)NetMessage, (strlen(NetMessage))); // 添加数据,发布给服务器
}
}
else
{
printf("连接TCP 81端口超时,程序更新失败,准备等待看门狗复位\r\n");
for (; i > 0; i--)
{
printf("%d", i);
delay_ms(1000);
}
}
}
else
{
Ping_flag = 0; // 要清除Ping_flag标志
Connect_flag = 0;
ConnectPack_flag = 0;
SubcribePack_flag = 0;
printf("解析指令失败可能不是Bin文件 准备重连\r\n");
memset(NetMessage, 0, 512 * sizeof(char)); // 清零消息
sprintf(NetMessage, "AT+MSUB=\"/iot/data/up/%s\",0,0,0,\"{\\\"header\\\":\\\"iot.ota.result.post\\\",\\\"body\\\":{\\\"id\\\":\\\"%.16s\\\",\\\"success\\\":false}}\"\r\n", DEVICEID, IapFlashStuct.iapid); // 构建回复数据
TxDataBuf_Deal((u8 *)NetMessage, (strlen(NetMessage))); // 添加数据,发布给服务器
}
}
//获取升级文件
u8 GetUpgradeFile()
{
char TempStr[80];
uint8_t count = 0;
u16 i=0;
u8 UpdataOkFlag = 0;
log_info("准备获取更新数据\r\n"); //串口提示数据
while((count<30)&&(UpdataOkFlag == 0))
{
count ++;
IapStuct.GetBinFlag = 1;//获取Bin文件标志位置1,提示串口接收中断放大其接收数组
IOT_RxCounter = 0;
sprintf(TempStr,"GET /ota/pull/%.20s HTTP/1.1\r\nHost: %s:81\r\n\r\n",IapStuct.iapUrl,ServerIP);
IOT_printf("%s",TempStr);
printf("发送的网络指令是:%s\r\n",TempStr);
if(!WaitDownLoad(90000000))
{
IapStuct.bit2K_Pointer = 2048 - DMA_GetCurrDataCounter(DMA1_Channel6);
if(IapStuct.bit2K_Pointer != 0)
{
Crc = GetCRC(BIN_RX_BUF[IapStuct.bit2K_Select],IapStuct.bit2K_Pointer,Crc);//校验最后一部分CRC
for(i=0;i<IapStuct.bit2K_Pointer;i++)
{
printf("%.2X ",BIN_RX_BUF[IapStuct.bit2K_Select][i]);
}
printf("\r\n");
iap_write_appbin(IapStuct.BinWriteAdd,(u8 *)BIN_RX_BUF[IapStuct.bit2K_Select],IapStuct.bit2K_Pointer);//写入剩下的代码
}
if( IapStuct.binLength <= (Bin2KCount*2048+IapStuct.bit2K_Pointer))
{//判断是否接收到足够的数据
Usart2_RxCounter = 0;
if(Crc == IapStuct.iapCrc)//CRC校验通过
{
if(((*(vu32*)(FLASH_APP2_ADDR+4))&0xFF000000)==0x08000000)//判断是否为0X08XXXXXX.
{
IapFlashStuct.iapCount++;//iap计数值++
IapFlashStuct.iapFlag = 1;//iap升级成功标志位置1
STMFLASH_Write(IAP_FLASH_ADDR,(u16*)&IapFlashStuct,((((sizeof(struct IAP_FLASH_Stuct))%2) == 0) ? ((sizeof(struct IAP_FLASH_Stuct))/2) : (((sizeof(struct IAP_FLASH_Stuct))/2)+1)));//写入Flash
UpdataOkFlag = 1;//标记更新成功
TIM_Cmd(TIM4,ENABLE);//打开定时器4开始计算ping包时间
printf("固件更新完成!\r\n");
//printf("请实现跳转到BootLoader再由BootLoader跳转到第二段程序\r\n");
printf("开始跳转到BootLoader程序!!\r\n");
if(((*(vu32*)(FLASH_BASE_ADDR+4))&0xFF000000)==0x08000000)//判断是否为0X08XXXXXX.
{
printf("等待看门狗复位系统!!\r\n");
for(i=0;i<100;i++)//延时100*800ms 等待看门狗复位
{
delay_ms(800);
printf("%d ",i);
}
}
else
{
printf("非FLASH应用程序,无法执行!\r\n");
}
}
else
{
printf("固件校验失败\r\n");
Usart2_RxCounter = 0;
IapStuct.HttpHeadcount = 0;
IapStuct.bit2K_Pointer = 0;
IapStuct.bit2K_Select = 0;
IapStuct.HttpFlag = 0;
Bin2KCount = 0;
Crc = 0xFFFF;
IapStuct.BinWriteAdd = FLASH_APP2_ADDR;
USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);//使能接收中断
memset(BIN_RX_BUF,0,2048*3);
}
}
else
{
printf("CRC校验未通过服务器上传的CRC是%x,由%d字节的数据计算出的CRC值是%x\r\n",IapStuct.iapCrc,(Bin2KCount*2048+IapStuct.bit2K_Pointer),Crc);
Usart2_RxCounter = 0;
IapStuct.HttpHeadcount = 0;
IapStuct.bit2K_Pointer = 0;
IapStuct.bit2K_Select = 0;
IapStuct.HttpFlag = 0;
Bin2KCount = 0;
Crc = 0xFFFF;
IapStuct.BinWriteAdd = FLASH_APP2_ADDR;
USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);//使能接收中断
memset(BIN_RX_BUF,0,2048*3);
}
}
else
{
printf("未接收到完整的程序数据,程序长度应该为%dbytes,实际收到数据长度为%dytes\r\n",IapStuct.binLength,(Bin2KCount*2048+IapStuct.bit2K_Pointer));
Usart2_RxCounter = 0;
IapStuct.HttpHeadcount = 0;
IapStuct.bit2K_Pointer = 0;
IapStuct.bit2K_Select = 0;
IapStuct.HttpFlag = 0;
Bin2KCount = 0;
Crc = 0xFFFF;
IapStuct.BinWriteAdd = FLASH_APP2_ADDR;
USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);//使能接收中断
memset(BIN_RX_BUF,0,2048*3);
}
}
else
{
printf("等待网络数据包时间过短\r\n");
}
}
return UpdataOkFlag;
}
#endif