全部例程

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

W55MH32

更新于 2026年9月17日

本篇总结

使用 USB DFU 实现 W55MH32 固件升级全流程,配套 KEIL 工程:DFU 引导加载程序(BOOT,按键 PG6)+ SysTick 测试 APP,支持现场反复升级。

🔑 KEIL MDK、UART调试、USB、DFU、dfu-util

硬件平台:本例程基于 W55MH32L-EVB 开发板运行。

采购推荐:点击前往 WIZnet 官方淘宝店铺 选购 W55MH32L-EVB

本示例演示 W55MH32 通过 USB DFU 实现固件升级的全流程。
DFU 支持直接通过 USB 接口进行可靠的固件恢复和更新,将 FLASH 分为 BOOT 引导区和 APP 应用区,引导程序根据按键状态和应用程序有效性决定进入 DFU 模式或跳转执行用户程序。
方案配套两份 KEIL 例程:BOOT 引导加载程序(USB DFU 设备)与 SysTick 测试 APP(延时/时钟打印),编译、烧录、升级、验证全部在 Windows 下完成。

前置工具准备

开始本例程前,请确认以下工具已安装:

  • WIZ UartTool V1.0:串口调试工具,用于查看 APP 运行输出:点击下载
  • Zadig:WinUSB 驱动安装工具,首次使用需为 DFU 设备安装驱动:点击下载

硬件连接

W55MH32 开发板提供两个 USB 端口:DAPLink 调试端口用于 KEIL 烧录引导程序,USB Device 端口用于 DFU 固件升级。开发板自带的按键(丝印 KEY:PG6)用于强制进入 DFU 模式。

接口/引脚功能说明
DAPLink USB调试/烧录口通过 KEIL 烧录 DFU 引导加载程序
USB DeviceDFU 设备端口固件升级时使用,连接主机 USB
KEY:PG6(板载按键)BOOT 按键按下时强制进入 DFU 模式(低电平有效)
RESET复位按键配合 KEY:PG6 进入 DFU 模式

DFU 特性与应用领域

特性类别功能说明
引导恢复从变砖状态恢复,APP 无效时自动进入 DFU 等待升级
编程支持USB DFU 类协议,兼容 dfu-util,支持 bin 固件格式
易用性组合按键进入 DFU,兼容工厂编程,支持终端用户现场更新

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

FLASH 存储架构设计

固件升级需要在 FLASH 中存储多个程序:BOOT 程序负责判断是否升级及跳转,APP 程序是主应用程序。因此需要对 FLASH 进行分区。

分区起始地址大小用途
BOOT0x0800000020KBDFU 引导加载程序
APP0x080050001004KB用户应用程序(APP)
RAM0x2000000096KB运行时内存

分区关键点

前 20KB(0x08000000~0x08005000)预留给 DFU 引导加载程序,APP 必须以 0x08005000 开始编译。KEIL 工程内存窗口中 APP 的 IROM 起始地址必须与此地址一致,同时 APP 启动时需将中断向量表重定位到 0x08005000。

步骤1:编译并烧录 DFU 引导加载程序(BOOT)

配套 KEIL 工程 Device_Firmware_Upgrade_BOOTDFU 引导加载程序包含关键决策逻辑,决定设备启动进入主应用程序还是 DFU 模式。以下三段代码构成引导加载程序的核心。

1.1 DFU 引导逻辑 (main.c)

代码首先初始化 BOOT 按键 GPIO,检查按键是否未按下(低电平有效)。若未按下,验证 ApplicationAddress(0x08005000)处是否存在有效应用程序——检查该地址第一个 32 位值(初始堆栈指针)是否在 RAM 范围(0x20000000~0x20020000)内。验证通过则提取复位向量并跳转;否则进入 DFU 模式等待主机命令。

