硬件: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的起始地址。