fs4412开发板学习笔记(七)

来源:互联网 发布:网络竞价排名 编辑:程序博客网 时间:2024/06/05 07:50
摄像头驱动:目录:Linux3.0 drivers\media\video    Linux3.14.29  drivers\media\i2c\soc_cameraCMOS摄像头驱动:一、device1.设备地址    从OV3640_CSP_11_SPEC.pdf  P39可知道到    The device slave addresses are 0x78 for write (01111000)                                                 and 0x79 for read  (01111001)I2C的地址:  8bit的地址=7bit设备地址+1bit的读/写控制位因此该设备地址=0111100 =0x3C二、driver/*1.1 分配、设置一个i2c_driver*/static struct i2c_driver cmos_ov3640_driver={    .driver={        .name = "cmos_ov3640",        .owner=THIS_MODULE,    },    .probe   =cmos_ov3640_probe,    .remove  =cmos_ov3640_remove,    .id_table=cmos_ov3640_id_table,}; static int cmos_ov3640_drv_init(void){    /*1.2 注册*/    i2c_add_driver(&cmos_ov3640_driver);    return 0;}static const struct v4l2_file_operations cmos_ov3640_fops={    .owner          =THIS_MODULE,    .open           =cmos_ov3640_open,    .release        =cmos_ov3640_close,    .unlocked_ioctl =video_ioctl2,    .read       =cmos_ov3640_read,};static const struct v4l2_ioctl_ops cmos_ov3640_ioctl_ops={        // 表示它是一个摄像头设备    .vidioc_querycap      = cmos_ov3640_vidioc_querycap,        /* 用于列举、获得、测试、设置摄像头的数据的格式 */    .vidioc_enum_fmt_vid_cap  = cmos_ov3640_vidioc_enum_fmt_vid_cap,    .vidioc_g_fmt_vid_cap     = cmos_ov3640_vidioc_g_fmt_vid_cap,    .vidioc_try_fmt_vid_cap   = cmos_ov3640_vidioc_try_fmt_vid_cap,    .vidioc_s_fmt_vid_cap     = cmos_ov3640_vidioc_s_fmt_vid_cap,        /* 缓冲区操作: 申请/查询/放入队列/取出队列 */    .vidioc_reqbufs       = cmos_ov3640_vidioc_reqbufs,    /*说明:因为本次是通过读的方式来获得摄像头数据,因此     *查询/放入队列/取出队列这些函数将不需要     */#if 0    .vidioc_querybuf      = cmos_ov3640_vidioc_querybuf,    .vidioc_qbuf          = cmos_ov3640_vidioc_qbuf,    .vidioc_dqbuf         = cmos_ov3640_vidioc_dqbuf,#endif    // 启动/停止    .vidioc_streamon      = cmos_ov3640_vidioc_streamon,    .vidioc_streamoff     = cmos_ov3640_vidioc_streamoff,   };/* 2.1 分配、设置一个video_device结构体 */static struct video_device cmos_ov3640_vdev={    .release       =cmos_ov3640_release,    .fops      =&cmos_ov3640_fops,    .ioctl_ops     =&cmos_ov3640_ioctl_ops,    .name      ="cmos_ov3640",};static int cmos_ov3640_probe(struct i2c_client *client, const struct i2c_device_id *id){    int ret;    printk("%s %s %d\n",__FILE__,__FUNCTION__,__LINE__);    /*2.3 硬件相关*/    /*2.3.1 映射相应的寄存器*/    /*2.3.2 设置相应的GPIO用于CAMIF(摄像头接口)*/    /*2.2 注册*/    //-1表示让系统自动找一个设备节点号    ret=video_register_device(&cmos_ov3640_vdev,VFL_TYPE_GRABBER,-1);    return 0;}======================编译测试该框架是否可以。(若没有配置,编译内核会有:WARNING: "video_ioctl2" [/home/linux/workdir/camera/cmos_ov3640/cmos_ov3640_drv.ko] undefined!WARNING: "__video_register_device" [/home/linux/workdir/camera/cmos_ov3640/cmos_ov3640_drv.ko] undefined!   insmod内核的时候也会失败,符号无法识别。)首先:重新配置内核:make menuconfig    Device Drivers  --->            <*> Multimedia support  --->               [*]   Cameras/video grabbers support              [*]   V4L platform devices  --->                               <*>   SoC camera support                                                                                            x x                           <*>   platform camera support     编译:make uImage    使用新内核:cp arch/arm/boot/uImage /tftpboot/uImage_3.14.29 -rfstatic int cmos_ov3640_remove(struct i2c_client *client){    printk("%s %s %d\n",__FILE__,__FUNCTION__,__LINE__);    video_unregister_device(&cmos_ov3640_vdev);//如果没有这个,insmod的时候会发生如下的错误。    return 0;}[   43.250000] /home/linux/workdir/camera/cmos_ov3640/cmos_ov3640_drv.c cmos_ov3640_probe 173[   43.255000] ------------[ cut here ]------------[   43.260000] WARNING: CPU: 0 PID: 1196 at drivers/media/v4l2-core/v4l2-dev.c:779 __video_register_device+0xee4/0xf74()//=========>>                                                                            /* the v4l2_dev pointer MUST be present */                                                                                if (WARN_ON(!vdev->v4l2_dev))                                                                                    return -EINVAL;[   43.270000] Modules linked in: cmos_ov3640_drv(O+) cmos_ov3640_dev(O)[   43.275000] CPU: 0 PID: 1196 Comm: insmod Tainted: G           O 3.14.29 #4[   43.285000] [<c0013d90>] (unwind_backtrace) from [<c00111f0>] (show_stack+0x10/0x14)[   43.290000] [<c00111f0>] (show_stack) from [<c03d653c>] (dump_stack+0x64/0xb4)[   43.300000] [<c03d653c>] (dump_stack) from [<c001ce6c>] (warn_slowpath_common+0x68/0x88)[   43.305000] [<c001ce6c>] (warn_slowpath_common) from [<c001cea8>] (warn_slowpath_null+0x1c/0x24)[   43.315000] [<c001cea8>] (warn_slowpath_null) from [<c02cb650>] (__video_register_device+0xee4/0xf74)[   43.325000] [<c02cb650>] (__video_register_device) from [<bf0040a0>] (cmos_ov3640_probe+0x3c/0x70 [cmos_ov3640_drv])[   43.335000] [<bf0040a0>] (cmos_ov3640_probe [cmos_ov3640_drv]) from [<c02c5808>] (i2c_device_probe+0xac/0xd4)[   43.345000] [<c02c5808>] (i2c_device_probe) from [<c024a4bc>] (driver_probe_device+0x104/0x228)[   43.355000] [<c024a4bc>] (driver_probe_device) from [<c024a66c>] (__driver_attach+0x8c/0x90)[   43.365000] [<c024a66c>] (__driver_attach) from [<c0248e00>] (bus_for_each_dev+0x58/0x88)[   43.370000] [<c0248e00>] (bus_for_each_dev) from [<c0249c70>] (bus_add_driver+0xd8/0x1cc)[   43.380000] [<c0249c70>] (bus_add_driver) from [<c024ac84>] (driver_register+0x78/0xf4)[   43.385000] [<c024ac84>] (driver_register) from [<c02c770c>] (i2c_register_driver+0x2c/0xb4)[   43.395000] [<c02c770c>] (i2c_register_driver) from [<bf0040e8>] (cmos_ov3640_drv_init+0x14/0x20 [cmos_ov3640_drv])[   43.405000] [<bf0040e8>] (cmos_ov3640_drv_init [cmos_ov3640_drv]) from [<c00087b4>] (do_one_initcall+0x30/0x144)[   43.415000] [<c00087b4>] (do_one_initcall) from [<c00755cc>] (load_module+0x173c/0x1c68)[   43.425000] [<c00755cc>] (load_module) from [<c0075bd4>] (SyS_init_module+0xdc/0xe0)[   43.430000] [<c0075bd4>] (SyS_init_module) from [<c000e420>] (ret_fast_syscall+0x0/0x30)[   43.440000] ---[ end trace 3b8e306fb947a72a ]---[   43.445000] video_register_device error![   43.450000] cmos_ov3640: probe of 0-003c failed with error -1e:\fs4412\linux-3.14.29_c\drivers\media\v4l2-core\V4l2-dev.c933 if (vdev->v4l2_dev)934     v4l2_device_get(vdev->v4l2_dev);//出错处            ||           /**增加引用计数            * kref_get - increment refcount for object.            * @kref: object.            */        static inline void kref_get(struct kref *kref)        {            /* If refcount(重新计算) was 0 before incrementing(增量的)              * then we have a race(比赛)             * condition(条件、情况) when this kref is freeing by              * some other thread right now.             * In this case one should use kref_get_unless_zero()             */            WARN_ON_ONCE(atomic_inc_return(&kref->refcount) < 2); //这里出错.??????????        }
0 0