• 【Linux】在Xilinx平台上实现UVC Gadget(1)


    前言:关于UVC

    UVC全称为USB Video Class,即:USB视频类,是一种为USB视频捕获设备定义的协议标准。是Microsoft与另外几家设备厂商联合推出的为USB视频捕获设备定义的协议标准之一。

    UVC设备都是多Interface设备,这点同普通的u盘不同。UVC设备最起码有两个Interface,VideoControl(VC)Interface和VideoStream(VS) Interface; 这也是最常见的UVC设备。 Spec明确要求一个具有可用的,具有实际UVC功能的设备要有一个VC Interface,一个或多个VS Interface。

    VCInterface用于进行配置,操控,设置UVC设备进入不同的功能状态,而VSInterface则负责视频数据流的传输;完整的UVC功能需依赖VS,VC Interfaces的配合才能实现。

    Linux下的uvc驱动位于drivers/usb/gadget/目录下,需要的话可以仔细读一下源代码。
    我这篇文章主要记录了一下大概的调试过程,时间有限,断断续续写了一星期才写完,可能有些细节没写到的,见谅。

    参考链接
    https://xilinx-wiki.atlassian.net/wiki/spaces/A/pages/2046001302/Building+Linux+usb+device+drivers+with+2021.1

    开发环境
    ubuntu16.04.1
    zcu104或者zcu106,其他开发板根据硬件配置稍做修改
    官方推荐petalinux2021.1,实测2019.2也可以,但是内核的配置菜单选项位置不太一样,需要自己调整



    一、创建Petalinux工程并修改设备树

    1) 创建一个基本的petalinux工程

    参考以下链接
    Petalinux快速入门向导 (4) 第三章.PetaLinux开发基本流程

    先从www.xilinx.com官网下载zcu104对应的bsp文件xilinx-zcu104-v2021.1-final.bsp
    然后用bsp创建petalinux工程

    petalinux-create -t project -s xilinx-zcu104-v2021.1-final.bsp
    
    • 1

    2) 配置sstate和downloads

    gedit project-spec/meta-user/conf/petalinuxbsp.conf
    
    • 1

    增加以下几行,路径按自己的路径配置

    DL_DIR = "/opt/xilinx/p211/downloads"
    SSTATE_DIR = "/opt/xilinx/p211/sstate/aarch64"
    RM_WORK_EXCLUDE += "linux-xlnx"
    RM_WORK_EXCLUDE += "u-boot-xlnx"
    
    • 1
    • 2
    • 3
    • 4

    3) 配置内核

    petalinux-config -c kernel
    
    • 1

    Device Drivers ->USB support -> USB Gadget Support
    默认值

    在这里插入图片描述

    修改后
    在这里插入图片描述

    Device Drivers ->USB support -> USB Gadget Support -> USB Gadget precomposed configurations
    默认值
    在这里插入图片描述
    修改后
    在这里插入图片描述

    Device Drivers -> Multimedia support(第2页第5个) -> Media drivers(倒数第2个) -> V4L test drivers
    先选中
    在这里插入图片描述
    默认
    在这里插入图片描述
    修改后
    在这里插入图片描述

    NOTE: Executing Tasks
    NOTE: Tasks Summary: Attempted 475 tasks of which 463 didn't need to be rerun and all succeeded.
    [INFO] bitbake virtual/kernel -c diffconfig
    NOTE: Started PRServer with DBfile: /opt/work/uvc-demo/xilinx-zcu104-2021.1/build/cache/prserv.sqlite3, IP: 127.0.0.1, PORT: 44949, PID: 17197
    Loading cache...done.
    Loaded 5098 entries from dependency cache.
    Parsing recipes...done.
    Parsing of 3471 .bb files complete (3463 cached, 8 parsed). 5106 targets, 222 skipped, 0 masked, 0 errors.
    NOTE: Resolving any missing task queue dependencies
    Initialising tasks...done.
    Sstate summary: Wanted 11 Found 11 Missed 0 Current 54 (100% match, 100% complete)
    NOTE: Executing Tasks
    NOTE: Running task 300 of 300 (/opt/work/uvc-demo/xilinx-zcu104-2021.1/components/yocto/layers/meta-xilinx/meta-xilinx-bsp/recipes-kernel/linux/linux-xlnx_2021.1.bb:do_diffconfig)
    NOTE: recipe linux-xlnx-5.10+gitAUTOINC+c830a552a6-r0: task do_diffconfig: Started
    Config fragment has been dumped into:
     /opt/work/uvc-demo/xilinx-zcu104-2021.1/build/tmp/work/zynqmp_generic-xilinx-linux/linux-xlnx/5.10+gitAUTOINC+c830a552a6-r0/fragment.cfg
    NOTE: recipe linux-xlnx-5.10+gitAUTOINC+c830a552a6-r0: task do_diffconfig: Succeeded
    NOTE: Tasks Summary: Attempted 300 tasks of which 299 didn't need to be rerun and all succeeded.
    
    generate_bbappend /opt/work/uvc-demo/xilinx-zcu104-2021.1/build/tmp/work/zynqmp_generic-xilinx-linux/linux-xlnx/5.10+gitAUTOINC+c830a552a6-r0/user_2022-11-19-04-16-00.cfg /opt/work/uvc-demo/xilinx-zcu104-2021.1/project-spec/meta-user/
    [INFO] recipetool appendsrcfile -wW /opt/work/uvc-demo/xilinx-zcu104-2021.1/project-spec/meta-user/ virtual/kernel /opt/work/uvc-demo/xilinx-zcu104-2021.1/build/tmp/work/zynqmp_generic-xilinx-linux/linux-xlnx/5.10+gitAUTOINC+c830a552a6-r0/user_2022-11-19-04-16-00.cfg
    NOTE: Starting bitbake server...
    NOTE: Started PRServer with DBfile: /opt/work/uvc-demo/xilinx-zcu104-2021.1/build/cache/prserv.sqlite3, IP: 127.0.0.1, PORT: 38335, PID: 17550
    Loading cache...done.
    Loaded 5098 entries from dependency cache.
    Parsing recipes...done.
    Parsing of 3471 .bb files complete (3463 cached, 8 parsed). 5106 targets, 222 skipped, 0 masked, 0 errors.
    NOTE: Writing append file /opt/work/uvc-demo/xilinx-zcu104-2021.1/project-spec/meta-user/recipes-kernel/linux/linux-xlnx_%.bbappend
    NOTE: Copying /opt/work/uvc-demo/xilinx-zcu104-2021.1/build/tmp/work/zynqmp_generic-xilinx-linux/linux-xlnx/5.10+gitAUTOINC+c830a552a6-r0/user_2022-11-19-04-16-00.cfg to /opt/work/uvc-demo/xilinx-zcu104-2021.1/project-spec/meta-user/recipes-kernel/linux/linux-xlnx/user_2022-11-19-04-16-00.cfg
    [INFO] bitbake virtual/kernel -c cleansstate
    NOTE: Started PRServer with DBfile: /opt/work/uvc-demo/xilinx-zcu104-2021.1/build/cache/prserv.sqlite3, IP: 127.0.0.1, PORT: 45175, PID: 17636
    Loading cache: 100% |########################################################################################################################################################################| Time: 0:00:01
    Loaded 5098 entries from dependency cache.
    Parsing recipes: 100% |######################################################################################################################################################################| Time: 0:00:02
    Parsing of 3471 .bb files complete (3462 cached, 9 parsed). 5106 targets, 222 skipped, 0 masked, 0 errors.
    NOTE: Resolving any missing task queue dependencies
    Initialising tasks: 100% |###################################################################################################################################################################| Time: 0:00:02
    Sstate summary: Wanted 0 Found 0 Missed 0 Current 0 (0% match, 0% complete)
    NOTE: No setscene tasks
    NOTE: Executing Tasks
    NOTE: Tasks Summary: Attempted 3 tasks of which 0 didn't need to be rerun and all succeeded.
    [INFO] Successfully configured kernel
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42




    4) 修改设备树

    如下图
    (注意原wiki链接少了一个s)

    gedit project-spec/meta-user/recipes-bsp/device-tree/files/system-user.dtsi
    
    • 1





    在这里插入图片描述




    system-user.dtsi修改后的内容为

    /include/ "system-conf.dtsi"
    
    &usb0 {
      status = "okay";
    };
    
    &dwc3_0 {
      status = "okay";
      dr_mode = "peripheral";
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10




    二、在petalinux下添加uvc-gadget测试程序

    1) 创建一个空应用程序,并用hello world模板填充

    这个命令会在project-spec/meta-user/recipes-apps/目录下生成一个uvc-gadget的文件夹,并创建对应的Makefile和空的c模板文件

    petalinux-create -t apps -n uvc-gadget --enable
    
    • 1

    可以看到project-spec/meta-user/recipes-apps/uvc-gadget/files下自动生成了两个文件
    在这里插入图片描述





    Makefile文件如下


    在这里插入图片描述


    uvc-gadget.c如下


    在这里插入图片描述

    这两个文件是petalinux生成app模板的标准文件,它提供了一个可以编译通过的基本框架。只需要在这个基础上增加自己的业务代码,不需要再手工写Makefile。

    我们这个例子比较特殊,因为源代码是github提供的开源代码,所以后续我们会直接删除这两个文件,用网上的源码替代

    2) 把源代码clone到应用程序文件夹

    uvv-gadget是一个uvc测试的小程序
    具体可以看这个链接,作者是比利时的Laurent Pinchart
    https://git.ideasonboard.org/uvc-gadget.git

    我们把源码clone到uvc-gadget/files/目录,可能会提示files目录非空,这是git的问题。
    直接先删除这个目录,git clone以后会自动重新生成

    rm -rf project-spec/meta-user/recipes-apps/uvc-gadget/files
    git clone https://github.com/wlhe/uvc-gadget.git  project-spec/meta-user/recipes-apps/uvc-gadget/files/
    
    • 1
    • 2

    在这里插入图片描述

    3) 编辑recipe文件,把应用加到petalinux最终生成的镜像中

    这一步是petalinux独有的,目的是把生成的二进制文件加到rootfs的对应位置
    这样不需要再手动把文件复制到rootfs

    gedit project-spec/meta-user/recipes-apps/uvc-gadget/uvc-gadget.bb
    
    • 1

    原始文件
    在这里插入图片描述

    #
    # This file is the uvc-gadget recipe.
    #
    
    SUMMARY = "Simple uvc-gadget application"
    SECTION = "PETALINUX/apps"
    LICENSE = "MIT"
    LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302"
    
    SRC_URI = "file://uvc-gadget.c \
    	   file://Makefile \
    		  "
    
    S = "${WORKDIR}"
    
    do_compile() {
    	     oe_runmake
    }
    
    do_install() {
    	     install -d ${D}${bindir}
    	     install -m 0755 uvc-gadget ${D}${bindir}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    修改后

    SUMMARY = "Simple uvc-gadget application"
    SECTION = "PETALINUX/apps"
    LICENSE = "MIT"
    LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302"
    
    SRC_URI = "file://uvc-gadget.c \
    file://uvc.h \
    file://Makefile \
    "
    #INHIBIT_PACKAGE_STRIP = 1
    
    S = "${WORKDIR}"
    
    do_compile() {
    	     oe_runmake
    }
    
    do_install() {
    	     install -d ${D}${bindir}
    	     install -m 0755 uvc-gadget ${D}${bindir}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    4) 修改Makefile

    github下载的源码是针对x86的,我们在嵌入式里面,需要修改对应 的Makefile文件

    gedit project-spec/meta-user/recipes-apps/uvc-gadget/files/Makefile
    
    • 1

    原来的Makefile
    https://github.com/wlhe/uvc-gadget/blob/master/Makefile

    CROSS_COMPILE	?= 
    ARCH		?= x86
    KERNEL_DIR	?= /usr/src/linux
    
    CC		:= $(CROSS_COMPILE)gcc
    KERNEL_INCLUDE	:= -I$(KERNEL_DIR)/include -I$(KERNEL_DIR)/arch/$(ARCH)/include
    CFLAGS		:= -W -Wall -g $(KERNEL_INCLUDE)
    LDFLAGS		:= -g
    
    all: uvc-gadget
    
    uvc-gadget: uvc-gadget.o
    	$(CC) $(LDFLAGS) -o $@ $^
    
    clean:
    	rm -f *.o
    	rm -f uvc-gadget
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    修改后的Makefile

    APP = uvc-gadget
    APP_OBJS = uvc-gadget.o
    
    all: $(APP)
    
    $(APP): $(APP_OBJS)
    	$(CC) $(LDFLAGS) -o $@ $(APP_OBJS) $(LDLIBS)
    
    clean:
    	-rm -f $(APP) *.elf *.gdb *.o
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    5) 编译Petalinux,生成镜像文件

    依次运行以下命令编译并打包
    如果要加快编译速度,一是在电源管理里面,设置为高性能,这样cpu才是全速
    二是把虚拟机文件放在固态硬盘里面

    time petalinux-build
    
    • 1
    cd images/linux
    petalinux-package --boot --fsbl zynqmp_fsbl.elf --u-boot u-boot.elf --pmufw pmufw.elf --fpga system.bit --force
    
    • 1
    • 2

    执行结果

    [INFO] Sourcing buildtools
    INFO: Getting system flash information...
    INFO: File in BOOT BIN: "/opt/work/uvc-demo/xilinx-zcu104-2021.1/images/linux/zynqmp_fsbl.elf"
    INFO: File in BOOT BIN: "/opt/work/uvc-demo/xilinx-zcu104-2021.1/images/linux/pmufw.elf"
    INFO: File in BOOT BIN: "/opt/work/uvc-demo/xilinx-zcu104-2021.1/images/linux/system.bit"
    INFO: File in BOOT BIN: "/opt/work/uvc-demo/xilinx-zcu104-2021.1/images/linux/bl31.elf"
    INFO: File in BOOT BIN: "/opt/work/uvc-demo/xilinx-zcu104-2021.1/images/linux/system.dtb"
    INFO: File in BOOT BIN: "/opt/work/uvc-demo/xilinx-zcu104-2021.1/images/linux/u-boot.elf"
    INFO: Generating zynqmp binary package BOOT.BIN...
    
    
    ****** Xilinx Bootgen v2021.1
      **** Build date : May 28 2021-21:36:22
        ** Copyright 1986-2021 Xilinx, Inc. All Rights Reserved.
    
    
    [INFO]   : Bootimage generated successfully
    
    INFO: Binary is ready.
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    6) 对sd卡分区,并把文件复制到sd卡

    参考这个链接,对sd卡进行分区
    Petalinux快速入门向导 (14) 第十三章.制作带根文件分区的sd卡

    然后把images/linux目录下的BOOT.BIN、image.ub、boot.scr复制到sd卡的分区1
    /media/xlx/BOOT/是我挂载sd卡的目录,修改成你自己对应的目录

    cp boot.scr /media/xlx/BOOT/
    cp BOOT.BIN /media/xlx/BOOT/
    cp image.ub /media/xlx/BOOT/
    
    
    • 1
    • 2
    • 3
    • 4

    把rootfs复制到sd卡的分区2

    sudo dd if=rootfs.ext4 of=/dev/sdc2
    
    • 1

    三、测试步骤

    1) 在嵌入式Linux里

    登录系统,默认没有密码,如果有的话,用户名和密码都是root

    在控制台输入以下命令

    modprobe g_ffs.ko
    modprobe g-webcam streaming_maxburst=15 streaming_maxpacket=3072
    modprobe vivid
    uvc-gadget -u /dev/video0 -v /dev/video1 -t 15 -r 0 -n 2 &
    
    • 1
    • 2
    • 3
    • 4

    执行结果如下,可以对照看输出是否正确

    root@xilinx-zcu104-2021_1:~# modprobe g_ffs.ko
    [   40.744693] file system registered
    
    root@xilinx-zcu104-2021_1:~# modprobe g-webcam streaming_maxburst=15 streaming_maxpacket=3072 streaming_interval=2 
    [   43.871356] g_webcam gadget: uvc: uvc_function_bind()
    [   43.876605] g_webcam gadget: Webcam Video Gadget
    [   43.881234] g_webcam gadget: g_webcam ready
    
    root@xilinx-zcu104-2021_1:~# modprobe vivid
    [   49.702111] vivid-000: using single planar format API
    [   49.709263] vivid-000: CEC adapter cec0 registered for HDMI input 0
    [   49.715639] vivid-000: V4L2 capture device registered as video1
    [   49.721753] vivid-000: CEC adapter cec1 registered for HDMI output 0
    [   49.728238] vivid-000: V4L2 output device registered as video2
    [   49.734256] vivid-000: V4L2 capture device registered as vbi0, supports raw and sliced VBI
    [   49.742645] vivid-000: V4L2 output device registered as vbi1, supports raw and sliced VBI
    [   49.750999] vivid-000: V4L2 capture device registered as swradio0
    [   49.757213] vivid-000: V4L2 receiver device registered as radio0
    [   49.763395] vivid-000: V4L2 transmitter device registered as radio1
    [   49.769790] vivid-000: V4L2 metadata capture device registered as video3
    [   49.776657] vivid-000: V4L2 metadata output device registered as video4
    [   49.783437] vivid-000: V4L2 touch capture device registered as v4l-touch0
    
    root@xilinx-zcu104-2021_1:~# uvc-gadget -u /dev/video0 -v /dev/video1 -t 15 -r 0 -n 2 &
    [1] 1111
    Requested Burst value = 15
    Number of buffers requested = 2
    V4L2 device is vivid on bus platform:vivid-000
    V4L2: Getting current format: YUYV 640x360
    V4L2: Setting format to: YUYV 640x360
    V4L2: Getting current format: YUYV 640x360
    v4l2 open succeeded, file descriptor = 3
    uvc device is dwc3-gadget on bus gadget
    uvc open succeeded, file descriptor = 4
    V4L2: Buffer 0 mapped at address 0xffffa4b38000.
    V4L2: Buffer 1 mapped at address 0xffffa4ac7000.
    V4L2: 2 buffers allocated.
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    2) 在主机Windows/Ubuntu输入以下命令

    需要用到一根usb公对公的线,连接电脑和zcu104的usb口(J96)

    在这里插入图片描述

    在这里插入图片描述
    打开设备管理器,可以看到在"照相机"下多了一个"UVC Camera"

    安装potplayer
    https://potplayer.daum.net/

    ps

    在2019.2中有可能报这个错

    [ 10.690415] mmc0: Tuning failed, falling back to fixed sampling clock
    [ 10.741866] mmc0: Tuning failed, falling back to fixed sampling clock

    https://blog.csdn.net/weixin_31099291/article/details/113689988

    &sdhci1 {
    no-1-8-v;
    };

    Clean the device-tree sstate cache and rebuild the device-tree:

    $ petalinux-build -c device-tree -x cleansstate
    $ petalinux-build -c device-tree

  • 相关阅读:
    html 按钮点击倒计时,限制不可点击
    现在玩51单片机,这也太LOW了?
    Linux内存管理(五):memblock初始化
    Python数据可视化------下载数据
    多线程设计模式-全面详解(学习总结---从入门到深化)
    因果论 —— 模型、推理和推断(概率、图及因果模型)②
    R语言中的prophet预测时间序列数据模型
    力扣-279题 完全平方数(C++)- 完全背包
    一个UWP 框架开发的哔哩哔哩非官方应用
    EPICS自定义设备支持--longin记录的异步设备支持编写
  • 原文地址:https://blog.csdn.net/aatu/article/details/127815729