Linux UVC Camera的介绍与实践应用(二)

本文基于rk3568 开发板 在之前文章基础上将探讨和学习UVC ,通过 Linux USB Gadget 配置系统 类配置linux 系统下如何配置UVC camera的配置, 欢迎技术和项目探讨。luoshanxuli2010@163.com。


一 USB 介绍

1.1 USB引脚定义

以USB 2.0的标准A型接口为例,它有4个引脚,从外到内分别是VCC(+5V电源)、D-(数据负)、D+(数据正)、GND(地)。其中D+和D-是一对差分信号线,用于数据传输。

OTG是USB 2.0引入的一项技术,允许设备在主机和从机之间动态切换。

ID接地(低电平)→(主机角色,Host)

ID悬空(高电平)→ (从机角色,Device)

1.2 USB 规范

OHCI: 全称为 Open Host Controller Interface
UHCI: 全称是 Universal Host Controller Interface, UHCI 是 Inter 主导的一个于 USB1.0/1.1 的标准,与 OHCI 不兼容
EHCI: 全称是 Enhanced Host Controller Interface,是 Inter 主导的一个用于 USB2.0 的 USB控制器标准
xHCI: 全称是 eXtensible Host Controller Interface,是目前最流行的 USB3.0 控制器标准,在速度、能效和虚拟化等方面比前三个都有较大的提高

USB Host:

通信的发起者和控制者。 它负责管理总线、检测设备的接入/移除、给设备供电(如果是 从总线取电)、发起所有通信请求、枚举设备 分配 地址。当手机连接电脑时,手机是 Device ,电脑是 Host

USB Device

通信的响应者和受控者。 它不能主动发起通信,只能被动地响应 主机的请求。它向主机 报告自己是什么设备(如键盘、U盘),并按照主机的指令进行数据传输。当手机连接U盘 通过OTG线)时,手机变成了 Host ,U盘是 Device

USB电气特性

USB 2.0定义了三种速度模式:低速(Low Speed)1.5Mbps、全速(Full Speed)12Mbps和高速(High Speed)480Mbps。

1.3 USB Gadget

USB Gadget 是让 Linux 设备充当 USB 外设(而不是主机)的机制。 Configfs 是一个基于 RAM 的虚拟文件系统,用于在运行时动态配置内核对象,无需重新编译内核。 手机连接电脑后,手机充当 U盘、摄像头、以太网卡。

Gadget 类型

|--------------|----------------|------------|------------|
| Gadget 类型 | 内核模块 | PC 识别为 | 用途 |
| Mass Storage | g_mass_storage | U 盘 | 文件传输 |
| Serial | g_serial | 串口 (COM) | 调试通信 |
| Ethernet | g_ether | 网卡 (RNDIS) | 网络共享 |
| UVC | g_webcam | 摄像头 | 视频传输 |
| HID | g_hid | 键盘/鼠标 | 输入设备 |
| ADB | functionfs | ADB 设备 | Android 调试 |

1.4 UVC 通信流程

Linux-4.19 UVC 通信流程V4L2 框架,实现与 UVC 应用程序进行 queue buf 和 dequeue buf 的操作。

USB DWC2 OTG 控制器调试接口

/sys/kernel/debug/dwc2_controller_base_addr.usb

ep*in/out: 用于查询 Device 模式下,每个端点的状态信息;

fifo: 用于查询 DWC2 硬件FIFO的配置,如 RXFIFO Size,NPTXFIFO Size,每个端点的 TXFIFO Size; state: 用于查询 DWC2 控制器的中断 MASK寄存器,

Device 模式的控制和配置寄存器信息;

regdump: 打印 DWC2 控制器的所有寄存器状态信息;

testmode: 设置 USB 进入测试模式,主要用于 USB 眼图测试;

二. 硬件环境

