hi

全部例程

基于DFU的W55MH32固件升级解决方案

W55MH32

更新于 2026年1月8日

设备固件更新(DFU)是一项无需物理拆解即可更新嵌入式设备固件的技术。对于W55MH32芯片,DFU支持直接通过USB接口进行可靠的固件恢复和更新。

特性

  1. 引导加载程序
    • 设备从变砖状态恢复
    • 具有回滚保护的双存储区闪存
    • 用于固件完整性验证的CRC校验
  2. 编程
    • 支持USB DFU类协议
    • 可与DFU-util和STM32CubeProgrammer配合使用
    • 支持二进制和hex文件格式
  3. 安全
    • 固件签名验证
    • 闪存扇区写保护
    • 安全启动验证
  4. 易用性
    • 简单的组合按键进入方式
    • 兼容工厂编程
    • 支持终端用户现场更新

应用领域

  • 工业:生产线更新、远程维护、紧急补丁
  • IoT:智能家居设备、传感器网络、边缘计算
  • 消费电子:家用电器、安防设备、医疗设备
  • 开发:快速原型开发、生产编程、现场更新

存储架构设计

在固件升级过程中,我们需要在FLASH存储器中存储多个程序,例如BOOT程序和APP程序。BOOT程序是设备启动时首先运行的程序,主要负责判断是否需要升级APP程序以及后续的跳转操作。APP程序是主要的运行应用程序。

因此,我们需要对FLASH存储器进行分区,通常分为BOOT程序区、APP程序区和APP备份区。

FLASH分区设计

内存布局配置

实现过程(MicroPython环境)

此方法利用USB设备固件更新协议对MicroPython固件进行编程。DFU方法利用专用的USB设备端口,特别适用于生产部署和现场更新,因为它将编程功能与开发接口分离。

所需硬件

  • W55MH32开发板
  • USB Type-C 数据线(用于DAPLink端口和USB设备端口)
  • 启用WSL2的Windows 10/11系统

软件要求

  • Windows:usbipd,设备管理器访问权限
  • WSL:OpenOCD, git, make
  • Keil MDK(用于DFU烧录)

 

步骤 1:使用Keil安装DFU引导加载程序

DFU引导加载程序包含关键决策逻辑,用于决定是停留在DFU模式还是跳转到主应用程序。

  1. 准备DFU项目

1.1.  DFU引导逻辑 (main.c)
此代码实现了W55MH32芯片的DFU引导加载程序逻辑。它决定设备是启动进入主应用程序还是进入DFU模式以进行固件更新。

代码首先初始化BOOT按键的GPIO。关键决策点检查BOOT按键是否按下(低电平有效逻辑,按下=0,未按下≠0)。这是一个关键设计选择——通常在启动时按住按键会强制进入DFU模式。

如果按键未按下,代码会验证在ApplicationAddress(0x8005000)处是否存在有效的用户应用程序。验证会检查该地址的第一个32位值(初始堆栈指针)是否在RAM地址范围(对于Cortex-M为0x20000000-0x20020000)内具有合理值。

如果验证通过,代码执行三个基本操作:

  1. 从 ApplicationAddress + 4 提取复位处理程序地址
  2. 从向量表的第一个条目设置主堆栈指针
  3. 跳转到应用程序的复位处理程序

     

     

    如果按键被按下或未检测到有效的应用程序,设备则进入DFU模式。它为USB通信配置系统,启用USB上拉电阻,并进入一个无限循环,等待来自主机的DFU命令。

     

    
    int main(void)
    {
       DFU_Button_Init();  // Initialize the BOOT button GPIO
        
            /* CRITICAL DECISION POINT: Check if BOOT button is pressed */
       if (DFU_Button_Read() != 0x00) // Button NOT pressed (active-low logic)
       {     
                    /* Test if user code is programmed starting from address 0x8005000 */
           if (((*(__IO uint32_t *)ApplicationAddress) & 0x2FFE0000) == 0x20000000)
           { 
                            /* Jump to user application */
                            // 1. Get the application's reset handler address (ApplicationAddress + 4)
               JumpAddress         = *(__IO uint32_t *)(ApplicationAddress + 4);
               Jump_To_Application = (pFunction)JumpAddress;
                        
               // 2. Set Main Stack Pointer from application's vector table
               __set_MSP(*(__IO uint32_t *)ApplicationAddress);
                        
                            // 3. Jump to the application's reset handler
               Jump_To_Application();
           }
       } /* Otherwise enters DFU mode to allow user to program his application */
       /* Enter DFU mode */
       DeviceState     = STATE_dfuERROR;
       DeviceStatus[0] = STATUS_ERRFIRMWARE;
       DeviceStatus[4] = DeviceState;
            // Initialize system for USB DFU
       Set_System();
       Set_USBClock();
       USB_Init();
       DP_PUUP = 1;// Enable USB pull-up
            
       while (1)
       {
       }
    }

