硬件:stm32f407VET6芯片;
軟件:STM32CubeMx、Keil5
上位機:Dfuse DemoV3.06
? ? 這里給出通過在Bootlaoder中使用USB方式來更新APP程序的方法,首先我們編寫一個自己的bootloader,關于bootloader的大致原理可以參考我之前的文章HAL庫執行bootloader跳轉操作:_hal庫bootloader-CSDN博客,這里boot升級我采用單APP升級的方式 ,主要分為三部分講解:
? ? 一、程序配置和Bootlaoder編寫;
? ? 二、Dfuse DemoV3.06上位機和對應USB驅動安裝;
? ? 三、使用上位機配合Boot程序進行USB方式的單APP升級;
一、程序配置和Bootlaoder編寫
? ? 這里我們先打開cubemx配置芯片的USB硬件模式,需要使能USB_OTG_FS,設置如下圖,需要注意開啟USB的NVIC中斷;
? ? 使能完USB硬件后,我們還需要配置USB工作在DFU模式,DFU全稱為Download?Firmware?Update,是ST官方推出的一個通過USB接口進行IAP升級的方案,我們就是通過該模式來進行Boot升級,相關配置如下:
? ? 需要注意的是下圖中關于“USBD_DFU_APP_DEFAULT_ADD(Base_Address)”這里設置的值為我們APP程序的起始地址,這里我將APP程序起始地址設為0x08010000;
? ? ?將上述程序進行生成,然后在生成的文件中找到usbd_dfu_if.c文件并打開,添加Flash操作相關代碼分別是 上鎖、解鎖、擦除、寫入、讀取、返回Flash操作時間,代碼如下:
/* Private functions ---------------------------------------------------------*/
/*** @brief Memory initialization routine.* @retval USBD_OK if operation is successful, MAL_FAIL else.*/
uint16_t MEM_If_Init_FS(void)
{/* USER CODE BEGIN 0 */HAL_FLASH_Unlock();__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR);return (USBD_OK);/* USER CODE END 0 */
}/*** @brief De-Initializes Memory* @retval USBD_OK if operation is successful, MAL_FAIL else*/
uint16_t MEM_If_DeInit_FS(void)
{/* USER CODE BEGIN 1 */HAL_FLASH_Lock();return (USBD_OK);/* USER CODE END 1 */
}/*** @brief Erase sector.* @param Add: Address of sector to be erased.* @retval 0 if operation is successful, MAL_FAIL else.*/
uint16_t MEM_If_Erase_FS(uint32_t Add)
{/* USER CODE BEGIN 2 */UNUSED(Add);uint32_t error = 0;FLASH_EraseInitTypeDef flash_dat; //定義一個結構體變量,里面有擦除操作需要定義的變量HAL_FLASH_Unlock(); //第二步:解鎖 flash_dat.TypeErase = FLASH_TYPEERASE_SECTORS; //擦除類型是“Page Erase” 僅刪除頁面 另外一個參數是全部刪除flash_dat.Sector = FLASH_SECTOR_5; //擦除地址對應的頁flash_dat.NbSectors = 1; //一次性擦除1頁,可以是任意頁flash_dat.Banks=FLASH_BANK_1;flash_dat.VoltageRange=FLASH_VOLTAGE_RANGE_3;HAL_FLASHEx_Erase(&flash_dat,&error); //第三步:參數寫好后調用擦除函數return (USBD_OK);/* USER CODE END 2 */
}/*** @brief Memory write routine.* @param src: Pointer to the source buffer. Address to be written to.* @param dest: Pointer to the destination buffer.* @param Len: Number of data to be written (in bytes).* @retval USBD_OK if operation is successful, MAL_FAIL else.*/
uint16_t MEM_If_Write_FS(uint8_t *src, uint8_t *dest, uint32_t Len)
{/* USER CODE BEGIN 3 */UNUSED(src);UNUSED(dest);UNUSED(Len);uint32_t i = 0;for(i=0;i<Len;i+=4){ HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, (uint32_t)(dest + i), *(uint32_t *)(src + i));if(*(uint32_t *)(src + i) != *(uint32_t *)(dest + i)){/* Flash content doesn't match SRAM content */return (USBD_FAIL);}}return (USBD_OK);/* USER CODE END 3 */
}/*** @brief Memory read routine.* @param src: Pointer to the source buffer. Address to be written to.* @param dest: Pointer to the destination buffer.* @param Len: Number of data to be read (in bytes).* @retval Pointer to the physical address where data should be read.*/
uint8_t *MEM_If_Read_FS(uint8_t *src, uint8_t *dest, uint32_t Len)
{/* Return a valid address to avoid HardFault *//* USER CODE BEGIN 4 */UNUSED(src);UNUSED(dest);UNUSED(Len);uint32_t i = 0;uint8_t *psrc = src;for (i = 0; i < Len; i++){dest[i] = *psrc++;}/* Return a valid address to avoid HardFault */return (uint8_t *)(dest);/* USER CODE END 4 */
}/*** @brief Get status routine* @param Add: Address to be read from* @param Cmd: Number of data to be read (in bytes)* @param buffer: used for returning the time necessary for a program or an erase operation* @retval USBD_OK if operation is successful*/
uint16_t MEM_If_GetStatus_FS(uint32_t Add, uint8_t Cmd, uint8_t *buffer)
{/* USER CODE BEGIN 5 */UNUSED(Add);UNUSED(buffer);uint16_t FLASH_PROGRAM_TIME = 50;uint16_t FLASH_ERASE_TIME = 50;switch(Cmd){case DFU_MEDIA_PROGRAM:buffer[1] = (uint8_t)FLASH_PROGRAM_TIME;buffer[2] = (uint8_t)(FLASH_PROGRAM_TIME << 8);buffer[3] = 0;break;case DFU_MEDIA_ERASE:default:buffer[1] = (uint8_t)FLASH_ERASE_TIME;}return (USBD_OK);/* USER CODE END 5 */
}
? ? ? 配置好USB升級方式后,我們就需要編寫Boot程序中關于升級的一些判斷,這里的判斷根據不同的交互方式有所不同,有些使用串口通訊交互,有些使用按鍵+指示燈/屏幕交互,這里我使用的是按鍵+屏幕交互,按鍵接入單片機Wake_Up引腳,Bootloader和APP大體程序執行流程如下:
參考文章:
【STM32】HAL庫USB實現軟件升級DFU的功能操作及配置_stm32f205 dfu-CSDN博客
STM32 USB的DFU模式升級_stm32 dfu-CSDN博客
二、Dfuse DemoV3.06上位機和對應USB驅動安裝
1、下載Dfuse DemoV3.06上位機安裝包,下載地址如下:
STSW-STM32080 - DfuSe USB device firmware upgrade (UM0412) - STMicroelectronics
2、點擊下述紅色方框中的安裝文件,一直點“next”直至完成安裝;
3、通過USB線連接電腦和單片機的USB接口,進入單片機BOOT升級模式,此時打開windows設備管理器,查看連接設備,出現下述圖標是因為沒有安裝Dfuse Demo相關驅動,這里我們右鍵有感嘆號的設備,選擇“更新驅動程序”,選擇“瀏覽我的電腦以查找驅動程序”
? 這里驅動程序的路徑如下,根據電腦的系統選擇相應的文件夾,這里由于我的電腦是win10系統,我就選擇“win10”文件夾作為驅動路徑
如下圖,選擇完驅動路徑后點擊“下一步”等待驅動安裝即可,
? ? 安裝完后再在“設備管理器”可以看到下述兩種情況,都表示驅動安裝成功。(針對本人的USB Boot升級程序,驅動安裝成功后單片機仍處于BOOT模式,此時我們只需要長按wake_up鍵3s左右等待單片機關機以退出BOOT模式,后面正常使用即可;)
? ? 三、使用上位機配合Boot程序進行USB方式的單APP升級
? 1、通過USB線連接電腦和單片機的USB接口,使單片機進入BOOT模式,打開Dfuse Demo程序
? 2、程序左上角紅框內顯示設備名稱即表示連接正常,此時點擊上位機下方“Choose...”加載我們提供的.dfu格式的升級文件
? 3、提示加載完畢,并選擇“Verify after download”
4、點擊“Upgrade”按鈕,有個彈窗,選擇“是”,然后等待Boot升級程序
5、出現下述紅框中的內容表示升級成功。(針對本人的Boot程序,需要再次長按wake_up鍵3s左右等待單片機進入深度休眠以退出BOOT模式,后面正常使用即可)
? ? 注意如果未安裝驅動、單片機不處于BOOT模式、電腦未和單片機連接等異常情況,上位機界面左上角是空的;
如何生成.dfu文件:
1、生成app程序bin文件:
2、將bin文件轉化為.dfu文件:
官方DFU固件更新軟件實現對STM32的USB方式代碼升級簡易說明(STM32-V5開發板) - 開發環境 - 硬漢嵌入式論壇 - Powered by Discuz!
? ? 下面這里的Address填APP的起始地址。