int main(void)
{
    DFU_Button_Init();  // 初始化 BOOT 按键 GPIO

    /* 关键决策点:检查 BOOT 按键是否按下 */
    if (DFU_Button_Read() != 0x00) // 按键未按下(低电平有效)
    {
        /* 验证 0x08005000 处是否存在有效用户程序 */
        if (((*(__IO uint32_t *)ApplicationAddress) & 0x2FFE0000) == 0x20000000)
        {
            /* 跳转到用户应用程序 */
            // 1. 获取应用复位向量地址 (ApplicationAddress + 4)
            JumpAddress         = *(__IO uint32_t *)(ApplicationAddress + 4);
            Jump_To_Application = (pFunction)JumpAddress;

            // 2. 从向量表设置主堆栈指针
            __set_MSP(*(__IO uint32_t *)ApplicationAddress);

            // 3. 跳转到应用程序复位向量
            Jump_To_Application();
        }
    } /* 否则进入 DFU 模式 */

    /* 进入 DFU 模式 */
    DeviceState     = STATE_dfuERROR;
    DeviceStatus[0] = STATUS_ERRFIRMWARE;
    DeviceStatus[4] = DeviceState;

    // 初始化 USB DFU 系统
    Set_System();
    Set_USBClock();
    USB_Init();
    DP_PUUP = 1;  // 使能 USB 上拉

    while (1)
    {
    }
}

堆栈指针验证原理

&0x2FFE0000 掩码检查 SP 高 3 位是否为 0x200,即 SP 落在 0x20000000~0x2001FFFF 范围内。W55MH32 RAM 共 96KB(0x20000000~0x20018000),此范围内即为合法堆栈指针。若 FLASH 未编程,值为 0xFFFFFFFF,掩码结果为 0x20000000≠0x20000000,校验不通过。

1.2 DFU 按键配置 (hw_config.c)

配置 GPIOG 引脚 6(PG6)为上拉输入模式。按键按下 = 低电平(0)→ 强制进入 DFU 模式;按键未按下 = 高电平(1)→ 尝试启动应用程序。

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;     // PG6
    GPIO_Init(GPIOG, &GPIO_InitStruct);
}

uint8_t DFU_Button_Read(void)
{
    return GPIO_ReadInputDataBit(GPIOG, GPIO_Pin_6);
}

1.3 应用程序地址配置 (hw_config.h)

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

1.4 烧录 BOOT

打开 KEIL MDK → 加载 Device_Firmware_Upgrade_BOOT 工程 → 选择调试器 CMSIS-DAP → 编译 → F8 下载(写入 0x08000000 起始的 BOOT 区)。烧录完成后验证:按住 KEY:PG6 同时复位,设备应枚举为 "WIZ DFU" 设备。

步骤2:编译测试 APP

配套 KEIL 工程 SysTick_Test_App,基于 W55MH32 SysTick 系统定时器例程:USART1 打印系统时钟,循环进行中断方式与轮询方式延时测试。该工程已按 DFU 分区完成适配。

2.1 链接地址配置 (SysTick.uvprojx 内存窗口)

APP 的 IROM 起始地址必须偏移到 0x08005000,大小 0xFB000(1004KB),避开前 20KB BOOT 区:

<!-- 内存窗口:IROM 从 0x08005000 开始,大小 0xFB000 -->
<IROM>
  <StartAddress>0x08005000</StartAddress>
  <Size>0xFB000</Size>
</IROM>

2.2 中断向量表重定位 (main.c)

APP 启动早期必须重定位中断向量表,否则任何中断(SysTick/UART 等)都会去 0x08000000(BOOT 区)取向量导致跑飞。本工程采用双保险:SystemInit 中 VECT_TAB_OFFSET=0x5000 + main 首行显式设置:

/* system_w55mh32.c:SystemInit 中 VECT_TAB_OFFSET */
#define VECT_TAB_OFFSET  0x5000   /* 0x08005000 - 0x08000000 */

/* main.c:main 函数首行显式重定位(双保险) */
int main(void)
{
    SCB->VTOR = 0x08005000;  /* 重定位中断向量表到 APP 区 */
    ...
}

2.3 编译 APP

KEIL 中编译工程,生成 SysTick.bin,烧录地址从 0x08005000 开始。编译后可用文本编辑器打开 SysTick.hex 首行确认地址记录为 0x08005000。

APP 适配必要条件

任意自研 APP 接入本 DFU 方案,必须满足 4 个条件:① 链接地址偏移 0x08005000;② 启动早期 SCB->VTOR = 0x08005000;③ 0x08005000 首字为合法 SP(0x20000000~0x2001FFFF 范围);④ 烧录地址一致(dfu-util 用 -s 0x08005000 指定)。

步骤3:安装驱动并烧录 APP

