DFU RUNTIME和DFU MODE的区别
2026-10-23
本文链接为:http://www.usbzh.com/article/detail-1815.html ,欢迎转载,转载请附上本文链接。
DFU 实现原理
dfu 功能分为两个模式: runtime 模式与 dfu 模式
- runtime 模式: 正常工作状态,此时需要host设备发送detach命令使设备转换成dfu模式
- dfu 模式 : 升级状态,host设备可以读写相应分区的数据来升级设备
二者通过 DETACH + 复位/跳转衔接,构成完整的 USB 固件升级链路。
dfu 具体工作流程如下:
- host设备给device设备发送准备升级固件命令
- device 在接收到命令时会卸载所有已经加载的驱动,并切换到DFU 模式
- host 给device发起usb reset
- device 发送DFU 模式下的描述符,进行重新枚举识别
- host 给设备发送需要升级的固件
- host 收到设备端数据处理成功的信息,给device发送转换模式的命令
- device 重新切换到 runtime 模式
- host 发起usb reset,并重新识别device设备
DFU模式与runtime模式的客制化流程:
- device 正常启动到linux,配置相关的usb device驱动使设备处于runtime模式
- 当用户需要升级firmware时,需要通过host端软件发送runtime模式detach命令(DFU-util -e)
- 当device 接收到detach命令,会通过fw_setenv工具配置uboot环境变量enter_dfu_mode为1,并重启
- device 重启进入uboot过程中会读取enter_dfu_mode变量的值,当为1时,执行相应的dfu命令(例dfu 0 ram 0)
进入dfu模式并等待升级 - 用户通过DFU-util工具发送firmware 到对应配置分区
- device 收到数据包并写入相应配置分区
- 当升级完毕,用户使用DFU-util工具重启device
- device 收到重启命令,配置环境变量enter_dfu_mode为0,并重启进入linux,配置模式为runtime
用户配置dfu流程: - 编译生成fw_setenv,以便支持linux下配置uboot环境变量
i. 使用uboot编译生成fw_setenv,并拷贝到linux 文件系统中的/etc目录
make env; ln -sf fw_printenv fw_setenv
ii. 配置fw_env.config,并拷贝到linux 文件系统中/etc目录 - linux的配置以支持usbcam以及dfu
- uboot的配置以支持dfu功能
- 设置uboot环境变量
i. 分区表变量 dfu_alt_info
ii. 缓存大小配置 dfu_bufsiz
| 维度 | DFU Runtime | DFU Mode |
|---|---|---|
| 协议号 | DFU_PROTOCOL_RT (0x01) | DFU_PROTOCOL_DFU (0x02) |
| 描述符 | 单接口,固定 18 字节(9+9) | 多 alternate setting 接口(每个 alt = 一个分区,如 Flash/EEPROM) |
| 状态机 | 无(始终报告 APP_IDLE) | 完整 11 状态(IDLE→DNLOAD→DNBUSY→MANIFEST→…) |
| 支持的请求 | 仅 DETACH、GETSTATUS(+SET_INTERFACE) | 全量 DETACH/DNLOAD/UPLOAD/GETSTATUS/CLRSTATUS/GETSTATE/ABORT |
| 功能定位 | 正常运行阶段,引导切入 DFU Mode | 下载模式,真正收发固件 |
描述符结构不同
- TDFU Runtime 只有 1 个接口,后面跟 1 个功能描述符。
- DFU Mode 用
_TUD_DFU_ALT_1 ... _TUD_DFU_ALT_8宏展开出多个 alternate setting(最多 8 个),每个 alt 对应一个可升级分区。
一、DFU Runtime —— 部署在「正常运行的应用固件」里
部署位置
Runtime 接口跟着应用固件一起烧进去,是设备每天正常工作的那段代码里附带的一个”小尾巴”。它只占极小开销(一个接口描述符 + 极简的请求处理),不影响应用正常运行。
作用场景
当设备正在正常跑业务(比如鼠标在移动、U 盘在读数据、传感器在采集)时,它对外暴露 Runtime 接口,向主机宣告:”我支持固件升级,随时可以把我切进升级模式“。
典型例子
- 一个正常工作的键盘/鼠标/传感器设备,其应用固件里带 Runtime 接口。
- 主机运行
dfu-util -l时,能列出设备处于Runtime状态。 - 用户想升级时,执行
dfu-util -e发 DETACH,Runtime 触发tud_dfu_runtime_reboot_to_dfu_cb(),应用复位并跳到 bootloader。
关键点:应用固件本身不参与烧写,它只负责”听到命令 → 跳转”。
二、DFU Mode —— 部署在「Bootloader(引导加载程序)」里
部署位置
DFU Mode 接口烧在 Bootloader 里,这是一段独立的、通常常驻在 Flash 起始地址或专用区域的小程序。设备复位/跳转后,由 Bootloader 接管,此时对外暴露的是 DFU Mode 接口。
作用场景
设备进入 Bootloader 后,应用已不在运行,Bootloader 专门负责”接收新固件 → 擦写 Flash → 校验 → 跳转到新固件”。这是真正的升级执行阶段。
典型例子
- 设备复位后 Bootloader 启动,主机用
dfu-util -d cafe -a 0 -D new_firmware.bin下发新固件。 - Bootloader 的
tud_dfu_download_cb()把数据块逐块写入 Flash,tud_dfu_manifest_cb()做校验,最后复位运行新固件。
关键点:Bootloader 专注升级,不跑业务。
三、两者的衔接关系(完整升级流程)
┌─────────────────────────────────────────────────────────────┐
│ 同一颗 MCU │
│ │
│ ┌───────────────┐ DETACH ┌───────────────────────┐ │
│ │ 应用固件 │ ─────────▶ │ Bootloader │ │
│ │ (正常运行) │ 复位/跳转 │ (升级模式) │ │
│ │ │ │ │ │
│ │ DFU Runtime │ │ DFU Mode │ │
│ │ 接口 (0x01) │ │ 接口 (0x02) │ │
│ │ 只负责引导 │ │ 完整状态机 + 收发固件 │ │
│ └───────────────┘ └───────────┬────────────┘ │
│ ▲ │ 烧写完成复位 │
│ └────────── 运行新固件 ◀────────────┘ │
└─────────────────────────────────────────────────────────────┘
- 设备正常跑 应用固件(带 Runtime)。
- 主机发 DETACH,Runtime 回调触发复位/跳转。
- Bootloader 接管,暴露 DFU Mode。
- 主机下发新固件,Bootloader 烧写。
- 烧写完成,复位运行新的应用固件(新固件里依然带 Runtime,循环往复)。
四、应用场景对照表
| 场景 | 用的是 | 部署在哪 | 谁在跑 |
|---|---|---|---|
| 设备正常工作、等待升级指令 | Runtime | 应用固件 | 应用 |
| 实际接收/写入新固件 | DFU Mode | Bootloader | Bootloader |
| 只想”宣布可升级”、不写 Flash | Runtime | 应用固件 | 应用 |
| 需要多分区(Flash+EEPROM)分别升级 | DFU Mode(多 alt) | Bootloader | Bootloader |
| 只想读回固件(备份/校验) | DFU Mode(UPLOAD) |
Bootloader | Bootloader |
五、特殊情况:两者也能”物理上在一起”
虽然典型做法是分开放(应用=Runtime,Bootloader=DFU Mode),但规范也允许两者共存于同一配置:
- 某些设备在应用固件里同时声明 Runtime 接口和 DFU Mode 接口(不同接口号),主机通过
SET_INTERFACE或选接口切换,无需复位。 - 这种做法的好处是”不跳 Bootloader 也能升级”,但代价是应用固件要自己实现 Flash 烧写逻辑(即上一轮说的
download_cb/manifest_cb那一堆),且升级期间应用自身还在内存里,有一定风险(比如自毁正在运行的程序)。
因此工程上更主流、更安全的是分开部署:应用固件只带 Runtime,Bootloader 专门带 DFU Mode。
一句话总结
- DFU Runtime → 应用固件:设备的”门铃”,负责把主机引导到升级流程。
- DFU Mode → Bootloader:设备的”施工队”,负责真正接收并烧写新固件。
HID人机交互QQ群:564808376
UAC音频QQ群:218581009
UVC相机QQ群:331552032
BOT&UASP大容量存储QQ群:258159197
STC-USB单片机QQ群:315457461
USB技术交流QQ群2:580684376
USB技术交流QQ群:952873936 USB技术交流3:1031974172
DFU





