GC0308摄像头驱动程序使用的是linux v4l2协议,通过i2c信号进行控制。GC0308摄像头。对上电时序要求非常严格,一定要依据datasheet初始化摄像头。

本驱动使用的3.10内核,所以首先要配置dts,在内核启动阶段支持摄像头,结合硬件原理图。首先配置硬件接口属性:

pinctrl_ipu1_4: ipu1grp-4 { /*++++  GC0308  camera */
fsl,pins = <
MX6QDL_PAD_GPIO_3__CCM_CLKO2 0x130b0 /*时钟*/
MX6QDL_PAD_CSI0_DAT10__GPIO5_IO28 0x80000000 <span style="font-family: Arial, Helvetica, sans-serif;">/*CAM_nRST_CSI0_DAT10*/</span>
MX6QDL_PAD_CSI0_DAT11__GPIO5_IO29 0x80000000 /* DAT11 */ <span style="font-family: Arial, Helvetica, sans-serif;">/*CAM_SHDN_CSI0_DAT11*/</span>
MX6QDL_PAD_CSI0_DAT12__IPU1_CSI0_DATA12 0x80000000 /*12-19八条数据线*/
MX6QDL_PAD_CSI0_DAT13__IPU1_CSI0_DATA13 0x80000000
MX6QDL_PAD_CSI0_DAT14__IPU1_CSI0_DATA14 0x80000000
MX6QDL_PAD_CSI0_DAT15__IPU1_CSI0_DATA15 0x80000000
MX6QDL_PAD_CSI0_DAT16__IPU1_CSI0_DATA16 0x80000000
MX6QDL_PAD_CSI0_DAT17__IPU1_CSI0_DATA17 0x80000000
MX6QDL_PAD_CSI0_DAT18__IPU1_CSI0_DATA18 0x80000000
MX6QDL_PAD_CSI0_DAT19__IPU1_CSI0_DATA19 0x80000000
MX6QDL_PAD_CSI0_DATA_EN__IPU1_CSI0_DATA_EN 0x80000000 /* 硬件悬空*/
MX6QDL_PAD_CSI0_PIXCLK__IPU1_CSI0_PIXCLK 0x80000000 /*像素时钟*/
MX6QDL_PAD_CSI0_MCLK__IPU1_CSI0_HSYNC 0x80000000
MX6QDL_PAD_CSI0_VSYNC__IPU1_CSI0_VSYNC 0x80000000
>;
};

然后配置摄像头属性:

&i2c3{
clock-frequency = <100000>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_i2c3_1>;
status = "okay"; gc0308: gc0308@21{
compatible = "gc0308-capture";
reg = <0x21>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_ipu1_4>; /* GC0308 camera*/
clocks = <&clks 201>;
clock-names = "csi_mclk";
DOVDD-supply = <&vgen4_reg>; /* 1.8v */
AVDD-supply = <&vgen3_reg>; /* 2.8v, on rev C board is VGEN3,
on rev B board is VGEN5 */
DVDD-supply = <&vgen2_reg>; /* 1.5v*/
pwn-gpios = <&gpio5 29 1>; /* active low: SD1_DAT0 */
rst-gpios = <&gpio5 28 0>; /* active high: SD1_DAT1 */
csi_id = <0>;
mclk = <24000000>;
mclk_source = <0>;
}; };

部分内核驱动代码分析:

static const struct i2c_device_id gc0308_id[] = {                                                                     
    {"gc0308-capture", 0},                                                                                            
    {},                                                                                                               
};                                                                                                                    
                                                                                                                      
MODULE_DEVICE_TABLE(i2c, gc0308_id);

将gc0308_id增加i2c队列。当在dts中有对应名字的设备声明时,调用驱动程序的probe函数。

static struct i2c_driver gc0308_i2c_driver = {
.driver = {
.owner = THIS_MODULE,
.name = "gc0308-capture",
},
.probe = gc0308_probe,
.remove = gc0308_remove,
.id_table = gc0308_id,
};

驱动程序初始化的时候,增加到i2c设备。

static s32 gc0308_write_reg(u8 reg, u8 val)
{
u8 au8Buf[3] = {0}; au8Buf[0] = reg;
au8Buf[1] = val; if (i2c_master_send(gc0308_data.i2c_client, au8Buf, 2) < 0) {
pr_err("%s:write reg error:reg=%x,val=%x\n",
__func__, reg, val);
return -1;
} return 0;
}

