1. 程式人生 > >STM32 BootLoader升級韌體

STM32 BootLoader升級韌體

BootLoader

關於Bootloader,從書上的文字描述,很難理解這個名詞是什麼,有什麼用。這次用到了,算是有了更進一步的認識。

一、知識點

  • 1、BootLoader就是微控制器啟動時候執行的一段小程式,這段程式負責微控制器韌體的更新,也就是微控制器選擇性的自己給自己下程式。可以更新,也可以不更新,更新的話,BootLoader更新完程式後,跳轉到新程式執行;不更新的話,BootLoader直接跳轉到原來的程式去執行。
  • 2、BootLoader更新完程式後並不擦除自己,下次啟動後依然先執行BootLoader程式,又可以選擇性的更新或者不更新程式,所以BootLoader就是用來管理微控制器程式的更新。
  • 3、在實際的微控制器工程專案中,如果加入了BootLoader功能,就可以給微控制器日後升級程式留出一個介面,方便日後微控制器程式更新。當然,這就需要建立兩個工程專案,一個為BootLoader工程,一個為APP工程。
  • 4、BootLoader工程生成的.hex或者.bin檔案通常下載到ROM或Flash中的首地址,這樣可以保證上電後先執行BootLoader程式。而APP工程生成的.hex或者.bin檔案則下載到ROM或Flash中BootLoader後面的地址中。也就是說,存在ROM/Flash中的內容是分為兩部分的。
  • 5、要實現在同一個ROM/Flash中儲存兩段程式,並且保證不能相互覆蓋,則需要在下載程式時指定地址。如在Keil下,可以進行如下的調整。

這裡寫圖片描述

  • 6、實際上,在STM32系列的微控制器中,Flash本身就是分扇區的,一個扇區16KB的樣子,具體可以檢視手冊。那麼就可以用從第一個扇區的首地址開始下載BootLoader的程式,而從第二個扇區的起始地址開始下載APP程式。如下為STM32F4系列晶片的Flash模組。

這裡寫圖片描述

  • 7、微控制器上電之後開始執行BootLoader程式,這是微控制器會檢測使用者是否有升級應用程式(APP)的請求,具體表現有很多種,例如檢測記憶體卡,Nand Flash中是否包含升級檔案,串列埠/I2C/SPI等外設介面是否傳來升級檔案。據說還有使用GSM來升級的。
  • 8、所謂的升級,就是將ROM/Flash中儲存APP程式的扇區內容擦除並寫入新檔案。例如一次韌體升級的過程可以是:1、微控制器上電執行BootLoader,2、BootLoader查詢升級檔案,3、若找到檔案,擦除Flash中的部分扇區(存APP的),4、在擦除的扇區寫入升級的檔案,5、寫入完成,讀取資料檢驗是否出錯,6、若資料一致,升級成功,刪除升級檔案,7、BootLoader程式跳轉到APP程式執行。刪除升級檔案是為了下次上電後不再進行升級。
  • 9、所謂的跳轉,可以理解程式指標的改變,變為指向APP程式扇區的起始地址。

二、部分程式碼

  • 1、主函式
int main(void)
{
    HAL_Init();//STM32初始化
    SystemClock_Config();//時鐘配置
    System_GPIOInit();//IO口配置

    #ifdef BOOTLOAD_DISPLAY_ENABLE
    SystemColorInit();//顯示屏配置
    #endif

    System_LoadUpdateFile();//升級函式
    while (1)
    {

    }
}
  • 2、升級函式
void System_LoadUpdateFile(void)
{
    uint8_t res;    
    if(bNandFlash_Error)//如果NandFlash錯誤,串列埠列印錯誤資訊,跳轉到使用者程式
    {
        d_printf("NandFlash_Error jump\n");
        BootLoad_Jump();//跳轉函式
        return;
    }
    if(bNo_FileSystem)//如果沒有檔案系統,串列埠列印錯誤資訊,跳轉到使用者程式
    {
        d_printf("no file system jump\n");
        BootLoad_Jump();//跳轉函式
        return;
    }
    if(f_open(&File, (char *)UPDATE_FILE_PATH, FA_READ)==FR_OK)//如果存在升級檔案,開始執行升級
    {
        d_printf("update\n");
        if(BootLoad_Program())//是否寫入成功
        {
            f_close(&File);//關閉升級檔案
            res=f_unlink((char *)UPDATE_FILE_PATH);//刪除升級檔案
            d_printfhex(res);d_printf("\n");
            res=f_unlink((char *)UPDATE_DIR_PATH);//刪除升級目錄
            d_printfhex(res);d_printf("\n");

            BootLoad_Jump();//跳轉函式
        }
        else
        {
            HAL_FLASH_Lock();//鎖定Flash
            d_printf("update fail\n");
            f_close(&File);//關閉升級檔案
            BootLoad_Jump();//跳轉函式
        }       
    }
    else
    {
        d_printf("jump\n");
        f_close(&File);
        BootLoad_Jump();
    }
}
  • 3、重寫Flash函式
