# USB Host 外接 UVC 摄像头示例 ## 功能说明 本工程 `cherryusb_video_usb` 支持 **Venusa RD EVB(`venusa_rd_evb`)** 和 **ARCS EVB(`arcs_evb`)** 两种开发板。开发板作为 **USB Host(主机)**,通过 USB 接口接收**外接 UVC 摄像头**的视频,将帧数据缓存在 PSRAM 中,再通过 LVGL 显示到 ST7789P3 SPI LCD。 两种板型使用相同的视频接收与显示流程,屏幕连接方式不同:**Venusa RD EVB 使用外接 SPI 屏,ARCS EVB 使用开发板原配 SPI 屏**。 ```text 外接 UVC 摄像头(USB Device) │ USB 视频数据 ▼ 开发板(USB Host,CherryUSB → PSRAM → LVGL) │ SPI ▼ ST7789P3 LCD(320×240 横屏预览) ``` 摄像头使用 USB 数据接口,不使用板上的 DVP 摄像头接口。电脑连接开发板用于烧录和查看串口日志;视频数据来自外接摄像头。 ### 特性 - **UVC Host 接收**:支持 Bulk 和 ISO(等时)传输,使用工程内的 CherryUSB Video 和 MUSB 接收实现。 - **格式自动协商**:优先选择 MJPEG,未找到时回退到 YUY2(UNCOMPRESSED / YUV422);分辨率和帧间隔通过摄像头描述符及 UVC Probe/Commit 协商。 - **全屏预览**:YUY2 转换或 MJPEG 解码后输出 RGB565,缩放到 320×240;图像处理和 LVGL 更新在 UI 任务中执行。 - **帧缓冲保护**:使用双帧缓冲接收视频,避免覆盖显示任务正在使用的数据,并丢弃检测到的异常帧。 - **设备热插拔**:插入后启动接收,拔出后停止视频流并释放资源。 当前预览界面只有一个全屏区域。配置最多允许 2 台摄像头,经 USB Hub 接入时,各摄像头分别接收数据,但共用此预览区域,标签显示当前画面的 `CAM0` 或 `CAM1`。 ## 硬件连接 ### 开发板和摄像头 - 开发板 × 1:`venusa_rd_evb` 或 `arcs_evb`,编译时通过 `-DBOARD` 指定。 - 外接 USB UVC 摄像头 × 1,支持 MJPEG 或 YUY2;建议使用 USB 2.0 High-speed 摄像头。 - 与板端接口匹配、支持 Host 连接的 USB 数据线或转接板。 - ST7789P3 SPI LCD × 1:Venusa 使用外接屏,ARCS EVB 使用开发板原配屏。 ### USB 接口用途 两种板型的摄像头均通过芯片 USB 数据口外接,烧录与串口日志使用独立的烧录/串口口: | 板型 | 摄像头连接口 | 烧录/串口口 | |---|---|---| | `venusa_rd_evb` | **J1(丝印 `USB_ARCS`)** | **J46(CH343P)** | | `arcs_evb` | 芯片 USB 数据口 | 板载烧录/串口口 | > Venusa 的 J1/J46 编号以 `7S_RD_EVB_V1_0.pdf` 原理图为准;ARCS EVB 接口位置请参考 [ARCS EVB 板型说明](../../../../../boards/arcs_evb/README.md)。 单摄像头直接通过合适的转接线连接。需要连接两台时,在开发板与摄像头之间增加 USB 2.0 High-speed Hub,建议使用带独立电源的 Hub,以满足摄像头供电需求。 ### USB Host 供电与 CC 配置 两种板型作为 Host 接外设时,都需要保证摄像头获得稳定的 5 V 供电,并按实际板卡和转接线确认 Type-C CC 配置。可使用带 Host 供电的转接板或带独立电源的 USB Hub。 **Venusa RD EVB 的 J1 默认硬件配置面向 Device 使用**,依据上述原理图: - **VBUS 5 V 输出**:J1 的 VBUS 经 D2(SS24)连接板内 `VBUS`,默认方向是外部 VBUS 输入,不能保证向摄像头输出 5 V。应在 J1 连接器侧实测约 5 V;若为 0 V,按板级方案调整供电路径,或使用带 Host 供电的外部转接板。SW1 仅控制板内 `5V_IN → VBUS`,仍需确认连接器侧电压。 - **CC1 / CC2**:默认 R3/R4 为 5.1 kΩ 下拉(Rd,Device/受电端)。作为 Type-C Host/供电端时,应按板级供电设计配置 Rp 上拉,具体阻值与供电能力匹配。 **ARCS EVB** 的供电路径和 CC 配置应以实际板卡原理图为准,上述 D2、SW1、R3/R4 说明仅适用于 Venusa RD EVB。 软件中的 `USBC_CFG_IDDIG = 0` 只切换 USB 控制器角色,不会改变板上的供电路径或 CC 电阻。供电及 CC 配置不正确时,摄像头可能无法上电或枚举。 ### 显示屏 ST7789P3 LCD 的物理分辨率为 240×320,LVGL 旋转 270° 后逻辑分辨率为 **320×240**。 - **Venusa RD EVB**:使用外接 ST7789P3 SPI 屏,LCD 引脚在 `src/video_display.c` 中配置,并覆盖板级默认 pinmux: | LCD 信号 | Venusa 引脚 | 复用功能 | |---|---|---| | SCLK | PA22 | SPI1 CLK,ALT6 | | MOSI / SDA / D0 | PA23 | SPI1 MOSI,ALT6 | | CS | PA21 | GPIOA 输出,ALT0,软件片选 | | D/C / DC / RS | PA24 | GPIOA 输出,ALT0 | | RST / RES | PA26 | GPIOA 输出,ALT0 | | BL 控制 | PA14 | PWM0 channel 0,ALT11,2 kHz,低电平有效 | 此引脚映射针对 Venusa;`soc/arcs/pinmux.yaml` 是 ARCS/LS26XX 的映射,不能套用于 Venusa。 - **ARCS EVB**:使用开发板原配 SPI 屏,通过板载屏幕连接器连接,无需按 Venusa 的引脚表重新接线。`src/video_display.c` 的 ARCS 分支沿用原配屏的引脚分配,并覆盖板级 SPI1 和 GPIO pinmux,将 PB5 配置为 GPIO 软件片选;背光继续使用 `boards/arcs_evb/pinmux.c` 中的默认 PWM 配置。以下复用功能已按 `soc/arcs/pinmux.yaml` 核对: | LCD 信号 | ARCS EVB 引脚 | 复用功能 | |---|---|---| | SCLK | PB3 | SPI1 CLK,ALT6 | | MOSI / D0 | PB1 | SPI1 MOSI,ALT6 | | CS | PB5 | GPIOB 输出,ALT0,软件片选 | | D/C / DC | PB0 | GPIOB 输出,ALT0 | | RST / RES | PA1 | GPIOA 输出,ALT1 | | BL 控制 | PA0 | PWM channel 0,ALT12,2 kHz,低电平有效 | SPI 配置为 Mode 3、50 MHz;MISO 和 TE 未使用。屏幕与开发板须共地,供电和背光接法按屏幕模组规格连接。不要同时启用占用这些引脚的 DVP/RGB 接口。 ## 示例内容 1. 根据目标板型配置 USB PHY 和时钟为 Host 模式,并初始化对应的 ST7789P3 SPI LCD 和 LVGL。 2. 外接 UVC 摄像头插入后,枚举设备并解析支持的格式、分辨率和端点信息。 3. 选择格式和分辨率,通过 UVC Probe/Commit 协商视频参数;ISO 模式下还会结合接收带宽选择未压缩视频分辨率。 4. 从 PSRAM 分配帧缓冲,按摄像头端点类型启动 Bulk 或 ISO 接收,组装完整视频帧。 5. 将待显示帧交给 UI 任务,完成 YUY2 转换或 MJPEG 解码,更新全屏预览;运行期间约每秒打印接收和显示统计。 6. 摄像头拔出后停止 URB,释放帧缓冲等资源,等待再次插入。 主要文件: | 文件 | 作用 | |---|---| | `src/main.c` | Host 初始化、格式选择、采集任务和周期统计 | | `src/video_display.c` | LCD 引脚配置(区分板型)、图像转换、LVGL 预览 | | `src/cherryusb/usbh_video.c` | UVC 协商、帧组装、Bulk/ISO 接收和帧缓冲管理 | | `src/cherryusb/usb_hc_musb.c` | 本工程使用的 MUSB Host 控制器实现 | | `src/usb_config.h` | USB 设备数量、缓冲对齐等配置 | ## 编译 安装 SDK 所需工具链后,在 SDK 根目录执行: **Venusa RD EVB:** ```bash bash build.sh -j8 \ -S samples/subsys/usb/host/cherryusb_video_usb \ -B build_cherryusb_video_usb_venusa \ -DBOARD=venusa_rd_evb ``` **ARCS EVB:** ```bash bash build.sh -j8 \ -S samples/subsys/usb/host/cherryusb_video_usb \ -B build_cherryusb_video_usb_arcs \ -DBOARD=arcs_evb ``` 本示例未显式切换应用核心,沿用芯片默认配置:Venusa 为 **AP 核(Hart 0)**,ARCS 为 **CP 核(Hart 1)**,实际结果以构建目录中的 `.config` 为准。生成的固件位于对应 `-B` 指定的构建目录下的 `arcs.bin`。 ## 烧录 电脑连接板载**烧录/串口口**,按板卡操作进入下载模式。在 SDK 根目录执行: **Venusa RD EVB:** ```bash ./tools/burn/cskburn -C venusa -s /dev/ttyACM0 -b 3000000 \ 0x0 build_cherryusb_video_usb_venusa/arcs.bin ``` **ARCS EVB:** ```bash ./tools/burn/cskburn -C arcs -s /dev/ttyACM0 -b 3000000 \ 0x0 build_cherryusb_video_usb_arcs/arcs.bin ``` 将 `/dev/ttyACM0` 替换为实际串口设备。`-C` 指定芯片系列(Venusa 为 `venusa`,ARCS/LS26 为 `arcs`),`0x0` 为固件烧录地址。烧录完成后复位开发板,通过烧录/串口口以 **921600** 波特率查看日志,将外接摄像头连接到已配置好 Host 供电的 USB 口。 ## 预期输出 启动时可看到以下日志,具体前缀以实际日志配置为准: ```text ======================================== CherryUSB Host Video Example Preferred format: MJPEG (auto-negotiated from device) Max devices: 2 ======================================== [INFO] Initializing display... [INFO] Initializing USB Host... [INFO] USB Host initialized, please connect USB cameras ``` 插入摄像头后会打印设备信息、协商结果及接收模式。以下为 **YUY2、320×240、ISO** 模式的日志片段示意,实际值取决于摄像头: ```text [VIDEO0] Camera connected: video0 [VIDEO0] Opening device (format=UNCOMPRESSED 320x240)... ... [VIDEO0] frame_buf allocated: 153600 B (320x240) [VIDEO0] Starting ISO streaming... [VIDEO0] Streaming started ``` 运行期间约每秒输出 `[VIDEO0] Running: ...` 和 `[DISP0] ...`,主要字段如下: | 字段 | 含义 | |---|---| | `frames` / `last` | 已交付完整帧数 / 最近一帧的视频数据字节数 | | `gap` | 完整帧交付间隔,以及观测到的最小、最大间隔(ms) | | `bad` / `last_bad` | 被丢弃的异常帧数 / 最近异常帧的数据字节数 | | `busy` | 因帧缓冲仍被显示任务占用而丢弃的帧数 | | `pkt_err` | 检测到的接收或 UVC payload 错误计数,不等同于精确丢包数 | | `converted` / `decode_err` | 成功转换或解码的帧数 / 解码失败数 | | `convert` / `wait` | 图像处理耗时 / 帧等待显示处理的时间(ms) | YUY2 的完整帧大小为 `宽 × 高 × 2`,例如 320×240 对应 **153600 字节**;MJPEG 为压缩数据,帧大小可随图像内容变化。LCD 显示缩放到 320×240 的全屏画面,并标注摄像头编号。 ## 验证方法 分别在 `venusa_rd_evb` 和 `arcs_evb` 上执行以下步骤,保存各板型的串口日志和画面观察结果: 1. **启动显示和 Host**:烧录对应板型固件后复位,确认出现 `USB Host initialized`,LCD 点亮并显示 `CAM: waiting...`。 2. **插入摄像头**:通过芯片 USB 数据口连接已供电的 UVC 摄像头,确认出现 `Camera connected`、协商格式和分辨率,以及 `Streaming started`。 3. **确认实际出图**:移动摄像头或镜头前的物体,确认 LCD 画面随之变化、颜色和布局正常,无局部错位、重复条带或持续停帧。仅有 `Streaming started` 不能证明图像显示成功。 4. **观察运行统计**:连续运行数分钟,确认 `frames` 和 `converted` 持续增加;记录 `bad`、`busy`、`pkt_err` 和 `decode_err` 的变化,结合实际画面判断是否存在接收或解码异常。`busy` 增加可能是显示处理较慢导致丢帧,不等同于摄像头断开。 5. **热插拔验证**:拔出摄像头,确认出现 `Camera disconnected` 和资源清理日志;重新插入后应再次启动视频流并恢复画面,系统不应崩溃。 基础验证使用一台摄像头即可。若需要验证 MJPEG、YUY2 或双摄像头 Hub 场景,应分别记录协商结果与显示情况;双摄像头共用一个全屏预览区域,并非分屏显示。 ## 配置说明 ### prj.conf | 配置项 | 值 | 说明 | |---|---|---| | `CONFIG_CHERRYUSB_HOST_VIDEO` | `y` | 启用 UVC Host | | `CONFIG_CHERRYUSB_HOST_MUSB_LISA` | `y` | 启用 MUSB Host 控制器 | | `CONFIG_PSRAM_HEAP` | `y` | 启用 PSRAM 动态堆 | | `CONFIG_PSRAM_HEAP_SIZE` | `0x500000` | PSRAM 堆大小,5 MiB | | `CONFIG_LISA_DISPLAY_PANEL_ST7789P3` | `y` | 启用 ST7789P3 LCD 驱动 | | `CONFIG_LV_DRIVER_ROTATE_270` | `y` | 旋转为 320×240 横屏 | | `CONFIG_LV_USE_GPU_CSK_DMA2D` | `y` | 启用 DMA2D 显示加速 | | `CONFIG_LV_USE_SJPG` | `y` | 启用 TJpgDec,供 MJPEG 解码使用 | ### src/usb_config.h | 配置项 | 值 | 说明 | |---|---|---| | `CONFIG_USBHOST_MAX_VIDEO_CLASS` | `2` | 最多可分配的 UVC 设备实例数 | | `CONFIG_USB_ALIGN_SIZE` | `32` | DMA 缓冲区对齐字节数 | | `CONFIG_USBH_VIDEO_BULK_CHUNK_SIZE` | `512` | `dwMaxPayloadTransferSize` 为 0 时,Bulk 接收缓冲区的默认长度,不代表固定的 USB 包大小 | 首选视频格式由 `src/main.c` 中的 `VIDEO_FORMAT_PREF` 控制,当前为 `USBH_VIDEO_FORMAT_MJPEG`。 ## 注意事项 1. **适用板型**:本工程同时支持 Venusa RD EVB(`-DBOARD=venusa_rd_evb`)和 ARCS EVB(`-DBOARD=arcs_evb`)。Venusa 使用外接 ST7789P3 SPI 屏,ARCS EVB 使用开发板原配 SPI 屏。 2. **ISO 带宽限制**:当前接收实现按每微帧最多 1 次事务、最多 1024 字节设计,不支持每微帧多次事务的高带宽 ISO 模式。摄像头分辨率、帧率应匹配实际接收带宽。 3. **预览和采集帧率**:USB 2.0 High-speed 的 480 Mbps 是总线标称速率,实际帧率还取决于摄像头协商参数、接收处理、解码及 SPI 显示耗时。 4. **兼容性验证**:MJPEG 解码和多摄像头路径已实现,但尚未完成对应的实板验证;实际使用需结合摄像头格式、供电和日志确认。