【STM32F407開發板用戶手冊】第30章 STM32F407的系統bootloader之串口IAP固件升級


最新教程下載:http://www.armbbs.cn/forum.php?mod=viewthread&tid=93255

第30章       STM32F407的系統bootloader之串口IAP固件升級

本章節為大家講解使用系統bootloader做程序升級的方法,即使不依賴外部boot引腳也可以方便升級。

IAP的全稱是In Application Programming,即在線應用編程。

30.1 初學者重要提示

30.2 跳轉到系統bootloader的程序設計

30.3 STM32CubeProg的安裝說明

30.3 STM32CubeProg的程序下載說明

30.4 串口方式系統bootloader驅動移植和使用

30.6 實驗例程設計框架

30.7 實驗例程說明(MDK)

30.8 實驗例程說明(IAR)

30.9 總結

 

 

30.1 初學者重要提示

  1.   學習本章節前,務必優先學習第28章。
  2.   本章用到的相關軟件和文檔下載:http://www.armbbs.cn/forum.php?mod=viewthread&tid=96573
  3.   本章節的串口IAP下載軟件使用STM32CubeProg,此軟件實現了之前的DfuSe,STLINK小軟件和Flashloader三合一,並且支持外部EEPROM,NOR Flash,SPI Flash,NAND Flash等燒寫,也支持OTA編程。
  4.   使用系統bootloader做串口IAP升級時,MicroUSB接口不要接線到電腦端,因為這會導致系統bootloader工作在USB DFU模式,無法再使用串口IAP。

30.2 跳轉到系統bootLoader的程序設計

程序設計如下,基本是按照第28章3.2小節的方法進行設計

1.    /*
2.    ******************************************************************************************************
3.    *    函 數 名: JumpToBootloader
4.    *    功能說明: 跳轉到系統BootLoader
5.    *    形    參: 無
6.    *    返 回 值: 無
7.    ******************************************************************************************************
8.    */
9.    static void JumpToBootloader(void)
10.    {
11.        uint32_t i=0;
12.        void (*SysMemBootJump)(void);        /* 聲明一個函數指針 */
13.        __IO uint32_t BootAddr = 0x1FF09800; /* STM32F4的系統BootLoader地址 */
14.    
15.        /* 關閉全局中斷 */
16.        DISABLE_INT(); 
17.    
18.        /* 關閉滴答定時器,復位到默認值 */
19.        SysTick->CTRL = 0;
20.        SysTick->LOAD = 0;
21.        SysTick->VAL = 0;
22.    
23.        /* 設置所有時鍾到默認狀態,使用HSI時鍾 */
24.        HAL_RCC_DeInit();
25.    
26.        /* 關閉所有中斷,清除所有中斷掛起標志 */
27.        for (i = 0; i < 8; i++)
28.        {
29.            NVIC->ICER[i]=0xFFFFFFFF;
30.            NVIC->ICPR[i]=0xFFFFFFFF;
31.        }    
32.    
33.        /* 使能全局中斷 */
34.        ENABLE_INT();
35.    
36.        /* 跳轉到系統BootLoader,首地址是MSP,地址+4是復位中斷服務程序地址 */
37.        SysMemBootJump = (void (*)(void)) (*((uint32_t *) (BootAddr + 4)));
38.    
39.        /* 設置主堆棧指針 */
40.        __set_MSP(*(uint32_t *)BootAddr);
41.        
42.        /* 在RTOS工程,這條語句很重要,設置為特權級模式,使用MSP指針 */
43.        __set_CONTROL(0);
44.    
45.        /* 跳轉到系統BootLoader */
46.        SysMemBootJump(); 
47.    
48.        /* 跳轉成功的話,不會執行到這里,用戶可以在這里添加代碼 */
49.        while (1)
50.        {
51.    
52.        }
53.    }

這里把程序設計中的幾個關鍵地方做個說明:

  •   第12行,聲明一個函數指針。
  •   第13行,這個要特別注意,F4的系統Bootloader地址。
  •   第19到21行,設置滴答定時器到復位值。
  •   第24行,此函數比較省事,可以方便的設置F4所有時鍾到復位值,內部時鍾使用HSI。
  •   第27到31行,清除所有中斷掛起標志並關閉中斷,這里是直接通過一個for循環設置了NVIC所有配置位,共8組。

 

  •   第37行,將系統bootloader的地址映射到0x0000 0000。這點非常重要,根本原因是F4的系統bootloader要從0x00000000地址讀取中斷向量。
  •   第40行,將系統bootLoader的中斷復位服務程序的入口地址賦給第12行聲明的函數,用戶執行這個函數時,就會直接跳轉過去。
  •   第43行,設置主堆棧指針位置,即系統bootloader的首地址存儲的就是棧地址。
  •   第46行,這個設置在RTOS應用程序中比較重要,因為基於Cortex-M內核的RTOS任務堆棧基本都是使用線程堆棧指針PSP。但系統bootLoader使用的是主堆棧指針MSP,所以務必要設置下,同時讓M內核工作於特權級。此寄存器的作用:

 

  • 第46行,跳轉到系統bootLoader。

