STM32F103_Bootloader程序開發11 - 實現 App 安全跳轉至 Bootloader

導言


想象一下,我們的單片機 App 正在穩定地運行著,突然我們想給它升級一下,添加個新功能。我們該如何安全地通知它:“嘿,準備好接收新固件了” ? 這就需要 App 和 Bootloader 之間建立一個可靠的"秘密握手"機制。

整個流程就像一次精心策劃的"交接儀式":

  1. 外部通知:上位機(比如我們的電腦)通過串口向正在運行的 App 發送一個預設好的"升級"指令。
  2. 設置信物:App 收到指令后,并不會立刻停止工作,而是在一塊共享的 RAM 內存中寫入一個"暗號"(我們稱之為"升級標志位")。這塊內存就像是 App 留給 Bootloader 的一個"秘密信箱"。
  3. 主動重啟:留下"暗號"后,App 主動觸發一次軟件復位,開始"交接"。
  4. 驗證信物:系統重啟后,控制權首先交給 Bootloader。Bootloader 會立刻檢查那個"秘密信箱"。
    • 如果發現了預設的"暗號",它就知道:“哦,App 需要我來執行升級任務”,隨即進入 IAP(In-Application Programming)模式,準備接收新固件。
    • 如果信箱是空的,它就認為一切正常,直接跳轉到 App,讓 App 像往常一樣運行。

在這里插入圖片描述
為了簡化演示,我們約定,當 App 的串口收到字符串 A5A5A5A5 時,就觸發這次跳轉。

在這里插入圖片描述

友情提示:在真實的商業項目中,簡單的字符串匹配是遠遠不夠的。為了保證通信的絕對可靠,防止數據干擾導致意外的固件升級,我們必須引入 CRC 校驗 等錯誤檢測機制。這里的 A5A5A5A5 只是一個為了教學目的而簡化的觸發信號。

項目地址:

  • Gitee (國內推薦): https://gitee.com/wallace89/MCU_Develop/tree/main/bootloader11_stm32f103_app_jump_boot
  • GitHub: https://github.com/q164129345/MCU_Develop/tree/main/bootloader11_stm32f103_app_jump_boot

一、App 端代碼


現在,我們來看看 App 程序需要增加哪些代碼來實現這個"交接儀式"。

1.1、 jump_boot.c

這個文件負責處理從 App 跳轉到 Bootloader 的所有核心邏輯。

#include "bootloader_define.h"
#include "flash_map.h"
#include "jump_boot.h"#if defined(__IS_COMPILER_ARM_COMPILER_5__)
volatile uint64_t update_flag __attribute__((at(FIRMWARE_UPDATE_VAR_ADDR), zero_init));#elif defined(__IS_COMPILER_ARM_COMPILER_6__)#define __INT_TO_STR(x)     #x#define INT_TO_STR(x)       __INT_TO_STR(x)volatile uint64_t update_flag __attribute__((section(".bss.ARM.__at_" INT_TO_STR(FIRMWARE_UPDATE_VAR_ADDR))));#else#error "variable placement not supported for this compiler."
#endif/*** @brief  獲取固件升級標志位* @note   讀取保存于指定RAM地址的升級標志變量(通常用于判斷bootloader的運行狀態)* @retval uint64_t 固件升級標志的當前值*/
static uint64_t IAP_GetUpdateFlag(void)
{return update_flag;
}/*** @brief  設置固件升級標志位* @param  flag 需要設置的標志值* @note   修改指定RAM地址的升級標志變量* @retval 無*/
static void IAP_SetUpdateFlag(uint64_t flag)
{update_flag = flag;
}/*** @brief  解析串口接收到的數據* @note   根據接收到的數據,判斷是否需要跳轉到Bootloader*         目標字符串: "A5A5A5A5" (8字節)*         ASCII: 0x41,0x35,0x41,0x35,0x41,0x35,0x41,0x35* @param  data 接收到的數據* @retval 無*/
void IAP_Parse_Command(uint8_t data)
{// 目標字符串"A5A5A5A5"的ASCII碼序列static const uint8_t target_sequence[8] = {0x41, 0x35, 0x41, 0x35,  // "A5A5"0x41, 0x35, 0x41, 0x35   // "A5A5"};// 靜態變量:記錄當前匹配的字節位置static uint8_t match_index = 0;// 檢查當前字節是否與目標序列匹配if (data == target_sequence[match_index]) {match_index++;  // 匹配成功,移動到下一個位置// 檢查是否接收完整的8字節序列if (match_index >= sizeof(target_sequence)) {// 完整匹配成功,跳轉到Bootloadermatch_index = 0;  // 重置狀態,為下次做準備//! 設置固件升級標志位IAP_SetUpdateFlag(FIRMWARE_UPDATE_MAGIC_WORD);//! 等待10ms,確保標志位設置成功LL_mDelay(10);//!此函數不會返回,MCU將復位NVIC_SystemReset();}} else {// 不匹配,重置狀態機match_index = 0;// 特殊處理:如果當前字節恰好是序列的第一個字節,則開始新的匹配if (data == target_sequence[0]) {match_index = 1;}}
}

