DFU GetStatus
2026-10-23
本文链接为:http://www.usbzh.com/article/detail-1819.html ,欢迎转载,转载请附上本文链接。
GetStatus是DFU的类请求
CTL a1 03 0000 0000 0006 get status
6 IN 00 01 00 00 04 00 ......
CTL a1 03 0000 0000 0006 get status
6 IN 00 00 00 00 05 00 ......
一、结构体定义
typedef struct TU_ATTR_PACKED
{
uint8_t bStatus; // 字节 0
uint8_t bwPollTimeout[3]; // 字节 1~3
uint8_t bState; // 字节 4
uint8_t iString; // 字节 5
} dfu_status_response_t;
TU_VERIFY_STATIC( sizeof(dfu_status_response_t) == 6, "size is not correct");
TU_ATTR_PACKED 保证结构体紧凑排列无填充,总共 6 字节。TU_VERIFY_STATIC 是编译期静态断言,确保大小严格等于 6。
二、逐字节含义
| 字节偏移 | 字段 | 类型 | 含义 |
|---|---|---|---|
| 0 | bStatus |
uint8 | 状态码(成功/错误类型) |
| 1~3 | bwPollTimeout[3] |
3 字节小端 | 主机在下一次 GETSTATUS 前需等待的毫秒数 |
| 4 | bState |
uint8 | 设备当前/即将进入的状态 |
| 5 | iString |
uint8 | 附加状态描述字符串索引(0=无) |
三、各字段详解
1. bStatus(状态码)
| 值 | 枚举 | 含义 |
|---|---|---|
| 0x00 | DFU_STATUS_OK |
成功 |
| 0x01 | DFU_STATUS_ERR_TARGET |
目标错误 |
| 0x02 | DFU_STATUS_ERR_FILE |
文件错误 |
| 0x03 | DFU_STATUS_ERR_WRITE |
写入错误 |
| 0x04 | DFU_STATUS_ERR_ERASE |
擦除错误 |
| 0x05 | DFU_STATUS_ERR_CHECK_ERASED |
擦除校验错误 |
| 0x06 | DFU_STATUS_ERR_PROG |
编程错误 |
| 0x07 | DFU_STATUS_ERR_VERIFY |
校验错误 |
| 0x08 | DFU_STATUS_ERR_ADDRESS |
地址错误 |
| 0x09 | DFU_STATUS_ERR_NOTDONE |
未完成 |
| 0x0A | DFU_STATUS_ERR_FIRMWARE |
固件错误 |
| 0x0B | DFU_STATUS_ERR_VENDOR |
厂商自定义错误 |
| 0x0C | DFU_STATUS_ERR_USBR |
USB 复位 |
| 0x0D | DFU_STATUS_ERR_POR |
上电复位 |
| 0x0E | DFU_STATUS_ERR_UNKNOWN |
未知错误 |
| 0x0F | DFU_STATUS_ERR_STALLEDPKT |
数据包被 stall |
2. bwPollTimeout(3 字节,小端)—— 等待时间
这是主机轮询节奏控制的核心字段。含义:主机应在 bwPollTimeout 毫秒之后再发下一个 GETSTATUS。
resp.bwPollTimeout[0] = TU_U32_BYTE0(timeout); // 低字节
resp.bwPollTimeout[1] = TU_U32_BYTE1(timeout); // 中字节
resp.bwPollTimeout[2] = TU_U32_BYTE2(timeout); // 高字节
例:timeout = 100 毫秒 → 字节为 0x64, 0x00, 0x00。
取值来源:
- 下载/Manifest 忙时:来自
tud_dfu_get_timeout_cb()(应用决定,如 Flash 1ms、EEPROM 100ms)。 - 空闲/非忙状态:
timeout = 0(主机无需等待,立即轮询)。
3. bState(状态)
| 值 | 枚举 | 含义 |
|---|---|---|
| 0 | APP_IDLE |
应用空闲(Runtime 态) |
| 1 | APP_DETACH |
应用脱离 |
| 2 | DFU_IDLE |
DFU 空闲,可接收 |
| 3 | DFU_DNLOAD_SYNC |
下载同步中 |
| 4 | DFU_DNBUSY |
下载忙(正在烧写) |
| 5 | DFU_DNLOAD_IDLE |
下载空闲(一块完成,可接下一块) |
| 6 | DFU_MANIFEST_SYNC |
Manifest 同步中 |
| 7 | DFU_MANIFEST |
Manifest 阶段(校验/落盘) |
| 8 | DFU_MANIFEST_WAIT_RESET |
等待复位 |
| 9 | DFU_UPLOAD_IDLE |
上传空闲 |
| 10 | DFU_ERROR |
错误状态 |
4. iString(字符串索引)
可选的字符串描述符索引,用于描述状态(如错误详情)。TinyUSB 实现里固定为 0(表示无附加字符串):
resp.iString = 0;
四、典型 GETSTATUS 响应示例
例 1:下载忙(DFU_DNBUSY)
主机发 GETSTATUS,设备正在烧 Flash(假设应用返回超时 100ms):
字节: [0x00] [0x64] [0x00] [0x00] [0x04] [0x00]
含义: OK 100ms(小端) DNBUSY 无字符串
→ 主机解读:状态 OK,当前 DNBUSY 忙,等 100ms 后再轮询。
例 2:空闲可接下一块(DFU_DNLOAD_IDLE)
字节: [0x00] [0x00] [0x00] [0x00] [0x05] [0x00]
含义: OK 0ms(无需等待) DNLOAD_IDLE 无字符串
→ 主机解读:就绪,立即发下一块。
例 3:Manifest 完成等待复位(DFU_MANIFEST_WAIT_RESET)
字节: [0x00] [0x00] [0x00] [0x00] [0x08] [0x00]
含义: OK 0ms MANIFEST_WAIT_RESET
→ 主机解读:升级完成,等待设备复位。
例 4:错误(DFU_ERROR,校验失败 errVERIFY)
字节: [0x07] [0x00] [0x00] [0x00] [0x0A] [0x00]
含义: errVERIFY 0ms ERROR
→ 主机解读:校验失败,需发 CLRSTATUS 清除。
五、总结
这 6 字节是 DFU 协议的”心跳包”,主机靠反复发 GETSTATUS 来:
bStatus判断操作成败;bwPollTimeout决定等待多久再问(流控);bState判断设备处于状态机哪一步、下一步该发什么命令;iString提供可选的错误详情(TinyUSB 固定为 0)。
其中 bwPollTimeout 是最关键的字段——它是”异步烧写”机制得以工作的基础,让主机在设备烧 Flash 的期间不打扰,烧完后再来轮询。
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