1.2. DFU按键配置 (hw_config.c)
函数: DFU_Button_Init(void)
目的: 配置用于进入DFU模式的硬件按键
具体设置:

按键引脚: GPIO端口G,引脚6 (GPIOG_Pin_6)

模式: 带上拉电阻的输入模式 (GPIO_Mode_IPU)

有效状态: 按键按下 = 低电平(0),未按下 = 高电平(1)
启动行为:

按键按下(低电平) → 强制进入DFU模式

按键未按下(高电平) → 尝试启动应用程序
 

void DFU_Button_Init(void)
{
   GPIO_InitTypeDef GPIO_InitStruct;
   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOG, ENABLE);
   GPIO_StructInit(&GPIO_InitStruct);
   GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;
   GPIO_InitStruct.GPIO_Pin  = GPIO_Pin_6;
   GPIO_Init(GPIOG, &GPIO_InitStruct);
}

1.3. 应用程序地址配置(hw-config.h)

目的: 定义用户应用程序在闪存中的起始地址

/* Flash memory address from where user application will be loaded */
#define ApplicationAddress 0x08005000

2. 理解DFU引导加载程序代码
让我们来查看决定是跳转到主应用程序还是停留在DFU模式的关键DFU引导加载程序代码:
a. 使用Keil进行DFU烧录
b. 打开Keil MDK
c. 加载W55MH32的DFU项目
d. 通过DAPLink端口连接开发板
e. 编译并烧录DFU引导加载程序

 

3.验证DFU安装
a. 按住BOOT按键的同时复位开发板
b. 设备在Windows中应枚举为DFU设备
c. 确认出现"WIZ DFU"设备

 

步骤 2:USB设备转发到WSL

此过程将开发板的USB编程接口从Windows转发到WSL环境,使基于Linux的工具能够访问硬件。

  1. 启动终端环境:
    a. 以管理员权限打开Windows PowerShell
    b. 打开一个WSL终端
  2. 在Windows PowerShell中按顺序执行以下命令:
    a. usbipd list
    * 识别对应W55MH32设备的USB端口。将显示总线ID(例如:4-4)。
    b. usbipd bind --busid 4-4
    * 此命令绑定指定的USB设备以用于WSL共享。
    c. usbipd attach --wsl --busid 4-4
    * 此命令将绑定的USB设备附加到WSL环境。

     

  3. 通过检查WSL中的USB设备来验证连接:
    a. lsusb
    * 输出中应包含该设备。


注意: 将 4-4 替换为 usbipd list 命令显示的实际总线ID。有关usbipd的详细文档,请参考此链接

 

 

 

步骤 3:构建并烧录MicroPython

本节详细介绍了通过DFU方法将MicroPython固件编译并编程到W55MH32开发板的过程。在继续之前,请确保所有先前的步骤——包括代码仓库准备、DFU引导加载程序安装、USB设备转发以及成功进入DFU模式——均已成功完成。DFU方法提供了一种适用于生产部署和现场更新的标准化基于USB的编程方式。

  1. 在WSL终端中依次执行以下命令:
    a. cd /home/你的用户名/micropython/ports/w55mh32
    * 切换到MicroPython仓库中的W55MH32端口目录。
    b. make clean
    * 清理构建环境
    c. sudo make deploy
    * 编译并烧录固件