3.1 进入 DFU 模式

  • 按住开发板按键 KEY:PG6 → 按下并松开 RESET 按键 → 松开 KEY:PG6 → 开发板进入 DFU 模式
  • 设备管理器应出现 "WIZ DFU" 设备(VID 0483 / PID DF11)
设备管理器-通用串行总线设备-WIZ DFU

3.2 安装 WinUSB 驱动(首次必需)

Windows 默认不识别 DFU 设备,需用 Zadig 安装 WinUSB 驱动:

  • 首先,按住开发板按键 KEY:PG6 → 按下并松开 RESET 按键 → 松开 KEY:PG6 → 开发板进入 DFU 模式
  • 运行 Zadig 默认自动识别WIZ DFU
  • 若未识别,则运行 Zadig → 菜单 Options → 勾选 List All Devices
  • 下拉框选择 WIZ DFU(USB ID 显示 0483 DF11)
  • 确认目标驱动为 WinUSB (v6.1.7600.16385) → 点击 Install Driver
首次使用未安装驱动
打开Zadig-WIZ DFU
安装完毕

3.3 验证设备并烧录 APP

烧录 APP 使用命令行工具 dfu-util 完成。命令由固定参数与 APP 固件路径组成,下面按步骤说明路径与命令的对应关系。

① 打开命令提示符

按 Win 键 → 输入 cmd → 回车(或按 Win+R,输入 cmd 后回车),打开命令提示符窗口。

② 确认 DFU 设备可见

dfu-util -l

输出中出现 0483:df11 即设备已就绪。若主机存在多个 DFU 设备(如带 DFU 接口的摄像头),烧录命令中必须加 -d 0483:df11 指定目标设备,避免误烧。

③ 执行烧录命令

命令格式如下,将 -D 后双引号内的路径替换为你电脑上 SysTick.bin 的实际路径:

dfu-util -d 0483:df11 -a 0 -s 0x08005000:leave -D "SysTick.bin 的完整路径"

示例:APP 例程解压到 D:\W55MH32_DFU_APP_SysTick,bin 文件位于 ModuleDemo\SysTick\USER\Bin\SysTick.bin,则完整命令为:

dfu-util -d 0483:df11 -a 0 -s 0x08005000:leave -D "D:\W55MH32_DFU_APP_SysTick\ModuleDemo\SysTick\USER\Bin\SysTick.bin"

也可以先用 cd 命令进入 bin 所在目录,再直接写文件名(路径不含中文时更稳妥):

cd /d D:\W55MH32_DFU_APP_SysTick\ModuleDemo\SysTick\USER\Bin
dfu-util -d 0483:df11 -a 0 -s 0x08005000:leave -D SysTick.bin

命令无法识别的处理

若执行时报 'dfu-util' 不是内部或外部命令,说明 dfu-util 未加入系统 PATH 环境变量(见前置工具准备)。此时改用 dfu-util.exe 完整路径调用,命令参数不变,仅将开头的 dfu-util 替换为解压目录下的完整路径:

"C:\dfu-util-0.11-win64\dfu-util.exe" -d 0483:df11 -a 0 -s 0x08005000:leave -D "D:\W55MH32_DFU_APP_SysTick\ModuleDemo\SysTick\USER\Bin\SysTick.bin"

将双引号内的路径替换为实际解压目录与 bin 文件路径即可。建议按前置工具准备完成 PATH 配置,之后直接使用简洁命令。

dfu-util 输出 "File downloaded successfully" 即烧录成功,开发板自动复位并跳转运行 APP。

命令参数说明:

参数含义
-d 0483:df11指定烧录目标设备(防止多设备误烧)
-a 0选择内部 Flash 接口
-s 0x08005000:leave从 0x08005000 开始写入(保护前 20KB BOOT 区),烧录完成后自动跳转运行
-D 文件路径指定要烧录的固件文件(SysTick.bin 的路径)

步骤4:验证固件

4.1 DFU 模式验证

  • 按住开发板按键 KEY:PG6 → 按下并松开 RESET 按键 → 松开 KEY:PG6 → 开发板进入 DFU 模式
  • 运行 dfu-util -l 确认枚举 "STM Device in DFU Mode"(0483:df11)

4.2 WIZ UartTool 验证

烧录完成后复位开发板,BOOT 检测按键未按下且 APP 有效,跳转执行 SysTick 测试 APP。打开 WIZ UartTool V1.0,选择开发板对应 COM 口验证输出:

