我学嵌入式linux(二)V4L2(持续更新中)

计划研究uboot,学到半途,工作需要搞camera驱动,计划赶不上变化,本章后续持续更新。
0.前言
网上关于V4L2的架构有很多,看了些资料后了解,camera驱动应该只是v4l2的一个subdev,主要接口是I2C和MIPI,不懂啊,亚历山大,身边还没有测试设备和平台,搜索资料有个vivid的虚拟驱动,好像把vivid搞定,一切camera驱动都是纸老虎。
1.Articles
V4L2 Arch
https://www.pianshen.com/article/35341095550/
https://blog.csdn.net/u013904227/article/details/80718831
V4l2 camera driver
https://blog.csdn.net/wh_19910525/article/details/18077971
V4L2 api
https://www.cnblogs.com/emouse/archive/2013/03/04/2943243.html
V4L2 vivi
https://blog.csdn.net/hceng_linux/article/details/89874036
https://www.cnblogs.com/Lxk0825/p/10407913.html
https://blog.csdn.net/weixin_41944449/article/details/80556222?utm_medium=distribute.pc_relevant.none-task-blog-baidujs-3
V4L2 driver (soc camera/vivid…)
https://www.kernel.org/doc/html/v4.11/media/v4l-drivers/soc-camera.html
V4L2 subdev
https://blog.csdn.net/sq336/article/details/39204169
V4L2 media
https://www.jianshu.com/p/83dcdc679901
V4L2 controls
https://blog.csdn.net/u013904227/article/details/81430870
https://blog.csdn.net/qq_33160790/article/details/79606233
V4L2 buffer
https://lwn.net/Articles/447435/
https://www.cnblogs.com/andrew-wang/archive/2012/11/14/2770701.html
https://blog.csdn.net/hnllei/article/details/45564125
https://www.cnblogs.com/cyyljw/p/11269859.html
V4L2 Register Process
https://www.cnblogs.com/linhaostudy/p/9486511.html structure
https://blog.csdn.net/armwind/article/details/88781335
V4L2 Capture App Example
https://www.kernel.org/doc/html/v4.13/media/uapi/v4l/capture.c.html
https://www.cnblogs.com/aquafly/p/6474555.html
UVC USB Video Class
MMAP
https://www.cnblogs.com/wanghuaijun/p/7624564.html
Xilinx
http://www.manongjc.com/detail/16-gsazogtnypktkad.html
2.编译vivid
vivid与硬件无关,是一个虚拟的驱动,所以理论上可以直接运行在电脑上,关于在ubuntu上编译vivid,躺了很多坑,掉了不止一根头发,究其原因,主要是还是对linux的编译环境不熟悉。要在电脑端编译模块生成.ko文件,可以先试试hello world,因为hello world没有太多相关的依赖,所以挺顺利。但是vivid不一样,要先留意ubuntu内核的版本下载对应的linux源码,用里面的vivid编译,先修改Makefile,运行时要指定“ARCH=x86_64”,不然问题一大堆,”CROSS_COMPILE=“,这两个关键字应该是linux系统编译环境的变量,安装流程参考vivid的第一篇文章。
3.Omap3isp
看了一天的资料,从一片文章中发现Ti的这个Omap3isp才是最好的例子,与vivid的区别是:
a)vivid除了video capture之外还包含了vbi,radio等,这些不在目前的学习范围内,增加了阅读负担;
b) Omap3isp,包含了MIPI phy,ISP等子设备比较符合实际应用情况,vivid好像没有子设备;
看了关于这个工程的介绍,大概明白了isp/mipi phy/3a/csid/hist等这一坨可视为控制子对象,是怎么嵌入到一个video device下面的,代码还没开始啃,主要是参考一个大牛文章里画的架构图。
但这里面还缺少了一个子设备sensor,随便看一个ov的例子,可以发现sensor需要异步注册个子设备。
4.自己写vivid+App
直接看代码,发现有很多实现的接口,但无法理解接口的功能和作用,这里推荐结合v4l2的应用代码来理解。后续发现有些部分还是难以理解,特别是数据队列的操作,隐藏再v4l2的代码里面,于是乎想,能不能想vivid的case一样,先不考虑底层硬件部分如sensor,isp等,出图部分用一个定时器来做,说干就干,先谈app部分,
网上可以直接找到读capture的代码,主要流程为:
Open “dev/video0”->枚举所支持的图像格式->设置图像格式->申请buffer(VIDIOC_REQBUFS)->获取buffer信息并MMAP(VIDIOC_QUERYBUF)->buffer入队(VIDIOC_QBUF)->启动camera->循环出队(VIDIOC_DQBUF,图像数据在这里)入队(VIDIOC_QBUF)->关闭camera->释放MMAP->close
驱动部分比较多,更多的是各种结构体的填充和赋值,还没想好如何介绍这块,如果自己动手的话,你就会发现那么多结构体的的成员,如果没有正确赋值的话,一定会出错的
注册流程:v4l2_device_register->video_register_device
重要的结构体:
v4l2_ioctl_ops,
vb2_ops
细节部分:
video_device的release,v4l2_dev,queue,device_caps 等属性要赋值。
vb2_queue.dev 要指向platfomr的dev。
===2020/10/27=
很有必要多次阅读kernel中的documentation文档(framework)
1.通常包含如下结构
v4l2_device: device instance
v4l2_subdev : sub-device instances
video_device : V4L2 device node data
v4l2_fh : file handle instances
说明,如果包含了media framework,子设备和video node会以实体的形式自动出现再该结构下。
2.struct v4l2_device
使用v4l2_device_register注册device instance。
注:
a.如果集成了media framework,需要在注册V4L2 device实例前,给v4l2中的mdev赋值以初始化并完成注册的media_device实例。
b.可以提供一个notify的回调函数,供子设备调用。
3.struct v4l2_subdev
该结构体包含了很多函数指针,并进行了分类,供特定的子设备实现特定的功能。
使用v4l2_subdev_init初始化,如果包含media framework,则必须通过调用media_entity_init初始化media_entity 结构体。
注:
a.初始化media前需要先初始化pads。
b.如果子设备想要处理包含media的video相关的设置,则需要实现v4l2_subdev_pad_ops。
c.每个子设备需要提供link validation函数,用于子设备互联,负责检查format等参数的正确性。如果没有,存在一个默认的检查函数。
d.two ways to register subdevices with the V4L2 core
i.synchronous case
使用v4l2_device_register_subdev注册函数
ii.asynchronous case
使用v4l2_async_register_subdev注册函数,此外bridge driver需要一个带有一组子设备descriptors的notifier,v4l2_async_notifier_register实现,v4l2 core会根据这些descriptors来匹配异步注册的子设备,当存在匹配时,会调用notifier的回调函数。
4.struct video_device(这块先稍等)

