【STM32H7教程】第69章 STM32H7的系統bootloader之串口IAP固件升級

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

第69章       STM32H7的系統bootloader之串口IAP固件升級

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

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

69.1 初學者重要提示函數

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

69.3 STM32CubeProg的安裝說明ui

69.3 STM32CubeProg的程序下載說明spa

69.4 串口方式系統bootloader驅動移植和使用線程

69.6 實驗例程設計框架設計

69.7 實驗例程說明(MDK)3d

69.8 實驗例程說明(IAR)

69.9 總結

 

 

69.1 初學者重要提示

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

69.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。

69.3 STM32CubeProg的安裝說明

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

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

 

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

 

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

 

69.4 STM32CubeProg的程序下載說明

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

69.4.1 選擇好用的串口線

(注:MicroUSB接口不要接線到電腦端,由於這會致使系統bootloader工做在USB DFU模式,沒法再使用串口IAP)

選擇好用的USB線很重要,好比咱們開發板贈送的那根USB轉RS232串口線是不能夠用在這裏作串口IAP的,這根線只能用於通常的串口通訊和串口打印功能。

 

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

 

注,我這裏沒有接共地線,推薦你們接上,3.3V能夠不接。

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

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

 

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

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

 

69.4.3 應用程序跳轉到系統bootloader

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

 

69.4.4 STM32CubeProg下載程序設置

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

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

 

識別成功後的效果以下:

 

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

 

  •   Start address選項不填的話,默認會下載到內部Flash的首地址,保險起見,你們也能夠填上首地址0x0800 0000,或者其它要下載的地址。
  •   Run after programming選項能夠根據須要勾上,若是勾上此選項後,下載完畢程序後,會自動斷開鏈接,並彈出一些列窗口,最終彈出下面這個窗口:

 

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

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

 

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

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

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

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

 

69.6 實驗例程設計框架

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

 

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

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

  第2階段,進入main函數:

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

69.7 實驗例程說明(MDK)

配套例子:

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

實驗目的:

  1. 學習基於系統bootloader的串口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; } } } }

 

69.8 實驗例程說明(IAR)

配套例子:

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

實驗目的:

  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; } } } }

 

69.9 總結

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

相關文章
相關標籤/搜索