30.3 STM32CubeProg的安裝說明

STM32CubeProg的安裝比較簡單,如果大家的電腦中缺少JAVA環境,會提示安裝,按照提示操作即可。

這里特別注意USB DFU驅動的安裝,如果大家的電腦上安裝了DfuSe軟件,那邊板子工作在系統bootLoader模式時,電腦端的設備管理器識別出來的標識是這樣的:

 

如果用STM32CubeProg的話,務必要將此驅動刪掉,鼠標右擊此標識,選擇卸載,彈出如下對話框:

 

卸載完畢后,重啟電腦,然后運行STM32CubeProg安裝目錄里面的STM32Bootloader.bat即可,最后插上設備就可以正常識別了。識別后的標識:

 

30.4 STM32CubeProg的程序下載說明

這里把兩種下載方式都做個說明,一種是設置外部bot引腳進行下載,另一種是設置程序跳轉到系統botloader進行下載。

30.4.1 選擇好用的串口線

(注:MicroUSB接口不要接線到電腦端,因為這會導致系統bootloader工作在USB DFU模式,無法再使用串口IAP)

選擇好用的USB線很重要,比如我們開發板贈送的那根USB轉RS232串口線是不可以用在這里做串口IAP的,這根線只能用於一般的串口通信和串口打印功能。

 

當前我這里是用的我們H7-TOOL的USB轉TTL輸出,注意交叉方式連接,即RX接TX,TX接RX。

GNG接GND。

 

注,我這里沒有接共地線,推薦大家接上,3.3V可以不接。

30.4.2 設置boot引腳跳轉到系統botLoader

  •   第1步:板子上電前按住右下角的BOOT引腳。

 

  •   第2步:板子上電3秒左右,松手。

在電腦端設備管理器就可以看到已經識別出來:

 

30.4.3 應用程序跳轉到系統bootloader

應用程序跳轉到系統bootLoader比較方便,無需用戶操作外置的boot引腳了,只需調用本章第2小節的程序就可以跳轉。本章配套的例子是用戶按下按鍵K1后執行跳轉程序,大家可以根據需要實現各種觸發跳轉的方式。跳轉成功后,在電腦端設備管理器里面也會看到bootloader標識:

 

30.4.4 STM32CubeProg下載程序設置

識別成功后就可以下載程序了。

  第1步,選擇UART方式,配置使用的串口號,串口波特率115200和偶校驗,點擊Connect按鈕。

 

識別成功后的效果如下:

 

  第2步,添加要下載的hex文件,勾選需要設置的選項,點擊啟動編程。

 

  •   Start address選項不填的話,默認會下載到內部Flash的首地址,保險起見,大家也可以填上首地址0x0800 0000,或者其它要下載的地址。
  •   Run after programming選項可以根據需要勾上,如果勾上此選項后,下載完畢程序后,會自動斷開連接,並彈出一些列窗口,最終彈出下面這個窗口:

 

彈出這個窗口並不是表示下載失敗了,而是下載完成后退出了系統bootloader,啟動用剛剛下載的程序了。

  第3步,完成下載后的效果如下:

 

下載完成后板子重新上電就可以看到程序已經成功下載了。

30.5 串口方式系統Bootloader驅動移植和使用

系統bootloader的移植比較簡單,僅需添加本章第2小節的程序到自己工程里面即可。里面有個開關中斷API,是在bsp.h文件里面定義的:

/* 開關全局中斷的宏 */
#define ENABLE_INT()    __set_PRIMASK(0)    /* 使能全局中斷 */
#define DISABLE_INT()    __set_PRIMASK(1)    /* 禁止全局中斷 */

30.6 實驗例程設計框架

通過程序設計框架,讓大家先對配套例程有一個全面的認識,然后再理解細節,本次實驗例程的設計框架如下:

  第1階段,上電啟動階段:

  • 這部分在第14章進行了詳細說明。

  第2階段,進入main函數:

  •   第1部分,硬件初始化,主要是HAL庫,系統時鍾,滴答定時器和LED。
  •   第2部分,應用程序設計部分,K1按鍵按下后跳轉到系統bootloader。。