2.1 RK3568 硬件

   ATK-DLRK3568 提供 2 个原生的 USB2.0 HOST 接口,这两个 USB 接口都是支持高速模式,也就是 480Mbit/S。提供了 2 个 USB3.0 HOST 接口(OTG3.0+HOST3.0),其中一路用于连接 5G 模组,另外一路作为板载的 USB 3.0 接口。支持标准UVC Camera功能,最高支持4k预览(RK356X),支持USB复合设备稳定传输,支持智能电视或PC等多种终端设备预览。

2.2 USB3.0 HOST 接口

开发板的 1 路 USB3.0 HOST 接口, RK3568 有 2 个 USB3.0 HOST 接口,其中一路用于连接 5G 模组。这是另外一路,作为 USB3.0 HOST 接口,可以连接 USB 鼠标、键盘、 U 盘等设备

2.3 USB2.0 HOST 接口

开发板上两个 USB2.0 HOST 接口, RK3568 原生支持 2 路 USB2.0 HOST 外设,速度会比上面的 USB3.0 慢。可以通过这两个 USB2.0 HOST 接口连一些低速 USB 设备

2.3 电路图

ATKDL-RK3568 开发板上有一路 USB OTG 接口,使用的是 RK3568 的 USB3_OTG0 接口。此路 USB OTG 既可以作为主机(HOST),也可以作为从机(DEVICE),从而实现完整的 OTG功能

注意

  1. DP/DM 必须分别串接 2.2 Ω 电阻,提⾼ DP/DM 的抗压/抗静电能⼒

  2. 如果要⽀持 USB Device 动态拔插检测和充电类型检测功能,则 VBUSDET 脚⼀定要连接到 USB Type-A 接口;

  3. 如果不需要⽀持 USB Device 动态拔插检测和充电类型检测功能,可以允许 VBUSDET 脚固 定拉⾼

  4. USB3_OTG0_ID 未使⽤,悬空即可,芯⽚内部拉⾼到 1.8V

  5. gpio-5 (vcc5v0-otg-regulator) out hi gpio-6 (vcc5v0-host-regulato) out hi

2.4 USB 子系统简介

在 Linux 系统中,提供了主机侧和设备侧视角的 USB 驱动框架及通用驱动程序。主机侧分为 USB Core、HOST 控制器驱动,HUB 驱动和各设备类驱动。设备侧分为 Gadget 框架、Devices 控制器驱动和各设备类 Function 驱动

从机(DEVICE)模式:

使用配套赠送的 USB Type-C 连接线连接 OTG 接口到 PC(电脑), USB Type-C 线会将 CC1 和 CC2 拉高,因此 USB3_OTG0_ID 线为高,表示 OTG 工作在从机模式

主机(HOST)模式:

如果要使用 OTG 的 HOST 功能,那么必须要使用到 Type-c OTG 先。Type-C OTG 线会将 CC1 和 CC2 拉低,因此 USB3_OTG0_ID 线为低,表示 OTG 工作在主机模式。 USB3_OTG0_ID 默认为低电平

三. RK3568 USB配置

3.1 RK3568 USB接口

  RK3568 有两个 USB 2.0 PHY, USB 3.0 OTG 控制器和 USB 3.0 Host_1 的控制器分别使用 USB 2.0 Comb PHY_0 的 port0 和 port1; USB 2.0 Host_2 控制器和 USB 2.0 Host_3 控制器分别使用 USB 2.0 Comb PHY_1 的 port0 和 port1。

PHY 映射表

|----------------|------------|------|-----------------------------|------|
| 节点 | 地址 | 类型 | 速度 | 模式 |
| usb_host0_ehci | 0xfd800000 | EHCI | High Speed (480Mbps) | HOST |
| usb_host0_ohci | 0xfd840000 | OHCI | Full/Low Speed (12/1.5Mbps) | HOST |
| usb_host1_ehci | 0xfd880000 | EHCI | High Speed (480Mbps) | HOST |
| usb_host1_ohci | 0xfd8c0000 | OHCI | Full/Low Speed (12/1.5Mbps) | HOST |