uint8_t BootLoad_Program(void)
{
    uint32_t BaseAddress=APPLICATION_ADDRESS;//APP地址
    uint32_t i,br,datacnt=0;
    uint8_t data8;
    GlobalPtr32=(uint32_t *)BootBuff;
    HAL_FLASH_Unlock();//解鎖Flash
    if(BootLoad_Erase()==false)//擦除Flash
    {
        return false;
    }
    d_printf("size:");d_printfhex32(File.fsize);d_printf("\n");
    while(1)
    {
        f_read(&File,BootBuff,8192,(void *)&br);//讀取升級檔案
        for (i=0;i<(br>>2);i++)
        {
            if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, BaseAddress, GlobalPtr32[i]) == HAL_OK)//寫入升級檔案
            {
                BaseAddress = BaseAddress +4;
            }
            else
            { 
                d_printf("program err\n");
                return false;
            }
        }
        datacnt+=br;
        if(datacnt>=File.fsize)//寫入完成
        {
            break;
        }
    }
    d_printf("verify\n");       //驗證Flash中的內容與升級檔案是否一致
    f_lseek(&File,0);           //若一致代表升級成功
    datacnt=0;                  //若不一致代表升級失敗
    BaseAddress=APPLICATION_ADDRESS;
    while(1)
    {
        f_read(&File,BootBuff,8192,(void *)&br);
        for (i=0;i<br;i++)
        {
            data8 = *(__IO uint8_t*)BaseAddress;
            if (data8 != BootBuff[i])
            {
                d_printf("error!\n");
                return false;
            }
            BaseAddress ++;
        }
        datacnt+=br;
        if(datacnt>=File.fsize)
        {
            break;
        }
    }
    HAL_FLASH_Lock();//鎖定Flash
    return true;
}
  • 4、跳轉函式(從BootLoader中跳轉到APP的main函式)
void BootLoad_Jump(void)
{
    /* Check Vector Table: Test if user code is programmed starting from address 
    "APPLICATION_ADDRESS" */
    d_printfhex32((*(__IO uint32_t*)APPLICATION_ADDRESS));d_printf("\n");
    if (((*(__IO uint32_t*)APPLICATION_ADDRESS) & 0x2FFE0000 ) == 0x20000000)
    {
    JumpAddress = *(__IO uint32_t*) (APPLICATION_ADDRESS +4);
    d_printfhex32(JumpAddress);d_printf("\n");
    HAL_Delay(100);
    Jump_To_Application = (pFunction) JumpAddress;
    /* Initialize user application's Stack Pointer */
    __set_MSP(*(__IO uint32_t*) APPLICATION_ADDRESS);
    Jump_To_Application();
    }
}

相關推薦

STM32 BootLoader升級

BootLoader 關於Bootloader,從書上的文字描述,很難理解這個名詞是什麼,有什麼用。這次用到了,算是有了更進一步的認識。 一、知識點 1、BootLoader就是微控制器啟動

STM32網路遠端升級的IAP程式實現與解析 ---附親測穩定能用的程式

STM32網路遠端升級韌體的IAP程式實現與解析 ---附親測穩定能用的程式 http://www.openedv.com/thread-104667-1-1.html (出處: OpenEdv-開源電子網)  

RK3288移植Ubuntu 檔案系統及升級製作

1,  linux下 unpack 解包 報錯 [email protected]:/opt/rk-linux/mkimg# ./unpack.sh start to unpack update.img... ********RKImageMaker v

RK3288升級

1 前言本文介紹瞭如何將主機上的韌體檔案,通過 Micro USB OTG 線,燒錄到開發板的快閃記憶體中。升級時,需要根據主機作業系統和韌體型別來選擇合適的升級方式。2 準備工作Firefly RK3288 開發板韌體主機良好的 Micro USB OTG 線韌體檔案一般有兩種:單個統一韌體 update.

Netcore磊科無線路由器nw606升級為NW615後用作無線中繼使用

筆者有一臺Netcore磊科nw606無線路由器,想用它做無線橋接,但進入管理頁面後,發現[無線配置]中,[模式]的可選框是灰色的,顯示為 “AP”模式,不能進行選擇,也就是說,NW606是不帶橋接功能的,去網上查詢,發現還是高人多啊,居然有人通過升級NW606韌體將其升級為

[RK3288][Android6.0] 使用SD卡升級到eMMC

Platform: RK3288 OS: Android 6.0 Kernel: 3.10.92 使用SD升級韌體到eMMC比較方便, 插卡後完全自動升級,不需要連到PC端,省時省力. a. 編譯整