参数值
波特率115200
数据位8
校验位无
停止位1
流控制无

选择对应 COM 端口(USART1:PA9 发送 / PA10 接收),波特率 115200,按下 RESET 按键,应看到系统时钟打印及 SysTick 延时循环输出:

SYSCLK: 72.0Mhz, HCLK: 72.0Mhz, PCLK1: 36.0Mhz, PCLK2: 72.0Mhz, ADCCLK: 36.0Mhz
SysTick Delay Test.
[0] interrupt delay 1s ...
[1] polling delay 500ms ...
[2] interrupt delay 1s ...
[3] polling delay 500ms ...
...

4.3 再次升级验证(核心闭环)

APP 运行中,随时可再次升级:按住 PG6 → 复位 → 松开 → 重新进入 DFU 模式 → 重新执行 dfu-util 烧录命令。BOOT 引导程序永久驻留 0x08000000~0x08005000,升级只擦写 APP 区,BOOT 不会被覆盖。

擦除与烧录
SysTick.bin 运行

常见问题

Q: 设备未枚举为 "WIZ DFU"

确认引导加载程序已正确烧录到 0x08000000。按住板载按键 KEY:PG6 后按 RESET 进入 DFU,检查设备管理器是否出现 DFU 设备。若未出现,可能 BOOT 程序未烧录或 USB Device 线连接到错误端口。

Q: dfu-util 报 "No DFU capable USB device" / "More than one DFU capable USB device"

设备未进入 DFU 模式,或主机存在多个 DFU 设备(如带 DFU 接口的摄像头)。先按住 PG6 复位进入 DFU,再用 dfu-util -l 查看;多设备时使用 -d 0483:df11 指定目标。

Q: 跳转到 APP 后立即 HardFault

APP 的中断向量表起始地址与 ApplicationAddress(0x08005000) 不一致。检查 KEIL 内存窗口 IROM 起始地址是否为 0x08005000,并在 APP 启动早期调用 SCB->VTOR = 0x08005000 重定位向量表。

Q: 烧录 APP 成功后,设备管理器仍显示 "WIZ DFU"

这是正常现象。BOOT 引导程序跳转 APP 时未关闭 USB 外设,设备管理器会残留一个 "WIZ DFU" 空壳设备,不影响 APP 运行。拔掉 USB 线重新插入,或再次复位开发板后该残留设备即消失。若希望彻底避免,可在 APP 代码中调用 USB_DeInit() 关闭 USB 外设。

Q: 按住 PG6 复位后仍然运行 APP

BOOT 未读到按键按下。确认 BOOT 工程 hw_config.c 中按键配置为 GPIOG GPIO_Pin_6(PG6)且已重新编译烧录;用万用表量 PG6 引脚,按下时应为低电平。

Q: dfu-util 烧录失败(驱动问题)

DFU 设备需要 WinUSB 驱动。用 Zadig 重新安装:Options → List All Devices → 选择 STM Device in DFU Mode → Replace Driver 为 WinUSB,然后重试烧录。

Q: 堆栈指针验证始终不通过

APP 未烧录或烧录地址错误。检查 0x08005000 处第一个 32 位值是否为合法 SP(0x2000xxxx)。若为 0xFFFFFFFF 说明 APP 未编程;KEIL 内存窗口 IROM 起始地址不对会导致向量表写入错误位置。

总结

本 DFU 解决方案为 W55MH32 平台提供了可靠的固件恢复与更新能力:

  • FLASH 分区:前 20KB 留给 BOOT 引导加载程序,APP 以 0x08005000 开始,KEIL 内存窗口与地址宏必须一致
  • 引导决策:检查 PG6 按键 + 验证 SP 合法性(&0x2FFE0000 == 0x20000000),通过则跳转 APP,否则进入 DFU
  • 跳转三步:提取复位向量 → 设置 MSP → 调用函数指针跳转,APP 需在 SystemInit 中设置 VTOR
  • Windows 直烧:Zadig 安装 WinUSB 驱动后,dfu-util 从 0x08005000 开始编程
  • 双重验证:dfu-util 烧录结果 + WIZ UartTool 115200 连接确认 APP 运行,支持现场反复升级

下载本章例程

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

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

Administrator

Wiznet 雇员