日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

STM32在线升级OTA,看这一篇就够啦~

發布時間:2023/12/3 编程问答 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 STM32在线升级OTA,看这一篇就够啦~ 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

本文是博主在學習OTA時參考的文章,原作者leafguo,獲得授權后整理發布,原文鏈接如下:
STM32CubeMx開發之路—在線升級OTA(1/4)—基礎知識

簡介

本文主要講解在線升級(OTA)的基礎知識, 主要是針對IAP OTA從原理分析, 分區劃分, 到代碼編寫和實驗驗證等過程闡述這一過程. 幫助大家加深對OTA的認識.


1. OTA基礎知識

什么是BootLoader?

BootLoader可以理解成是引導程序, 它的作用是啟動正式的App應用程序.
換言之, BootLoader是一個程序, App也是一個程序, BootLoader程序是用于啟動App程序的.

STM32中的程序在哪兒?

正常情況下, 我們寫的程序都是放在STM32片內Flash中(暫不考慮外擴Flash).
我們寫的代碼最終會變成二進制文件, 放進Flash中
感興趣的話可以在Keil>>>Debug>>>Memory中查看, 右邊Memory窗口存儲的就是代碼

接下來就可以進入正題了.

進行分區

既然我們寫的程序都會變成二進制文件存放到Flash中, 那么我們就可以進一步對我們程序進行分區.
我使用的是F103RB-NUCLEO開發板,他的Flash一共128頁, 每頁1K.見下圖:


以它為例, 我將它分為三個區.BootLoader區、 App1區、 App2區(備份區)具體劃分如下圖:

  • BootLoader區存放啟動代碼
  • App1區存放應用代碼
  • App2區存放暫存的升級代碼

總體流程圖

  • 先執行BootLoader程序, 先去檢查APP2區有沒有程序, 如果有就將App2區(備份區)的程序拷貝到App1區, 然后再跳轉去執行App1的程序.
  • 然后執行App1程序, 因為BootLoader和App1這兩個程序的向量表不一樣, 所以跳轉到App1之后第一步是先去更改程序的向量表. 然后再去執行其他的應用程序.
  • 在應用程序里面會加入程序升級的部分, 這部分主要工作是拿到升級程序, 然后將他們放到App2區(備份區), 以便下次啟動的時候通過BootLoader更新App1的程序.
    流程圖如下圖所示:

2. BootLoader的編寫

本節主要講解在線升級(OTA)的BooLoader的編寫,我將以我例程的BootLoader為例, 講解BootLoader(文末會提供免費的代碼下載鏈接),其他的大體上原理都差不多。

流程圖分析

以我例程的BootLoader為例:

我將App2區的最后一個字節(0x0801FFFC)用來表示App2區是否有升級程序, STM32在擦除之后Flash的數據存放的都是0xFFFFFFFF, 如果有, 我們將這個地址存放0xAAAAAAAA. 具體的流程圖見下圖所示

程序編寫和分析

所需STM32的資源有:

  • printf的使用, 可以參考以前的博文STM32CubeMx開發之路—3發送USART數據和printf重定向
  • Flash的讀寫, 可以參考以前的博文STM32CubeMX開發之路—8Flash讀寫
  • 程序跳轉指令:可以參考如下代碼:
