簡(jiǎn)介
本文主要講解在線升級(jí)IAP的基礎(chǔ)知識(shí), 主要是針對(duì)IAP從原理分析,分區(qū)劃分, 到代碼編寫(xiě)和實(shí)驗(yàn)驗(yàn)證等過(guò)程闡述這一過(guò)程. 幫助大家加深對(duì)在線升級(jí)的認(rèn)識(shí).
1. 在線升級(jí)知識(shí)
什么是BootLoader?
BootLoader
可以理解成是引導(dǎo)程序, 它的作用是啟動(dòng)正式的App應(yīng)用程序
. 換言之,BootLoader
是一個(gè)程序, App也是一個(gè)程序, BootLoader程序
是用于啟動(dòng)App程序
的.
STM32中的程序在哪兒?
正常情況下, 我們寫(xiě)的程序都是放在STM32片內(nèi)Flash中(暫不考慮外擴(kuò)Flash). 我們寫(xiě)的代碼最終會(huì)變成二進(jìn)制文件, 放進(jìn)Flash中 感興趣的話可以在Keil
>>>Debug
>>>Memory
中查看, 右邊Memory窗口存儲(chǔ)的就是代碼
接下來(lái)就可以進(jìn)入正題了.
進(jìn)行分區(qū)
既然我們寫(xiě)的程序都會(huì)變成二進(jìn)制文件存放到Flash中, 那么我們就可以進(jìn)一步對(duì)我們程序進(jìn)行分區(qū). 我使用的是F103RB-NUCLEO開(kāi)發(fā)板
,他的Flash一共128頁(yè), 每頁(yè)1K.見(jiàn)下圖:
以它為例, 我將它分為三個(gè)區(qū).BootLoader區(qū)
、App1區(qū)
、App2區(qū)(備份區(qū))
具體劃分如下圖:
-
BootLoader區(qū)
存放啟動(dòng)代碼 -
App1區(qū)
存放應(yīng)用代碼 -
App2區(qū)
存放暫存的升級(jí)代碼
總體流程圖
-
先執(zhí)行
BootLoader
程序, 先去檢查APP2
區(qū)有沒(méi)有程序, 如果有就將App2區(qū)(備份區(qū))的程序拷貝到App1區(qū)
, 然后再跳轉(zhuǎn)去執(zhí)行App1
的程序. -
然后執(zhí)行
App1
程序, 因?yàn)?/span>BootLoader
和App1
這兩個(gè)程序的向量表不一樣, 所以跳轉(zhuǎn)到App1
之后第一步是先去更改程序的向量表. 然后再去執(zhí)行其他的應(yīng)用程序. -
在應(yīng)用程序里面會(huì)加入程序升級(jí)的部分, 這部分主要工作是拿到升級(jí)程序, 然后將他們放到
App2區(qū)(備份區(qū))
, 以便下次啟動(dòng)的時(shí)候通過(guò)BootLoader
更新App1
的程序. 流程圖如下圖所示:
2. BootLoader的編寫(xiě)
本節(jié)主要講解在線升級(jí)(OTA)的BooLoader
的編寫(xiě),我將以我例程的BootLoader為例, 講解BootLoader
(文末會(huì)提供免費(fèi)的代碼下載鏈接),其他的大體上原理都差不多。
流程圖分析
以我例程的BootLoader為例:
我將App2區(qū)
的最后一個(gè)字節(jié)(0x0801FFFC
)用來(lái)表示App2區(qū)
是否有升級(jí)程序, STM32在擦除之后Flash的數(shù)據(jù)存放的都是0xFFFFFFFF
, 如果有, 我們將這個(gè)地址存放0xAAAAAAAA
. 具體的流程圖見(jiàn)下圖所示
程序編寫(xiě)和分析
所需STM32的資源有:
-
發(fā)送USART數(shù)據(jù)和printf重定向
-
Flash的讀寫(xiě)
-
程序跳轉(zhuǎn)指令,可以參考如下代碼:
1/*采用匯編設(shè)置棧的值*/ 2__asmvoidMSR_MSP(uint32_tulAddr) 3{ 4MSRMSP,r0//設(shè)置MainStack的值 5BXr14 6} 7 8 9/*程序跳轉(zhuǎn)函數(shù)*/ 10typedefvoid(*Jump_Fun)(void); 11voidIAP_ExecuteApp(uint32_tApp_Addr) 12{ 13Jump_FunJumpToApp; 14 15if(((*(__IOuint32_t*)App_Addr)&0x2FFE0000)==0x20000000)//檢查棧頂?shù)刂肥欠窈戏? 16{ 17JumpToApp=(Jump_Fun)*(__IOuint32_t*)(App_Addr+4);//用戶代碼區(qū)第二個(gè)字為程序開(kāi)始地址(復(fù)位地址) 18MSR_MSP(*(__IOuint32_t*)App_Addr);//初始化APP堆棧指針(用戶代碼區(qū)的第一個(gè)字用于存放棧頂?shù)刂? 19JumpToApp();//跳轉(zhuǎn)到APP. 20} 21}
-
在需要跳轉(zhuǎn)的地方執(zhí)行這個(gè)函數(shù)就可以了
IAP_ExecuteApp(Application_1_Addr);
-
其他的代碼請(qǐng)參考
BootLoader
源代碼
3. APP的編寫(xiě)
本節(jié)主要講解在線升級(jí)(OTA)的App1
的編寫(xiě)以及整個(gè)流程的說(shuō)明,我將以我例程的App為例, 采用Ymodem協(xié)議進(jìn)行串口傳輸,講解App
的編寫(xiě)(后面會(huì)提供免費(fèi)的代碼下載鏈接), 其他的協(xié)議原理大體上都差不多, 都是通過(guò)某種協(xié)議拿到升級(jí)的代碼。
流程圖分析
以我例程的App1為例:
-
先修改向量表, 因?yàn)楸境绦蚴怯葿ootLoader跳轉(zhuǎn)過(guò)來(lái)的, 不修改向量表后面會(huì)出現(xiàn)問(wèn)題;
-
打印版本信息, 方便查看不同的App版本;
-
本例程的升級(jí)程序采用串口的Ymoderm協(xié)議進(jìn)行傳輸bin文件. 具體的流程圖見(jiàn)下圖所示:
程序編寫(xiě)和分析
所需STM32的資源有:
-
發(fā)送USART數(shù)據(jù)和printf重定向
-
Flash的讀寫(xiě)
-
串口的DMA收發(fā)
-
YModem協(xié)議相關(guān)
Ymodem協(xié)議
-
百度百科[Ymodem協(xié)議]
-
具體流程可自行查找相關(guān)文檔, 這兒提供一個(gè)我找到的 XYmodem.pdf(文末和源碼一起提供).
-
Ymodem協(xié)議相關(guān)介紹可參考我的這篇教程 YModem介紹
(https://blog.csdn.net/weixin_41294615/article/details/104652105).
代碼分析
- 代碼大多數(shù)都是通過(guò)串口實(shí)現(xiàn)Ymodem協(xié)議的接收, 這兒就不詳細(xì)說(shuō)明
- 后面放了我的源代碼, 詳情請(qǐng)參考我的源代碼.
- 主函數(shù)添加修改向量表的指令
- 打印版本信息以及跳轉(zhuǎn)指令
- YModem相關(guān)的文件接收部分
1/** 2*@bieafYModem升級(jí) 3* 4*@paramnone 5*@returnnone 6*/ 7voidymodem_fun(void) 8{ 9inti; 10if(Get_state()==TO_START) 11{ 12send_command(CCC); 13HAL_Delay(1000); 14} 15if(Rx_Flag)//Receiveflag 16{ 17Rx_Flag=0;//cleanflag 18 19/*拷貝*/ 20temp_len=Rx_Len; 21for(i=0;i22{ 23temp_buf[i]=Rx_Buf[i]; 24} 25 26switch(temp_buf[0]) 27{ 28caseSOH:///<數(shù)據(jù)包開(kāi)始 29{ 30staticunsignedchardata_state=0; 31staticunsignedintapp2_size=0; 32if(Check_CRC(temp_buf,temp_len)==1)/// 33{ 34if((Get_state()==TO_START)&&(temp_buf[1]==0x00)&&(temp_buf[2]==(unsignedchar)(~temp_buf[1])))/// 35{ 36printf(">Receivestart... "); 37 38Set_state(TO_RECEIVE_DATA); 39data_state=0x01; 40send_command(ACK); 41send_command(CCC); 42 43/*擦除App2*/ 44Erase_page(Application_2_Addr,40); 45} 46elseif((Get_state()==TO_RECEIVE_END)&&(temp_buf[1]==0x00)&&(temp_buf[2]==(unsignedchar)(~temp_buf[1])))/// 47{ 48printf(">Receiveend... "); 49 50Set_Update_Down(); 51Set_state(TO_START); 52send_command(ACK); 53HAL_NVIC_SystemReset(); 54} 55elseif((Get_state()==TO_RECEIVE_DATA)&&(temp_buf[1]==data_state)&&(temp_buf[2]==(unsignedchar)(~temp_buf[1])))/// 56{ 57printf(">Receivedatabag:%dbyte ",data_state*128); 58 59/*燒錄程序*/ 60WriteFlash((Application_2_Addr+(data_state-1)*128),(uint32_t*)(&temp_buf[3]),32); 61data_state++; 62 63send_command(ACK); 64} 65} 66else 67{ 68printf(">Notpasscrc "); 69} 70 71}break; 72caseEOT://數(shù)據(jù)包開(kāi)始 73{ 74if(Get_state()==TO_RECEIVE_DATA) 75{ 76printf(">ReceiveEOT1... "); 77 78Set_state(TO_RECEIVE_EOT2); 79send_command(NACK); 80} 81elseif(Get_state()==TO_RECEIVE_EOT2) 82{ 83printf(">ReceiveEOT2... "); 84 85Set_state(TO_RECEIVE_END); 86send_command(ACK); 87send_command(CCC); 88} 89else 90{ 91printf(">ReceiveEOT,Buterror... "); 92} 93}break; 94} 95} 96}
- 其中部分函數(shù)未在以上代碼中展現(xiàn), 詳情請(qǐng)參看文末給出的源碼鏈接.
4. 整體測(cè)試
本節(jié)主要對(duì)前三節(jié)的教程做測(cè)試驗(yàn)證BootLoader
+App
的升級(jí)功能。源代碼
BootLoader源代碼和App1源代碼可以在原作者的gitee獲?。?/span>https://gitee.com/leafguo/leaf_notes/STM32CubeMX/STM32CubeMx_OTA代碼的下載
- 由下圖可知兩份代碼的下載區(qū)域是不一樣的,所以他們「下載的區(qū)域也不一樣」。
BootLoader的下載
- BootLoader的代碼默認(rèn)是最開(kāi)始的所以不需要特別設(shè)置代碼的下載位置
-
按照下圖, 修改擦除方式為
Erase Sectors
, 大小限制在0X5000
(20K)
- 燒錄代碼
- 運(yùn)行, 通過(guò)串口1打印輸出, 會(huì)看到以下打印消息
- 說(shuō)明BootLoader已經(jīng)成功運(yùn)行
App1的下載
-
App1稍微復(fù)雜一點(diǎn), 需要將代碼的起始位置設(shè)置為
0x08005000
-
同時(shí)也要修改擦除方式為
Erase Sectors
, 見(jiàn)下圖
- 燒錄代碼
- 運(yùn)行, 通過(guò)串口1打印輸出, 會(huì)看到以下打印消息
-
說(shuō)明
BootLoader
已經(jīng)成功跳轉(zhuǎn)到版本號(hào)為0.0.1的App1
生成App2的.bin文件
- Keil如何生成.bin文件, 請(qǐng)參考這篇博文 Keil如何生成.bin文件
- 修改代碼, 把版本號(hào)改為0.0.2, 并且編譯并且生成.bin文件
- 生成好之后你會(huì)得到一個(gè).bin結(jié)尾的文件, 這就是我們待會(huì)兒YModem要傳輸?shù)奈募?/span>
使用Xshell進(jìn)行文件傳輸
- 打開(kāi)Xshell
- 代碼中, 串口1進(jìn)行調(diào)試信息的打印, 串口2進(jìn)行YModem升級(jí)的
- 所以使用Xshell打開(kāi)串口2進(jìn)行文件傳輸, 串口1則可以通過(guò)串口調(diào)試助手查看調(diào)試消息
- 你會(huì)看到App的版本成功升級(jí)到0.0.2了.
- 如果你到了這一步.
- 那么恭喜你! 你已經(jīng)能夠使用在線升級(jí)了!
5. 總結(jié)
通過(guò)本幾節(jié)的教程, 想必你已經(jīng)會(huì)使用在線升級(jí)了, 只要原理知道了其他的問(wèn)題都可以迎刃而解了, 除了使用YModem協(xié)議傳輸.bin文件, 你還可以通過(guò)藍(lán)牙, WIFI,等其他協(xié)議傳輸, 只要能夠?qū)?bin文件傳輸過(guò)去, 那其他的部分原理都差不多。原文標(biāo)題:詳解STM32在線IAP升級(jí)
文章出處:【微信公眾號(hào):硬件攻城獅】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
-
STM32
+關(guān)注
關(guān)注
2273文章
10927瀏覽量
357844 -
IAP
+關(guān)注
關(guān)注
2文章
164瀏覽量
24404 -
在線升級(jí)
+關(guān)注
關(guān)注
0文章
8瀏覽量
6001
原文標(biāo)題:詳解STM32在線IAP升級(jí)
文章出處:【微信號(hào):mcu168,微信公眾號(hào):硬件攻城獅】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
STM32 IAP在線升級(jí)
介紹關(guān)于編程的基礎(chǔ)知識(shí)
IAP在線升級(jí)
如何去實(shí)現(xiàn)stm32的IAP在線升級(jí)呢
串口藍(lán)牙IAP在線升級(jí)的相關(guān)資料推薦
IAP在線升級(jí)相關(guān)資料分享
STM32 IAP在線升級(jí)詳解
STM8在線升級(jí):關(guān)于IAP與APP互相跳轉(zhuǎn)的實(shí)現(xiàn)
ARM在線升級(jí)的應(yīng)用IAP代碼
ARM在線升級(jí)的應(yīng)用IAP代碼
51單片機(jī)IAP在線升級(jí)
![51單片機(jī)<b class='flag-5'>IAP</b><b class='flag-5'>在線</b><b class='flag-5'>升級(jí)</b>](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
AT32 MCU如何使用IAP通過(guò)USART實(shí)現(xiàn)對(duì)固件的在線升級(jí)更新
![AT32 MCU如何使用<b class='flag-5'>IAP</b>通過(guò)USART實(shí)現(xiàn)對(duì)固件的<b class='flag-5'>在線</b><b class='flag-5'>升級(jí)</b>更新](https://file1.elecfans.com/web2/M00/A3/34/wKgZomUD6nKANoIKAAJNjPhBAIw039.png)
評(píng)論