首页 » 通讯 » STM32控制4G模组SIMCOM7600CE实现OTA进级_法式_烧录

STM32控制4G模组SIMCOM7600CE实现OTA进级_法式_烧录

萌界大人物 2024-12-08 20:53:02 0

扫一扫用手机浏览

文章目录 [+]

第一部分: Boot_Loader 起始地址: 0x0800F000 大小为:60K 占30页第二部分:Application_1 起始地址: 0x0800F000 大小为:90K 占45页第三部分:Application_2 起始地址: 0x08025800 大小为:90K 占45页

  OTA升级的程序包含三部分,分别命名为BOOT,APP1,APP2。
(名字自己随便取,本例程我是为了方便理解这样子取的,这三部分的程序实质上还是嵌入式程序,和我们平常编写的程序没有什么差异)

STM32控制4G模组SIMCOM7600CE实现OTA进级_法式_烧录 通讯

( 1 ) BOOT:紧张实现的功能是开机检讨是否有升级的标志位。
  如果没有升级的标志位,那就把程序的指针跳转到APP1的地址,正常启动APP1的业务逻辑。
  如果 有升级的标志位,BOOT会先把APP1霸占的内部Flash清空,然后将APP2的内容搬运到APP1内,搬运完成后打消升级的标志位以及重启单片机,重启后BOOT先运行,检测到没有升级的标志位。
那就把程序的指针跳转到APP1的地址,正常启动APP1的业务逻辑。

( 2 )APP1里存的是主业务逻辑的程序。
(如果没有升级的标志位,每次BOOT启动后下一个就会运行APP1)

( 3 )APP2里存的是将要升级的业务逻辑的程序。
(APP2内只卖力存储将要升级的BIN文件,程序永久不会跳转到这里)

第二步OTA本地升级测试

  先说一下测试的大概思路,我们用STM32CubeProgrammer这个工具代替4G将APP2的BIN文件刷到APP2的地址空间内。
然后微调代码让程序完成升级。
紧张目的是测试BOOT的嵌入式程序是否正常。

BOOT的程序大致分为以下几块

1,内部Flash的读写。
(内部Flash的读写的不展开了,详细参考源码)

2,搬运APP的BIN文件到APP1的位置。

/ @bieaf 进行程序的覆盖 @detail 1.擦除目的地址 @detail 2.源地址的代码拷贝到目的地址 @detail 3.擦除源地址 @param 搬运的源地址 @param 搬运的目的地址 @return 搬运的程序大小/void MoveCode(unsigned int src_addr, unsigned int des_addr, unsigned int byte_size){ /1.擦除目的地址/ printf("> Start erase des flash......\r\n"); Erase_page(des_addr, (byte_size/PageSize)); printf("> Erase des flash sucessfully......\r\n"); /2.开始拷贝/ uint8_t temp[1024]; printf("> Start copy......\r\n"); for(int i = 0; i < byte_size/1024; i++) { ReadFlash((src_addr + i1024), temp, 1024); WriteFlash((des_addr + i1024), temp, 1024); } printf("> Copy sucessfully......\r\n"); /3.擦除源地址/ printf("> Start erase src flash......\r\n"); Erase_page(src_addr, (byte_size/PageSize)); printf("> Erase src flash sucessfully......\r\n");}

3,开机判断启动办法

/ @bieaf 进行BootLoader的启动 @return none/void Start_BootLoader(void){ printf("\r\n"); printf("\r\n"); printf(" \r\n"); printf(" BootLoader \r\n"); printf(" \r\n"); printf("\r\n"); printf("> Choose a startup method......\r\n");switch(Read_Start_Mode())//读取是否启动运用程序{case Startup_Normal://正常启动{printf("> Normal start......\r\n");break;}case Startup_Update://升级再启动{printf("> Start update......\r\n");MoveCode(Application_2_Addr, Application_1_Addr, Application_Size);printf("> Update sucessfully......\r\n");break;}default://启动失落败{printf("> Error:%X!!!......\r\n", Read_Start_Mode());return;}}/ 跳转到运用程序 /// __disable_irq() ; //很主要!
经测试STM32F4必要!
貌似F105也须要 L431 裸机 却不须要 RTOS须要printf("> Start up......\r\n\r\n");IAP_ExecuteApp(Application_1_Addr);}

