{"code":1,"msg":"成功","time":"1793358217","data":{"title":"〖2026嵌入式大赛〗ART-Pi2 USB 枚举可视化与描述符规则诊断仪","content":"## 一、从一次真实 USB 枚举开始\r\n\r\n在项目记录的一次 Mi USB Receiver 枚举中，配置描述符偏移 4 的 `0x03` 声明了 3 个接口。网页上的“接口数量通过”可以回查到这条响应、对应的 Host 事件和原始字节。本文从这个例子出发，介绍数据怎样从 USB Host 观测进入 RT-Thread 分析线程，再变成可阅读、可导出的结果。\r\n\r\n本项目运行在 ART-Pi2 和 RT-Thread 上，观察真实 HID 设备的枚举过程。板端把主机请求、设备响应、规则判定和原始字节组织成会话证据，再通过 4.3 寸 LCD 和局域网网页展示。读者可以沿时间线学习，也可以从一项规则结论回查对应事件。\r\n\r\n作品的使用过程是：**接入 HID → 观察枚举 → 选择规则 → 定位事件和字节 → 保存报告或原始证据。** 本文以实际捕获中的“接口数量”规则为例，说明这套流程如何工作。\r\n\r\n[![ART-Pi2 主板与配套 4.3 寸 RGB LCD 实机照片](https:\/\/raw.githubusercontent.com\/ArthurPan2026\/artpi2-usbdiag\/3eb6a6b84a7fa386119af47acd509d9b3b638b4e\/docs\/competition\/artpi2-overview.jpg)](https:\/\/raw.githubusercontent.com\/ArthurPan2026\/artpi2-usbdiag\/3eb6a6b84a7fa386119af47acd509d9b3b638b4e\/docs\/competition\/artpi2-overview.jpg)\r\n\r\n*图 1：ART-Pi2 与配套屏幕。LCD 显示一次真实 HID 枚举的结果，点击图片可查看原图。*\r\n\r\n## 二、硬件组成与接线\r\n\r\n主控采用 ART-Pi2 的 STM32H7R7，屏幕配套使用正点原子 `ATK-MD0430R-800480` 4.3 寸 RGB LCD 模块，分辨率为 800 × 480。USB Host 连接真实 HID，板载 CYW43438 通过 2.4 GHz Wi-Fi 提供网页访问。\r\n\r\n| 硬件或连接               | 在项目中的用途                               |\r\n| ------------------------ | -------------------------------------------- |\r\n| ART-Pi2 开发板           | 运行 RT-Thread、USB Host、规则分析和网络服务 |\r\n| 800 × 480 RGB LCD        | 显示枚举阶段、描述符、诊断与 Wi-Fi 设置      |\r\n| 真实 HID 设备            | 提供主机实际观测的枚举请求响应               |\r\n| USB-C 转 USB-A 转接头    | 将 HID 接入开发板的 USB Host Type-C 口       |\r\n| ST-Link 与 Windows 电脑  | 构建固件、首次部署 Boot 和 Appli             |\r\n| 同一局域网中的浏览器设备 | 查看网页、预览 PDF、导出证据                 |\r\n\r\n板端 CC 电阻配置可能影响部分 USB-C 直连组合，强烈建议通过 USB-C 转 USB-A 转接头接入 HID。若仍无法识别，再核对设备、线缆和供电，具体兼容情况以实测为准。\r\n\r\n[![ART-Pi2、LCD、HID、ST-Link 与局域网的硬件连接图](https:\/\/raw.githubusercontent.com\/ArthurPan2026\/artpi2-usbdiag\/3eb6a6b84a7fa386119af47acd509d9b3b638b4e\/docs\/competition\/hardware-connection.svg)](https:\/\/raw.githubusercontent.com\/ArthurPan2026\/artpi2-usbdiag\/3eb6a6b84a7fa386119af47acd509d9b3b638b4e\/docs\/competition\/hardware-connection.svg)\r\n\r\n*图 2：硬件连接与访问路径。HID 接到开发板，浏览器通过局域网访问板端服务。*\r\n\r\n## 三、一次枚举怎样形成证据\r\n\r\nCherryUSB 主机适配层在控制传输开始和完成时记录观测信息，包括请求参数、返回状态以及捕获到的描述符字节。事件进入有容量上限的队列，再由 RT-Thread 分析线程读取，调用共享 C99 规则核心生成判定。\r\n\r\n规则结果保留来源事件和字节引用。板端随后发布带代号的不可变证据快照，LCD 与网页围绕这份会话展示结果。这样，界面中的一个结论可以继续追到主机事件和具体响应字节。\r\n\r\n[![从真实 HID 观测到规则、快照、LCD、网页和证据导出的数据流](https:\/\/raw.githubusercontent.com\/ArthurPan2026\/artpi2-usbdiag\/3eb6a6b84a7fa386119af47acd509d9b3b638b4e\/docs\/competition\/evidence-flow.svg)](https:\/\/raw.githubusercontent.com\/ArthurPan2026\/artpi2-usbdiag\/3eb6a6b84a7fa386119af47acd509d9b3b638b4e\/docs\/competition\/evidence-flow.svg)\r\n\r\n*图 3：枚举观测、规则分析、会话发布和证据导出的数据路径。*\r\n\r\n界面把枚举观测组织为 8 个阶段：端口复位、读取设备描述符前 8 字节、设置地址、读取完整设备描述符、读取配置描述符、读取字符串描述符、设置配置和枚举完成。阶段用于组织当前主机观察到的过程；具体请求次数、重试和响应仍以设备的实际记录为准。\r\n\r\n规则核心会记录缺失证据、来源事件丢失、容量耗尽和未知速度等情况。受影响的规则无法给出通过结论；会话存在采集缺口或未观察规则时，整体不会被判为完整通过。其他不受影响的规则仍可能单独显示 `PASS`，需要结合采集完整性解读。\r\n\r\n## 四、从“接口数量通过”追到原始字节\r\n\r\n网页提供三个视图，分别对应接入观察、教学和开发复核：\r\n\r\n| 视图     | 主要内容                                            | 适合的操作                       |\r\n| -------- | --------------------------------------------------- | -------------------------------- |\r\n| HID 接入 | 接口、端点、类别、主机类驱动绑定及描述符完整性      | 确认当前连接的设备与接口结构     |\r\n| 教学导览 | 8 阶段时间线、主机请求、设备响应及 4 项证据核验任务 | 把协议概念与真实枚举过程对应起来 |\r\n| 研发核验 | 12 项规则的期望值、实测值、来源事件和原始字节       | 复查一项判断的依据               |\r\n\r\nLCD 提供实时、描述符、诊断和设置页面，便于在板端查看会话状态及配置 Wi-Fi。\r\n\r\n[![Release 版 LVGL 首页的完整 800 × 480 实机帧缓冲画面](https:\/\/raw.githubusercontent.com\/ArthurPan2026\/artpi2-usbdiag\/3eb6a6b84a7fa386119af47acd509d9b3b638b4e\/docs\/competition\/lvgl-home-release.png)](https:\/\/raw.githubusercontent.com\/ArthurPan2026\/artpi2-usbdiag\/3eb6a6b84a7fa386119af47acd509d9b3b638b4e\/docs\/competition\/lvgl-home-release.png)\r\n\r\n*图 4：Release 版 LCD 首页。画面从运行中的开发板帧缓冲只读采集，保留完整界面。*\r\n\r\n已有参考捕获使用 Xiaomi Mi USB Receiver，VID:PID 为 `2717:5091`，呈现三个 HID 接口。该次记录包含 17 个事件，12 条规则通过，丢失事件数为 0。这些数字只对应这台设备和这次捕获，其他 HID 的接口数、事件顺序和规则结果以实际观测为准。\r\n\r\n以这份已记录的 Release 会话为例，在研发页选择“接口数量”规则后，可以定位到主机事件 #6。它对应读取完整配置描述符的 `GET_DESCRIPTOR` 请求，期望读取长度为 84 字节，实际响应也为 84 字节。响应开头包含：\r\n\r\n```text\r\n偏移：00 01 02 03 04 ...\r\n字节：09 02 54 00 03 ...\r\n```\r\n\r\n| 字节位置           | 字段              | 该次捕获的含义                    |\r\n| ------------------ | ----------------- | --------------------------------- |\r\n| 偏移 0：`09`       | `bLength`         | 配置描述符自身长度为 9 字节       |\r\n| 偏移 1：`02`       | `bDescriptorType` | 描述符类型为 Configuration        |\r\n| 偏移 2、3：`54 00` | `wTotalLength`    | 按小端解释为 `0x0054`，即 84 字节 |\r\n| 偏移 4：`03`       | `bNumInterfaces`  | 声明包含 3 个接口                 |\r\n\r\n规则核心遍历完整配置数据，并统计不同接口编号。该次解析结果为 3，与 `bNumInterfaces` 一致，因此接口数量规则通过。统计时使用不同接口编号；一个接口存在多个 alternate setting 时，不把它们直接累加为多个接口。\r\n\r\n[![网页研发核验页：接口数量规则、事件 #6 与偏移 4 的原始字节](https:\/\/raw.githubusercontent.com\/ArthurPan2026\/artpi2-usbdiag\/3eb6a6b84a7fa386119af47acd509d9b3b638b4e\/docs\/competition\/web-rule-evidence.png)](https:\/\/raw.githubusercontent.com\/ArthurPan2026\/artpi2-usbdiag\/3eb6a6b84a7fa386119af47acd509d9b3b638b4e\/docs\/competition\/web-rule-evidence.png)\r\n\r\n*图 5：完整网页研发核验画面。选中的规则、来源事件和响应字节同时可见，点击图片可查看大图。*\r\n\r\n项目当前的 12 项规则如下。它们检查捕获到的枚举与描述符证据，不覆盖整套 USB 规范。\r\n\r\n| 规则                  | 检查内容                                         |\r\n| --------------------- | ------------------------------------------------ |\r\n| `DEV_B_LENGTH`        | 设备描述符 `bLength` 是否为 18                   |\r\n| `DEV_TYPE`            | 返回的描述符类型是否为 Device                    |\r\n| `DEV_8B_PREFIX`       | 最初 8 字节是否与完整设备描述符前缀一致          |\r\n| `DEV_FIELDS`          | `bMaxPacketSize0` 是否适用于观测到的速度         |\r\n| `CFG_B_LENGTH`        | 配置描述符长度是否为 9、类型是否为 Configuration |\r\n| `CFG_TOTAL_LENGTH`    | 完整响应与 `wTotalLength` 是否一致               |\r\n| `CFG_TREE_WALK`       | 每个描述符是否在边界内且可继续遍历               |\r\n| `CFG_INTERFACE_COUNT` | 不同接口编号的数量是否符合 `bNumInterfaces`      |\r\n| `IF_ENDPOINT_COUNT`   | 每个 alternate setting 的端点数量是否与声明一致  |\r\n| `EP_PACKET_SIZE`      | 最大包长是否适用于速度与传输类型                 |\r\n| `EP_INTERVAL`         | 周期端点的 `bInterval` 是否有效                  |\r\n| `EP0_STALL`           | 必需的枚举请求是否均未因 STALL 失败              |\r\n\r\n## 五、保持会话一致，再保存结果\r\n\r\n网页一次显示的数据可能来自多次请求。若读取期间设备变化，简单拼接分页结果容易混入不同会话的数据。项目使用快照代号，把分页读取限定在同一份冻结会话；CRC 用于检查读回数据是否意外损坏。\r\n\r\n实时 USB 拓扑另行读取，并带有设备代次号；它不属于冻结会话快照 CRC 的校验范围。生成 PDF 时，板端会核对设备代次、设备身份、接口数量和端点数量。若校验失败，报告会将拓扑标记为不可用，并省略不匹配的拓扑。\r\n\r\n两种导出形式服务于不同的复核工作：\r\n\r\n- **中文 PDF：** 由板端使用 libHaru 生成，浏览器负责预览、下载和打印。适合阅读、交流和归档，默认遮盖设备序列号，不包含原始传输负载。\r\n- **完整证据 JSON：** 保留当前会话、规则结果、事件、固件捕获的原始字节以及 CRC 信息，适合继续比对和分析。导出会按当前快照代号取齐并校验数据。\r\n\r\n历史接口只保存摘要。需要保留完整原始证据时，应在对应会话仍可读取时导出 JSON。快照代号和 CRC 解决一致性及意外损坏检查，不提供加密或身份认证。\r\n\r\n## 六、RT-Thread 软件框架与组件复用\r\n\r\n| 层次         | 主要组件                                  | 职责                                    |\r\n| ------------ | ----------------------------------------- | --------------------------------------- |\r\n| 系统与外设   | RT-Thread 5.3.0、STM32CubeMX\/HAL          | 线程运行、时钟与外设初始化、驱动适配    |\r\n| USB 观测     | CherryUSB 1.5.2 与项目适配层              | 记录枚举控制传输、响应及描述符          |\r\n| 规则与证据   | C99 `usb_enum_diag`、有界队列、会话快照   | 生成规则结论，保留来源事件和字节引用    |\r\n| LCD          | LVGL 9.6.0、NemaGFX M7 1.4.17、DMA2D\/LTDC | 显示状态、描述符、诊断和设置            |\r\n| Wi-Fi 与网页 | Infineon WHD 3.3.3.26314、Mongoose 7.23   | 驱动 CYW43438，通过局域网提供页面和数据 |\r\n| 报告         | libHaru 2.4.6                             | 在板端生成中文 PDF                      |\r\n\r\n规则计算与硬件采集分开组织。`usb_enum_diag` 核心不依赖 RT-Thread、CherryUSB、HAL、LVGL 或网络栈，也不分配动态内存。固件与主机侧测试编译同一份核心，适配层负责把真实事件交给它，并把结果转换成应用展示的数据。\r\n\r\n工程使用 Boot 和 Appli 两个镜像。启动程序 Boot 初始化外部存储、检查应用入口并跳转到 Appli；应用从外部 XSPI 映射地址 `0x70000000` 就地执行（XIP）。Boot 也负责启动阶段的看门狗记录处理。\r\n\r\nWi-Fi 配置管理和看门狗记录也提取成了 C99 组件。Wi-Fi 核心描述连接与保存策略，平台适配层执行无线和存储操作；故障记录核心处理记录格式与校验，平台端负责 IWDG、保留内存和 Flash。ART-Pi2 集成了这些组件，并提供主机侧检查和 RT-Thread 集成入口。它们目前随项目提供，尚未发布到 RT-Thread 软件包索引。\r\n\r\n在故障恢复方面，应用周期保存最近的组件进度和 CPU 现场摘要，Boot 在看门狗复位或已捕获异常后保存相应日志。记录来自最近一次成功采样，无法保证保留 CPU 停机瞬间的全部寄存器。这个边界也决定了日志只能作为进一步排查的依据。\r\n\r\n## 七、下载、构建与首次运行\r\n\r\n项目地址：[ArthurPan2026\/artpi2-usbdiag](https:\/\/github.com\/ArthurPan2026\/artpi2-usbdiag)。仓库包含固件源码、三个 C99 组件、稳定 Release 镜像、Windows 工具及许可材料。本帖图片与文档链接固定到提交 `3eb6a6b`，便于对照相同版本。\r\n\r\n项目自有代码与捆绑组件分别适用各自许可证，复用时请保留对应许可与来源说明。\r\n\r\n可以在仓库页面下载 ZIP。使用 Git 克隆时，需要 Git LFS 取得两份大归档；如果工具归档只有几行以 `version https:\/\/git-lfs.github.com\/spec\/v1` 开头的文本，说明拿到的是 LFS 指针，需要补齐大文件后再使用。\r\n\r\n### 1. 准备镜像\r\n\r\n在 Windows 10\/11 x64 打开项目根目录的 `ArtPi2Studio.exe`。先体验作品时可直接选择包内稳定 Release 镜像；从源码构建时，选择 Debug 或 Release，再点击“构建”。\r\n\r\nStudio 默认使用包内 CMake、Ninja 和 GNU Arm GCC。首次构建缺少缓存时，程序会校验并自动解压；同时准备三种工具约需 1.33 GiB 可用空间。普通图形流程不需要另装 PowerShell、Node.js 或全局 .NET Runtime。\r\n\r\n[![ArtPi2Studio 构建区的配置、输出目录与构建入口](https:\/\/raw.githubusercontent.com\/ArthurPan2026\/artpi2-usbdiag\/3eb6a6b84a7fa386119af47acd509d9b3b638b4e\/docs\/competition\/artpi2studio-build.png)](https:\/\/raw.githubusercontent.com\/ArthurPan2026\/artpi2-usbdiag\/3eb6a6b84a7fa386119af47acd509d9b3b638b4e\/docs\/competition\/artpi2studio-build.png)\r\n\r\n*图 6：构建区原始截图。Appli 与 Boot 的输出目录可分别选择，构建成功后显示镜像路径、大小和 SHA-256。*\r\n\r\n### 2. 首次部署 Boot 和 Appli\r\n\r\n连接 ST-Link，核对目标探针、镜像来源、地址和 SHA-256。首次部署同时写入 Boot 与 Appli：Boot 位于内部 Flash `0x08000000`，Appli 位于外部 Flash 映射区 `0x70000000`。构建完成后需要单独执行刷写。\r\n\r\n[![ArtPi2Studio 刷写区的镜像来源、Boot 和校验及擦除选项](https:\/\/raw.githubusercontent.com\/ArthurPan2026\/artpi2-usbdiag\/3eb6a6b84a7fa386119af47acd509d9b3b638b4e\/docs\/competition\/artpi2studio-flash.png)](https:\/\/raw.githubusercontent.com\/ArthurPan2026\/artpi2-usbdiag\/3eb6a6b84a7fa386119af47acd509d9b3b638b4e\/docs\/competition\/artpi2studio-flash.png)\r\n\r\n*图 7：首次部署可选包内稳定 Release 镜像。回读校验和完整擦除默认关闭，具体目标以刷写确认页为准。*\r\n\r\n普通刷写保留 Wi-Fi 配置和看门狗历史。“完整擦除 Flash”会清除内部 Flash、外部 Flash 及其中配置和日志，首次体验通常不需要启用。\r\n\r\n### 3. 联网并接入 HID\r\n\r\n在 LCD 打开“设置 → WiFi → 扫描”，连接目标 2.4 GHz 网络，等待页面显示已连接和 IP 地址。让电脑接入同一局域网，通过 USB-C 转 USB-A 转接头连接真实 HID，再在浏览器打开 `http:\/\/<板端IP>\/`。\r\n\r\n从“HID 接入”确认当前设备和接口结构，再到“教学导览”查看过程，或在“研发核验”中选择规则并回查字节。需要保存时，预览 PDF 或导出完整证据 JSON。\r\n\r\n### 4. 复现时先核对的几项信息\r\n\r\n| 情况               | 建议检查                                                  |\r\n| ------------------ | --------------------------------------------------------- |\r\n| 页面无法打开       | LCD 是否已取得有效 IP，浏览器与开发板是否在同一局域网     |\r\n| HID 没有识别       | USB Host 接口、转接头、线缆与供电，以及当前拓扑与捕获状态 |\r\n| 页面仍显示旧结果   | 当前会话代号、设备代次，以及是否停留在“上次已校验快照”    |\r\n| 规则结果不符合预期 | 先看采集完整性，再看来源事件、传输状态和原始字节          |\r\n| 工具归档无法解压   | 是否下载了 LFS 实际文件，归档大小与清单是否相符           |\r\n\r\n## 八、源码入口与使用边界\r\n\r\n| 阅读目的                      | 推荐入口                                                     |\r\n| ----------------------------- | ------------------------------------------------------------ |\r\n| 了解完整工程                  | [README 与项目目录说明](https:\/\/github.com\/ArthurPan2026\/artpi2-usbdiag\/blob\/3eb6a6b84a7fa386119af47acd509d9b3b638b4e\/README.md) |\r\n| 了解模块职责和资源所有权      | [软件架构](https:\/\/github.com\/ArthurPan2026\/artpi2-usbdiag\/blob\/3eb6a6b84a7fa386119af47acd509d9b3b638b4e\/docs\/competition\/project-architecture.md) |\r\n| 接入设备、查看会话和导出证据  | [使用指南](https:\/\/github.com\/ArthurPan2026\/artpi2-usbdiag\/blob\/3eb6a6b84a7fa386119af47acd509d9b3b638b4e\/docs\/competition\/user-guide.md) |\r\n| 构建、刷写和核对配置          | [构建与运行指南](https:\/\/github.com\/ArthurPan2026\/artpi2-usbdiag\/blob\/3eb6a6b84a7fa386119af47acd509d9b3b638b4e\/docs\/competition\/reproducibility.md) |\r\n| 阅读与复用 USB 规则核心       | [usb_enum_diag](https:\/\/github.com\/ArthurPan2026\/artpi2-usbdiag\/tree\/3eb6a6b84a7fa386119af47acd509d9b3b638b4e\/packages\/usb_enum_diag) |\r\n| 了解 Wi-Fi 策略与故障记录组件 | [wifi_profile_manager](https:\/\/github.com\/ArthurPan2026\/artpi2-usbdiag\/tree\/3eb6a6b84a7fa386119af47acd509d9b3b638b4e\/packages\/wifi_profile_manager)、[watchdog_crashlog](https:\/\/github.com\/ArthurPan2026\/artpi2-usbdiag\/tree\/3eb6a6b84a7fa386119af47acd509d9b3b638b4e\/packages\/watchdog_crashlog) |\r\n\r\n项目记录 Host 软件观察到的枚举事件和时间，不提供 USB 总线分析仪的电气波形或总线级时序。规则 `PASS` 只表示当前捕获数据满足对应规则，不构成 USB 合规认证；主机类驱动绑定也不代表已经验证 HID 输入报告的收发。\r\n\r\n规则失败或 Host 超时仍需结合设备、接线、供电与协议上下文排查，不能单独据此判断硬件根因。完整证据 JSON 保留捕获原值，分享前应检查设备信息和原始字节。","updatetime":"2026-10-25 10:39:53","author":"ArthurPan"}}