30.7 實驗例程說明(MDK)

配套例子:

V5-010_基於系統bootloader的串口IAP方式固件升級

實驗目的:

  1. 學習基於系統bootloader的串口IAP方式固件升級。

實驗內容:

  1. STM32的系統存儲區自帶bootLoader,可以方便的實現串口,I2C,CAN,SPI,USB等接口方式的程序升級。
  2. 如果使用系統bootLoader支持的接口升級方式,基本就不需要用戶自己做bootLoader了。
  3. 除了通過boot引腳控制啟動地址,也可以直接從應用程序里面跳轉到系統存儲區。

實驗操作:

  1. K1鍵按下,跳轉到系統bootLoader。

上電后串口打印的信息:

波特率 115200,數據位 8,奇偶校驗位無,停止位 1。

 

程序設計:

  系統棧大小分配:

 

  硬件外設初始化

硬件外設的初始化是在 bsp.c 文件實現:

/*
*********************************************************************************************************
*    函 數 名: bsp_Init
*    功能說明: 初始化所有的硬件設備。該函數配置CPU寄存器和外設的寄存器並初始化一些全局變量。只需要調用一次
*    形    參:無
*    返 回 值: 無
*********************************************************************************************************
*/
void bsp_Init(void)
{
    /* 
       STM32F407 HAL 庫初始化,此時系統用的還是F407自帶的16MHz,HSI時鍾:
       - 調用函數HAL_InitTick,初始化滴答時鍾中斷1ms。
       - 設置NVIV優先級分組為4。
     */
    HAL_Init();

    /* 
       配置系統時鍾到168MHz
       - 切換使用HSE。
       - 此函數會更新全局變量SystemCoreClock,並重新配置HAL_InitTick。
    */
    SystemClock_Config();

    /* 
       Event Recorder:
       - 可用於代碼執行時間測量,MDK5.25及其以上版本才支持,IAR不支持。
       - 默認不開啟,如果要使能此選項,務必看V5開發板用戶手冊第8章
    */    
#if Enable_EventRecorder == 1  
    /* 初始化EventRecorder並開啟 */
    EventRecorderInitialize(EventRecordAll, 1U);
    EventRecorderStart();
#endif
    
    bsp_InitKey();        /* 按鍵初始化,要放在滴答定時器之前,因為按鈕檢測是通過滴答定時器掃描 */
    bsp_InitTimer();      /* 初始化滴答定時器 */
    bsp_InitUart();        /* 初始化串口 */
    bsp_InitExtIO();    /* 初始化擴展IO */
    bsp_InitLed();        /* 初始化LED */    
    BEEP_InitHard();    /* 初始化蜂鳴器 */
}

  主功能:

主程序實現如下操作:

  •   啟動一個自動重裝軟件定時器,每100ms翻轉一次LED2。
  •   K1鍵按下,跳轉到系統BootLoader。
/*
*********************************************************************************************************
*    函 數 名: main
*    功能說明: c程序入口
*    形    參: 無
*    返 回 值: 錯誤代碼(無需處理)
*********************************************************************************************************
*/
int main(void)
{
    uint8_t ucKeyCode;    /* 按鍵代碼 */

    
    bsp_Init();        /* 硬件初始化 */
    PrintfLogo();    /* 打印例程名稱和版本等信息 */
    PrintfHelp();    /* 打印操作提示 */
    
    bsp_StartAutoTimer(0, 100);    /* 啟動1個100ms的自動重裝的定時器 */
    
    while (1)
    {
        bsp_Idle();        /* 這個函數在bsp.c文件。用戶可以修改這個函數實現CPU休眠和喂狗 */

        /* 判斷定時器超時時間 */
        if (bsp_CheckTimer(0))    
        {
            /* 每隔100ms 進來一次 */  
            bsp_LedToggle(2);
        }

        /* 按鍵濾波和檢測由后台systick中斷服務程序實現,我們只需要調用bsp_GetKey讀取鍵值即可。 */
        ucKeyCode = bsp_GetKey();    /* 讀取鍵值, 無鍵按下時返回 KEY_NONE = 0 */
        if (ucKeyCode != KEY_NONE)
        {
            switch (ucKeyCode)
            {
                case KEY_DOWN_K1:            /* K1鍵按下,K1鍵按下,跳轉到系統BootLoader */
                    JumpToBootloader();
                    break;
                    
                default:
                    /* 其它的鍵值不處理 */
                    break;
            }
        }
    }
}