|--------------------|-------|----------------|----------------------|
| PHY | Port | 控制器 | 接口类型 |
| USB 2.0 Comb PHY_0 | Port0 | DWC3 OTG | USB 3.0 OTG (Type-C) |
| | Port1 | USB 3.0 Host_1 | USB 3.0 HOST (5G模组) |
| USB 2.0 Comb PHY_1 | Port2 | USB 2.0 Host_2 | USB 2.0 HOST |
| | Port3 | USB 2.0 Host_3 | USB 2.0 HOST |

phy控制器映射地址

|----------|--------------|---------------------|-------------------|-------------------|
| PHY 节点 | PHY 子节点 | 对应控制器 | 地址 | 模式 |
| usb2phy0 | usbphy0_otg | usbdrd30 (DWC3) | 0xfcc00000 | OTG (Host/Device) |
| usb2phy1 | usbphy1_otg | usb_host0_ehci/ohci | 0xfd800000/840000 | Host Only |
| usb2phy1 | usbphy1_host | usb_host1_ehci/ohci | 0xfd880000/8c0000 | Host Only |

示意图

DTS 中的引用关系

复制代码
  /* USB 2.0 PHY 0 - 给 USB3 OTG 用 */
  usb2phy0: usb2phy@fe8a0000 {
      compatible = "rockchip,rk3568-usb2phy";

      usb2phy0_otg: otg-port {
          /* 连接到 usbdrd30 (DWC3) */
      };
  };

  /* USB 2.0 PHY 1 - 给两个 USB2 Host 用 */
  usb2phy1: usb2phy@fe8b0000 {
      compatible = "rockchip,rk3568-usb2phy";

      usb2phy1_otg: otg-port {
          /* 连接到 usb_host0_ehci/ohci */
      };

      usb2phy1_host: host-port {
          /* 连接到 usb_host1_ehci/ohci */
      };
  };

  /* USB3 OTG 控制器 - UVC Gadget 用这个 */
  usbdrd30: usbdrd@fcc00000 {
      phys = <&usb2phy0_otg>;  /* 引用 PHY */
  };

|---------------------|-------------------------|---------------------|
| 用途 | 使用的 PHY | 使用的控制器 |
| UVC Gadget (Device) | usb2phy0 → usbphy0_otg | usbdrd30 (DWC3) |
| 接 USB 外设 | usb2phy1 → usbphy1_otg | usb_host0_ehci/ohci |
| 接 USB 外设 | usb2phy1 → usbphy1_host | usb_host1_ehci/ohci |

3.2 硬件连接

标准 Type-C 线,检测到 Rd,CC 上拉 USB3_OTG0_ID 为高电平,RK3568作为Device (连电脑)

Type-C OTG 线 检测到 Ra,CC 下拉 USB3_OTG0_ID 为低电平 , RK3568作为Host (连 U盘)

3.3 RK3568 UVC驱动

修改kernel 添加补丁

复制代码
diff --git a/arch/arm64/boot/dts/rockchip/rk3568-evb.dtsi
b/arch/arm64/boot/dts/rockchip/rk3568-evb.dtsi
index 18d6115341cd..268f5d2b1c05 100644
--- a/arch/arm64/boot/dts/rockchip/rk3568-evb.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3568-evb.dtsi
@@ -1778,6 +1778,8 @@
&usbdrd_dwc3 {
dr_mode = "otg";
+ snps,tx-fifo-resize;
+ snps,dis-u1u2-quirk;
extcon = <&usb2phy0>;
status = "okay";
};



  /* 在 DTS 中强制设为 Device 模式 */
  &usbdrd_dwc3 {
      dr_mode = "peripheral";  /* 强制 Device 模式 */
      /* dr_mode = "host";     强制 Host 模式 */
      /* dr_mode = "otg";      自动检测 (默认) */
  };

配置menuconfig

DWC3 Mode Selection (Dual Role mode) --->

( ) Host only mode

( ) Gadget only mode # 可能不可选或不存在

(X) Dual Role mode

需要修改内核配置,确保以下选项都启用:

CONFIG_USB_DWC3=y

CONFIG_USB_DWC3_DUAL_ROLE=y

CONFIG_USB_GADGET=y

CONFIG_USB_CONFIGFS=y

CONFIG_USB_CONFIGFS_F_UVC=y # 如果需要 UVC gadget

CONFIG_USB_DWC3_GADGET = y

Device Drivers

└─► USB support

└─► USB Gadget Support

├─► USB Gadget functions configurable through configfs

│ └─► <*> USB Webcam function ← UVC Gadget 在这里

└─► USB Gadget precomposed configurations

└─► <M> Mass Storage Gadget

Device Drivers --->

\* USB support --->

\* USB Gadget Support --->

\* USB Gadget functions configurable through configfs --->

<*> USB Webcam function --->

进入后用 / 键搜索:

例如搜索关键字输入: USB_F_UVC

检查内核

3.4 gadget 设备安装

复制代码
  USB Device (设备)
  ├── Configuration 1 (配置1)
  │   ├── Interface 1 → Function (串口)
  │   └── Interface 2 → Function (UVC 摄像头)
  └── Configuration 2 (配置2)
      └── Interface 1 → Function (大容量存储)

打开"相机"应用或打开 VLC → 媒体 → 打开捕获设备

当前是 ADB 模式,需要切换到 UVC 模式:

VID: 2207 (Rockchip)

PID: 0006 (ADB Interface)

停止 USBdevice

/usr/bin/usbdevice stop

修改默认 USB 功能为 UVC 开启动为android adb interface

修改 /usr/bin/usbdevice 中的默认功能:

修改 /etc/profile.d/usbdevice.sh

找到这一行:

USB_FUNCS=${USB_FUNCS:-adb}

改为:

USB_FUNCS=${USB_FUNCS:-uvc}

3.5 配置调试方法

sudo ./uvc_config.sh

编译并将camera_uvc拷贝到/usr/bin目录下

sudo ./uvc_app 640 480 &

挂载 configfs

mount configfs /sys/kernel/config

解绑 UDC

echo "" > /sys/kernel/config/usb_gadget/rockchip/UDC

查看当前绑定的 function

ls -la /sys/kernel/config/usb_gadget/rockchip/configs/b.1/

移除 ADB function

rm /sys/kernel/config/usb_gadget/rockchip/configs/b.1/f-ffs.adb

重新绑定 UDC

echo "fcc00000.dwc3" > /sys/kernel/config/usb_gadget/rockchip/UDC

创建 UVC function

mkdir /sys/kernel/config/usb_gadget/rockchip/functions/uvc.gs6

uvc_num_request: 配置 UVC 驱动与 USB 控制器驱动交互的 request 和 buffer 数量; streaming_maxpacket: 配置 USB 2.0 物理总线上每个微帧传输的数据包大小,最大为3072;

streaming_bulk:配置 UVC 使用 bulk 传输类型(默认使用 isoc 传输类型)

配置 信息

echo "0x2207 " > /sys/kernel/config/usb_gadget/my_gadget/idVendo

echo "0x0005 " > /sys/kernel/config/usb_gadget/my_gadget/idProduct

配置 control

mkdir -p /sys/kernel/config/usb_gadget/rockchip/functions/uvc.gs6/control/header/h

ln -s /sys/kernel/config/usb_gadget/rockchip/functions/uvc.gs6/control/header/h /sys/kernel/config/usb_gadget/rockchip/functions/uvc.gs6/control/class/fs/h

ln -s /sys/kernel/config/usb_gadget/rockchip/functions/uvc.gs6/control/header/h /sys/kernel/config/usb_gadget/rockchip/functions/uvc.gs6/control/class/ss/h

创建 streaming 目录

mkdir -p /sys/kernel/config/usb_gadget/rockchip/functions/uvc.gs6/streaming/uncompressed/u

mkdir -p /sys/kernel/config/usb_gadget/rockchip/functions/uvc.gs6/streaming/mjpeg/m

