/*---------------------------------------------------------------------------------- * 备份寄存器的说明 * BKP_DR0: 写入的RTC标志 * BKP_DR1: 写入升级标志码 * BKP_DR2: 写入升级状态码 * BKP_DR3: 写入升级任务号 * BKP_DR4: 升级的来源: 0x22:来源于服务器下发的 0x44:来源于网关的离线升级 * BKP_DR5: 上电后升级从设备 * BKP_DR6: 升级的固件类型 * ---------------------------------------------------------------------------------*/ #include "ota_update.h" #include "dn_4g.h" #include "up_4g.h" #include "air780e.h" #include "masterslave.h" static uint8_t _buff[256]; UpdateDa g_updateDa; OtaUpdateTime g_otaTimer; static otaUpdatMsg ota_devMsg; static uint16_t updata_state,updata_state_save; static void send_update_code_to_serve(uint16_t devtype, uint32_t devsn,uint16_t taskId,uint8_t upcode,uint8_t firmType) { uint8_t bufflen; memset(_buff,0,256); up_update_cmd_0x2002(_buff,&bufflen,devtype,devsn,taskId,firmType,upcode); add_data_to_4G_txfifo(_buff,bufflen,0x04,0x2002); } static void waiting_4g_tx_fifo_empty(void) { uint8_t len; do{ if(fifo_is_empty(&g_4Gtxfifo) == TRUE) break ;// 发送fifo为空 if(g_uart1Info.bSdFinish != 1) continue; printf("发送4G数据到服务器\r\n"); len = fifo_read(&g_4Gtxfifo,_buff); data_dump("4g-data-to-server",_buff,len); send_data_to_mqtt(0x00,_buff,len); }while(1); } /*-------------------------------------------------------------------------- * 上电读取升级的状态 * --------------------------------------------------------------------------*/ void ota_power_up_read_update_status(void) { uint16_t data; data = bkp_data_read(BKP_DATA_1); // 读取入标志码 if(data != 0){ if(updata_state_cmp(data)){ if((data&0x00ff) == 0x82){ // 升级成功 data = set_updata_state(UPDATE_SUCCESS); bkp_data_write(BKP_DATA_2, data); printf("\r\n send to net update sucess\r\n"); } else if((data&0x00ff) == 0x83) { // 回退成功 data = set_updata_state(UPDATE_RETURN_SUCESS); bkp_data_write(BKP_DATA_2, data); printf("\r\n send to net return sucess\r\n"); } printf("\r\n update status1 = %x\r\n",data); data = bkp_data_read(BKP_DATA_2); bkp_data_write(BKP_DATA_1, 0); g_updateDa.updateCode = data&0xFF; data = bkp_data_read(BKP_DATA_3);//升级任务号 g_updateDa.taskNo = data; data = bkp_data_read(BKP_DATA_4); //if(data == UP_PROG_FROM_NET) g_updateDa.bResetUpdate = 1; //else g_updateDa.bResetUpdate = 2; if(data == UP_PROG_FROM_GAT) { set_start_ota_timer(&g_otaTimer.randomTmr,(rand()%150+200)); } g_updateDa.Update_Source = data; g_updateDa.bResetUpdate = 1; printf("g_updateDa.bResetUpdate = %d\r\n",g_updateDa.bResetUpdate); bkp_data_write(BKP_DATA_4, 0); data = bkp_data_read(BKP_DATA_6);//固件类型 g_updateDa.bfirmware_type = data; data = bkp_data_read(BKP_DATA_5); printf("bkp5=%04x\n",data); if(data == UPDATE_SLAVE)//需要升级从设备 { if(ota_offline_init(OTA_UPDATE_APP3_FLASH_START_ADDR,OTA_UPDATE_APP3_FLASH_SIZE))//升级包正确 { ota_master_init_update_msg_offline(g_devMsg.devType,0xffffffff,g_devMsg.devType,0xffffffff,g_updateDa.bfirmware_type); // g_updateDa.bOffline_s = 1;//可以离线升级 g_updateDa.bUpdate_slave = data; g_updateDa.bOffline_addr = OTA_UPDATE_APP3_FLASH_START_ADDR; g_devMsg.workMode = WORK_UPDATE; g_devMsg.ledgreen = 2; printf("升级从设备\n"); } } bkp_data_write(BKP_DATA_5, 0); } } else{ g_updateDa.bResetUpdate = 0; printf("\r\n no update program, data = %x\r\n",data); } } void set_start_ota_timer(otaTimeSet *timer, uint32_t delay) { timeout_stop(&(timer->timer)); timeout_setValue(&(timer->timer),delay); timeout_start(&(timer->timer)); timer->status = OTA_TIMER_START; } void ota_timer_stop(otaTimeSet *timer) { timeout_stop(&timer->timer); timer->status = OTA_TIMER_END; } /*---------------------------------------------------------------------- * 1: 超时 0: 未超时 * ---------------------------------------------------------------------*/ uint8_t ota_timer_is_timeout(otaTimeSet * timer) { if(timer->status == OTA_TIMER_NULL) return 0; // 定时器还未启动时 if((OTA_TIMER_START == timer->status) && timeout_isOut(&(timer->timer))){ timer->status = OTA_TIMER_END; return 1; } else return 0; } void ota_master_update_slave_continue(otaUpdatMsg *msg,uint32_t addr) { updateCmd0x1004 *pmsg = NULL; // uint8_t i; pmsg = (updateCmd0x1004*)_buff; memset(_buff,0,256); pmsg->rcvDevType = msg->rcvDevType; pmsg->rcvDevSn = msg->rcvDevSn; pmsg->desDevType = msg->rcvDevType; pmsg->desDevSn = msg->rcvDevSn; pmsg->totalPage = msg->totalPage; pmsg->subPkgId = msg->subPkgId; pmsg->subPkgLen = msg->subPkgLen; while(ota_devMsg.subPkgId <= ota_devMsg.totalPage){ start_delay_ms(msg->sendInterval); printf("lora_gw_ota_continues %d\r\n", msg->subPkgId); pmsg->subPkgId = msg->subPkgId++; Flash_BufferRead(addr + (pmsg->subPkgId - 1)*OTA_MASTER_SEND_PKG_SIZE, ((uint8_t *)pmsg) + OTA_CONTINUES_INFO_LEN, OTA_MASTER_SEND_PKG_SIZE); // if(pmsg->subPkgId%30) slave_send_data_to_uart(0x04,0x1004,(uint8_t*)pmsg,sizeof(updateCmd0x1004)+OTA_MASTER_SEND_PKG_SIZE); // for(i=0;i< sizeof(updateCmd0x1004)+OTA_MASTER_SEND_PKG_SIZE-OTA_CONTINUES_INFO_LEN;i++){ // printf("%02x ",_buff[i]); // } // printf("\r\n"); // printf("发送间隔:%u\n",msg->sendInterval); // start_delay_ms(msg->sendInterval); while(!g_iDelayfinish); } printf("continue finish, start repeat\r\n"); } void ota_master_init_update_msg(dnUpdateCmd0x1004 *msg,uint32_t version,uint32_t totallen,uint16_t losepage) { memset(&ota_devMsg,0,sizeof(otaUpdatMsg)); ota_devMsg.rcvDevType = msg->rcvDevType; // 接收设备类型 ota_devMsg.rcvDevSn = msg->rcvDevSn; // 接收设备SN ota_devMsg.desDevType = msg->desDevType; // 升级目标设备类型 ota_devMsg.desDevSn = msg->desDevSn; // 升级目标设备SN ota_devMsg.firmType = msg->firmType; // 升级的固件类型 ota_devMsg.version = version; ota_devMsg.totalByte = totallen; // 升级的总大小 ota_devMsg.losePage = losepage; ota_devMsg.sendInterval = 300; ota_devMsg.totalPage = totallen/OTA_MASTER_SEND_PKG_SIZE; if(totallen%OTA_MASTER_SEND_PKG_SIZE) ota_devMsg.totalPage += 1; ota_devMsg.subPkgLen = OTA_MASTER_SEND_PKG_SIZE; ota_devMsg.subPkgId = 1; ota_devMsg.lastRightPkgNum = 1; ota_devMsg.lossPkgIndex = 0; } /*------------------------------------------------------------------------------- * 从设备初化 * ------------------------------------------------------------------------------*/ void ota_slave_init_update_msg(updateCmd0x1003 *msg) { memset(&ota_devMsg,0,sizeof(otaUpdatMsg)); ota_devMsg.rcvDevType = msg->rcvDevType; // 接收设备类型 ota_devMsg.rcvDevSn = msg->rcvDevSn; // 接收设备SN ota_devMsg.desDevType = msg->desDevType; // 升级目标设备类型 ota_devMsg.desDevSn = msg->desDevSn; // 升级目标设备SN ota_devMsg.firmType = msg->firmType; // 固件类型 ota_devMsg.totalByte = msg->totalByte; // 升级总总长度 ota_devMsg.eachMaxByte = msg->eachMaxByte; // 单包最大字节类 ota_devMsg.losePage = msg->losePage; // 最大丢包面分比 最小为10%,最大为60% ota_devMsg.sendInterval = msg->sendInterval; // 连续阶段发 送包的时间间隔(单位:ms) ota_devMsg.totalPage = msg->totalByte/OTA_MASTER_SEND_PKG_SIZE; //总包数 if(msg->totalByte%OTA_MASTER_SEND_PKG_SIZE) ota_devMsg.totalPage += 1; ota_devMsg.loseTotalPage = (ota_devMsg.totalPage*ota_devMsg.losePage)/100;//计算最大丢包数 ota_devMsg.loseTotalPage = (ota_devMsg.loseTotalPage>250)?250:ota_devMsg.loseTotalPage;//最大丢包数不能超过250个 printf("losetotalpage=%d\n",ota_devMsg.loseTotalPage); ota_devMsg.subPkgId = 1; // 升级包编号 ota_devMsg.subPkgLen = 0; // 本升级包的长度 ota_devMsg.lastRightPkgNum = 1; ota_devMsg.lossPkgIndex = 0; } /*-------------------------------------------------------------------------- * 主设备升级从设备 * -------------------------------------------------------------------------*/ void ota_master_update_salve(otaUpdatMsg*msg,uint32_t addr) { uint8_t i; updateCmd0x1003 pMsg; pMsg.rcvDevType = msg->rcvDevType; pMsg.rcvDevSn = msg->rcvDevSn; pMsg.desDevType = msg->desDevType; pMsg.desDevSn = msg->desDevSn; pMsg.firmType = msg->firmType; pMsg.updateVer = msg->version; pMsg.totalByte = msg->totalByte; pMsg.eachMaxByte= OTA_MASTER_SEND_PKG_SIZE; pMsg.losePage = msg->losePage; pMsg.sendInterval = msg->sendInterval; for(i=0;i<3;i++){ // 下发启动升级指令 slave_send_data_to_uart(0x04,0x1003,(uint8_t*)&pMsg,sizeof(updateCmd0x1003)); start_delay_ms(2000); while(!g_iDelayfinish); } set_start_ota_timer(&g_otaTimer.totalTmr,OTA_TIM_TOTALTMR); // 升级的总时间 printf("启动升级总定时时间\r\n"); ota_master_update_slave_continue(msg,addr);// 处理连续升级指令 set_start_ota_timer(&g_otaTimer.repeatTmr,OTA_TIM_REPEAT); //启动重传定时器 printf("启动升级重传时间\r\n"); } /*-------------------------------------------------------------------------- * 主设备升级 * updateType: 1: 升级主设备 2:升级从设备 * -------------------------------------------------------------------------*/ void ota_master_update_task(uint16_t cmd,uint8_t *data) { uint32_t Version; char *binPos = NULL; uint8_t updateCode,sendbuff[200] = {0}; uint8_t *p_content = NULL; uint16_t pages = 0,send_data_dr2 = 0,losepage = 10; uint32_t fileVer,addr,filelen,crcVl,fixChar,getcrc; uint32_t start_addr = 0, total_len = 0, remain_len, read_len; dnUpdateCmd0x1002 *msg1002 = NULL; dnUpdateCmd0x1004 *msg = NULL; if(cmd == 0x1002){ msg = (dnUpdateCmd0x1004*)sendbuff; msg1002 = (dnUpdateCmd0x1002*)data; msg->devType = g_devMsg.devType; msg->devSn = g_devMsg.devSn; msg->rcvDevType = msg1002->devType; msg->rcvDevSn = msg1002->devSn; msg->desDevType = msg1002->devType; msg->desDevSn = msg1002->devSn; msg->firmType = msg1002->firmType; msg->taskId = msg1002->taskId; msg->urllen = msg1002->urllen; memcpy(msg->url,msg1002->url,msg->urllen); losepage = msg1002->losePage; } else { msg = (dnUpdateCmd0x1004*)data; losepage = 10; } printf("主设备收到升级指令\r\n"); g_devMsg.workMode = WORK_UPDATE; g_devMsg.ledgreen = 2; send_update_code_to_serve(msg->desDevType,msg->desDevSn,msg->taskId,UPDATE_RECEIVE_UPDATEFLAG,0x03); waiting_4g_tx_fifo_empty(); start_delay_ms(1000); while(!g_iDelayfinish); bkp_data_write(BKP_DATA_3, msg->taskId);// 升级任务号 BKP_DATA_4 g_updateDa.taskNo = msg->taskId; binPos = strstr((char*)msg->url,".bin") - 8; memset(_buff,0,sizeof(_buff)); memcpy(_buff,binPos,8); sscanf((char*)_buff,"%x",&Version); memcpy(_buff,msg->url,msg->urllen); _buff[msg->urllen] = '\0'; AIR_HTTP_GET((char*)_buff,&total_len); // 得到文件总大小 if(total_len<=2){ updateCode = UPDATE_DOWNLOADFILE_FAILED;// 文件下载失败 goto UPDATE_END; } else if(total_len>98304){ // 96K的文件 updateCode = UPdATE_FILE_LEN_ERROR; goto UPDATE_END; } Flash_RangeErase(OTA_UPDATE_APP3_FLASH_START_ADDR, OTA_UPDATE_APP3_FLASH_SIZE); // 擦除APP3区 printf("total len=%d\n",total_len); while(start_addr < total_len) {//每次读取512字节,写入到flash中 remain_len = total_len - start_addr; read_len = (remain_len > 512)?512:remain_len; p_content = AIR_HTTP_READ(start_addr, read_len); printf("update recive page = %d\r\n",pages++); //data_dump("Update Data", p_content+read_len-16,16);// read_len); Flash_BufferWrite(OTA_UPDATE_APP3_FLASH_START_ADDR + start_addr, (uint32_t *)p_content, read_len); start_addr += read_len; } crcVl = *(uint32_t*)(OTA_UPDATE_APP3_FLASH_START_ADDR+total_len-4); //CRC校验 fixChar = *(uint32_t*)(OTA_UPDATE_APP3_FLASH_START_ADDR+total_len-8); // 固定字符 WBJW fileVer = *(uint32_t*)(OTA_UPDATE_APP3_FLASH_START_ADDR+total_len-12); // 固件信息 filelen = *(uint32_t*)(OTA_UPDATE_APP3_FLASH_START_ADDR+total_len-20); // 文件总长度 addr = *(uint32_t*)(OTA_UPDATE_APP3_FLASH_START_ADDR+total_len-16); // 文件写入的地址 app_check_crc(OTA_UPDATE_APP3_FLASH_START_ADDR,OTA_UPDATE_APP3_FLASH_SIZE,&getcrc); printf("crcVl=%08x, getcrc=%08x\n",crcVl,getcrc); if(getcrc!=crcVl) { updateCode = UPDATE_CRCERROR; printf("update file crc error\r\n");// 升级文件crc校验错误 goto UPDATE_END; } if(Version!=fileVer){ updateCode = UPDATE_URL_FILE_TYPE_ERROR; goto UPDATE_END; } printf("~~~~~~~~update file download sucess~~~~~~~~~~\r\n"); send_update_code_to_serve(msg->desDevType,msg->desDevSn,msg->taskId,UPDATE_DOWNLOADFILE_SUCCESS,0x03); // 文件下载成功并写入到APP3中 waiting_4g_tx_fifo_empty(); bkp_data_write(BKP_DATA_3, msg->taskId); // 升级任务号 if(cmd == 0x1004){ if(msg->desDevSn != g_devMsg.devSn){ g_updateDa.iDentity = IDENTITY_MASTER;//标记为下发升级设备 ota_master_init_update_msg(msg,Version,total_len,losepage); ota_master_update_salve(&ota_devMsg,OTA_UPDATE_APP3_FLASH_START_ADDR); return; } } if(msg->desDevType == DEV_TYPE){ if(fixChar != 0x57424A57) {//固定字符错误 goto UPDATE_END; } if((fileVer&0xfffff000) != (APP_VERSION&0xFFFFF000)){ //固件信息错误 updateCode = UPDATE_DEVICETYPEERROR; goto UPDATE_END; } if(msg->desDevSn == g_devMsg.devSn || (0xFFFFFFFF == msg->desDevSn)){//|| (0xFFFFFFFF == msg->devSn) //if(0xFFFFFFFF == msg->desDevSn) bkp_data_write(BKP_DATA_5,(uint16_t)UPDATE_SLAVE);// 记录升级的设备,如果是广播升级,则需要重新启动后,升级从设备 //else bkp_data_write(BKP_DATA_5,0); g_updateDa.bfirmware_type = msg->firmType; bkp_data_write(BKP_DATA_6,g_updateDa.bfirmware_type);//记录固件类型 printf("1\n"); send_data_dr2 = set_updata_state(UPDATE_DOWNLOADFILE_SUCCESS); bkp_data_write(BKP_DATA_2, send_data_dr2); // 写入状态码 send_data_dr2 = set_updata_state(UPDATE_FLAG); // 升级标志0x81,bootloader可以根据此标志进行升级 bkp_data_write(BKP_DATA_1, send_data_dr2); // 写入标志码 g_updateDa.Update_Source = UP_PROG_FROM_NET; bkp_data_write(BKP_DATA_4, UP_PROG_FROM_NET); // 升级的来源 0x22 来源来网络服务下发的 start_delay_ms(2000); while(!g_iDelayfinish); printf("\r\n gateway update ======================\r\n"); NVIC_SystemReset();//复位//设备重新启动//写升级标志位,然后复位,进入bootloader程序中 } } else { // 从设备升级 g_updateDa.iDentity = IDENTITY_MASTER;//标记为下发升级设备 ota_master_init_update_msg(msg,Version,total_len,losepage); ota_master_update_salve(&ota_devMsg,OTA_UPDATE_APP3_FLASH_START_ADDR); } return; UPDATE_END: send_update_code_to_serve(msg->desDevType,msg->desDevSn,msg->taskId,updateCode,0x03); waiting_4g_tx_fifo_empty(); g_devMsg.workMode = WORK_NORMAL; return; } //重传随机延时 void ota_repeat_rand_timer(uint8_t status) { static uint32_t randDa; // srand(randDa+g_devMsg.devSn); if(status == 0) randDa = rand()%150 + 200; else randDa = rand()%150 + 500; printf("重传随机时间 = %d\r\n",randDa); set_start_ota_timer(&g_otaTimer.repeatRandomTmr,randDa); } void ota_check_update_timer(void) { int i; uint32_t randDa; //if(g_updateDa.Work_State == OTA_UPDATE_CONTINUE_END){ ota_update_slave_continue_end(g_updateDa.Work_State); //} if(ota_timer_is_timeout(&g_otaTimer.totalTmr)){ // 总定时器超时 g_updateDa.Work_State = OTA_UPDATE_NULL; //g_devMsg.workMode = WORK_NORMAL; reset_work_mode(); printf("启动升级总定时时间--超时\r\n"); } if(ota_timer_is_timeout(&g_otaTimer.onlookerTmr)){ // 旁观都定时器超时 if(g_updateDa.iDentity == IDENTITY_SLAVE) { if(g_updateDa.ResetUpdate_s) { g_updateDa.ResetUpdate_s = 0; g_updateDa.bResetUpdate = 1; randDa = rand()%150+200; set_start_ota_timer(&g_otaTimer.randomTmr,randDa); printf("上报升级状态\n"); } } //g_devMsg.workMode = WORK_NORMAL; reset_work_mode(); ota_timer_stop(&g_otaTimer.continueTmr); ota_timer_stop(&g_otaTimer.repeatTmr); ota_timer_stop(&g_otaTimer.totalTmr); printf("旁观者时间到\r\n"); } if(ota_timer_is_timeout(&g_otaTimer.continueTmr)) { printf("连续发包超时\n"); if(IDENTITY_MASTER != g_updateDa.iDentity)//被升级设备 { for(i=ota_devMsg.lastRightPkgNum;idesDevType,msg1003->desDevSn)){ g_updateDa.Work_State = OTA_UPDATE_ONLOOKER; set_start_ota_timer(&g_otaTimer.onlookerTmr,OTA_TIM_ONLOOKER);// 打开旁观者定时器 printf("cur mode outlooker \r\n"); break; } if(OTA_UPDATE_NULL == g_updateDa.Work_State){ Flash_RangeErase(OTA_UPDATE_APP3_FLASH_START_ADDR, OTA_UPDATE_APP3_FLASH_SIZE); //擦除app3 } g_updateDa.iDentity = IDENTITY_SLAVE;//标记为被升级状态 g_updateDa.ResetUpdate_s = 1;//需要上报升级状态 g_updateDa.Update_Source = UP_PROG_FROM_GAT; bkp_data_write(BKP_DATA_4, UP_PROG_FROM_GAT); // 升级的来源 0x44 来源来网关下发的 g_updateDa.bfirmware_type = msg1003->firmType; bkp_data_write(BKP_DATA_6,g_updateDa.bfirmware_type);//记录固件类型 set_start_ota_timer(&g_otaTimer.totalTmr,OTA_TIM_TOTALTMR); // 打开总定时器 //收到升级指令 updata_state = START_UPDATA; updata_state_save = set_updata_state(updata_state); bkp_data_write(BKP_DATA_2, updata_state_save); g_updateDa.Work_State = OTA_UPDATE_BEGIN; totalPkg = (msg1003->totalByte%msg1003->eachMaxByte) ? msg1003->totalByte/msg1003->eachMaxByte+1 : msg1003->totalByte/msg1003->eachMaxByte; otaContinueTmr = totalPkg*msg1003->sendInterval + OTA_TIM_CONTINUE; if(otaContinueTmr > 8*60*1000){ g_updateDa.Work_State = OTA_UPDATE_ONLOOKER; set_start_ota_timer(&g_otaTimer.onlookerTmr,OTA_TIM_ONLOOKER); return; } ota_slave_init_update_msg(msg1003); set_start_ota_timer(&g_otaTimer.continueTmr,otaContinueTmr); // 启用续传定时器 printf("ota_totle_byte:%d, ota_totle_pkg:%d\n",msg1003->totalByte,totalPkg); printf("send interval:%d, continuous time:%d\n",msg1003->sendInterval,otaContinueTmr); break; case 0x1004: msg1004 = (updateCmd0x1004*)data; if((OTA_UPDATE_BEGIN == g_updateDa.Work_State) || (OTA_UPDATE_CONTINUE == g_updateDa.Work_State)){ if(0 == check_dev_type_sn(msg1004->desDevType,msg1004->desDevSn)){ g_updateDa.Work_State = OTA_UPDATE_ONLOOKER; set_start_ota_timer(&g_otaTimer.onlookerTmr,OTA_TIM_ONLOOKER);// 打开旁观者定时器 ota_timer_stop(&g_otaTimer.continueTmr);// 关闭连续定时器 break; } if(msg1004->subPkgLen > ota_devMsg.eachMaxByte) break; // 接收错误 if(OTA_UPDATE_BEGIN == g_updateDa.Work_State) g_updateDa.Work_State = OTA_UPDATE_CONTINUE; if((msg1004->totalPage == ota_devMsg.totalPage) && (msg1004->subPkgId <= ota_devMsg.totalPage)){ printf("update continue type=0x%x,sn=0x%x,{%d/%d/%d}\r\n",msg1004->rcvDevType,msg1004->rcvDevSn, msg1004->totalPage,msg1004->subPkgId,ota_devMsg.losePkgNum); Flash_BufferWrite(OTA_UPDATE_APP3_FLASH_START_ADDR + (msg1004->subPkgId - 1)*OTA_MASTER_SEND_PKG_SIZE, (uint32_t *)((data+OTA_CONTINUES_INFO_LEN)), msg1004->subPkgLen); //data_dump("收到1004",(uint8_t*)data+OTA_CONTINUES_INFO_LEN,msg1004->subPkgLen); for(i=ota_devMsg.lastRightPkgNum;isubPkgId;i++){ ota_devMsg.losePkgNum++; ota_devMsg.lossPkgId[ota_devMsg.lossPkgIndex++] = i; if(ota_devMsg.losePkgNum == ota_devMsg.loseTotalPage) {// 丢10条 set_start_ota_timer(&g_otaTimer.onlookerTmr,OTA_TIM_ONLOOKER); updata_state_save = set_updata_state(PACKET_LOSS_MORE);// 丢包太多 bkp_data_write(BKP_DATA_2,updata_state_save); return; } } ota_devMsg.lastRightPkgNum = msg1004->subPkgId +1; if(msg1004->subPkgId == msg1004->totalPage){ // 最后一包 if(0 == ota_devMsg.losePkgNum){ // 没有丢包 printf("传输完成,没有丢包\r\n"); ota_timer_stop(&g_otaTimer.continueTmr);// 关闭连续定时器 g_updateDa.Work_State = OTA_UPDATE_CONTINUE_END; // 接收完成 printf("check program right\r\n"); } else { // 有丢包 printf("传输完成,有丢包,启动重传指令\r\n"); g_updateDa.Work_State = OTA_UPDATE_REPEAT; set_start_ota_timer(&g_otaTimer.repeatTmr,OTA_TIM_REPEAT); ota_repeat_rand_timer(0);//重传随机延时 } ota_timer_stop(&g_otaTimer.continueTmr);// 关闭连续定时器 } else { // 不是最后一包 } } } else { g_updateDa.Work_State = OTA_UPDATE_ONLOOKER; set_start_ota_timer(&g_otaTimer.onlookerTmr,OTA_TIM_ONLOOKER); ota_timer_stop(&g_otaTimer.continueTmr);// 关闭连续定时器 } break; case 0x1005: msg1005 = (updateCmd0x1005*)data; if(g_updateDa.Work_State == OTA_UPDATE_REPEAT) { // ota_timer_stop(&g_otaTimer.repeatTmr); if(msg1005->totalPage == ota_devMsg.totalPage){ if(msg1005->subPkgLen > OTA_MASTER_SEND_PKG_SIZE) return; //判定该包是否为本设备丢的那些包之中的子包 for(i = 0;i < ota_devMsg.lossPkgIndex;i++) { if(ota_devMsg.lossPkgId[i] == msg1005->subPkgId) { ota_devMsg.losePkgNum--; ota_devMsg.lossPkgId[i] = 0; //接受本包并写入flash的对应位置 Flash_BufferWrite(OTA_UPDATE_APP3_FLASH_START_ADDR + (msg1005->subPkgId - 1)*OTA_MASTER_SEND_PKG_SIZE, (uint32_t *)(data+OTA_CONTINUES_INFO_LEN ), msg1005->subPkgLen); printf("rcv retransmit pkgid:%d\n",msg1005->subPkgId); break; } } if(ota_devMsg.losePkgNum == 0) //丢包已收完 { //ota_continuous_end_flag = OTA_CONTINUOUS_DIRECT; //g_updateDa.Work_State = DEV_WORK_STATE_OTA_UPGRADE_RCV_END; g_updateDa.Work_State = OTA_UPDATE_REPEAT_END; ota_timer_stop(&g_otaTimer.repeatRandomTmr); } printf("ota_info.lossPkgCounter = %d, lossPkgId:%d\r\n", ota_devMsg.losePkgNum,msg1005->subPkgId); //指示灯显示 //remain_pkg = ota_info.lossPkgCounter; //gch } // set_start_ota_timer(&g_otaTimer.repeatTmr,OTA_TIM_REPEAT); g_updateDa.retransmit_s = 0; } else { g_updateDa.Work_State = OTA_UPDATE_ONLOOKER; set_start_ota_timer(&g_otaTimer.onlookerTmr,OTA_TIM_ONLOOKER); ota_timer_stop(&g_otaTimer.continueTmr);// 关闭连续定时器 } break; } } } void ota_update_slave_retransmit(uint16_t index) { updateCmd0x2005 *msg = (updateCmd0x2005*)_buff; memset(_buff,0,256); msg->slaveDevType = g_devMsg.devType; msg->slaveDevSn = g_devMsg.devSn; msg->repDevType = g_devMsg.devType; msg->repDevSn = g_devMsg.devSn; msg->repPkgId = index; slave_send_data_to_uart(0x04,0x2005,(uint8_t*)msg,sizeof(updateCmd0x2005)); } /*---------------------------------------------------------------------------- * 主设备收到重传指令 * ---------------------------------------------------------------------------*/ void ota_update_master_retransmit(uint8_t *data) { updateCmd0x2005 *msg = (updateCmd0x2005*)data; updateCmd0x1005 *pmsg = (updateCmd0x1005*)_buff; ota_timer_stop(&g_otaTimer.repeatTmr); memset(_buff,0,256); pmsg->rcvDevSn = ota_devMsg.rcvDevSn; //msg->slaveDevSn; ota_devMsg.rcvDevSn; pmsg->rcvDevType = ota_devMsg.rcvDevType; //msg->slaveDevType; ota_devMsg.rcvDevType; pmsg->desDevSn = ota_devMsg.desDevSn; //msg->repDevSn; ota_devMsg.desDevSn; pmsg->desDevType = ota_devMsg.desDevType; //msg->repDevType; ota_devMsg.desDevType; pmsg->subPkgId = msg->repPkgId; pmsg->subPkgLen = OTA_MASTER_SEND_PKG_SIZE; pmsg->totalPage = ota_devMsg.totalPage; Flash_BufferRead(OTA_UPDATE_APP3_FLASH_START_ADDR + (pmsg->subPkgId - 1)*OTA_MASTER_SEND_PKG_SIZE, ((uint8_t *)pmsg) + OTA_CONTINUES_INFO_LEN, OTA_MASTER_SEND_PKG_SIZE); slave_send_data_to_uart(0x04,0x1005,(uint8_t*)pmsg,sizeof(updateCmd0x1005)+OTA_MASTER_SEND_PKG_SIZE); set_start_ota_timer(&g_otaTimer.repeatTmr,OTA_TIM_REPEAT); } void ota_update_slave_continue_end(uint8_t workMode) { uint32_t crcVl,fixChar,fileVer,filelen,i; uint32_t getcrc; switch(workMode){ case OTA_UPDATE_CONTINUE_END: case OTA_UPDATE_REPEAT_END: crcVl = *(uint32_t*)(OTA_UPDATE_APP3_FLASH_START_ADDR+ota_devMsg.totalByte-4); //CRC校验 fixChar = *(uint32_t*)(OTA_UPDATE_APP3_FLASH_START_ADDR+ota_devMsg.totalByte-8); // 固定字符 WBJW fileVer = *(uint32_t*)(OTA_UPDATE_APP3_FLASH_START_ADDR+ota_devMsg.totalByte-12); // 固件信息 filelen = *(uint32_t*)(OTA_UPDATE_APP3_FLASH_START_ADDR+ota_devMsg.totalByte-20); // 文件总长度 printf("read_fixchar:%08x, fixchar:%08x\n",fixChar,0x57424A57); if(fixChar != 0x57424A57) //固定字符错误 { g_updateDa.Work_State = OTA_UPDATE_ONLOOKER; set_start_ota_timer(&g_otaTimer.onlookerTmr,OTA_TIM_ONLOOKER); //打开旁观者定时器 updata_state = FIXED_CHARACTER_ERROR; updata_state_save = set_updata_state(updata_state); bkp_data_write(BKP_DATA_2, updata_state_save); printf("fixChar error\r\n");// 升级文件固定字符校验错误 return; } printf("read_filever:%08x, device_type:%08x\n",fileVer,0x01013000); if((fileVer&0xfffff000) != (APP_VERSION&0xFFFFF000)) //固件信息错误 { g_updateDa.Work_State = OTA_UPDATE_ONLOOKER; set_start_ota_timer(&g_otaTimer.onlookerTmr,OTA_TIM_ONLOOKER); //打开旁观者定时器 updata_state = DEVICE_TYPE_ERROR; updata_state_save = set_updata_state(updata_state); bkp_data_write(BKP_DATA_2, updata_state_save); printf("fileVer error\r\n");// 升级文件固件信息校验错误 return; } printf("read_filelen:%08x, total_bytes:%08x\n",filelen,(ota_devMsg.totalByte-20)); if(ota_devMsg.totalByte != (filelen+20))//长度错误 { g_updateDa.Work_State = OTA_UPDATE_ONLOOKER; set_start_ota_timer(&g_otaTimer.onlookerTmr,OTA_TIM_ONLOOKER); //打开旁观者定时器 updata_state = UPDATA_PACKAGE_LENGTH_ERROR; updata_state_save = set_updata_state(updata_state); bkp_data_write(BKP_DATA_2, updata_state_save); printf("filelen error\r\n");// 升级文件长度校验错误 return; } app_check_crc(OTA_UPDATE_APP3_FLASH_START_ADDR,OTA_UPDATE_APP3_FLASH_SIZE,&getcrc); printf("read_crc:%x, get_crc:%x\n",crcVl,getcrc); if(getcrc!=crcVl) { //校验错误 printf("update file crc error\r\n");// 升级文件crc校验错误 g_updateDa.Work_State = OTA_UPDATE_ONLOOKER; set_start_ota_timer(&g_otaTimer.onlookerTmr,OTA_TIM_ONLOOKER); //打开旁观者定时器 updata_state = UPDATA_CRC_ERROR; updata_state_save = set_updata_state(updata_state); bkp_data_write(BKP_DATA_2, updata_state_save); return; } printf("收包正确\n"); updata_state = UPDATA_DATA_SUCCESS; updata_state_save = set_updata_state(updata_state); bkp_data_write(BKP_DATA_2, updata_state_save); updata_state = set_updata_state(UPDATE_FLAG);//置升级标志 bkp_data_write(BKP_DATA_1, updata_state); //g_firmwareMsg.gatewayMsg.verMsg.gate_appVr3 = fileVer;//存储APP3版本 //fram_write_gateway_version(); NVIC_SystemReset(); break; case OTA_UPDATE_REPEAT: // if(!timeout_isOut(&g_otaTimer.randomTmr.timer)) break; if(!timeout_isOut(&g_otaTimer.repeatRandomTmr.timer)) break; // if(1 == g_updateDa.bRetransmit) break; dma_channel_disable(DMA1, DMA_CH2); if(USART3_RX_SIZE - dma_transfer_number_get(DMA1,DMA_CH2)) { dma_channel_enable(DMA1, DMA_CH2);/* enable USART1_RX DMA_Channel */ ota_repeat_rand_timer(1);//重传随机延时 break; } dma_channel_enable(DMA1, DMA_CH2);/* enable USART1_RX DMA_Channel */ for(i = 0;i < ota_devMsg.lossPkgIndex;i++) { if(ota_devMsg.lossPkgId[i]) { ota_update_slave_retransmit(ota_devMsg.lossPkgId[i]); printf("send retransmit pkgid:%d\n",ota_devMsg.lossPkgId[i]); g_updateDa.bRetransmit = 1; g_updateDa.retransmit_s = 1; break; } } ota_repeat_rand_timer(0);//重传随机延时 break; } } void ota_update_send_update_status(uint16_t desDevType,uint32_t desDevSn) { updateCmd0x2007 *msg = (updateCmd0x2007*)_buff; memset(_buff,0,256); msg->slaveDevType = g_devMsg.devType; msg->slaveDevSn = g_devMsg.devSn; msg->desDevType = desDevType; msg->desDevSn = desDevSn; msg->ptVer = g_devAppVer.ptVer; msg->appVer = APP_VERSION; msg->updateCode = g_updateDa.updateCode; msg->reserve = 0x00; slave_send_data_to_uart(0x04,0x2007,(uint8_t*)_buff,sizeof(updateCmd0x2007)); } void ota_update_deal_upstatus(void) { static uint8_t flag = 0; if((0x01 ==g_updateDa.bResetUpdate) ) { // 连接网络且有升级 if(g_updateDa.Update_Source == UP_PROG_FROM_NET){//升级来源于网络 if(0x01 == g_4gMsg.bconnect){ send_update_code_to_serve(g_devMsg.devType,g_devMsg.devSn,g_updateDa.taskNo,g_updateDa.updateCode,0x03); printf("上传升级标志到服务器\r\n"); g_updateDa.bResetUpdate = 0; if(g_updateDa.bUpdate_slave==UPDATE_SLAVE) { g_updateDa.bOffline_s = 1;//可以离线升级 g_devMsg.workMode = WORK_UPDATE; g_devMsg.ledgreen = 2; } } } else { if(timeout_isOut(&(g_otaTimer.randomTmr.timer))){ //超时,可以发送 printf("发送升级标志 %d\r\n",g_updateDa.updateCode); ota_update_send_update_status(g_devMsg.devType,g_devMsg.devSn); flag++; if(flag >=3 ){ bkp_data_write(BKP_DATA_2,0);//清除标志备份寄存器 g_updateDa.bResetUpdate = 0x00; memset(&g_updateDa,0,sizeof(UpdateDa)); flag = 0; } set_start_ota_timer(&g_otaTimer.randomTmr,(rand()%150+200)); } } } } ///////////////////////离线升级//////////////////////////// //读取app程序包的大小并校验 uint32_t Read_APP_datalen_check(uint32_t addr, uint32_t len) { uint32_t datalen = 0; uint32_t crcVl,fixChar,fileVer,filelen,getcrc,t_addr; uint32_t bin_data[6] = {0}; uint8_t flag = 0; uint8_t check_flag = 0; printf("addr=%08x\n",addr); datalen = Flash_DatalenRead(addr,len); if((datalen > (96*1024)) || (datalen < (20))) { printf("升级包长度超过128K: %d\n",datalen); datalen = 0; return datalen; } filelen = *(uint32_t*)(addr+datalen-20); // 文件总长度 printf("datalen=%08x,%u; filelen=%08x,%u\n",datalen,datalen,filelen,filelen); printf("addr=%08x\n",addr); crcVl = *(uint32_t*)(addr + datalen-4); //CRC校验 fixChar = *(uint32_t*)(addr + datalen-8); // 固定字符 WBJW fileVer = *(uint32_t*)(addr + datalen-12); // 固件信息 filelen = *(uint32_t*)(addr + datalen-20); // 文件总长度 t_addr = *(uint32_t*)(addr + datalen-16); // 文件写入的地址 printf("crcVl=%08x,fixChar=%08x,fileVer=%08x,filelen=%08x,t_addr=%08x\n",crcVl,fixChar,fileVer,filelen,t_addr); //判断后20字节是否正确 if((fixChar == 0x57424A57) && (t_addr == 0x08018000))//升级包中包含了后20字节 { printf("升级包包含了后20字节\n"); if(datalen != (filelen+20)) { printf("升级包长度校验错误\n"); check_flag = 1; } // else if(fileVer != device_fixed_info.Soft_ver_app) // { // printf("固件信息错误\n"); // printf("filever=%08x,app=%08x\n",fileVer,device_fixed_info.Soft_ver_app); // check_flag = 1; // } else { app_check_crc(addr,datalen,&getcrc); printf("read_crc:%08x, get_crc:%08x\n",crcVl,getcrc); if(crcVl != getcrc) { printf("crc 错误\n"); check_flag = 1; } } } else { check_flag = 1; } if(check_flag)//后20字节错误 { if(addr==OTA_UPDATE_APP1_FLASH_START_ADDR)//app1需要计算后20个字节 { bin_data[0] = datalen; //原始bin文件字节长度 bin_data[1] = OTA_UPDATE_APP1_FLASH_START_ADDR; //存储地址 bin_data[2] = APP_VERSION; //固件版本 bin_data[3] = 0x57424A57; //固定标记,"WBJW" fileVer = bin_data[2]; flag = Flash_BufferWrite(addr+datalen,bin_data,16); printf("first flag = %d\n",flag); datalen += 20; printf("datalen1=%08x\n",datalen); //app_check_crc(addr,datalen,&getcrc); rcu_periph_clock_enable(RCU_CRC); //打开crc时钟 crc_data_register_reset(); //复位crc数据寄存器 getcrc = crc_block_data_calculate((uint32_t*)addr,(datalen -4)/4);//计算crc数值 rcu_periph_clock_disable(RCU_CRC); //关闭crc时钟 bin_data[0] = getcrc; printf("crc=%08x\n",bin_data[0]); flag = Flash_BufferWrite(addr+datalen-4,bin_data,4); //crc校验 printf("second flag = %d\n",flag); } else { datalen = 0; } } if(datalen) { memset(&ota_devMsg,0,sizeof(otaUpdatMsg)); ota_devMsg.version = fileVer; // 升级的软件版本号 ota_devMsg.totalByte = datalen; // 升级的总大小 } return datalen; } void ota_master_init_update_msg_offline(uint16_t rcvdevtype,uint32_t rcvdevsn,uint16_t desdevtype,uint32_t desdevsn,uint8_t firmtype) { // memset(&ota_devMsg,0,sizeof(otaUpdatMsg)); ota_devMsg.rcvDevType = rcvdevtype; // 接收设备类型 ota_devMsg.rcvDevSn = rcvdevsn; // 接收设备SN ota_devMsg.desDevType = desdevtype; // 升级目标设备类型 ota_devMsg.desDevSn = desdevsn; // 升级目标设备SN ota_devMsg.firmType = firmtype; // 升级固件类型 // ota_devMsg.version = version; // 升级的软件版本号 // ota_devMsg.totalByte = totallen; // 升级的总大小 ota_devMsg.losePage = 20; ota_devMsg.sendInterval = 300; ota_devMsg.totalPage = ota_devMsg.totalByte/OTA_MASTER_SEND_PKG_SIZE; if(ota_devMsg.totalByte%OTA_MASTER_SEND_PKG_SIZE) ota_devMsg.totalPage += 1; ota_devMsg.subPkgLen = OTA_MASTER_SEND_PKG_SIZE; ota_devMsg.subPkgId = 1; ota_devMsg.lastRightPkgNum = 1; ota_devMsg.lossPkgIndex = 0; } //离线升级初始化 uint8_t ota_offline_init(uint32_t addr,uint32_t len) { uint32_t total_bytes = 0; total_bytes = Read_APP_datalen_check(addr,len); if(total_bytes==0) //升级包长度错误,升级结束 { printf("升级包长度错误 "); return 0; } return 1; } //离线升级过程 void ota_offline_proc(void) { g_updateDa.iDentity = IDENTITY_MASTER;//标记为下发升级设备 g_devMsg.workMode = WORK_UPDATE; g_devMsg.ledgreen = 2; ota_master_update_salve(&ota_devMsg,g_updateDa.bOffline_addr); } //离线升级处理函数 void ota_offline_handle(void) { //离线升级 if(g_updateDa.bOffline_s) { g_updateDa.bOffline_s = 0; printf("开始离线升级\n"); ota_offline_proc(); } } //从设备收到离线升级指令 void ota_update_slave_offline(uint8_t *data,uint8_t len) { updateCmd0x1006* msg1006 = (updateCmd0x1006*)data; if(g_devMsg.workMode == WORK_UPDATE) return; if((msg1006->masterDevType==g_devMsg.devType) && (msg1006->masterDevSn==g_devMsg.devSn)) { if(msg1006->firmType != 0x03) return; //不是升级app if(ota_offline_init(OTA_UPDATE_APP1_FLASH_START_ADDR,OTA_UPDATE_APP1_FLASH_SIZE))//升级包正确 { ota_master_init_update_msg_offline(msg1006->slaveDevType,msg1006->slaveDevSn,msg1006->desDevType,msg1006->desDevSn,msg1006->firmType); g_updateDa.bOffline_s = 1;//可以离线升级 g_updateDa.bOffline_addr = OTA_UPDATE_APP1_FLASH_START_ADDR; g_devMsg.workMode = WORK_UPDATE; g_devMsg.ledgreen = 2; printf("升级从设备\n"); } } } /*------------------------------------------------------------------------------- * 按键启动离线升级 * -----------------------------------------------------------------------------*/ void ota_start_offline_update(void) { if(g_devMsg.workMode != WORK_UPDATE)//非升级模式 { if(ota_offline_init(OTA_UPDATE_APP1_FLASH_START_ADDR,OTA_UPDATE_APP1_FLASH_SIZE))//升级包正确 { ota_master_init_update_msg_offline(DEV_TYPE,0xffffffff,DEV_TYPE,0xffffffff,0x03);//升级app g_updateDa.bOffline_s = 1;//可以离线升级 g_updateDa.bOffline_addr = OTA_UPDATE_APP1_FLASH_START_ADDR; printf("升级从设备\n"); } g_devMsg.workMode = WORK_UPDATE; g_devMsg.ledgreen = 2; } } /*------------------------------------------------------------------------------- * 升级成功后,主设备 接收升级的状态 * --------------------------------------------------------------------------------*/ void master_update_status_rcv(uint8_t *data, uint32_t len) { updateCmd0x2007 *msg = (updateCmd0x2007*)data; printf("^^^^^^^rcv type = %04x sn = %08x app = %08x, status = %d\r\n",msg->desDevType, msg->desDevSn,msg->appVer,msg->updateCode); if((IDENTITY_MASTER == g_updateDa.iDentity) || (IDENTITY_MASTER == g_iDentity)) { send_update_code_to_serve(msg->desDevType,msg->desDevSn,g_updateDa.taskNo,msg->updateCode,0x03); } }