异步注册
异步注册的一个作用是,等待外部硬件或者其他模块(一般指sensor,下文简称slave设备或从设备)连接系统,从设备自身驱动匹配后,触发“相连”模块(一般指mipi的phy,下文简称host设备或主设备)响应事件。
1.设备树中,主从设备通过remote-endpoint指定连接的另一端设备,一般先注册主设备,并提供从设备bound的事件处理,相关类型及函数如下
v4l2_async_notifier (提供bound,unbind事件回调函数)
v4l2_async_notifier_parse_fwnode_endpoints_by_port
v4l2_async_subdev_notifier_register
主从设备对,sensor-mipi_phy, mipi_phy-isp
2.从设备通过如下函数进行异步注册并触发主设备的异步事件
v4l2_async_register_subdev_sensor_common
异步bound事件,v4l2中主要是建立主从设备结构体中的entities连接(link),从而在V4l2设备中通过相连entity pad来遍历整个entities并做相应的直接控制。控制相关函数及参数
v4l2_subdev_call (set_fmt, s_power, s_stream…从设备需要提供具体的响应函数)

v4l2内存管理
https://www.cnblogs.com/cyyljw/p/11269859.html
应用命令调用与驱动函数对应关系
app driver
ioctl (VIDIOC_REQBUFS) vb2_ops->queue_setup
(填充信息,https://blog.csdn.net/u013904227/article/details/81054611)
ioctl (VIDIOC_QBUF) vb2_ops->buf_queue
(一般都是单个缓存区顺序入队,每次入队,都会获取物理地址信息,并调用list_add_tail,放在list尾部,当获取完一个整帧,会从该list弹出一个buf,为接收下一帧数据做准备)

颜色与格式
https://www.kernel.org/doc/html/latest/userspace-api/media/v4l/pixfmt.html
https://blog.csdn.net/panda19881/article/details/8740827?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-1.not_use_machine_learn_pai&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-1.not_use_machine_learn_pai
文中提到存储格式分密集存储和平面存储,平面存储举例说明如下,假设图像是YUV描述的,则一幅图像的所有像素Y值放在一起,同样将U,V也分别存储在一起。
https://blog.csdn.net/qq_30263737/article/details/90406094 图像sensor Bayer格式说明
https://blog.csdn.net/airk000/article/details/23875759

你可能感兴趣的:(Documents)