【STM32H7教程】第68章 STM32H7的系統bootloader之USB DFU方式固件升級

完整教程下載地址:http://www.armbbs.cn/forum.php?mod=viewthread&tid=86980php

第68章       STM32H7的系統bootloader之USB DFU方式固件升級

本章節爲你們講解使用系統bootloader作程序升級的方法,即便不依賴外部boot引腳也能夠方便升級。編程

DFU的全稱是Device Firmware Upgrade,即設備固件升級框架

68.1 初學者重要提示函數

68.2 跳轉到系統bootloader的程序設計學習

68.3 STM32CubeProg的安裝說明測試

68.3 STM32CubeProg的程序下載說明ui

68.4 USB DFU方式系統bootloader驅動移植和使用spa

68.6 實驗例程設計框架線程

68.7 實驗例程說明(MDK)設計

68.8 實驗例程說明(IAR)

68.9 總結

 

 

68.1 初學者重要提示

  1.   學習本章節前,務必優先學習第67章。
  2.   特別注意STM32H7的系統bootLoader地址並非0x1FFF 0000。
  3.   本章用到的相關軟件和文檔下載:http://www.armbbs.cn/forum.php?mod=viewthread&tid=96573
  4.   軟件STM32CubeProg和DfuSe都支持USB DFU,可是兩個軟件不能都安裝使用,由於這兩個軟件的USB驅動不一樣,致使工做在系統bootloader模式的板子經過USB線接到電腦端時,只有一個軟件的驅動被識別。
  5.   DfuSe是老版的USB DFU軟件,不推薦你們使用了。建議使用STM32CubeProg,此軟件實現了以前的DfuSe,STLINK小軟件和Flashloader三合一,而且支持外部EEPROM,NOR Flash,SPI Flash,NAND Flash等燒寫,也支持OTA編程。
  6.   本章節的USB DFU的下載軟件採用STM32CubeProg,若是想使用DfuSe的話,此貼有詳細說明:http://www.armbbs.cn/forum.php?mod=viewthread&tid=11185
  7.   當芯片工做在系統bootLoader的USB DFU模式,更新完畢程序後,不會自動退出USB DFU,須要從新復位芯片後纔會退出。因爲DFU模式會用到USB線,插拔USB線是難以免的,因此是否支持自動退出,並不影響。

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