static s32 gc0308_read_reg(u8 reg, u8 *val)
{
u8 au8RegBuf[2] = {0};
u8 u8RdVal = 0; au8RegBuf[0] = reg; if (1 != i2c_master_send(gc0308_data.i2c_client, au8RegBuf, 1)) {
pr_err("%s:write reg error:reg=%x\n",
__func__, reg);
return -1;
} if (1 != i2c_master_recv(gc0308_data.i2c_client, &u8RdVal, 1)) {
pr_err("%s:read reg error:reg=%x,val=%x\n",
__func__, reg, u8RdVal);
return -1;
} return u8RdVal;
}

I2C数据读写

static struct v4l2_int_ioctl_desc gc0308_ioctl_desc[] = {
{vidioc_int_dev_init_num, (v4l2_int_ioctl_func *)ioctl_dev_init},
{vidioc_int_dev_exit_num, ioctl_dev_exit},
{vidioc_int_s_power_num, (v4l2_int_ioctl_func *)ioctl_s_power},
{vidioc_int_g_ifparm_num, (v4l2_int_ioctl_func *)ioctl_g_ifparm},
{vidioc_int_init_num, (v4l2_int_ioctl_func *)ioctl_init},
{vidioc_int_enum_fmt_cap_num,
(v4l2_int_ioctl_func *)ioctl_enum_fmt_cap},
{vidioc_int_g_fmt_cap_num, (v4l2_int_ioctl_func *)ioctl_g_fmt_cap},
{vidioc_int_g_parm_num, (v4l2_int_ioctl_func *)ioctl_g_parm},
{vidioc_int_s_parm_num, (v4l2_int_ioctl_func *)ioctl_s_parm},
{vidioc_int_g_ctrl_num, (v4l2_int_ioctl_func *)ioctl_g_ctrl},
{vidioc_int_s_ctrl_num, (v4l2_int_ioctl_func *)ioctl_s_ctrl},
{vidioc_int_enum_framesizes_num,
(v4l2_int_ioctl_func *)ioctl_enum_framesizes},
{vidioc_int_g_chip_ident_num,
(v4l2_int_ioctl_func *)ioctl_g_chip_ident},
};

一系列ioctl函数的指针数组,供应用程序调用。

static int get_device_id(void)
{
u8 au8RegBuf[2] = {0};
u8 u8RdVal = 0;
au8RegBuf[0] = 0x00; if (1 != i2c_master_send(gc0308_data.i2c_client, au8RegBuf, 1)) {
pr_err("%s:write reg error:reg=%x\n",
__func__, 0xfb);
return -1;
} if (1 != i2c_master_recv(gc0308_data.i2c_client, &u8RdVal, 1)) {
pr_err("%s:read reg error:reg=%x,val=%x\n",
__func__, 0xfb, u8RdVal);
return -1;
} printk(KERN_INFO "u8RdVal=%x\n\n", u8RdVal); return u8RdVal;
}

读取设备ID,详细读ID的指令,依据datasheet确定。

当ID成功读到了。接下来。设置多个摄像头属性,通常做成一个数组。此时摄像头基本能工作了。

当插入驱动模块以后会在/dev/ 文件夹下产生一个videoX 设备。这时候能够使用cheese xawtv等程序进行測试。

飞思卡尔 imx6 GC0308 摄像头驱动配置调试过程的更多相关文章

  1. 飞思卡尔IMX6处理器的GPIO配置方式

    在linux或android系统中,假如我们要配置飞思卡尔IMX6处理器的GPIO管脚,比如是GPIO_19这个管脚,那么要像这样: [cpp] view plaincopy #define  MX6 ...

  2. [i.MX]飞思卡尔IMX6处理器的GPIO-IOMUX_PAD说明

    在linux或android系统中,假如我们要配置飞思卡尔IMX6处理器的GPIO管脚,比如是GPIO_19这个管脚,那么要像这样: #define MX6Q_PAD_GPIO_19__GPIO_4_ ...

  3. 飞思卡尔imx6开发板Linux下GPIO驱动

    控制GPIO_1_28的输出: #define MY_BOMB_GPIO       IMX_GPIO_NR(1, 28) 配置为输出方式: gpio_direction_output (MY_BOM ...

  4. 基于飞思卡尔i.MX 6Quad Sabrelite开发板的触摸屏调试

    1      概述 本次任务是在飞思卡尔i.MX 6Quqd Sabrelite开发板上调试触屏驱动,触屏芯片是Goodix的gt828芯片,触屏接口是I2C. 操作系统:android 4.0.4 ...

  5. 痞子衡嵌入式:飞思卡尔i.MX RTyyyy系列MCU硬件那些事(2.1)- 玩转板载OpenSDA,Freelink调试器

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是飞思卡尔i.MX RTyyyy系列EVK上板载调试器的用法. 本文是i.MXRT硬件那些事系列第二篇,第一篇痞子衡给大家整体介绍了i.M ...

  6. 痞子衡嵌入式:飞思卡尔i.MX RTyyyy系列MCU硬件那些事(2.2)- 在串行NOR Flash XIP调试原理

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是飞思卡尔i.MX RTyyyy系列EVK在串行NOR Flash调试的原理. 本文是i.MXRT硬件那些事系列第二篇的续集,在第二篇首集 ...

  7. 痞子衡嵌入式:飞思卡尔Kinetis开发板OpenSDA调试器那些事(上)- 背景与架构

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是飞思卡尔Kinetis MCU开发板板载OpenSDA调试器(上篇). 众所周知,嵌入式软件开发几乎离不开调试器,因为写一个稍有代码规模 ...

  8. stm32 HardFault_Handler调试及问题查找方法——飞思卡尔

    看到有朋友遇到Hard Fault 异常错误,特地找到一篇飞思卡尔工程师写的一片经验帖,定位Hard Fault 异常. Kinetis MCU 采用 Cortex-M4 的内核,该内核的 Fault ...

  9. 关于GPL329A添加摄像头驱动需要更改的配置脚本

    我今天要添加一个ov2685的驱动进Digogo这部机子,当然要让它开机自动启动,就要想办法让它的.ko在启动文件系统的时候要自动被装载,这样上层打开摄像头才能加载摄像头驱动. 我找到源码工程对应添加 ...

随机推荐

  1. 北大ACM(POJ1016-Numbers That Count)

    Question:http://poj.org/problem?id=1016 问题点:水题. Memory: 232K Time: 125MS Language: C++ Result: Accep ...

  2. SDK_进度条和滑块

    进度条和滑块 进度条和滑块属于通用控件,通用控件的使用需要加 CommCtrl.h 头文件 如何初始化进度条和滑块的数值范围和默认的位置 // 设置默认的范围值SendDlgItemMessage(h ...

  3. 安卓app测试之cpu监控

    安卓app测试之cpu监控,如何获取监控的cpu数据呢? 一.通过Dumpsys 来取值 1.adb shell dumpsys cpuinfo 二.top 1.top -d 1|grep packa ...

  4. centos 搭建pptp

    很多朋友不会在CENTOS 在安装vpn,因为对于菜鸟来说安装VPN的确是个头晕的事情,特别是安装openvpn,不过安装pptp就稍微简单一点,国内网上有很多安装pptp的教程,但是都很繁杂,我在国 ...

  5. 梦想Android版CAD控件2018.10.12更新

    下载地址: http://www.mxdraw.com/ndetail_10106.html 1. 增加读写对象扩展字典功能 2. 修改样条线显示错误 3. 修改shx文字显示错误 4. 增加向量运算 ...

  6. Python基础之字符的编码

    参考原文 Python廖雪峰 为什么要进行编码? 计算机只能处理二进制数字(0100111),要处理文本,就必须先把文本转为数字才能处理,这个过程就叫编码. 字符的编码 ASCII编码 由于计算机是美 ...

  7. JAVA基础——IO流字节流

    在Java中把不同的输入输出源(键盘.文件.网路连接)抽象表述为“流”. 1.输入流.输出流 .字节输入流通过FileInputStream和来操作 字节输出流通过FileOutputStream来操 ...

  8. Re0:DP学习之路 母牛的故事 HDU - 2018

    解法 一定要注意斐波那契数列的原始意义,斐波那契数列也叫作兔子数列是兔子繁衍的一种表示方法.同样适用于别的情况的动物繁衍问题 原始的是3个月一胎现在四个月那么方程就是 f(n)=n n<=4 f ...

  9. 数据结构---二叉搜索树BST实现

    1. 二叉查找树 二叉查找树(Binary Search Tree),也称为二叉搜索树.有序二叉树(ordered binary tree)或排序二叉树(sorted binary tree),是指一 ...

  10. Java:冒泡排序 | 二分查找

    2018-10-29 20:16:46 冒泡排序 例子(对数字排序): 假设有这样一组数字:32, 8, 128, 2, 64 现在对其进行冒泡排序(*表示下次比较的开始数字): 32>8? t ...