第一章 s32v234摄像头驱动
1、驱动的总体框架
s32v234的摄像头驱动实现:在内核空间注册了一个字符设备驱动,然后提供了基本的ioctl函数,同时在用户空间提供了一个库函数,用来对ioctl函数进行封装,这里我们分析的是maxim_user.cpp。
2、用到的主要文件说明
cam_core.c 注册了一个字符设备驱动
cam_ioctl.c 对应的ioctl函数
cam_func.c ioctl函数里面调用的功能函数
maxim_user.cpp 使用maxim串行器摄像头的调用函数,调用cam_fun.c里面的函数
sdi_io.cpp 调用maxim_user.cpp里面的函数
sdi.cpp 调用sdi_io.cpp中的函数
main.cpp 用户的主函数,会去调用sdi.cpp中的函数
3、具体的流程分析
首先是CamInit函数,这个函数里面使用字符设备驱动的形式注册了一个摄像头的设备,它的设备名是cam_generic
这样的话,我们需要着重分析他的ioctl函数,下面我们开始:
IOCTL_CAM_CLI_ADD 增加一个i2c client,它的干活函数CAM_DRV_ClientAdd
IOCTL_CAM_CLI_REM 删除一个i2c client,它的干活函数CAM_DRV_ClientRem
IOCTL_CAM_REG_RDS 读一个寄存器,它的干活函数ReadRegSingle
IOCTL_CAM_REG_WRS 写一个寄存器,它的干活函数WriteRegSingle
其他的参数我们用不上,暂时不列出了
4、对干活的函数进行追踪
CAM_DRV_ClientAdd,这个函数用来增加一个i2c client,这个函数调用了另外一个函数--->
CAM_DRV_I2cClientAdd 在这个函数里面调用了,内核提供的接口函数--->
i2c_get_adapter、i2c_new_device、i2c_put_adapter实现了client的注册
CAM_DRV_ClientRem,这个函数用来删除一个i2c client,这个函数调用了另外一个函数--->
CAM_DRV_I2cClientRem,这个函数由调用了另外一个内核接口函数--->
i2c_del_driver、i2c_unregister_device实现client的删除
ReadRegSingle,这个函数实现了单个寄存器的读功能 --->
sppRegRead 一个函数指针,指向不同宽度的寄存器读函数,这里我们的是8bit --->
CAM_DRV_RegRead8 读8bit的寄存器函数 --->
LinuxI2cRead8 读linux i2c 8bit的寄存器 --->
i2c_master_send、i2c_master_recv 内核中的接口函数实现
WriteRegSingle,这个函数实现了单个寄存器的写功能 --->
sppRegWrite,一个函数指针,这里我们指向的是8位的寄存器函数 --->
CAM_DRV_RegWrite8 写一个8位的寄存器 --->
LinuxI2cWrite8,linux写一个8位的寄存器 --->
i2c_master_send 内核的i2c发送函数,实现写一个寄存器的功能
4、用户层库maxim_user.cpp分析
这层主要是针对不同的摄像头而设计的,这里我们的是maxim_user.cpp这个,最终它会生出一个.a的库文件。
这层函数是对cam_func.c里面的再次封装,我们主要讲如下几个函数。
MAXIM_Open 打开摄像头
MAXIM_Close 关闭摄像头
MAXIM_CsiEnable 使能CSI接口
MAXIM_CsiDisable 关闭CSI接口
MAXIM_OV10640_InitComplex 初始化maxim ov10640,这里要配置寄存器
MAXIM_CAM_RegWrite 写一个摄像头,对WriteRegSingle再次封装
MAXIM_CAM_RegRead 读一个摄像头,对ReadRegSingle再次封装
MAXIM_SER_RegWrite 写一个串行器,
MAXIM_SER_RegRead 读一个串行器,
MAXIM_DES_RegWrite 写一个解串器,
MAXIM_DES_RegRead 读一个解串器,
下面对上面的函数进行分析
MAXIM_Open 打开maxim摄像头函数,这个函数里面注册一个一个解码器的client,调用了初始化函数-->
CAM_ClientAdd 注册了一个解码器、MAXIM_OV10640_InitComplex初始化max ov10640
MAXIM_Close 关闭摄像头函数,这个函数里面主要是删除client -->
CAM_ClientRem 删除client函数
MAXIM_CsiEnable 使能CSI函数,这个函数会去写解串器的使能寄存器 --->
CAM_ReadSingle 写解串期
剩下的几个封装函数,这里不再进行详解
5、接下来我们分析再往上一层的函数,从开始的框架可以知道,是SDI库了
(SDI:Sensor Data Interface Libary 摄像头数据接口库)
我们只以一个MAXIM_Open函数的调用过程来分析
MAXIM_Open <--- 在maxim_user.cpp中
LIB_RESULT sdi_MipiCsiIO::Reserve <--- 在sdi_io.cpp中
mpIOs[i]->Reserve() <--- 在sdi.cpp中
LIB_RESULT sdi_grabber::IOsReserve <--- 在sdi.cpp中
LIB_RESULT sdi_grabber::PreStart() <--- 在sdi.cpp中
arContext.mpGrabber->PreStart() 已经在用户的主函数里面了