程序設計以下,基本是按照第67章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; /* STM32H7的系統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行,這個要特別注意,H7的系統Bootloader地址在0x1FF09800。
  •   第19到21行,設置滴答定時器到復位值。
  •   第24行,此函數比較省事,能夠方便的設置H7全部時鐘到復位值,內部時鐘使用HSI。
  •   第27到31行,清除全部中斷掛起標誌並關閉中斷,這裏是直接經過一個for循環設置了NVIC全部配置位,共8組。

 

  •   第37行,將系統bootLoader的中斷復位服務程序的入口地址賦給第12行聲明的函數,用戶執行這個函數時,就會直接跳轉過去。
  •   第40行,設置主堆棧指針位置,即系統bootloader的首地址存儲的就是棧地址。
  •   第43行,這個設置在RTOS應用程序中比較重要,由於基於Cortex-M內核的RTOS任務堆棧基本都是使用線程堆棧指針PSP。但系統bootLoader使用的是主堆棧指針MSP,因此務必要設置下,同時讓M內核工做於特權級。此寄存器的做用以下:

 

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

68.3 STM32CubeProg的安裝說明

STM32CubeProg的安裝比較簡單,若是你們的電腦中缺乏JAVA環境,會提示安裝,按照提示操做便可。

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

 

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

 

卸載完畢後,重啓電腦,而後運行STM32CubeProg安裝目錄裏面的STM32Bootloader.bat便可,最後插上設備就能夠正常識別了。識別後的標識:

 

68.4 STM32CubeProg的程序下載說明

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

68.4.1 設置boot引腳跳轉到系統bootLoader

  •   第1步:此接口插上USB線:

 

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

 

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

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

 

68.4.2 應用程序跳轉到系統bootloader

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

 

68.4.3 STM32CubeProg下載程序設置

識別成功後就能夠下載程序了。

  第1步,選擇USB方式,點擊Connect按鈕。

 

識別成功後的效果以下:

 

這裏要特別注意一點,若是用戶沒有關閉這個軟件,屢次插拔USB線時,記得點擊這裏的刷新按鈕,由於有時候這個軟件不會自動顯示出來,點擊刷新按鈕才行。

 

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

 

  •   Start address選項不填的話,默認會下載到內部Flash的首地址,保險起見,你們也能夠填上首地址0x0800 0000,或者其它要下載的地址。
  •   Run after programming選項勾選或者不勾選都可,由於測試發現STM32CubeProg不支持USB DFU編程後運行。這樣特別說一點,若是勾上此選項後,下載完畢程序後,會自動斷開鏈接,並彈出一些列窗口,最終彈出下面這個窗口:

 

彈出這個窗口並非表示下載失敗了,而是下載完成後退出了系統bootloader。

  第3步,完成下載後的效果以下:

 

下載完成後板子從新上電就能夠看到程序已經成功下載了。

68.5 USB DFU方式系統Bootloader驅動移植和使用

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

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

 

68.6 實驗例程設計框架

經過程序設計框架,讓你們先對配套例程有一個全面的認識,而後再理解細節,本次實驗例程的設計框架以下:

 

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

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

  第2階段,進入main函數:

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

68.7 實驗例程說明(MDK)

配套例子:

V7-047_基於系統bootloader的USB接口方式IAP升級(USB DFU)

實驗目的:

  1. 學習基於系統bootloader的USB接口方式IAP升級。

實驗內容:

  1. STM32的系統存儲區自帶bootLoader,能夠方便的實現串口,I2C,CAN,SPI,USB等接口方式的程序升級。
  2. 若是使用系統bootLoader支持的接口升級方式,基本就不須要用戶本身作bootLoader了。
  3. 除了經過boot引腳控制啓動地址,也能夠直接從應用程序裏面跳轉到系統存儲區。

實驗操做:

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

上電後串口打印的信息:

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

 

程序設計:

  系統棧大小分配:

 

  RAM空間用的DTCM:

 

  硬件外設初始化

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

/* ********************************************************************************************************* * 函 數 名: bsp_Init * 功能說明: 初始化全部的硬件設備。該函數配置CPU寄存器和外設的寄存器並初始化一些全局變量。只須要調用一次 * 形 參:無 * 返 回 值: 無 ********************************************************************************************************* */
void bsp_Init(void) { /* 配置MPU */ MPU_Config(); /* 使能L1 Cache */ CPU_CACHE_Enable(); /* STM32H7xx HAL 庫初始化,此時系統用的仍是H7自帶的64MHz,HSI時鐘: - 調用函數HAL_InitTick,初始化滴答時鐘中斷1ms。 - 設置NVIV優先級分組爲4。 */ HAL_Init(); /* 配置系統時鐘到400MHz - 切換使用HSE。 - 此函數會更新全局變量SystemCoreClock,並從新配置HAL_InitTick。 */ SystemClock_Config(); /* Event Recorder: - 可用於代碼執行時間測量,MDK5.25及其以上版本才支持,IAR不支持。 - 默認不開啓,若是要使能此選項,務必看V7開發板用戶手冊第xx章 */    
#if Enable_EventRecorder == 1  
    /* 初始化EventRecorder並開啓 */ EventRecorderInitialize(EventRecordAll, 1U); EventRecorderStart(); #endif bsp_InitDWT(); /* 初始化DWT時鐘週期計數器 */ bsp_InitKey(); /* 按鍵初始化,要放在滴答定時器以前,由於按鈕檢測是經過滴答定時器掃描 */ bsp_InitTimer(); /* 初始化滴答定時器 */ bsp_InitUart(); /* 初始化串口 */ bsp_InitExtIO(); /* 初始化FMC總線74HC574擴展IO. 必須在 bsp_InitLed()前執行 */ bsp_InitLed(); /* 初始化LED */ bsp_InitExtSDRAM(); /* 初始化SDRAM */ }

 

  MPU配置和Cache配置:

數據Cache和指令Cache都開啓。配置了AXI SRAM區(本例子未用到AXI SRAM)和FMC的擴展IO區。

/* ********************************************************************************************************* * 函 數 名: MPU_Config * 功能說明: 配置MPU * 形 參: 無 * 返 回 值: 無 ********************************************************************************************************* */
static void MPU_Config( void ) { MPU_Region_InitTypeDef MPU_InitStruct; /* 禁止 MPU */ HAL_MPU_Disable(); /* 配置AXI SRAM的MPU屬性爲Write back, Read allocate,Write allocate */ MPU_InitStruct.Enable = MPU_REGION_ENABLE; MPU_InitStruct.BaseAddress = 0x24000000; MPU_InitStruct.Size = MPU_REGION_SIZE_512KB; MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS; MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE; MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE; MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE; MPU_InitStruct.Number = MPU_REGION_NUMBER0; MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL1; MPU_InitStruct.SubRegionDisable = 0x00; MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE; HAL_MPU_ConfigRegion(&MPU_InitStruct); /* 配置FMC擴展IO的MPU屬性爲Device或者Strongly Ordered */ MPU_InitStruct.Enable = MPU_REGION_ENABLE; MPU_InitStruct.BaseAddress = 0x60000000; MPU_InitStruct.Size = ARM_MPU_REGION_SIZE_64KB; MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS; MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE; MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE; MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE; MPU_InitStruct.Number = MPU_REGION_NUMBER1; MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0; MPU_InitStruct.SubRegionDisable = 0x00; MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE; HAL_MPU_ConfigRegion(&MPU_InitStruct); /*使能 MPU */ HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT); } /* ********************************************************************************************************* * 函 數 名: CPU_CACHE_Enable * 功能說明: 使能L1 Cache * 形 參: 無 * 返 回 值: 無 ********************************************************************************************************* */
static void CPU_CACHE_Enable(void) { /* 使能 I-Cache */ SCB_EnableICache(); /* 使能 D-Cache */ SCB_EnableDCache(); }

 

  每10ms調用一次蜂鳴器處理:

蜂鳴器處理是在滴答定時器中斷裏面實現,每10ms執行一次檢測。

/* ********************************************************************************************************* * 函 數 名: bsp_RunPer10ms * 功能說明: 該函數每隔10ms被Systick中斷調用1次。詳見 bsp_timer.c的定時中斷服務程序。一些處理時間要求 * 不嚴格的任務能夠放在此函數。好比:按鍵掃描、蜂鳴器鳴叫控制等。 * 形 參: 無 * 返 回 值: 無 ********************************************************************************************************* */
void bsp_RunPer10ms(void) { bsp_KeyScan10ms(); }

 

  主功能:

主程序實現以下操做:

  •   啓動一個自動重裝軟件定時器,每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; } } } }

 

68.8 實驗例程說明(IAR)

配套例子:

V7-047_基於系統bootloader的USB接口方式IAP升級(USB DFU)

實驗目的:

  1. 學習基於系統bootloader的USB接口方式IAP升級。

實驗內容:

  1. STM32的系統存儲區自帶bootLoader,能夠方便的實現串口,I2C,CAN,SPI,USB等接口方式的程序升級。
  2. 若是使用系統bootLoader支持的接口升級方式,基本就不須要用戶本身作bootLoader了。
  3. 除了經過boot引腳控制啓動地址,也能夠直接從應用程序裏面跳轉到系統存儲區。

實驗操做:

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

上電後串口打印的信息:

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

 

程序設計:

  系統棧大小分配:

 

  RAM空間用的DTCM:

 

  硬件外設初始化

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