realsense升級(多次實測有效)

參考文件: https://www.intel.com/content/dam/support/us/en/documents/emerging-technologies/intel-realsense-technology/RealSense-D400-Series-Spec-Update

轉載_JLINK丟失或升級後提示Clone的解決辦法

J-LINK V8 韌體燒錄指導 J-LINK V8韌體燒錄指導 J-LINK 是使用過程中,如果內部韌體意外損壞或丟失,請參考下面操作步驟說明,重新燒錄JLINK韌體。 安裝韌體燒錄軟體 請ATMEL官方網址下載AT91-ISP下載軟體。 htt

openwrt下web方式升級提示檔案格式錯誤

最近公司產品使用openwrt,其中在使用openwrt的web方式升級核心和檔案系統時(即sysupgrade韌體)時,發現校驗檔案時提示The uploaded image file does not contain a supported format.

STM32 IAP更新,bootloader起始地址偏移後,程式碼中還需設定中斷向量的偏移。

在 stm32f10x_flash.icf 中設定ROM的起始結束地址 /*-Specials-*/ define symbol __ICFEDIT_intvec_start__ = 0x08004000; /*-Memory Regions-*/ define symbo

STM32+IAP方案 實現網路升級應用

概況: 什麼是IAP,為什麼要IAP 可實現的原理 實現過程 細節及實現  以上基本都可以從【IAR環境下STM32+IAP方案的實現】中找到答案。這裡只是貼圖,醒目:  IAP框架佈局:  STM32F103ZET6的啟動方式有三種:內建FLASH啟動、內

Huawei AP3030DN升級

進入uboot: 上電,當出現Press f of F stop Auto-Boot in 3 seconds: 0 時按鍵盤上的F鍵 Password for uboot cmd line : 密碼:[email protected] 繞過console密碼: <ap3030dn&

移遠BC系列模組升級

背景 前幾天做了BC28跟MCU的一體的板子,想去對接onenet平臺,一般命令可以正常返回,但是 AT+MIPLCREATE 這個命令居然也返回error,當時搞了半天以為是卡連結問題,或者卡有有問題,比如欠費什麼的,一直沒搞定… 最後只能是想到可能是模組不支援onene

2.0藍芽裝置的升級

首先針對2.0的藍芽裝置對於資料的傳送很有侷限,每次只能傳輸20個位元組,如果傳輸大資料還會特別不穩定,所以關於韌體升級,能不通過藍芽升級就不要通過藍芽升級,但是有時候必須實現這種需求,就沒辦法,一定得入坑去研究了,最近在做的一個專案,裝置需要兩個空中升級的功能,一個是給CPU晶片軟體升

STM32F10x IAP升級

    前言:這是小編的第一篇部落格,如有格式上的問題或者講的不好的地方敬請諒解。小編之所以想寫部落格,是希望別的童鞋不要像小編那樣走太多的彎路,甚至不惜花錢買了別人毫無參考價值的程式碼。     關於IAP原理部分,小編相信你應該已經在別的童鞋的部

03-IO模組DSQC1030版本升級

            前段時間在網上看到一個ABB的IO模組出現的問題,可以通過升級IO模組的韌體版本來解決。所以記錄下來方便以後遇到此類問題查閱。 IO板問題描述: 機器人收到正常的輸入反饋,IO模組上對應的輸入埠指示燈

STM32 標準庫的下載,檔案介紹和工程的建立(綜合)

前言 博文基於ARM Cortex-M3核心的STM32F103ZET6晶片和標準3.5.0庫; 博文介紹標準庫中個資料夾的含義和以及一個簡單工程的建立; 如有不足之處還請博友多多指教; 標準庫的下

STM32F10X 應用升級

IAP方案 把程式碼區分成了兩部分: 1.bootloader(啟動載入程式碼區) 2.user application(使用者應用程式碼區) 程式執行初始化進入bootloader,在bootloader裡面檢測條件是否被觸發(可通過按鍵是否被按下,串列埠是否

如何新建stm32庫工程

1、首先先新建一個工程資料夾,在它之下再新建7個資料夾 DOC用於存放程式說明檔案 Listing存放的是編譯器編譯時候產生的c/彙編/連結的列表清單 Output存放的是編譯產生的除錯資訊、hex檔案、預覽資訊、封裝庫等 Project用來存放工程 CMSIS

limeSDR 1.4s 升級失敗變磚 簡單解決辦法

最近入手limesdr 1.4s 一片,各種折騰,尤其在其韌體的坑中跌跌撞撞, 很小心的還是把其刷成了磚頭,網上有很多教程,對於不熟悉linux和ubuntu以及程式設計能力低下的玩友我來說都感覺到很