mkdir -p /sys/kernel/config/usb_gadget/rockchip/functions/uvc.gs6/streaming/header/h

配置 MJPEG 1280x720

mkdir /sys/kernel/config/usb_gadget/rockchip/functions/uvc.gs6/streaming/mjpeg/m/720p

cd /sys/kernel/config/usb_gadget/rockchip/functions/uvc.gs6/streaming/mjpeg/m/720p

echo 1280 > wWidth

echo 720 > wHeight

echo 333333 > dwDefaultFrameInterval

echo 18432000 > dwMinBitRate

echo 18432000 > dwMaxBitRate

echo 1843200 > dwMaxVideoFrameBufferSize

echo -e "333333\n666666\n1000000\n2000000" > dwFrameInterval

四 RK Linux USB gadget demo

参考Rockchip 平台的 UVC 摄像头应用 /external/uvc_app 。目前这个dmeo 模拟camera 通过USB 链路输出彩色条纹图像。 Rockchip Linux SDK集成了librkuvc.so库,其源码位于 external/uvc_app 。

代码目录结构

复制代码
├── build
│   ├── CMakeCache.txt
│   ├── CMakeFiles
│   ├── cmake_install.cmake
│   ├── Makefile
│   └── uvc_app
├── camera_uvc.c
├── CMakeLists.txt
├── main.c
├── readme.md
├── uvc
│   ├── drm.c
│   ├── drm.h
│   ├── mpi_enc.c
│   ├── mpi_enc.h
│   ├── mpp_common.h
│   ├── rk_type.h
│   ├── uevent.c
│   ├── uevent.h
│   ├── uvc_control.c
│   ├── uvc_control.h
│   ├── uvc_encode.cpp
│   ├── uvc_encode.h
│   ├── uvc-gadget.c
│   ├── uvc-gadget.h
│   ├── uvc_video.cpp
│   ├── uvc_video.h
│   ├── yuv.c
│   └── yuv.h
└── uvc_config.sh

uvc_control.c UVC控制管理层,监听uevent,管理编码器

uvc_encode.cpp 视频编码封装(YUYV/MJPEG/H264)

uvc_video.cpp 双队列缓冲管理(write队列/read队列)

uvc-gadget.c UVC协议处理,响应Host请求

mpi_enc.c MPP编码器接口封装

编译运行

cd uvc_app/build

在运行程序

uvc_app 640 480 &

设备管理器中出现

问题汇总:

  1. 设备Windows 黄色感叹号

添加 MS OS Descriptors

usbdevice 脚本中 streaming class 链接先于格式链接(u、m)创建,导致 header/h 被锁定,导致链接创建失败。

PC电脑上测试

VLC 查看 UVC 摄像头画面

在 Windows 上打开"相机"应用

相关推荐
HLC++7 小时前
Linux的进程间通信
android·linux·服务器
华清远见IT开放实验室8 小时前
实验室建设案例 | 石家庄科技信息职业学院嵌入式实验室——从底层硬件到系统应用,一所应用型高校的嵌入式人才培养这样落地
linux·arm开发·stm32·嵌入式硬件·高校·实验室建设
groundhappy11 小时前
idalib安装和codex ida-mcp配置
linux·开发语言·python
通信小小昕12 小时前
Ubuntu 26.04 中文输入法安装
linux·运维·ubuntu
张小姐的猫13 小时前
【Linux】网络编程 —— HTTP协议(上)
linux·运维·服务器·网络·http·单例模式·策略模式
栩栩云生13 小时前
AI 写代码犯的错,早被写进了错题集
linux·安全·ai编程
imc.1114 小时前
linux基础IO
linux·运维·服务器
BelongPanda16 小时前
Linux Nginx 纯手动 Let‘s Encrypt 泛域名证书配置教程
linux·nginx
酷可达拉斯16 小时前
Linux操作系统-shell编程(0)
linux·运维·服务器·python·云计算
2301_7779983417 小时前
Linux中断机制:操作系统如何高效运行
linux·运维·服务器