/* 采用匯編設置棧的值 */ __asm void MSR_MSP (uint32_t ulAddr) {MSR MSP, r0 //設置Main Stack的值BX r14 }/* 程序跳轉函數 */ 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.} }
  • 在需要跳轉的地方執行這個函數就可以了IAP_ExecuteApp(Application_1_Addr);
  • 其他的代碼請參考BootLoader源代碼

源碼

BootLoader源代碼 STM32F103rb_delay_us.zip


3. APP的編寫

本節主要講解在線升級(OTA)的App1的編寫以及整個流程的說明,我將以我例程的App為例, 采用Ymodem協議進行串口傳輸,講解App的編寫(后面會提供免費的代碼下載鏈接), 其他的協議原理大體上都差不多, 都是通過某種協議拿到升級的代碼。

流程圖分析

以我例程的App1為例:

  • 先修改向量表, 因為本程序是由BootLoader跳轉過來的, 不修改向量表后面會出現問題;
  • 打印版本信息, 方便查看不同的App版本;
  • 本例程的升級程序采用串口的Ymoderm協議進行傳輸bin文件. 具體的流程圖見下圖所示:

程序編寫和分析

所需STM32的資源有:

  • printf的使用, 詳情可參考 STM32CubeMx開發之路—3發送USART數據和printf重定向
  • Flash的讀寫, 詳情可參考 STM32CubeMX開發之路—8Flash讀寫
  • 串口的DMA收發, 詳情可參考 STM32CubeMx開發之路—4采用DMA方式收發數據
  • YModem協議相關的, 詳情可參考 YModem介紹

Ymodem協議

  • 百度百科Ymodem協議
  • 具體流程可自行查找相關文檔, 這兒提供一個我找到的 XYmodem.pdf.
  • Ymodem協議相關介紹可參考我的這篇教程 YModem介紹.

代碼分析

  • 代碼大多數都是通過串口實現Ymodem協議的接收, 這兒就不詳細說明

  • 后面放了我的源代碼, 詳情請參考我的源代碼.

  • 主函數添加修改向量表的指令


  • 打印版本信息以及跳轉指令
  • YModem相關的文件接收部分
/*** @bieaf YModem升級** @param none* @return none*/ void ymodem_fun(void) {int i;if(Get_state()==TO_START){send_command(CCC);HAL_Delay(1000);}if(Rx_Flag) // Receive flag{Rx_Flag=0; // clean flag/* 拷貝 */temp_len = Rx_Len;for(i = 0; i < temp_len; i++){temp_buf[i] = Rx_Buf[i];}switch(temp_buf[0]){case SOH:///<數據包開始{static unsigned char data_state = 0;static unsigned int app2_size = 0;if(Check_CRC(temp_buf, temp_len)==1)///< 通過CRC16校驗{ if((Get_state()==TO_START)&&(temp_buf[1] == 0x00)&&(temp_buf[2] == (unsigned char)(~temp_buf[1])))///< 開始{printf("> Receive start...\r\n");Set_state(TO_RECEIVE_DATA);data_state = 0x01; send_command(ACK);send_command(CCC);/* 擦除App2 */ Erase_page(Application_2_Addr, 40);}else if((Get_state()==TO_RECEIVE_END)&&(temp_buf[1] == 0x00)&&(temp_buf[2] == (unsigned char)(~temp_buf[1])))///< 結束{printf("> Receive end...\r\n");Set_Update_Down(); Set_state(TO_START);send_command(ACK);HAL_NVIC_SystemReset();} else if((Get_state()==TO_RECEIVE_DATA)&&(temp_buf[1] == data_state)&&(temp_buf[2] == (unsigned char)(~temp_buf[1])))///< 接收數據{printf("> Receive data bag:%d byte\r\n",data_state * 128);/* 燒錄程序 */WriteFlash((Application_2_Addr + (data_state-1) * 128), (uint32_t *)(&temp_buf[3]), 32);data_state++;send_command(ACK); }}else{printf("> Notpass crc\r\n");}}break;case EOT://數據包開始{if(Get_state()==TO_RECEIVE_DATA){printf("> Receive EOT1...\r\n");Set_state(TO_RECEIVE_EOT2); send_command(NACK);}else if(Get_state()==TO_RECEIVE_EOT2){printf("> Receive EOT2...\r\n");Set_state(TO_RECEIVE_END); send_command(ACK);send_command(CCC);}else{printf("> Receive EOT, But error...\r\n");}}break; }} }
  • 其中部分函數未在以上代碼中展現, 詳情請參看下面的源代碼(免費).

源碼

App1源代碼 STM32F103rb_App1.zip


4. 整體測試

本節主要對前三節的教程做測試驗證 BootLoader + App的升級功能。

源代碼

  • BootLoader源代碼 STM32F103rb_delay_us.zip
  • App1源代碼 STM32F103rb_App1.zip

代碼的下載

  • 由下圖可知兩份代碼的下載區域是不一樣的,所以他們下載的區域也不一樣

BootLoader的下載

  • BootLoader的代碼默認是最開始的所以不需要特別設置代碼的下載位置
  • 按照下圖, 修改擦除方式為Erase Sectors, 大小限制在0X5000(20K)
  • 燒錄代碼
  • 運行, 通過串口1打印輸出, 會看到以下打印消息
  • 說明BootLoader已經成功運行

App1的下載

  • App1稍微復雜一點, 需要將代碼的起始位置設置為0x08005000
  • 同時也要修改擦除方式為Erase Sectors, 見下圖
  • 燒錄代碼
  • 運行, 通過串口1打印輸出, 會看到以下打印消息
  • 說明BootLoader已經成功跳轉到版本號為0.0.1的App1

生成App2的.bin文件

  • Keil如何生成.bin文件, 請參考這篇博文 Keil如何生成.bin文件

  • 修改代碼, 把版本號改為0.0.2, 并且編譯并且生成.bin文件

  • 生成好之后你會得到一個.bin結尾的文件, 這就是我們待會兒YModem要傳輸的文件

使用Xshell進行文件傳輸

  • 打開Xshell
  • 代碼中, 串口1進行調試信息的打印, 串口2進行YModem升級的
  • 所以使用Xshell打開串口2進行文件傳輸, 串口1則可以通過串口調試助手查看調試消息, 具體過程如下
  • 你會看到App的版本成功升級到0.0.2了.
  • 如果你到了這一步.
  • 那么恭喜你! 你已經能夠使用在線升級了!

5. 總結

通過本幾節的教程, 想必你已經會使用在線升級了, 只要原理知道了其他的問題都可以迎刃而解了, 除了使用YModem協議傳輸.bin文件, 你還可以通過藍牙, WIFI,等其他協議傳輸, 只要能夠將.bin文件傳輸過去, 那其他的部分原理都差不多.

原作者備注:提供一下個人微信號 Hleafleafleaf,歡迎加好友,共同學習!共同進步!

總結

以上是生活随笔為你收集整理的STM32在线升级OTA,看这一篇就够啦~的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。