30.8 實驗例程說明(IAR)

配套例子:

V6-010_基於系統bootloader的串口IAP方式固件升級

實驗目的:

  1. 學習基於系統bootloader的串口IAP方式固件升級。

實驗內容:

  1. STM32的系統存儲區自帶bootLoader,可以方便的實現串口,I2C,CAN,SPI,USB等接口方式的程序升級。
  2. 如果使用系統bootLoader支持的接口升級方式,基本就不需要用戶自己做bootLoader了。
  3. 除了通過boot引腳控制啟動地址,也可以直接從應用程序里面跳轉到系統存儲區。

實驗操作:

  1. K1鍵按下,跳轉到系統bootLoader。

上電后串口打印的信息:

波特率 115200,數據位 8,奇偶校驗位無,停止位 1。

 

程序設計:

  系統棧大小分配:

 

  硬件外設初始化

硬件外設的初始化是在 bsp.c 文件實現:

/*
*********************************************************************************************************
*    函 數 名: bsp_Init
*    功能說明: 初始化所有的硬件設備。該函數配置CPU寄存器和外設的寄存器並初始化一些全局變量。只需要調用一次
*    形    參:無
*    返 回 值: 無
*********************************************************************************************************
*/
void bsp_Init(void)
{
    /* 
       STM32F407 HAL 庫初始化,此時系統用的還是F407自帶的16MHz,HSI時鍾:
       - 調用函數HAL_InitTick,初始化滴答時鍾中斷1ms。
       - 設置NVIV優先級分組為4。
     */
    HAL_Init();

    /* 
       配置系統時鍾到168MHz
       - 切換使用HSE。
       - 此函數會更新全局變量SystemCoreClock,並重新配置HAL_InitTick。
    */
    SystemClock_Config();

    /* 
       Event Recorder:
       - 可用於代碼執行時間測量,MDK5.25及其以上版本才支持,IAR不支持。
       - 默認不開啟,如果要使能此選項,務必看V5開發板用戶手冊第8章
    */    
#if Enable_EventRecorder == 1  
    /* 初始化EventRecorder並開啟 */
    EventRecorderInitialize(EventRecordAll, 1U);
    EventRecorderStart();
#endif
    
    bsp_InitKey();        /* 按鍵初始化,要放在滴答定時器之前,因為按鈕檢測是通過滴答定時器掃描 */
    bsp_InitTimer();      /* 初始化滴答定時器 */
    bsp_InitUart();        /* 初始化串口 */
    bsp_InitExtIO();    /* 初始化擴展IO */
    bsp_InitLed();        /* 初始化LED */    
    BEEP_InitHard();    /* 初始化蜂鳴器 */
}

  主功能:

主程序實現如下操作:

  •   啟動一個自動重裝軟件定時器,每100ms翻轉一次LED2。
  •   K1鍵按下,跳轉到系統BootLoader。
/*
*********************************************************************************************************
*    函 數 名: main
*    功能說明: c程序入口
*    形    參: 無
*    返 回 值: 錯誤代碼(無需處理)
*********************************************************************************************************
*/
int main(void)
{
    uint8_t ucKeyCode;    /* 按鍵代碼 */

    
    bsp_Init();        /* 硬件初始化 */
    PrintfLogo();    /* 打印例程名稱和版本等信息 */
    PrintfHelp();    /* 打印操作提示 */
    
    bsp_StartAutoTimer(0, 100);    /* 啟動1個100ms的自動重裝的定時器 */
    
    while (1)
    {
        bsp_Idle();        /* 這個函數在bsp.c文件。用戶可以修改這個函數實現CPU休眠和喂狗 */

        /* 判斷定時器超時時間 */
        if (bsp_CheckTimer(0))    
        {
            /* 每隔100ms 進來一次 */  
            bsp_LedToggle(2);
        }

        /* 按鍵濾波和檢測由后台systick中斷服務程序實現,我們只需要調用bsp_GetKey讀取鍵值即可。 */
        ucKeyCode = bsp_GetKey();    /* 讀取鍵值, 無鍵按下時返回 KEY_NONE = 0 */
        if (ucKeyCode != KEY_NONE)
        {
            switch (ucKeyCode)
            {
                case KEY_DOWN_K1:            /* K1鍵按下,K1鍵按下,跳轉到系統BootLoader */
                    JumpToBootloader();
                    break;
                    
                default:
                    /* 其它的鍵值不處理 */
                    break;
            }
        }
    }
}

30.9 總結

本章節為大家介紹的串口IAP方式還是非常實用的,特別是產品硬件不帶boot引腳時。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM