基于S3C6410芯片,linux-2.6.38内核的ov9650摄像头驱动

1编写OV9650驱动之前的准备工作:

1.1 使用资源:

    开发板:S3C6410芯片

Linux内核: linux-2.6.38

CMOS摄像头: ov9650

1.2 了解需要完成的工作:

  1.2.1 背景知识:

I2C驱动:

Linux I2C驱动是嵌入式Linux驱动开发人员经常需要编写的一种驱动,因为凡是系统中使用到的I2C设备,几乎都需要编写相应的I2C驱动去配置和控制它,例如 RTC实时时钟芯片、音视频采集芯片、音视频输出芯片、EEROM芯片、AD/DA转换芯片等等。

 在本例中,ov9650就是对应的I2C设备(但是它并不是用的标准I2C协议,后面会提到)。

1.2.1.1  Linux I2C子系统:

(参考链接:http://blog.csdn.net/jmq_0000/article/details/7473682

在内核中已经提供I2C子系统,所以在做I2C驱动之前,就必须要熟悉该子系统。

基于S3C6410芯片,linux-2.6.38内核的ov9650摄像头驱动

可以看出分为三大组成部分

1)I2C核心(i2c-core)

I2C核心提供了I2C总线驱动和设备驱动的注册、注销方法,I2C通信方法(algorithm)上层的、与具体适配器无关的代码以及探测设备、检测设备地址的上层代码等。

2)I2C总线驱动(I2C adapter/Algo driver)

I2C总线驱动是I2C适配器的软件实现,提供I2C适配器与从设备间完成数据通信的能力。

I2C总线驱动由i2c_adapter和i2c_algorithm来描述。

3I2C客户驱动程序 (I2C client driver)

I2C客户驱动是对I2C从设备的软件实现,一个具体的I2C客户驱动包括两个部分:一部分是i2c_driver,用于将设备挂接于i2c总线;

另一部分是设备本身的驱动。

I2C客户驱动程序由i2c_driver和i2c_client来描述。

所有的I2C驱动代码位于drivers/i2c目录下

*I2c-core.c    实现I2C核心的功能

*I2c-dev.c     通用的从设备驱动

Chips       特定的I2C设备驱动

Busses      I2C适配器的驱动

Algos       实现了一些I2C总线适配器的algorithm

 

1.2.1.2  I2C设备驱动编写步骤

    参考链接:http://www.it165.net/embed/html/201312/2376.html

编写一个I2C设备驱动程序的工作可分为三部分:

1) 定义和注册I2C设备,即构建i2c_client;(在mach-mini6410.c中添加),参考arch/arm/mach-s3c24xx/mach-mini6410.c

        我们不用直接定义一个i2c_client结构,Linux会根据I2C设备的相关信息自动创建i2c_client。所以,我们需要提供I2C设备的相关信息。i2c_client 信息通常在BSP的板文件中通过i2c_board_info 填充。

 

    步骤1:用i2c_board_info结构体保存I2C设备相关信息

    步骤2:调用i2c_register_board_info函数注册i2c设备相关信息

2) 定义和注册I2C设备驱动,即i2c_driver利用内核提供的i2c-dev.c的框架来构建) 参考linux-2.6.38\drivers\i2c\i2c-dev.c

    步骤1:构建i2c_driver定义i2c_driver结构体变量。(struct i2c_driver)。

    步骤2:注册i2c_driver调用i2c_add_driver注册i2c_driver结构体变量。(__init函数中完成)

    步骤3:注销i2c_driver。 (__exit函数中完成)

    3 实现i2c_driver中要示实现的函数

 

几个重要的结构体:

i2c_msg(设置设备地址的)

i2c_client(从机设备的地址,一般采用平台设备的形式,用probe函数探测)

i2c_driver自己构建。

几个重要的方法:

i2c_add_driver添加设备

i2c_transfer用于进行I2C适配器和I2C设备之间的一组消息的交互

1.2.2任务规划

总线驱动:不需要实现,已有。

这里因为内核中已经提供了S3C6410的I2C总线驱动(在/linux-2.6.38/drivers/i2c/busses目录下的i2c-s3c2410.c文件就是总线驱动,虽然是S3C2410的,但是同样支持S3C6410)。

设备驱动:

1需要完成S3C6410 CAMIF的平台资源注册:

arch/arm/mach-s3c24xx/mach-mini6410.c文件中:

  定义并注册S3C6410CAMIFcamera interface

2 然后编写ov9650的设备驱动:

参照 linux-2.6.38\drivers\media\video\ov9640.h ov9640.c

 

 

2 开始编写ov9650驱动

2.1arch/arm/mach-s3c24xx/mach-mini6410.c

OV9650

OV9650的从设备地址:

官方资料:

基于S3C6410芯片,linux-2.6.38内核的ov9650摄像头驱动

 

   注意 由于摄像头本身使用的是SCCB协议(8位地址),换成I2C协议(7位地址后),地址0x60变为0x30

I2CSCCB协议区别:从机地址因为I2C7位地址,最后一位是读写位,而SCCB8位地址,比如ov9650,他是SCCB协议,他的地址是0x60,那么如果挂接到I2C总线上,他的地址就变成0x30了,这样算的:

SCCB地址:::  0x60   0 1 1 0_0 0 0 0     这个0还是地址位

I2C地址::::                 0 1 1 0_0 0 0 0最后红色的0是读写位,那么地址变成了7  +读写位  0 1 1_ 0 0 0 0 +0 读写位  所以从机地址变成了0x30  

 

   参考链接: http://www.cnblogs.com/crazybingo/archive/2012/03/31/2426226.html

 

CAMIF

Tiny6410-1107.pdf

基于S3C6410芯片,linux-2.6.38内核的ov9650摄像头驱动

基于S3C6410芯片,linux-2.6.38内核的ov9650摄像头驱动

编辑linux-2.6.38/arch/arm/mach-s3c64xx/ mach-mini6410.c

1 i2c对应的通道 ,是默认的,不需要修改

static struct i2c_board_info i2c_devs1[] __initdata = {

{

I2C_BOARD_INFO("ov965x", 0x30),    // 可以改为ov9650

},

};

ov9650设备驱动:

参照 linux-2.6.38\drivers\media\video\ov9640.h ov9640.c

对照寄存器地址表,可以看出9640的驱动兼容9650,又省去一大头工作。。。。。

 

其实内核里面的驱动都有了,所以我们不需要写驱动了。。。

只是分析一下大概的结构。

参考资料:

http://blog.csdn.net/mayaoyao11/article/details/6677141

http://www.cnblogs.com/crazybingo/archive/2012/03/31/2426226.html

http://www.cnblogs.com/liugf05/archive/2012/12/11/2812997.html



你可能感兴趣的:(基于S3C6410芯片,linux-2.6.38内核的ov9650摄像头驱动)