4,跳转运行程序到APP1的地址。

/ @bieaf 采取汇编设置栈的值 @return none返回值/__asm void MSR_MSP (uint32_t ulAddr){ MSR MSP, r0 //set Main Stack value BX r14}/ @bieaf 程序跳转函数 @return none返回值/typedef void (Jump_Fun)(void);void IAP_ExecuteApp (uint32_t App_Addr){Jump_Fun JumpToApp; if ((((__IO uint32_t )App_Addr) & 0x2FFE0000) == 0x20000000)//检讨栈顶地址是否合法.{ JumpToApp = (Jump_Fun) (__IO uint32_t )(App_Addr + 4);//用户代码区第二个字为程序开始地址(复位地址)MSR_MSP( (__IO uint32_t ) App_Addr);//初始化APP堆栈指针(用户代码区的第一个字用于存放栈顶地址)JumpToApp();//跳转到APP}else{printf("There is None APP to jump,ERROR!!!\r\n");}}

5,设置BOOT程序的ROM地址以及大小

6,用ST-Link下载时设置为全擦除内部Flash

APP1的程序

1,须要在main主程序的第一行变动中断向量表地址到0x800F000U。
2,将升级的标志位设为0xAA。
3,在升级标志位设为0xAA之前硬延迟10S,这一步的目的是有充足的韶光将APP2的BIN文件刷进板子里。
(在实际的项目中不会有这个东西)4,将LED的闪烁配置为1s闪烁一次。
(这是测试程序,故只配置了一个闪烁的LED灯来关注实验征象)5,设置APP1程序的ROM地址以及大小

6,用ST-Link下载时不要设置为全擦除内部Flash

APP2的程序

须要在main主程序的第一行变动中断向量表地址到0x800F000U。
须要将User的一下内容配置一下,这一步的目的是天生BIN文件。
(别去世搬硬抄,结合自己的工程微调一下)C:\Program Files\Keil_v5\ARM\ARMCC\bin\fromelf.exe --bin --output .\APP\APP.bin .\APP.axf

然后每次编译后就可以在自己电脑的工程文件夹里找到app.bin文件。

3,将LED的闪烁配置为50ms闪烁一次。
(这是测试程序,故只配置了一个闪烁的LED灯来关注实验征象)4,设置APP2程序的ROM地址以及大小

测试步骤

1,步骤1:先用ST-link将BOOT的程序刷进板子内。
2,步骤2:再用ST-link将APP1的程序双进板子内。
3,步骤3:将APP2的BIN文件通过工具STM32CubeProgrammer刷进板子内。
(经测试这一步往后程序会陷入假去世机状态,缘故原由未明,知道的大神可以给我留言阐明下,感激了)

4,复位开拓板,,经由十秒后开拓板的LED灯会满闪。
同时根据程序也可知道升级标志位已经写好了。
5,复位开拓板,就能创造LED灯快闪了。
表示升级完成。

第三步OTA升级的完备体

  这一步的紧张事情就算是把4G的联网驱动完善。
我们须要一个平台来供我们下载BIN文件,(平台须要找软件开拓,我不会。
我用的是公司的以是我不可能公开出来的)

1,首先我们先写联网驱动。
(采取有限的状态机编程,状态机是参考的正道老师的教程)

以下是完全联网+升级部分的代码,每次开机就会往我的平台(47.98.183.97:1884)上发送模组的旗子暗记值。

/设置CAT1状态的列举变量/typedef enum{ CAT1_IDIE = 0, CAT1_SEND, CAT1_WAIT, CAT1_ACCESS} teCAT1_TaskStatus;/设置AT指令集的列举变量/typedef enum{ //AT_RST, AT, ATE0, AT_CGSN, AT_CCID, AT_CEREG, AT_CGATT, AT_CSQ_1, AT_CMQTTSTART, AT_CMQTTACCQ, AT_CMQTTCONNECT, AT_CSQ_2, AT_CMQTTTOPIC, AT_TOPIC, AT_CMQTTPAYLOAD, AT_MESSAGE, AT_CMQTTPUB,/HTTP干系指令/AT_HTTPINIT_1,AT_HTTPPARA_VERSION,AT_HTTPACTION_1,AT_HTTPREAD_1,AT_HTTPTERM_1,AT_HTTPINIT_2,AT_HTTPPARA_DATA,AT_HTTPACTION_2,AT_HTTPREAD_2,AT_HTTPTERM_2,} teATCmdNum;/设置模组状态的列举变量/typedef enum{ SUCCESS_REC = 0, TIME_OUT, NO_REC} teATStatus;/设置AT指令集的构造体/typedef struct{ char ATSendStr; char ATRecStr; uint16_t TimeOut; teATStatus ATStatus; uint8_t RtyNum;} tsATCmds;

/入网AT指令集/tsATCmds ATCmds[] ={ / 下面是关于连接MQTT的指令集/ //{"AT+CRESET\r\n","PB DONE",5000,NO_REC,3}, {"AT\r\n","OK",1000,NO_REC,3},//AT指令测试 {"ATE0\r\n","OK",1000,NO_REC,3},//关闭回显 {"AT+CGSN\r\n","OK",1000,NO_REC,3},//查询Imei {"AT+CCID\r\n","OK",1000,NO_REC,3},//查询ICCID {"AT+CEREG?\r\n","OK",1000,NO_REC,100},//查询当前GPRS注册状态 {"AT+CGATT?\r\n","OK",1000,NO_REC,3},//查询当前GPRS附着状态 {"AT+CSQ\r\n","OK",1000,NO_REC,3},//查询旗子暗记值 {"AT+CMQTTSTART\r\n","+CMQTTSTART: 0",2000,NO_REC,3},//开启MQTT连接 {"AT+CMQTTACCQ=0,\"clientid01\"\r\n","OK",2000,NO_REC,3},//注册MQTT的ClientID {"AT+CMQTTCONNECT=0,\"tcp://47.98.183.97:1884\",120,1,\"admin\",\"public\"\r\n","+CMQTTCONNECT: 0,0",3000,NO_REC,3},//设置IP port username password keepalive {"AT+CSQ\r\n","OK",1000,NO_REC,3},//查询CSQ {"AT+CMQTTTOPIC=0,",">",2000,NO_REC,3},//设置topic {topic_buffer,"OK",3000,NO_REC,3},//topic内容 {"AT+CMQTTPAYLOAD=0,",">",2000,NO_REC,3},//设置发送报文 {message_buffer,"OK",3000,NO_REC,5},//msg内容 {"AT+CMQTTPUB=0,1,60\r\n","+CMQTTPUB: 0,0",3000,NO_REC,5},//发送报文 / 下面是关于查询版本号的AT指令集/ {"AT+HTTPINIT\r\n","OK",1000,NO_REC,3},//开启HTTP做事 {"AT+HTTPPARA=\"URL\",\"http://47.98.248.24:8888/getVersion?device_id=123456\"\r\n","OK",1000,NO_REC,3},//设置HTTP参数 {"AT+HTTPACTION=0\r\n","+HTTP_PEER_CLOSED",1000,NO_REC,3},//操作HTTP方法 {"AT+HTTPREAD=0,100\r\n","+HTTPREAD:0",1000,NO_REC,3},//读取HTTP做事回答 {"AT+HTTPTERM\r\n","OK",1000,NO_REC,3},//关闭HTTP做事 / 下面是关于下载BIN文件的AT指令集/ {"AT+HTTPINIT\r\n","OK",1000,NO_REC,3},//开启HTTP做事 {"AT+HTTPPARA=\"URL\",\"http://47.98.248.24:8888/download1?device_id=123456&version=3.0.0\"\r\n","OK",3000,NO_REC,3},//设置HTTP参数 {"AT+HTTPACTION=0\r\n","+HTTPACTION:",3000,NO_REC,3},//操作HTTP方法 {"AT+HTTPREAD=0,1024\r\n","+HTTPREAD:",3000,NO_REC,3},//读取HTTP做事回答 {"AT+HTTPTERM\r\n","OK",1000,NO_REC,3},//关闭HTTP做事};/ AT指令发送处理逻辑 /void ATSend(teATCmdNum ATCmdNum){ //清空吸收缓存区 memset(Lpuart1type.Lpuart1RecBuff,0,LPUART1_REC_SIZE); ATCmds[ATCmdNum].ATStatus = NO_REC; ATRecCmdNum = ATCmdNum; printf("\r\n当前命令码:%d\r\n",ATCmdNum); / 设置topic的长度 / if(ATCmdNum == AT_CMQTTTOPIC) { memset(topic_buffer,0x00,sizeof(topic_buffer)); sprintf(topic_buffer,"dev/%s",Imei_buffer); sprintf(send_buffer,"%s%d\r\n",ATCmds[ATCmdNum].ATSendStr,strlen(topic_buffer)); HAL_UART_Transmit(&hlpuart1,(uint8_t)send_buffer,strlen(send_buffer),0xFF); printf("send_buffer:%s\r\n",send_buffer); memset(send_buffer,0x00,strlen(send_buffer)); } / 设置msg的长度 / else if(ATCmdNum == AT_CMQTTPAYLOAD) { memset(message_buffer,0x00,sizeof(message_buffer)); sprintf(message_buffer,"{\"CSQ\":%s}",CSQ_buffer); sprintf(send_buffer,"%s%d\r\n",ATCmds[ATCmdNum].ATSendStr,strlen(message_buffer)); HAL_UART_Transmit(&hlpuart1,(uint8_t)send_buffer,strlen(send_buffer),0xFF); printf("send_buffer:%s",send_buffer); memset(send_buffer,0x00,sizeof(send_buffer)); } else { HAL_UART_Transmit(&hlpuart1,(uint8_t)ATCmds[ATCmdNum].ATSendStr,strlen(ATCmds[ATCmdNum].ATSendStr),0xff); printf("send:%s",ATCmds[ATCmdNum].ATSendStr); } //打开超时定时器 SetTime(&TimeCAT1,ATCmds[ATCmdNum].TimeOut);}/ AT指令吸收处理逻辑 /void ATRec(void){ if(Lpuart1type.Lpuart1RecFlag) { if(strstr((const char)Lpuart1type.Lpuart1RecBuff,ATCmds[ATRecCmdNum].ATRecStr) != NULL) { ATCmds[ATRecCmdNum].ATStatus = SUCCESS_REC; } printf("收到数据:%s",Lpuart1type.Lpuart1RecBuff); Lpuart1type.Lpuart1RecFlag = 0; Lpuart1type.Lpuart1RecLen = 0; }}/ 初始化CAT1 /void CAT1_Init(void){ Start_4G(); CAT1_TaskStatus = CAT1_SEND; ATCurrentCmdNum = AT; ATNextCmdNum = ATE0;}/ AT指令交互逻辑 /void CAT1_Task(void){ while(1) { switch(CAT1_TaskStatus) { case CAT1_IDIE: //空闲态 return; case CAT1_SEND: if(ATCurrentCmdNum !=ATNextCmdNum) { CurrentRty = ATCmds[ATCurrentCmdNum].RtyNum; } ATSend(ATCurrentCmdNum); CAT1_TaskStatus = CAT1_WAIT; return; case CAT1_WAIT://等待态,等待CAT1返回的信息 ATRec();//调用吸收函数 if(ATCmds[ATRecCmdNum].ATStatus == SUCCESS_REC) { printf("当前码:%d\r\n",ATCurrentCmdNum); if(ATCurrentCmdNum == AT_CGSN)//如果AT指令为查询IMEI { ATCurrentCmdNum += 1; ATNextCmdNum = ATCurrentCmdNum+1; CAT1_TaskStatus = CAT1_SEND; memset (CSQ_buffer,0x00,sizeof(CSQ_buffer)); Find_string((char)Lpuart1type.Lpuart1RecBuff, "\r\n", "\r\n", Imei_buffer); printf("Imei_buffer=%s\r\n",Imei_buffer); break; } else if(ATCurrentCmdNum == AT_CSQ_2)//如果AT指令为查询CSQ { ATCurrentCmdNum += 1; ATNextCmdNum = ATCurrentCmdNum+1; CAT1_TaskStatus = CAT1_SEND; memset(CSQ_buffer,0x00,sizeof(CSQ_buffer)); Find_string((char)Lpuart1type.Lpuart1RecBuff, " ", ",", CSQ_buffer); printf("CSQ_buffer=%s\r\n",CSQ_buffer); break; } else if(ATCurrentCmdNum == AT_HTTPREAD_1)//如果AT指令为查询版本号 { ATCurrentCmdNum += 1; ATNextCmdNum = ATCurrentCmdNum+1; CAT1_TaskStatus = CAT1_SEND; memset(Version_buffer,0x00,sizeof(Version_buffer)); Find_string((char)Lpuart1type.Lpuart1RecBuff, "{", "}", Version_buffer); printf("Version_buffer=%s\r\n",Version_buffer); if(strcmp(Version_buffer,"\"version\":\"3.0.0\"") == 0) { printf("硬件版本和云端版本同等,无需升级!
\r\n"); } else { Update_Task(); } break; } else if(ATCurrentCmdNum == AT_HTTPACTION_2)//如果AT指令为读取BIN文件长度 { ATCurrentCmdNum += 1; ATNextCmdNum = ATCurrentCmdNum+1; CAT1_TaskStatus = CAT1_SEND; memset (Bin_len,0x00,sizeof(Bin_len)); Find_string((char)Lpuart1type.Lpuart1RecBuff, "200,", "\r\n", Bin_len); printf("Bin_len=%s\r\n",Bin_len); break; } else if(ATCurrentCmdNum == AT_HTTPREAD_2)//如果AT指令为下载BIN文件 { int len = 0; long compare_len = 0; memset(Msg_Len,0x00,sizeof(Msg_Len)); Find_string((char)Lpuart1type.Lpuart1RecBuff, "DATA,", "\r\n", Msg_Len); compare_len = atoi(Msg_Len); printf("Find_Buf:%lu\r\n",compare_len); if(Erase_flag == 1)//仅仅开始是擦除flash一次 { Erase_flag = 0; Erase_page(Application_2_Addr, 45); //擦除45页 90K } len = strstr((char )Lpuart1type.Lpuart1RecBuff, Msg_Len) - (char)Lpuart1type.Lpuart1RecBuff + strlen(Msg_Len) + 2; printf("offset address is: %d\r\n",len);if(compare_len == 1024){memset (Bin_len,0x00,sizeof(Bin_len));for(long b = 0; b < 1024; b++){Bin_buffer[b] = Lpuart1type.Lpuart1RecBuff[len+b];}/ 接下来将固件写进flash内 /printf("烧录第%d包...................\r\n",addr_count);WriteFlash((Application_2_Addr+(addr_count)1024), (uint8_t )(&Bin_buffer[0]), 1024);addr_count++;ATNextCmdNum = ATCurrentCmdNum;CAT1_TaskStatus = CAT1_SEND;}else if(compare_len < 1024){memset (Bin_len,0x00,sizeof(Bin_len));for(int b = 0; b < 1024; b++){Bin_buffer[b] = Lpuart1type.Lpuart1RecBuff[len+b];}/ 接下来将固件写进flash内 /printf("烧录第%d包...................\r\n",addr_count);WriteFlash((Application_2_Addr+(addr_count)1024), (uint8_t )(&Bin_buffer[0]), compare_len);addr_count = 0;Erase_flag =1;reboot_flag = 1;ATCurrentCmdNum += 1;ATNextCmdNum = ATCurrentCmdNum+1;CAT1_TaskStatus = CAT1_SEND;} break; } else if(ATCurrentCmdNum == AT_CMQTTPUB)//表示发送msg成功 { CAT1_TaskStatus = CAT1_ACCESS; break; } else if(ATCurrentCmdNum == AT_HTTPTERM_1)//表示查询版本号成功 { CAT1_TaskStatus = CAT1_ACCESS; break; } else if(ATCurrentCmdNum == AT_HTTPTERM_2)//表示下载BIN文件成功 { CAT1_TaskStatus = CAT1_ACCESS; break; } else { ATCurrentCmdNum += 1; ATNextCmdNum = ATCurrentCmdNum+1; CAT1_TaskStatus = CAT1_SEND; break; } } else if(CompareTime(&TimeCAT1))//表示发送超时 { printf("TimeOut:%s\r\n",Lpuart1type.Lpuart1RecBuff); ATCmds[ATRecCmdNum].ATStatus = TIME_OUT; if(CurrentRty > 0) { CurrentRty--; ATNextCmdNum = ATCurrentCmdNum; CAT1_TaskStatus = CAT1_SEND; break; } else { CAT1_Init(); return; } } return; case CAT1_ACCESS://成功态 CAT1_TaskStatus = CAT1_IDIE; break; default: return; } }}

设置按键1和按键2 分别是升级和查询版本号。

/ 外部中断触发 /void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){ / 判断哪个引脚触发了中断 / switch(GPIO_Pin) { case GPIO_PIN_2: ExitFlag = 1; break; case GPIO_PIN_3: ExitFlag = 2; break; default: break; }}void KEY_Task(void){ if(ExitFlag == 1) { ExitFlag = 0; Update_Task(); } else if(ExitFlag == 2) { ExitFlag = 0; Get_Version(); }}

下面是升级部分的详细代码以及流程图如下。

else if(ATCurrentCmdNum == AT_HTTPREAD_2)//如果AT指令为下载BIN文件{ int len = 0; long compare_len = 0; memset(Msg_Len,0x00,sizeof(Msg_Len)); Find_string((char)Lpuart1type.Lpuart1RecBuff, "DATA,", "\r\n", Msg_Len); compare_len = atoi(Msg_Len); printf("Find_Buf:%lu\r\n",compare_len); if(Erase_flag == 1)//仅仅开始是擦除flash一次 { Erase_flag = 0; Erase_page(Application_2_Addr, 45); //擦除45页 90K } len = strstr((char )Lpuart1type.Lpuart1RecBuff, Msg_Len) - (char)Lpuart1type.Lpuart1RecBuff + strlen(Msg_Len) + 2; printf("offset address is: %d\r\n",len); if(compare_len == 1024) { memset (Bin_len,0x00,sizeof(Bin_len)); for(long b = 0; b < 1024; b++) { Bin_buffer[b] = Lpuart1type.Lpuart1RecBuff[len+b]; } / 接下来将固件写进flash内 / printf("烧录第%d包...................\r\n",addr_count); WriteFlash((Application_2_Addr+(addr_count)1024), (uint8_t )(&Bin_buffer[0]), 1024); addr_count++; ATNextCmdNum = ATCurrentCmdNum; CAT1_TaskStatus = CAT1_SEND; } else if(compare_len < 1024) { memset (Bin_len,0x00,sizeof(Bin_len)); for(int b = 0; b < 1024; b++) { Bin_buffer[b] = Lpuart1type.Lpuart1RecBuff[len+b]; } / 接下来将固件写进flash内 / printf("烧录第%d包...................\r\n",addr_count); WriteFlash((Application_2_Addr+(addr_count)1024), (uint8_t )(&Bin_buffer[0]), compare_len); addr_count = 0; Erase_flag =1; reboot_flag = 1; ATCurrentCmdNum += 1; ATNextCmdNum = ATCurrentCmdNum+1; CAT1_TaskStatus = CAT1_SEND; }}

测试步骤步骤1:通过ST-Link将BOOT刷进单片机步骤2:通过ST-Link将APP1刷进单片机,刷完程序,单片机会自动重启并上报CSQ的值,如下图所示。

步骤3:复制一份APP1的代码,重命名为APP2,将上报旗子暗记的CSQ改成BSQ,如下所示。

sprintf(message_buffer,"{\"BSQ\":%s}",CSQ_buffer);

步骤4:将APP2上传到OTA平台上步骤4:按下按键2,查询版本号是否同等步骤5:按下按键1,升级程序。
通过串口信息判断是否升级完成,如果打印以下信息就表示升级完成了。
(通过4G模组下载BIN文件时显示下载数据有乱码是正常征象,由于BIN文件时二进制。

[16:58:39.108]收←◆当前命令码:21send:AT+HTTPINITDMA_len:6收到数据:OK当前码:21当前命令码:22send:AT+HTTPPARA="URL","http://47.98.248.24:8888/download1?device_id=123456&version=3.0.0"收到数据:OK当前码:22当前命令码:23send:AT+HTTPACTION=0DMA_len:6收到数据:OK[16:58:39.671]收←◆DMA_len:28收到数据:+HTTPACTION: 0,200,15364当前码:23Bin_len=15364当前命令码:24send:AT+HTTPREAD=0,1024[16:58:39.776]收←◆DMA_len:1069收到数据:OK+HTTPREAD: DATA,1024x当前码:24Find_Buf:1024[16:58:41.432]收←◆erase successoffset address is: 30烧录第0包...................当前命令码:24send:AT+HTTPREAD=0,1024[16:58:41.548]收←◆DMA_len:1069收到数据:OK+HTTPREAD: DATA,1024??当前码:24Find_Buf:1024offset address is: 30烧录第1包...................当前命令码:24send:AT+HTTPREAD=0,1024[16:58:41.670]收←◆DMA_len:1069收到数据:OK+HTTPREAD: DATA,10240?齥Kw?3wF当前码:24Find_Buf:1024offset address is: 30烧录第2包...................当前命令码:24send:AT+HTTPREAD=0,1024[16:58:41.793]收←◆DMA_len:1069收到数据:OK+HTTPREAD: DATA,1024`)?)?hA魛Q`h!魛Q`hA魛a`当前码:24Find_Buf:1024offset address is: 30烧录第3包...................当前命令码:24send:AT+HTTPREAD=0,1024[16:58:41.918]收←◆DMA_len:1069收到数据:OK+HTTPREAD: DATA,1024旞%`当前码:24Find_Buf:1024offset address is: 30烧录第4包...................当前命令码:24send:AT+HTTPREAD=0,1024[16:58:42.040]收←◆DMA_len:1069收到数据:OK+HTTPREAD: DATA,1024朇_陥(当前码:24Find_Buf:1024offset address is: 30烧录第5包...................当前命令码:24send:AT+HTTPREAD=0,1024[16:58:42.162]收←◆DMA_len:1069收到数据:OK+HTTPREAD: DATA,1024€1砒?砒惖鼻奥耄?4Find_Buf:1024offset address is: 30烧录第6包...................当前命令码:24send:AT+HTTPREAD=0,1024[16:58:42.285]收←◆DMA_len:1069收到数据:OK+HTTPREAD: DATA,1024醝 ?@@? h`???当前码:24Find_Buf:1024offset address is: 30烧录第7包...................当前命令码:24send:AT+HTTPREAD=0,1024[16:58:42.409]收←◆DMA_len:1069收到数据:OK+HTTPREAD: DATA,1024#?h€ ?h@饊p(`鑘@饊p鑐??F??鼻奥耄?4Find_Buf:1024offset address is: 30烧录第8包...................当前命令码:24send:AT+HTTPREAD=0,1024[16:58:42.533]收←◆DMA_len:1069收到数据:OK+HTTPREAD: DATA,1024a F??hi蒀I粤h蒀I詏餈a F当前码:24Find_Buf:1024offset address is: 30烧录第9包...................当前命令码:24send:AT+HTTPREAD=0,1024收到数据:OK[16:58:42.658]收←◆DMA_len:1063收到数据:+HTTPREAD: DATA,1024觖8? 鄃匄pP `g p絼鴓P hhA魛q` h乭A?乣 h乭A餈乣当前码:24Find_Buf:1024offset address is: 24烧录第10包...................当前命令码:24send:AT+HTTPREAD=0,1024[16:58:42.784]收←◆DMA_len:1069收到数据:OK+HTTPREAD: DATA,1024鄅ih荔@圔??(?(?(??h??hI当前码:24Find_Buf:1024offset address is: 30烧录第11包...................当前命令码:24send:AT+HTTPREAD=0,1024[16:58:42.910]收←◆DMA_len:1069收到数据:OK+HTTPREAD: DATA,1024奰慀$I?hJhl"魛CJ`l滨€?hJhCl"衾CJ`慀$?hJh€l"舻鼻奥耄?4Find_Buf:1024offset address is: 30烧录第12包...................当前命令码:24send:AT+HTTPREAD=0,1024[16:58:43.038]收←◆DMA_len:1069收到数据:OK+HTTPREAD: DATA,1024 h纈6甑鼻奥耄?4Find_Buf:1024offset address is: 30烧录第13包...................当前命令码:24send:AT+HTTPREAD=0,1024[16:58:43.161]收←◆DMA_len:1069收到数据:OK+HTTPREAD: DATA,1024当前码:24Find_Buf:1024offset address is: 30烧录第14包...................当前命令码:24send:AT+HTTPREAD=0,1024DMA_len:31收到数据:OK+HTTPREAD: DATA,4=当前码:24Find_Buf:4offset address is: 27烧录第15包...................当前命令码:25send:AT+HTTPTERM BootLoader > Choose a startup method......> Start update......> Start erase des flash......Bank_1识别的初始页数:30 共删除45页[16:58:44.228]收←◆Erase sucessfully!> Erase des flash sucessfully......> Start copy......[16:58:45.277]收←◆> Copy sucessfully......> Start erase src flash......Bank_1识别的初始页数:75 共删除45页[16:58:46.275]收←◆Erase sucessfully!> Erase src flash sucessfully......> Update sucessfully......> Start up......system init is complect![16:58:46.791]收←◆wait 14s for 4G power on !

6,升级成功须要手动断电重启。
(由于程序里没写重启4G模组部分的驱动。
如果不重启单片机和4G交互数据会出错。
后期读者可以在开机时加上复位的AT指令来办理。
)7,重启后等待4G模组组网。
然后就会创造报的数据变成了BSQ,如下图所示,表示升级成功。

把稳事变

  这只是个OTA升级的demo版程序。
可以借鉴,但不要拿来主义。
就不能重启这一个问题在项目上便是致命的。
我写这个条记的紧张目的还是记录下OTA升级的一套完全流程,以防后期自己忘却了。

参考资料工程资料 : https://gitee.com/linggan17/ota.git

标签:

相关文章

网络培训,开启终身学习的新时代

随着互联网技术的飞速发展,网络培训逐渐成为人们获取知识、提升技能的重要途径。在这个信息爆炸的时代,网络培训以其便捷性、多样性和互动...

通讯 2024-12-27 阅读0 评论0