代碼亮點解析:

  1. update_flag 變量的定義

    • __attribute__((at(...))): 這是告訴編譯器:“請務必把 update_flag 這個變量放在 FIRMWARE_UPDATE_VAR_ADDR 這個內存地址上”。這就像給 App 和 Bootloader 一個共同的、固定的"信箱"地址,確保雙方都能找到對方。
    • volatile: 這個關鍵字至關重要。它告訴編譯器:“這個變量的值隨時可能被意想不到的方式改變(比如被硬件或其他程序),所以你不要自作聰明地去優化它。每次使用它的時候,都必須老老實實地從內存里重新讀取”。這可以防止 App 重啟后,Bootloader 讀到一個被緩存的、不正確的值。
  2. IAP_Parse_Command 函數

    • 這個函數就像一個"哨兵",時刻監聽著串口發來的每一個字節。
    • 它內部的 match_index 就像一個進度條,記錄著"秘密口令"的匹配進度。每收到一個正確的字符,進度條就加一;一旦收到錯誤的字符,進度條就清零重來,非常嚴謹。
    • 當8個字符全部匹配成功,就意味著"口令正確",哨兵就會立刻執行預設的三個步驟:寫標志、延時、復位

1.2、jump_boot.h

頭文件很簡單,主要是聲明 IAP_Parse_Command 函數,以便在其他文件中(比如串口中斷服務程序中)調用它。

/*** @file    jump_boot.h* @brief   應用程序與Bootloader跳轉功能的頭文件聲明* @author  Wallace.zhang* @date    2025-05-25* @version 1.0.0*/#ifndef __JUMP_BOOT_H
#define __JUMP_BOOT_H#ifdef __cplusplus
extern "C" {
#endif#include <stdint.h>
#include "main.h"
#include <stdbool.h>/*** @brief  解析串口接收到的數據,判斷是否需要跳轉到Bootloader* @param  data 接收到的單個字節*/
void IAP_Parse_Command(uint8_t data);#ifdef __cplusplus
}
#endif#endif /* __JUMP_BOOT_H */

1.3、myUsartDrive_reg.c

在這里插入圖片描述
如上圖所示,在USART1的接收ringbuffer里,一個一個字節拿出去解析。

二、功能測試


現在,讓我們來驗證一下"交接儀式"是否能順利進行。

2.1、測試 App 跳轉到 Bootloader

我們使用一個 Python 腳本來模擬上位機,向單片機發送"秘密口令"。
在這里插入圖片描述
操作步驟:

  1. 將 App 程序下載到 STM32 開發板并運行。
  2. 在項目 iap_py 文件夾下打開終端,運行以下指令(請根據你的實際情況修改 COM 口):
    python3 jump_command.py --port COM8 --baud 115200
    
  3. 觀察 RTT Viewer 的日志。Bootloader 的日志出現,這表明 App 成功復位并跳轉到了 Bootloader!
    在這里插入圖片描述

jump_command.py 腳本是做什么的?
它其實很簡單,就是通過指定的串口(--port)和波特率(--baud),向上位機發送了一串文本 A5A5A5A5

腳本參數說明:

  • --port: 你的設備所連接的串口號 (必填),例如 COM8 (Windows) 或 /dev/ttyUSB0 (Linux)。
  • --baud: 波特率 (可選),默認為 115200

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/87237.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/87237.shtml
英文地址,請注明出處:http://en.pswp.cn/web/87237.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Explain解釋

