【stm32】STM32F407 如何使用代码进入USB-DFU模式?

STM32CubeMX学习笔记(50)——USB接口使用(DFU固件升级 USB(Universal Serial BUS)通用串行总线,是一个外部总线标准,用于规范电脑与外部设备的连接和通讯。是应用在 PC 领域的接口技术。USB 接口支持设备的即插即用和热插拔功能。USB 是在 1994 年底由英特尔、康柏、IBM、Microsoft 等多家公司联合提出的。USB 发展到现在已经有 USB1.0/1.1/2.0/3.0 等多个版本。目前用的最多的就是 USB1.1 和 USB2.0,USB3.0 目前已经开始普及。 阅读详情
AI摘要

本文介绍了一种不依赖外部引脚修改的STM32 DFU固件升级方法,通过软复位和代码跳转实现系统存储区Bootloader的调用,适用于无法直接接触硬件的产品升级场景。


前言

大家都知道,ST芯片预置了自己的bootloader,使用方法也很简单,通过配置Boot1 和Boot0 引脚,复位后即可进入bootloader。
在大部分成熟的产品中,一般不会像开发板一样预留这两个引脚的空间位置,在某些应用中,往往也不方便拆开外壳来修改Boot引脚进入DFU 模式。
那么,如何在不修改boot引脚的情况下进入DFU模式来进行程序升级?成为了产品的新需求。


一、ST芯片的启动模式

ST芯片的启动模式有三种。
Main Flash Memory 称为主Flash区,用来存放我们下载的程序,正常上电后,程序将从这里开始启动运行。
System Memory 称为系统存储区,用于存放预置的bootloader,在该模式下,可支持多种重新烧录程序的方式。
Embedded Memory 称为内置SRAM,这个模式一般用于快速的程序调试。
在这里插入图片描述

二、进入bootloader的方法

1.通过外部修改boot引脚的状态

正如前面所提及的,将Boot0置于高电平,Boot1置于地电平,复位后即可进入DFU模式。

2.通过软件直接跳转到System Memory

直接修改引脚的方法显然最直接,但是有时候却也很不方便。通过软件的方式,即用预先编辑好的代码,在外部条件触发下来引导进入bootloader。

从应用手册 AN2606《STM32 microcontroller system memory boot mode》查找证实,可以通过代码的方式跳转到system memory来执行bootloader,但是在这之前,需要满足一下4个要求:

  • 关闭时钟分频器
  • 关闭PLL
  • 禁用所有中断
  • 清除所有中断标记位
    在这里插入图片描述
    从编程手册PM0081《STM32F40xxx and STM32F41xxx Flash programming manual》手册查找,SystemMemory 的地址是从0x1FFF0000开始的,那么通过软件直接跳转到改地址,即可以进入bootloader。
    在这里插入图片描述

三、工程编写

在跳转到System memory之前,是需要完成前边提到的四项操作的,这里有两种方法。

第一种可以参考安富莱《【STM32H7教程】第68章 STM32H7的系统bootloader之USB DFU方式固件升级》 的教程,手动编辑配置以上4项要求,摘抄代码如下图。
另外一种是使用软复位的功能进行操作,因为在复位后,系统时钟初始化之前,所有的操作都是初始状态。此时可以直接跳转到system memory,而不用担心前边的四项要求是否处理正确。
个人倾向于第二种软复位的方式进行操作。
在这里插入图片描述
接下来,将使用arduino的方式演示整个过程的,实现软复位进入DFU模式。其他IDE工程除了代码风格不同,其他操作基本类似。
该方法经过STM32cube工程测试,一样可以实现。

1. 建立DFU触发方式及设立标记位

本案例使用按钮的方式来触发,利用RTC后备寄存器来保存标记位,标记有效时执行软复位。

#include <Arduino.h>
#include <timer.h>

#define LED PG0
#define BUTTON PB2
#define PRESSED LOW

int led_delay_time = 1000;

void setup()
{
  // put your setup code here, to run once:
  pinMode(LED, OUTPUT);
  pinMode(BUTTON, INPUT_PULLUP);
  RTC_init(HOUR_FORMAT_24, LSE_CLOCK, false);

  //software reset
  if (__HAL_RCC_GET_FLAG(RCC_FLAG_SFTRST) == SET)
    led_delay_time = 3000;
  __HAL_RCC_CLEAR_RESET_FLAGS();
}

void loop()
{
  // put your main code here, to run repeatedly:
  digitalToggle(LED);
  delay(led_delay_time);
  if (digitalRead(BUTTON) == PRESSED)
  {
    //Write a flag in the RTC backup register
    setBackupRegister(LL_RTC_BKP_DR0, 0x1498);
    if (getBackupRegister(LL_RTC_BKP_DR0) != 0x1498)
    {
      //not match, that means it is not written correctly. flashes quickly to warn
      while (1)
      {
        digitalToggle(LED);
        delay(200);
      }
    }
    else
    {
      //software reset, Prepare for entering dfu mode
      HAL_NVIC_SystemReset();
    }
  }
}

阶段性验证:烧录成功后,手动复位,led灯闪烁;当按钮按下后,led闪烁变慢,即可验证软复位成功执行。若按下按钮后,led灯闪烁加快,则证明动作标记位没有写入成功,需要检查RTC的配置是否正确,是否有读写授权。

2. 利用代码跳转进入DFU模式

软复位验证成功后,就需要在application启动之前添加代码,跳转到system memory执行bootloader。
这里参考启动文件 startup_stm32f407xx.s 可知,main函数(application)是在SystemInit函数(时钟系统初始化函数)之前执行的,因此,我们需要将跳转的代码添加在systemInit函数中,也就是在时钟系统初始化配置之前就执行判断是否进入bootloader。
在这里插入图片描述
systemInit函数位于.platformio\packages\framework-arduinoststm32\system\STM32F4xx\system_stm32f4xx.c文件中,修改内容如下。

void jumpToSystemBoot(void)
{
  /* RTC handler declaration */
  RTC_HandleTypeDef RtcHandle;
  RtcHandle.Instance = RTC;
  if (HAL_RTCEx_BKUPRead(&RtcHandle, RTC_BKP_DR0) == 0x1498)
  {
    __HAL_RCC_PWR_CLK_ENABLE();
    HAL_PWR_EnableBkUpAccess();

    __HAL_RCC_RTC_CONFIG(RCC_RTCCLKSOURCE_HSE_DIV2);
    __HAL_RCC_RTC_ENABLE();
    HAL_RTCEx_BKUPWrite(&RtcHandle, RTC_BKP_DR0, 0x0);

    __HAL_RCC_RTC_DISABLE();
    HAL_PWR_DisableBkUpAccess();
    __HAL_RCC_PWR_CLK_DISABLE();
    void (*SysMemBootJump)(void);

    __set_MSP(*(__IO uint32_t *)0x1FFF0000);
    SysMemBootJump = (void (*)(void))(*((uint32_t *)0x1FFF0004));
    SysMemBootJump();
    while (1);
  }
}
/**
  * @brief  Setup the microcontroller system
  *         Initialize the FPU setting, vector table location and External memory
  *         configuration.
  * @param  None
  * @retval None
  */
void SystemInit(void)
{
//将跳转函数放在前面执行,如果需要跳转,则执行跳转
  jumpToSystemBoot();
/* FPU settings ------------------------------------------------------------*/
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
  SCB->CPACR |= ((3UL << 10 * 2) | (3UL << 11 * 2)); /* set CP10 and CP11 Full Access */
#endif
  /* Reset the RCC clock configuration to the default reset state ------------*/
  /* Set HSION bit */
  RCC->CR |= (uint32_t)0x00000001;

  /* Reset CFGR register */
  RCC->CFGR = 0x00000000;

  /* Reset HSEON, CSSON and PLLON bits */
  RCC->CR &= (uint32_t)0xFEF6FFFF;

  /* Reset PLLCFGR register */
  RCC->PLLCFGR = 0x24003010;

  /* Reset HSEBYP bit */
  RCC->CR &= (uint32_t)0xFFFBFFFF;

  /* Disable all interrupts */
  RCC->CIR = 0x00000000;

#if defined(DATA_IN_ExtSRAM) || defined(DATA_IN_ExtSDRAM)
  SystemInit_ExtMemCtl();
#endif /* DATA_IN_ExtSRAM || DATA_IN_ExtSDRAM */

  /* Configure the Vector Table location add offset address ------------------*/
#ifdef VECT_TAB_SRAM
  SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */
#else
  SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */
#endif
}

验证:烧录成功后,手动复位,led灯闪烁;当按钮按下后,led熄灭,即可验证成功执行。此时将控制卡USB连接到电脑,可以看到STM32 DFU驱动已经被识别。(没有驱动的参考安装DfuSe下载软件的使用手册)。

自此,教程完成。

其实不管是Arduino还是CMSIS 或者是 STM32cube,除了调用的函数不一样之外,其实都是一样的操作,因为三种工程都是使用同一个启动文件(startup_stm32f407xx)去执行的。

参考文献

1.《一种从用户代码调用系统存储器中Bootloader 的方法》
2.《STM32通过USB方式烧录程序DFU详解》
3. AN2606 Application Note:《 STM32 microcontroller system memory boot mode》
4. PM0081 Programming manual:《STM32F40xxx and STM32F41xxx Flash programming manual》
5. DfuSE USB Programming Software

利用STM32内置Bootloader实现USB DFU固件升级 当设备进入DFU模式时,它将暂停运行当前固件,然后通过USB接口与主机进行通信。主机通过USB传输固件数据给设备,Bootloader程序接收并将固件数据写入设备的Flash存储器中。完成固件数据的传输和写入后,设备重启,并加载新的固件运行。步骤5:使用DFU工具(如STM32CubeProgrammer或DFU工具箱)将新的固件通过USB接口传输给设备,并触发设备进入DFU模式。通过使用USB接口和内置的Bootloader,开发者可以方便地进行物联网设备的固件升级,提升设备的灵活性和可维护性。 阅读详情

相关推荐

STM32CubeMX学习笔记(50)——USB接口使用(DFU固件升级)_usb dfu

修改参数配置。1024 Bytes0x08005800根据下面编译后 .map 文件大小,可以了解程序存储到了哪些区域。来设置Application程序起始地址,避开Bootloader程序地址范围。打开 map 文件后,查看文件最后部分的区域,可以看到一段以 “” 开头的记录(若找不到可用查找功能定位)Bootloader程序的基地址是 0x08000000,大小为 0x00004a84,可知它占用的最高的地址空间为 0x08004a84。

2501_90424728的博客 4836

STM32 IAP应用开发——通过内置DFU实现USB升级(方式2)

DFU全称为Download Firmware Update,是ST官方推出的一个通过USB接口进行IAP升级的方案,同串口ISP一样,他们都集成在了芯片内部的Bootloader区段,可以通过配置boot引脚来启动。

ShenZhen_zixian的博客 5766

USB DFU固件升级实现流程(基于STM32F407ZG,附源码)

使用 Dfuse 工具,利用 USB 的 DFU 功能实现固件升级,Bootloader分配32KBytes的Flash,剩余分配给Application。代码功能已验证,使用探索者开发板直接烧录即可测试。

Freddy_Ssc的博客 2759

【ARM】STM32内置DFU的使用

所有STM32系列芯片都自带ISP功能,进入ISP的方式就是BOOT0置1,然后上电或复位,这时候芯片从系统存储区启动,进入ISP功能,可以使用串口0进行软件烧写。 STM32F2/3/4系列芯片不仅有传统的UART ISP功能,还有USB ISP功能(拥有USB功能的芯片),工作方式就是使用自带的USB外设,配置成一个USB HID设备,通过HID协议下载软件,速度和串口相比......。从系统存储区启动即可进入USB ISP,然后通过USB接上Windows,无需安装驱动,设备管理器里面出现一个HID

欢迎光临 1万+

如何使用CubeMx生成一个DFU工程

DFU用来做IAP是很方便的,可以直接通过USB来对APP进行升级,因此,掌握DFU的制作还是挺有好处,特别是使用CubeMx工具可以快速制作,本文将基于STM3240G-EVL评估板来一步一步实现一个DFU的IAP工程。

放飞梦想,成就未来 9801

实战指南 | 基于STM32F407 - 利用STM32CubeProgrammer的USB DFU实现无感固件升级

本文详细介绍了基于STM32F407的USB DFU无感固件升级实战指南,涵盖硬件选型、软件配置、工程优化及全流程实现。通过STM32CubeProgrammer工具链,开发者可轻松实现自动触发、无缝切换和断电保护等关键功能,显著提升嵌入式设备的远程维护效率。

weixin_26742753的博客 398

STM32的三种更新固件的方式

记录DFU的下载

weixin_43705900的博客 8313

STM32F407实战:不用Boot引脚,用USB DFU实现一键固件升级(附Keil AC6配置避坑)

本文详细介绍了如何在STM32F407上通过USB DFU模式实现一键固件升级,无需依赖Boot引脚。内容涵盖软件触发DFU的设计原理、Keil AC6配置要点及STM32CubeProgrammer操作指南,帮助开发者解决传统升级方式的痛点,提升产品维护效率。

weixin_33724046的博客 460

STM32 IAP应用开发——通过内置DFU实现USB升级(方式1)

DFU全称为Download Firmware Update,是ST官方推出的一个通过USB接口进行IAP升级的方案,同串口ISP一样,他们都集成在了芯片内部的Bootloader区段,可以通过配置boot引脚来启动。

ShenZhen_zixian的博客 1万+

STM32 USB DFU固件烧录:原理、硬件约束与工程实践

USB DFU(Device Firmware Upgrade)是一种基于USB协议的嵌入式设备固件升级机制,其核心原理是利用芯片内置的只读系统存储器Bootloader接管启动流程,通过标准USB接口实现无需调试器的现场固件更新。该技术依托USB设备类规范,依赖BOOT引脚配置、USB信号完整性及Flash扇区对齐等底层硬件约束,具备零调试器依赖、支持固件校验、便于批量部署等工程价值。在机器人、工业控制器等STM32F4系列量产场景中,DFU已成为安全启动、OTA演进和产线烧录的关键基础能力;本文聚焦ST

weixin_42598278的博客 528

STM32 USB OTG_FS模块应用全面讲解

深入剖析STM32的USB OTG_FS模块工作原理与配置方法,结合实际案例讲解usb通信的实现流程,帮助开发者快速掌握嵌入式系统中usb通信的关键技术与调试技巧。

weixin_42602241的博客 1719

音诺ai翻译机搭载STM32F407与DFU模式进入简化固件升级流程

音诺AI翻译机基于STM32F407实现DFU固件升级,支持USB免驱更新与安全校验,结合Bootloader分区管理、状态机控制及图形化工具,提升维护效率与用户体验。

weixin_29859471的博客 889

【STM32】HAL库USB实现软件升级DFU的功能操作及配置

【STM32】HAL库USB实现软件升级DFU的功能操作及配置

Mike Zhou的博客 2064

【STM32F407开发板用户手册】第29章 STM32F407的系统bootloader之USB DFU方式固件升级

最新教程下载:http://www.armbbs.cn/forum.php?mod=viewthread&tid=93255 第29章 STM32F407的系统bootloader之USB DFU方式固件升级 本章节为大家讲解使用系统bootloader做程序升级的方法,即使不依赖外部boot引脚也可以方便升级。 DFU的全称是Device Firmware Upgrade,即设备固件升级 目录 第29章 STM32F407的系统bootloader之USB DFU...

Simon223的博客 1909

stm32F407USBDFU实验.zip

通过USB 更新stm32f407程序 DFU

STM32DFU操作步骤1

(1)Vendor ID,Product ID,和Version ID需要通过如下小软件进行获取:打开软件后,参数在这里:将其填写到DfuFileMgr里面:(

[记录]使用CubeProgrammer通过USB给stm32f407下载程序后,单片器没有启动的问题解决

使用CubeProgrammer通过usb给stm32芯片的天空星下载程序

weixin_42473339的博客 966

Windows摄像头错误0xA00F4240根因与注册表修复指南

Windows摄像头错误码0xA00F4240常被误判为硬件故障,实则源于UWP应用模型下权限调用链断裂——核心是COM组件调用失败(HRESULT 0x80004003),本质反映Windows Runtime API对注册表策略键值(如CapabilityAccessManager\ConsentStore\webcam)的强依赖。该机制涉及服务状态、DWORD权限配置、ACL继承控制等多层校验,任一环节异常(如ValueLastModified时间戳损坏或ALL APPLICATION PACKAGE

weixin_31742871的博客 386
上一篇: 【marlin学习】STM32 Flash 被锁,如何在PlatformIO中更改外部晶振频率值?
下一篇: 【Raspberry】给树莓派初上手安装(ubuntu mate)系统镜像
Colin Tang
博客等级 码龄8年 1805粉丝 27原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值