hi
基于DFU的W55MH32固件升级解决方案
更新于 2026年1月8日
设备固件更新(DFU)是一项无需物理拆解即可更新嵌入式设备固件的技术。对于W55MH32芯片,DFU支持直接通过USB接口进行可靠的固件恢复和更新。
特性
- 引导加载程序
- 设备从变砖状态恢复
- 具有回滚保护的双存储区闪存
- 用于固件完整性验证的CRC校验
- 编程
- 支持USB DFU类协议
- 可与DFU-util和STM32CubeProgrammer配合使用
- 支持二进制和hex文件格式
- 安全
- 固件签名验证
- 闪存扇区写保护
- 安全启动验证
- 易用性
- 简单的组合按键进入方式
- 兼容工厂编程
- 支持终端用户现场更新
应用领域
- 工业:生产线更新、远程维护、紧急补丁
- 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模式还是跳转到主应用程序。
- 准备DFU项目
1.1. DFU引导逻辑 (main.c)
此代码实现了W55MH32芯片的DFU引导加载程序逻辑。它决定设备是启动进入主应用程序还是进入DFU模式以进行固件更新。
代码首先初始化BOOT按键的GPIO。关键决策点检查BOOT按键是否未按下(低电平有效逻辑,按下=0,未按下≠0)。这是一个关键设计选择——通常在启动时按住按键会强制进入DFU模式。
如果按键未按下,代码会验证在ApplicationAddress(0x8005000)处是否存在有效的用户应用程序。验证会检查该地址的第一个32位值(初始堆栈指针)是否在RAM地址范围(对于Cortex-M为0x20000000-0x20020000)内具有合理值。
如果验证通过,代码执行三个基本操作:
- 从 ApplicationAddress + 4 提取复位处理程序地址
- 从向量表的第一个条目设置主堆栈指针
跳转到应用程序的复位处理程序
如果按键被按下或未检测到有效的应用程序,设备则进入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 0x080050002. 理解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的工具能够访问硬件。
- 启动终端环境:
a. 以管理员权限打开Windows PowerShell
b. 打开一个WSL终端 在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环境。- 通过检查WSL中的USB设备来验证连接:
a.lsusb
* 输出中应包含该设备。
注意: 将 4-4 替换为 usbipd list 命令显示的实际总线ID。有关usbipd的详细文档,请参考此链接


步骤 3:构建并烧录MicroPython
本节详细介绍了通过DFU方法将MicroPython固件编译并编程到W55MH32开发板的过程。在继续之前,请确保所有先前的步骤——包括代码仓库准备、DFU引导加载程序安装、USB设备转发以及成功进入DFU模式——均已成功完成。DFU方法提供了一种适用于生产部署和现场更新的标准化基于USB的编程方式。
- 在WSL终端中依次执行以下命令:
a.cd /home/你的用户名/micropython/ports/w55mh32
* 切换到MicroPython仓库中的W55MH32端口目录。
b.make clean
* 清理构建环境
c.sudo make deploy
* 编译并烧录固件
注意:
- 将
/home/你的用户名 替换为您的MicroPython安装的实际路径。 sudo命令用于授予访问USB DFU设备所需的权限。



DFU构建和编程过程
链接器脚本编译 (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 }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 内容。
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 引导加载程序。
启动顺序 (DFU 引导加载程序代码)
编程完成后,当开发板复位时:
• CPU 从 0x08000000(DFU 引导加载程序)开始执行。
• 引导加载程序检查 BOOT 按键并验证 0x08005000 地址处的应用程序。
• 根据检查结果,要么进入 DFU 模式,要么跳转到应用程序的中断向量表。
步骤 4.1:DFU模式验证
- 连接硬件:
a. 将USB数据线插入USB设备端口 - 进入DFU模式:
a. 按住 USER IO 按键
b. 按下并松开 RESET 按键
c. 松开 USER IO 按键
d. 开发板进入DFU模式 - 使用STM32CubeProgrammer进行软件验证:
a. 启动STM32CubeProgrammer
b. 选择 USB 连接模式
c. 在端口配置中点击 Refresh(刷新)
d. 点击 Connect(连接)按钮 内存验证:
a. 导航到内存视图
b. 搜索地址 0x08005000
c. 验证内存包含有效数据(非零,非0xFF值)

步骤 4.2:串口终端验证
成功安装MicroPython后,通过串口终端访问验证固件功能。
- 打开串口终端
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 接口支持现场升级,同时保障设备可恢复性,显著降低了开发与维护成本,并提升了系统的可靠性与可维护性。