本文以摄像头OV7725为例说明如何添加一个新的Video驱动到Zephyr。
通过前面几篇文章我们对Zephyr的视频驱动的模型使用和实现有一个大致的了解,本文通过OV7725在Zephyr上驱动的实现来说明如何添加新的Video驱动。
本文只说明实现Video驱动中和Zephyr驱动Video模型相关联的部分,不说明如何设置OV7725寄存器等硬件上的操作。
硬件接口分析
硬件上使用开发板mm_swiftio搭配正点原子的OV7725。
OV7725是一颗VGA CMOS的摄像头,硬件接口可分为下面四类:
- CSI接口:必须,包括D0~D7, PCLK, VYSNC,HSYNC。用于读取OV7725捕获的图像数据。
- SCCB接口:必须,包括SDA和SCL。用于读写OV7725寄存器,对OV7725进行控制,例如初始化硬件,设置画幅,格式,饱和度,亮度等等。
- Reset:必须,只有一个硬件引脚,用于硬件复位OV7725
- 外部clock: 非必须,包含一个CTRL和一个MCLK, 正点原子的OV7725模块带有时钟产生,可以不需要外部clock。 CTRL默认上拉选择内部Clock。这里我们不使用。
mm_swiftio使用rt1052为SOC,和OV7725对接的硬件接口:
- CSI接口
- 1个I2C接口,在Zephyr驱动SCCB设备一文中有说明Zephyr下可以用I2C驱动SCCB
- 1个GPIO用于硬件复位
RT1052的CSI Video驱动在zephyr已经实现,驱动OV7725只需要将OV7725作为senor添加即可。
驱动添加流程
1. 增加设备树绑定
Zephyr内目前没有支持OV7725,要根据OV7725的硬件添加新的设备树绑定,因此需要进行添加才能在设备树中进行使用。对于Sensor来说CSI out是以port的形式和CSI in交互, 这里相关的硬件就只有1个I2C和1个GPIO.
在dts/bindings/video下添加文件omnivision,ov7725.yaml,绑定文件的文件名由厂商名和器件名组成,内容如下:
1 | description: OV7725 CMOS video sensor |
compatible提供绑定名,dts中会引用。properties中的reset-gpios提供硬件复位引脚的绑定。I2C的绑定通过Include i2c-device.yaml来完成
2. 驱动代码添加
源文件
driver/video/下增加文件ov7725.c,里面包含的驱动ov7725的驱动代码,为了使驱动能够访问设备树,需要在文件开头放置如下内容
1 | #define DT_DRV_COMPAT ovti_ov7725 |
其中DT_DRV_COMPAT
定义非常重要,C对设备树中的节点和属性的访问是依靠宏生成的DT_DRV_COMPAT的内容就是设备树中设备区别于其它设备的关键内容,其内容是compatible的值将 , 转化为 _ . 例如这里ovti,ov7725被变为ovti_ov7725。
驱动的实现模式和mt9m114一样,目前主要实现了下面API并注册,由于Zephyr演进很快在我提交PR的时候,review已经要求从DEVICE_AND_API_INIT
修改为DEVICE_DT_INST_DEFINE
, 这点和前面的文章列举的示例代码有所差别。
1 | static const struct video_driver_api ov7725_driver_api = { |
重点分析Zephyr下驱动实现的特点,将配置硬件的部分省略掉。在注册ov7725 device驱动后,Zephyr系统初始化的时候会自动调用ov7725_init_0对ov7725驱动进行初始化,具体流程如下
1 | struct ov7725_data { |
ov7725_init
对ov7725进行初始化就是使用GPIO对ov7725的reset引脚进行操作和使用I2C对ov7725的寄存器进行配置。与硬件相关的配置不做说明,可以参考文末PR连接。
目前实现非常简单,sersor只提供一种格式ov7725_get_caps
给出的caps如下,ov7725支持的格式还很多,可以根据需要再进行添加
1 | static const struct video_format_cap fmts[] = { |
ov7725_set_fmt
会将符合caps的格式进行设置,并将格式保存在驱动内,使用ov7725_get_fmt
时将保存的格式送出,代码如下
1 | static int ov7725_set_fmt(const struct device *dev, |
这是一个简单的驱动实现示例,在ov7725初始化完成后,ov7725就开始工作了,没有提供start和stop的功能,因此ov7725_stream_start
和ov7725_stream_stop
留空不做任何事情
1 | static int ov7725_stream_start(const struct device *dev) |
到这里驱动的代码部分就已经全部完成了。
构建配置修改
在driver/video/下增加Kconfig.ov7725文件,用于配置启用OV7725,内容如下
1 | config VIDEO_OV7725 |
在drivers/video/Kconfig中增加
1 | source "drivers/video/Kconfig.ov7725" |
在drivers/video/CMakeLists.txt中增加如下内容,将ov7725.c加入构建
1 | zephyr_library_sources_ifdef(CONFIG_VIDEO_OV7725 ov7725.c) |
使用
以mm_swiftio为例说明如何使用OV7725
修改DTS
在boards/arm/mm_swiftio/mm_swiftio.dts中添加如下内容,和前面文章mt9m114区别不大,只多一个reset-gpios = <&gpio2 20 GPIO_ACTIVE_HIGH>;
用于指定gpio2.20作为reset引脚
1 | &lpi2c3 { |
添加PIN Mux
不同的开发板方式不一样,mm_swiftio需要在boards/arm/mm_swiftio/pinmux.c中将CSI使用的IO配置为CSI功能
1 | #if DT_NODE_HAS_STATUS(DT_NODELABEL(csi), okay) && CONFIG_VIDEO |
测试程序
这里测试程序就直接借用Zephyr的Sample了,新增文件samples/video/capture/boards/mm_swiftio.conf ,内容为
1 | CONFIG_VIDEO_OV7725=y |
然后使用west build -b mm_swiftio samples/video/capture 编译出结果即可运行测试。
参考
OV7725的支持已提交PR,正在接受review修改,这个版本的只是很基础的功能,以后会根据实际需求逐步添加
https://github.com/zephyrproject-rtos/zephyr/pull/30744/files