參考官方文檔&#xff1a;https://dev.mysql.com/doc/refman/5.7/en/explain-output.html explain關鍵字可以分析你的查詢語句的結構和性能。 explain select查詢&#xff0c; 執行會返回執行計劃的信息。 注意&#xff1a;如果from中有子查詢&#xff0c;仍然會執行該子查詢…

選擇 PDF 轉 HTML 轉換器的 5 個關鍵特性

市面上有很多 PDF 轉 HTML 的轉換器&#xff0c;每一款產品都有不同的功能組合。要理清并理解每個功能可能會讓人感到困惑。那么&#xff0c;真正重要的是什么呢&#xff1f; 這篇文章將介紹我們認為在選擇最佳 PDF 轉 HTML 轉換器時最重要的 5 個關鍵特性&#xff1a; 1. 轉換…

使用堡塔在服務器上部署寶塔面板-linux版

使用堡塔在服務器上部署寶塔面板-linux版 使用堡塔多機管理登錄服務器 進入寶塔官網&#xff0c;獲取安裝腳本 wget -O install_panel.sh https://download.bt.cn/install/install_panel.sh && sudo bash install_panel.sh ed8484bec3. 在堡塔多機管理中&#xff0c;…

【Unity高級】Unity多界面游戲場景管理方案詳解

引言&#xff1a;游戲界面管理的挑戰 在Unity游戲開發中&#xff0c;尤其是包含多個功能界面&#xff08;如主菜單、關卡選擇、游戲頁面、設置和商城&#xff09;的游戲&#xff0c;如何高效管理場景與界面是架構設計的核心挑戰。本文將深入探討三種主流實現方案&#xff1a;單…

WINDOWS最快布署WEB服務器:apache2

安裝JDK下載 https://tomcat.apache.org/ Index of /dist/tomcat/tomcat-9 安裝測試 http://localhost:8080/ 替換自己的文件 把自己的文件復制到&#xff1a; C:\Program Files\Apache Software Foundation\Tomcat 9.0\webapps\ROOT

Microsoft Edge 打開無反應、打開后顯示兼容性問題、卸載重裝 解決方案。一鍵卸載Microsoft Edge 。

背景&#xff1a;網絡上的瀏覽器修復、重裝、恢復默認應用測試后無用&#xff0c;以下卸載重裝方案經實測可以正常使用Microsoft Edg。 卸載軟件在資源里&#xff0c;請自取。 一、卸載軟件&#xff1a;Remove-Edge_GUI.exe 雙擊卸載等待即可。 二、在微軟商店重新安裝Micro…

Spring Boot - 參數校驗:分組校驗、自定義注解、嵌套對象全解析

01 依賴配置 在構建高效的校驗體系前&#xff0c;需先完善項目依賴配置。 以下是優化后的依賴示例&#xff1a; <dependencies><!-- Web 依賴&#xff0c;提供 RESTful 接口支持 --><dependency><groupId>org.springframework.boot</groupId>…

深入淺出多模態》(十一)之多模態經典模型:Flamingo系列

&#x1f389;AI學習星球推薦&#xff1a; GoAI的學習社區 知識星球是一個致力于提供《機器學習 | 深度學習 | CV | NLP | 大模型 | 多模態 | AIGC 》各個最新AI方向綜述、論文等成體系的學習資料&#xff0c;配有全面而有深度的專欄內容&#xff0c;包括不限于 前沿論文解讀、…

基于Pandas和FineBI的昆明職位數據分析與可視化實現(三)- 職位數據統計分析

文章目錄 一、職位數據分析1. 一級分類職位數量統計分析2. 職位二級分類分布分析3. 職位分布分析4. 工作經驗需求分布分析5. 學歷要求職位分布分析6. 企業職位供給前507. 不同規模公司的職位數量統計8. 區域職位分布分析9. 各區域平均薪資范圍分布分析10. 不同工作經驗平均薪資…

大數據Hadoop之——安裝部署hadoop

目錄 前期準備 一、JDK的安裝 1、安裝jdk 2、配置Java環境變量 3、加載環境變量 4、進行校驗 二、hadoop的環境搭建 1、hadoop的下載安裝 2、配置文件設置 2.1. 配置 hadoop-env.sh 2.2. 配置 core-site.xml 2.3. 配置 hdfs-site.xml 2.4. 配置 yarn-site.xml 2.…