/* ********************************************************************************************************* * 函 數 名: bsp_Init * 功能說明: 初始化全部的硬件設備。該函數配置CPU寄存器和外設的寄存器並初始化一些全局變量。只須要調用一次 * 形 參:無 * 返 回 值: 無 ********************************************************************************************************* */
void bsp_Init(void) { /* 配置MPU */ MPU_Config(); /* 使能L1 Cache */ CPU_CACHE_Enable(); /* STM32H7xx HAL 庫初始化,此時系統用的仍是H7自帶的64MHz,HSI時鐘: - 調用函數HAL_InitTick,初始化滴答時鐘中斷1ms。 - 設置NVIV優先級分組爲4。 */ HAL_Init(); /* 配置系統時鐘到400MHz - 切換使用HSE。 - 此函數會更新全局變量SystemCoreClock,並從新配置HAL_InitTick。 */ SystemClock_Config(); /* Event Recorder: - 可用於代碼執行時間測量,MDK5.25及其以上版本才支持,IAR不支持。 - 默認不開啓,若是要使能此選項,務必看V7開發板用戶手冊第xx章 */    
#if Enable_EventRecorder == 1  
    /* 初始化EventRecorder並開啓 */ EventRecorderInitialize(EventRecordAll, 1U); EventRecorderStart(); #endif bsp_InitDWT(); /* 初始化DWT時鐘週期計數器 */ bsp_InitKey(); /* 按鍵初始化,要放在滴答定時器以前,由於按鈕檢測是經過滴答定時器掃描 */ bsp_InitTimer(); /* 初始化滴答定時器 */ bsp_InitUart(); /* 初始化串口 */ bsp_InitExtIO(); /* 初始化FMC總線74HC574擴展IO. 必須在 bsp_InitLed()前執行 */ bsp_InitLed(); /* 初始化LED */ bsp_InitExtSDRAM(); /* 初始化SDRAM */ }

 

  MPU配置和Cache配置:

數據Cache和指令Cache都開啓。配置了AXI SRAM區(本例子未用到AXI SRAM)和FMC的擴展IO區。

/* ********************************************************************************************************* * 函 數 名: MPU_Config * 功能說明: 配置MPU * 形 參: 無 * 返 回 值: 無 ********************************************************************************************************* */
static void MPU_Config( void ) { MPU_Region_InitTypeDef MPU_InitStruct; /* 禁止 MPU */ HAL_MPU_Disable(); /* 配置AXI SRAM的MPU屬性爲Write back, Read allocate,Write allocate */ MPU_InitStruct.Enable = MPU_REGION_ENABLE; MPU_InitStruct.BaseAddress = 0x24000000; MPU_InitStruct.Size = MPU_REGION_SIZE_512KB; MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS; MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE; MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE; MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE; MPU_InitStruct.Number = MPU_REGION_NUMBER0; MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL1; MPU_InitStruct.SubRegionDisable = 0x00; MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE; HAL_MPU_ConfigRegion(&MPU_InitStruct); /* 配置FMC擴展IO的MPU屬性爲Device或者Strongly Ordered */ MPU_InitStruct.Enable = MPU_REGION_ENABLE; MPU_InitStruct.BaseAddress = 0x60000000; MPU_InitStruct.Size = ARM_MPU_REGION_SIZE_64KB; MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS; MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE; MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE; MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE; MPU_InitStruct.Number = MPU_REGION_NUMBER1; MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0; MPU_InitStruct.SubRegionDisable = 0x00; MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE; HAL_MPU_ConfigRegion(&MPU_InitStruct); /*使能 MPU */ HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT); } /* ********************************************************************************************************* * 函 數 名: CPU_CACHE_Enable * 功能說明: 使能L1 Cache * 形 參: 無 * 返 回 值: 無 ********************************************************************************************************* */
static void CPU_CACHE_Enable(void) { /* 使能 I-Cache */ SCB_EnableICache(); /* 使能 D-Cache */ SCB_EnableDCache(); }

 

  每10ms調用一次蜂鳴器處理:

蜂鳴器處理是在滴答定時器中斷裏面實現,每10ms執行一次檢測。

/* ********************************************************************************************************* * 函 數 名: bsp_RunPer10ms * 功能說明: 該函數每隔10ms被Systick中斷調用1次。詳見 bsp_timer.c的定時中斷服務程序。一些處理時間要求 * 不嚴格的任務能夠放在此函數。好比:按鍵掃描、蜂鳴器鳴叫控制等。 * 形 參: 無 * 返 回 值: 無 ********************************************************************************************************* */
void bsp_RunPer10ms(void) { bsp_KeyScan10ms(); }

 

  主功能:

主程序實現以下操做:

  •   啓動一個自動重裝軟件定時器,每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; } } } }

 

68.9 總結

本章節爲你們介紹的USB DFU方式仍是很是實用的,特別是產品硬件不帶boot引腳時。

相關文章
相關標籤/搜索