[ZYNQ Linux] V4L2视频驱动
发布时间:2026/10/23 6:10:36 锦皓数字建站

[ZYNQ Linux] V4L2视频驱动文章目录[ZYNQ Linux] V4L2视频驱动数据流搭建过程及问题AXI VDMA图像接收思路V4L2驱动V4L2驱动——视频设备ioctl_ops、vb2层与vb2_ops的调用关系AXI VDMA实现细节将缓冲区加入图像队列——buf_queue启动流式传输——start_streaming停止流式传输清空缓冲区队列——stop_streaming设备树设计用户空间使用代码使用步骤命令行工具 v4l2-ctlTODO其它问题数据流搭建过程及问题HDMI输入 → ADV7611解码 →AXIVDMA →PSADV7611复位接到了PL需要进行复位使用一个axi gpio进行复位axi gpio会注册一个gpiochip出来。echo507/sys/class/gpio/exportechoout/sys/class/gpio/gpio507/directionecho0/sys/class/gpio/gpio507/valuesleep1echo1/sys/class/gpio/gpio507/valueADV7611初始化配置一些寄存器i2cdetect -r -y扫描不到0x4C等地址不过可以读到数据可能是设备没有对i2cdetect的扫描进行响应不要过度依赖和相信工具i2cget-y10x4c 0x42重新尝试了下死活配置不成功改用AXI IIC后i2cdetect能扫描到初步判断PS I2C1转EMIO出来的问题不知道是不是需要一些特殊处理。EDID设置问题插电脑不能识别屏幕。HDMI接口的I2C没连接到解码芯片需要连接到一个EEPROM的IP核。EDID IP核需要配置1080的文件里面的名称不能空着添加之后连接到电脑电脑会识别到一个屏幕。时钟和缓冲问题问题VDMA传输的一帧图像只有前几行有效其余全0。数据流程中有一个IP核把视频时序转为了AXI Stream格式需要考虑写入速率写入时钟和读取速率读出时钟的问题。位宽一样的话读出时钟的频率要高于写入时钟。输入是148.5M(1080p60帧)AXIVDMA的时钟也要高于或者等于该时钟。还要考虑缓冲区设置多大比较合适。AXI VDMA图像接收思路通过DMA接口申请连续的内存块DMA传输需要特殊的内存块不能是malloc常规申请的调用DMA接口接收数据到内存空间内核空间提供mmap接口供用户空间使用用户空间调用mmap获取图像常规的图像接收思路原理都是类似的提供的API接口或者使用方式有所区别。还会有缓冲池、缓冲区、队列等等的区别。V4L2驱动V4L2驱动——视频设备接口说明int v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev);注册 V4L2 设备实例管理设备的数据结构用户空间不可见int video_register_device(struct video_device *vdev,int type, int nr);注册视频设备由V4L2设备进行管理即和上面注册v4l2设备关联创建/dev/videoX的设备节点struct video_device视频设备结构体设备的核心操作接口fops和ioctl_ops图像队列queueconst struct v4l2_file_operations *fops;open、release、mmap等内核有通用的vb2_fop_mmap操作接口等等const struct v4l2_ioctl_ops *ioctl_ops;ioctl操作一大堆需要实现一些关键的structvb2_queue*queue;管理视频缓冲区的队列一个缓冲区或者缓冲池内核fops通用接口v4l2_fh_open打开文件vb2_fop_release释放与视频缓冲区相关的资源vb2_fop_mmap内存映射vb2_fop_pollpoll机制内核ioctl_ops通用接口vb2_ioctl_create_bufs创建视频缓冲区vb2_ioctl_expbuf导出视频缓冲区可以与其他设备或进程共享内存ioctl_ops用户实现vidioc_querycap查询设备能力vidioc_g_fmt_vid_cap当前数据格式包括分辨率、像素格式等参数 get formatvidioc_try_fmt_vid_cap尝试设置视频捕获格式但不实际应用vidioc_s_fmt_vid_cap设置视频捕获设备的格式如分辨率、像素格式set formatvidioc_enum_fmt_vid_cap枚举视频捕获设备支持的像素格式 enum formatvidioc_reqbufs申请视频缓冲区内存vidioc_querybuf查询已申请缓冲区的详细信息包括内存偏移、长度等vidioc_qbuf将缓冲区放入队列或队列 queue buffervidioc_dqbuf从队列中取出缓冲区 dequeue buffervidioc_streamon启动视频流传输vidioc_streamoff停止视频流传输struct vb2_queue缓冲区队列需要实现对队列的操作vb2_ops内存操作mem_opsqueue_setup初始化视频缓冲区队列分配缓冲区内存buf_prepare准备缓冲区数据buf_queue将缓冲区加入队列start_streaming启动流式传输stop_streaming停止流式传输清空缓冲区队列wait_prepare等待缓冲区准备完成wait_finish等待缓冲区处理完vb2video buffer的通用接口vb2_fop层、vb2_ioctls层、vb2层、vb2_ops层vb2_ops_wait_finish等待所有缓冲区操作完成vb2_ops_wait_prepare等待所有缓冲区准备完成vb2_plane_vaddr获取缓冲区的虚拟地址vb2_plane_size获取缓冲区平面的大小vb2_set_plane_payload设置缓冲区平面的有效载荷大小vb2_is_busy检查缓冲区队列是否正忙vb2_reqbufs请求分配缓冲区vb2_querybuf查询缓冲区信息vb2_qbuf将缓冲区加入队列vb2_dqbuf从队列中取出缓冲区vb2_streamon启动流式传输vb2_streamoff停止流式传输vb2_buffer_done标记缓冲区处理完成vb2_dma_contig_plane_dma_addr获取DMA连续缓冲区的物理地址vb2_is_streaming检查是否正在流式传输vb2_queue_init初始化视频缓冲区队列vb2_dma_contig_memopsDMA内存操作集合可传给mem_opsioctl_ops、vb2层与vb2_ops的调用关系方向用户空间 → ioctl_ops → vb2层 → vb2_ops。用户空间通过ioctl系统调用传递到驱动中定义的ioctl_ops结构体ioctl_ops调用vb2层如vidioc_streamon等会进一步调用vb2层的通用接口vb2_streamonvb2层回调驱动实现的vb2_opsvb2_streamon回调start_streaming分工ioctl_ops处理用户请求的解析与转发。vb2层实现通用缓冲区管理逻辑。vb2_ops由驱动实现硬件细节。AXI VDMA实现细节将缓冲区加入图像队列——buf_queue获取缓冲区的物理地址用于DMA传输——vb2_dma_contig_plane_dma_addr准备交错传输DMA描述符需要设置DMA地址等参数——dmaengine_prep_interleaved_dma设置描述符的回调函数如果DMA传输完成就把缓冲区标记为有图像数据VB2_BUF_STATE_DONE)将描述符提交到 DMA 控制器的工作队列提交未开始——dmaengine_submit把缓冲区放到活动缓冲区队列里面后续获取图像就是从这个队列里面获取触发 DMA 控制器开始执行已提交的传输——dma_async_issue_pending启动流式传输——start_streaming让DMA开始工作就行——dma_async_issue_pending停止流式传输清空缓冲区队列——stop_streaming结束DMA传输——dmaengine_terminate_all将活动缓冲区队列里面的缓冲区设置为无效VB2_BUF_STATE_ERROR设备树设计vdma_capture:vdma-capture{compatiblexlnx,axi-vdma-capture;dmasaxi_vdma_11;dma-namesport0;};用户空间使用代码使用步骤打开设备使用open()函数打开V4L2设备文件通常是/dev/video0。根据需要可以选择阻塞或非阻塞模式。查询设备能力通过VIDIOC_QUERYCAP命令获取设备的能力例如是否支持视频采集V4L2_CAP_VIDEO_CAPTURE和流式I/OV4L2_CAP_STREAMING。设置图像格式使用VIDIOC_S_FMT命令配置采集的图像格式包括宽度、高度和像素格式如YUYV、MJPEG等。这是决定图像数据如何组织的关键一步。申请与映射缓冲区申请缓冲区通过VIDIOC_REQBUFS向驱动程序申请若干个视频缓冲区。映射缓冲区对于内存映射mmap方式使用VIDIOC_QUERYBUF查询每个缓冲区信息然后通过mmap()系统调用将内核空间的缓冲区映射到用户空间以便应用程序可以直接访问。这是最常用且高效的方式。缓冲区入队在开始采集前需要通过VIDIOC_QBUF命令将所有空闲的缓冲区放入驱动层的输入队列中。开始/停止视频流通过VIDIOC_STREAMON命令启动视频采集驱动程序开始向队列中的缓冲区填充数据。在循环中使用VIDIOC_DQBUF从驱动层的输出队列中取出已填充好数据的缓冲区。应用程序处理完该帧数据后必须再次调用VIDIOC_QBUF将其放回输入队列以便驱动程序循环使用。采集完成后通过VIDIOC_STREAMOFF命令停止视频流。关闭设备使用close()函数关闭设备文件并释放所有资源。命令行工具 v4l2-ctlTODO解码芯片在用户空间单独进行初始化和配置未加入到驱动框架里边。可以使能内核相关驱动作为v4l2子设备添加。联动Framebuffer、DRM进行图像输出。其它问题内核有个VVIP的驱动不是给AXI-VDMA用的是给另外的IP核用的不能直接使用。no VDMA channel foundVVIP驱动没找到DMA通道设备树通道有问题1是写从DMA向外写S2MM。[2.246473]xilinx-video axi-video-cap: no VDMA channel found[2.251733]xilinx-video axi-video-cap: /axi-video-cap/ports/port0 initialization failed[2.259907]xilinx-video axi-video-cap: DMA initialization failed\linux-xlnx\Documentation\devicetree\bindings\dma\xilinx\xilinx_dma.txt* DMA client Required properties: - dmas: a list of[Video DMA device phandle][Channel ID]pairs, where Channel ID is0forwrite/tx and1forread/rx channel. For MCMDA, MM2S channel(write/tx)ID start from0and isin[0-15]range. S2MM channel(read/rx)ID start from16and isin[16-31]range. These channels ID are fixed irrespective of IP configuration. - dma-names: a list of DMA channel names, one perdmasentryno subdev found in graphVVIP驱动没有子设备v4l2驱动需要子设备构成一个完整的数据流[2.253037]xilinx-video axi-video-cap: /axi-video-cap/ports/port0 initialization failed[2.260727]xilinx-video axi-video-cap: DMA initialization failed[4.528033]xilinx-video axi-video-cap: no subdev foundingraph[4.539722]xilinx-video: probe of axi-video-cap failed with error-2创建一个虚拟的子设备可以创建成功但还是不能用VVIP驱动驱动里面还是用不了没能成功获取到图像格式需要另一个IP核的支持。[2.373491]xilinx-video axi-video-cap: /axi-video-cap/ports/port0 initialization failed[2.381152]xilinx-video axi-video-cap: DMA initialization failed[4.646649]xilinx-video axi-video-cap: device registered
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。