Spring IoC DI介紹

文章目錄 IoC & DI 介紹IoC介紹DI 介紹 組件注冊Bean 命名約定方法注解 Bean總結 掃描路徑DI 詳解屬性注入構造方法注入Setter 注入三種注入優缺點分析 當同一類型存在多個Bean時,直接使用Autowired會存在問題使用Primary注解使用Qualifier注解使用Bean的名稱使用Resource注…

【Flutter】解決 flutter_inappwebview在 Windows 上使用導致應用閃退問題

問題背景 在 Windows 11 上運行 Flutter 桌面應用時&#xff0c;應用出現閃退現象。通過系統事件日志分析&#xff0c;發現是 MSVCP140.dll 模塊的訪問沖突異常&#xff08;錯誤代碼 c0000005&#xff09;導致的崩潰。 問題分析 1. 錯誤現象 應用啟動后立即閃退Windows 事件…

使用 JavaScript、Mastra 和 Elasticsearch 構建一個具備代理能力的 RAG 助手

作者&#xff1a;來自 Elastic JD Armada 了解如何在 JavaScript 生態系統中構建 AI 代理。 Elasticsearch 與業界領先的生成式 AI 工具和服務商有原生集成。查看我們的網絡研討會&#xff0c;了解如何超越 RAG 基礎&#xff0c;或使用 Elastic 向量數據庫構建可投入生產的應用…

Active Directory 環境下 Linux Samba 文件共享服務建設方案

Active Directory 環境下 Linux Samba 文件共享服務建設方案 目錄 需求分析方案總體設計技術架構與選型詳細部署規劃共享文件性能測試非域終端共享配置運維與權限安全管理建議1. 需求分析 因某公司(編的)新增多個部門,各部門之間存在多類型終端系統,但又有同時訪問文件庫…

Python爬蟲網安-項目-簡單網站爬取

源碼&#xff1a; https://github.com/Wist-fully/Attack/tree/pc pc_p1 目標&#xff1a; 1.進入列表頁&#xff0c;順著列表爬取每個電影詳情頁 2.利用正則來提取&#xff0c;海報&#xff0c;名稱&#xff0c;類別&#xff0c;上映的時間&#xff0c;評分&#xff0c;劇…

Golang中的數組

Golang Array和以往認知的數組有很大不同。有點像Python中的列表 1. 數組&#xff1a;是同一種數據類型的固定長度的序列。 2. 數組定義&#xff1a;var a [len]int&#xff0c;比如&#xff1a;var a [5]int&#xff0c;數組長度必須是常量&#xff0c;且是類型的組成部分。一…

《Origin畫百圖》之矩陣散點圖

矩陣散點圖的作用 一、直觀展示多變量間的兩兩關系 矩陣散點圖的基本單元是兩兩變量的散點圖&#xff0c;每個散點圖對應矩陣中的一個單元格&#xff0c;可直接反映變量間的&#xff1a; 相關性方向&#xff1a;正相關&#xff08;散點向右上傾斜&#xff09;或負相關&#x…

Flask文件下載send_file中文文件名處理解決方案

Flask文件下載send_file中文文件名處理解決方案 Flask文件下載中文文件名處理解決方案問題背景問題分析核心問題常見癥狀 解決方案技術實現關鍵技術點 完整實現示例 Flask文件下載中文文件名處理解決方案 問題背景 在Web應用開發中&#xff0c;當用戶下載包含中文字符的文件時…

新手指南:在 Ubuntu 上安裝 PostgreSQL 并通過 VS Code 連接及操作

本文檔記錄了一個初學者在 Ubuntu 系統上安裝、配置 PostgreSQL 數據庫&#xff0c;并使用 Visual Studio Code (VS Code) 作為客戶端進行連接和操作的全過程。其中包含了遇到的常見錯誤、分析和最終的解決方案&#xff0c;旨在為新手提供一個清晰、可復現的操作路徑。 最終目…

二刷 蒼穹外賣day10(含bug修改)

Spring Task Spring框架提供的任務調度工具&#xff0c;可以按照約定的時間自動執行某個代碼邏輯 cron表達式 一個字符串&#xff0c;通過cron表達式可以定義任務觸發的時間 **構成規則&#xff1a;**分為6或7個域&#xff0c;由空格分隔開&#xff0c;每個域代表一個含義 …