注意:

  1.  /home/你的用户名 替换为您的MicroPython安装的实际路径。
  2. sudo 命令用于授予访问USB DFU设备所需的权限。

 

DFU构建和编程过程

  1. 链接器脚本编译 (w55mh32.ld)
    W55MH32 链接器脚本将这些指令组织到特定的内存区域,将中断向量表放置在地址 0x08005000 处,并为 DFU 引导加载程序预留前 20KB 空间(0x08000000 至 0x08005000)。

    MEMORY
    {
       FLASH (rx)          : ORIGIN = 0x08000000, LENGTH = 1024K /* entire flash */
       FLASH_ISR (rx)      : ORIGIN = 0x08005000, LENGTH = 16K /* sector 0 */
       FLASH_FS (rx)       : ORIGIN = 0x08004000, LENGTH = 0K /* sectors 1,2,3 are 16K */
       FLASH_FIRMWARE (rx) : ORIGIN = 0x08010000, LENGTH = 972K /* sector 4 is 64K, sectors 5,6,7 are 128K */
       RAM (xrw)           : ORIGIN = 0x20000000, LENGTH = 96K
    }

     

  2. DFU 文件创建 (Makefile)
    使用 DFU 工具,配合正确的偏移量,将 firmware.bin 文件转换为 DFU 格式文件。

     

     

    $(BUILD)/firmware.dfu: $(BUILD)/firmware.bin
        $(ECHO) "Create $@"
        $(Q)$(PYTHON) $(DFU) -b 0x08005000:$(BUILD)/firmware.bin $@

     

    此命令创建的 DFU 文件会指示编程器从地址 0x08005000 开始写入 firmware.bin 内容。

     

  3. DFU  编程 (Makefile)
    执行 make deploy 时,DFU-util 通过 USB 将固件编程到 MCU:

     

    deploy: $(BUILD)/firmware.dfu
        $(ECHO) "Writing $< to the board"
        dfu-util -a 0 -D $(BUILD)/firmware.dfu -R

    固件从 0x08005000 地址开始编程,从而保留闪存前 20KB 中的 DFU 引导加载程序。

  4. 启动顺序 (DFU 引导加载程序代码)
    编程完成后,当开发板复位时:
    • CPU 从 0x08000000(DFU 引导加载程序)开始执行。
    • 引导加载程序检查 BOOT 按键并验证 0x08005000 地址处的应用程序。
    • 根据检查结果,要么进入 DFU 模式,要么跳转到应用程序的中断向量表。

     

     

步骤 4.1:DFU模式验证

  1. 连接硬件:
    a. 将USB数据线插入USB设备端口
  2. 进入DFU模式:
    a. 按住 USER IO 按键
    b. 按下并松开 RESET 按键
    c. 松开 USER IO 按键
    d. 开发板进入DFU模式
  3. 使用STM32CubeProgrammer进行软件验证:
    a. 启动STM32CubeProgrammer
    b. 选择 USB 连接模式
    c. 在端口配置中点击 Refresh(刷新)
    d. 点击 Connect(连接)按钮
  4. 内存验证:
    a. 导航到内存视图
    b. 搜索地址 0x08005000
    c. 验证内存包含有效数据(非零,非0xFF值)
     

步骤 4.2:串口终端验证

成功安装MicroPython后,通过串口终端访问验证固件功能。

  1. 打开串口终端
    a. 启动串口终端应用程序(如Tera Term、PuTTY等)
    b. 配置连接设置:
    i. 波特率:115200
    ii. 数据位:8
    iii. 校验位:无
    iv. 停止位:1
    v. 流控制:无
    c. 选择对应开发板UART接口的正确COM端口
    d. 按下W55MH32开发板上的 RESET 按键
    e. 这将触发MicroPython固件重启并显示REPL界面

 

总结

此 DFU 解决方案为 W55MH32 平台提供了可靠的固件恢复与更新能力。它通过 USB 接口支持现场升级,同时保障设备可恢复性,显著降低了开发与维护成本,并提升了系统的可靠性与可维护性。

下载本章例程

我们提供完整的工程文件以及配套开发板,方便你随时测试,快速完成产品开发:

开发环境: Keil MDK5 配套开发板