原创 从零开始摄像头驱动设计(一)_I2C框架及设备树插件应用

2024-3-31 09:22 1519 14 3 分类: MCU/ 嵌入式 文集: Rockchip
前言

像我这样很多学习驱动的同学都会想一个问题:学了这个能干嘛?学了那个能干嘛?

姑且找找网络上开源的项目,找找,看看,还是一脸懵。因为开源只提供源码和大致介绍下做什么和有什么。而面对于基础开发者的博客还是很少的。甚至有的博主只是放一些定义,丢几个结构体的注释就完结。我曾经就是通过查缺补漏才形成了一个完整的项目框架。

借此,我打算撰写一套驱动的开发流程,从硬件调试到驱动框架搭建,到系统调用验证。

因为AI的盛行,自动驾驶,人脸识别等应用都成了市场的领航者。而他们用到的最多的基础配件都是SOC和摄像头模块等,所以我后面将针对摄像头的开发流程撰写一整套系列教程。希望可以供小白参考学习,也期待大佬进行点评。

不说废话了,接下来请看我的展示。

在开始之前有必要说明下硬件环境:

  • 主芯片:瑞芯微的rv1126
  • 摄像头:ov5640
  • 内核版本:Linux 4.19

市面大多数摄像头都是使用I2C进行配置和初始化的,这里的I2C有时也叫SCCB,不过基本时序差不多的,一般不做区分。

一、确定I2C硬件连接正确

  1. 硬件接线:先将摄像头的i2c接到主板上的对应I2C上,然后接上电源,我的OV5640模块是接5V和3.3V
  2. 使用i2c-tool工具查看摄像头的i2c地址,下面介绍有两种方式

第一种

  • 命令行输入

i2cdetect -y 1 //“1”代表I2C编号,一般一个SOC有很多I2C,如果接的是I2C0,这里就写0

得到如下结果,3c则是当前摄像头的i2c设备地址,这里先说明一下,如果3C这个地址被驱动使用,则显示UU

  • 试试得到设备的各个寄存器的值,使用如下命令

i2cdump -f -y 1 0x3c

将得到如下结果

有这两个基本够用了,如果想了解更多,则可以看看如下文章

Linux系统下i2c工具 i2c-tool 的使用 

第二种

查看数据手册

看到这里就有人有疑问了,为啥这里的设备地址是78,而第一种方法得到的是3C。这个疑问我有个文章写过 ( I2C简单实验之LT6911UXC读取ChipID),大家可以看下,我也贴在这

然后咱们就可以使用i2c-tool进行调试了。

二、I2C驱动基本框架的搭建

我曾在 I2C简单实验之LT6911UXC读取ChipID搭建过一个基本框架,这里再给大家分享一个比较简单的框架

static int ov5640_probe(struct i2c_client *client, const struct i2c_device_id *id)
  • {
  • dev_info(dev,"\r\n this function is %s",__FUNCTION__);//封装好的打印api,其实就是经过一番操作最后调用printk函数
  • return 0;
  • }
  • static int ov5640_probe(struct i2c_client *client, const struct i2c_device_id *id)
  • {
  • dev_info(dev,"\r\n this function is %s",__FUNCTION__);
  • return 0;
  • }
  • const struct i2c_device_id ov5640_id[]={
  • {"ov5640",0},
  • {}
  • };
  • MODULE_DEVICE_TABLE(i2c, ov5640_id);
  • static const struct of_device_id ov5640_of_match[] = {
  • { .compatible = "ovti,ov5640" },
  • { /* sentinel */ }
  • };
  • MODULE_DEVICE_TABLE(of, ov5640_of_match);
  • static struct i2c_driver ov5640_i2c_driver = {
  • .driver = {
  • .of_match_table = of_match_ptr(ov5640_of_match),
  • .name = "ov5640",
  • },
  • .probe = ov5640_probe,
  • .remove = ov5640_remove,
  • .id_table = ov5640_id,
  • };
  • //这里是linux封装好的api,其中已经包含了init ,exit以及I2C设备的注册过程。
  • module_i2c_driver(ov5640_i2c_driver);
  • MODULE_DESCRIPTION("Omnivision OV5640 Camera Driver");
  • MODULE_AUTHOR("LY");
  • MODULE_LICENSE("GPL v2");
  • 复制代码

    代码阅读顺序

    按照以上的阅读顺序,有一点基础的同学肯定一目了然。这里就不做过多说明。

    三、设备树插件的使用

    设备树插件的原理和基本运用我在早期的文章已经写过:设备树插件_configfs学习笔记

    这里贴一下使用方式,毕竟原理大致了解了就行了。使用之前先下载好驱动

    链接: https://pan.baidu.com/s/1uuwqCwlZNkSLorEWTmkFrQ 提取码: 5dbv

    加载方式跟普通驱动加载方式一样,俩个命令加载insmod和卸载rmmod

    1.编写dts文件

    /dts-v1/;
  • /plugin/;
  • /{
  • fragment@0{
  • target=<&i2c1>;
  • __overlay__{
  • ov5640:ov5640@3c{
  • status="okay";
  • compatible = "ovti,ov5640";
  • reg=<0x3c>;
  • };
  • };
  • };
  • 复制代码

    2. 编译

    • 编译的方式和编译设备树是一样的

    sdk/kernel/scripts/dtc/dtc -I dts -O dtb overlay.dts -o overlay.dtbo

    • 反编译为

    sdk/kernel/scripts/dtc/dtc -I dtb -O dts overlay.dtbo -o overlay.dts

    3. 使用

    • 通过第三节加载相关驱动后,进入设备树插件相关configfs中

    cd /sys/kernel/config/device-tree/overlays

    • 创建一个内核对象

    mkdir test

    • 使用命令将dtbo写入到内核对象

    cat /overlay.dtbo > /test/dtbo

    • 使能dtbo

    echo 1>/test/status

    • 通过以下方式将能看到加载的节点

    ls /proc/device-tree/i2c@ff510000/

    如图所示

    四、加载之前编写好的i2c驱动

    1. 加载驱动之前需要先编译成KO文件,可以使用如下模板

    obj-m += <驱动的c文件名>.o
  • KDIR:=<内核路径>
  • PWD?=$(shell pwd)
  • all:
  • make -C $(KDIR) M=$(PWD) modules
  • clean:
  • rm -f *.ko *.o *.mod.o *.mod.c *.symvers *.order
  • 复制代码

    编译命令 make

    1. 加载

    insmod <驱动的C文件名>.KO

    正确执行了probe函数,证明我们的驱动和设备树插件都使用的完全正确。


    原文链接

    作者: 二月半, 来源:面包板社区

    链接: https://mbb.eet-china.com/blog/uid-me-1862109.html

    版权声明:本文为博主原创,未经本人允许,禁止转载!

    PARTNER CONTENT

    文章评论1条评论)

    登录后参与讨论

    开发工匠 2024-4-24 10:03

    写的好,学习和参考
    相关推荐阅读
    二月半 2025-06-17 16:39
    13. ESP32开发之定时器中断
    概述相关API函数举例:定时发送一个事件总结概述ESP32有一组外设--定时器组。它可以选择不同的时钟源和分配系数。该定时器应用灵活,超时报警可以自动更新计数值。相关API函数1.定时器配置结构体ty...
    二月半 2025-06-12 14:32
    【拆解】一款远程控制开关
    七年前买了个远程控制开关,想想那个时候应该物联网才兴起的时候吧。如今因为控制麻烦且经常出现连接掉线问题,于是给淘汰了。这个设备我是拿来控制吊灯,特别麻烦的是,当晚上关灯后,会有一点灯点亮着,掉线的时候...
    二月半 2025-06-12 10:11
    ESP32开发之GPIO中断
    电路图GPIO的中断类型相关API函数应用举例总结电路图在ESP32中内部有完整的控制电路,比如上下拉以及滤波器等,所以我们这里可以直接用一个微动开关连接到地。GPIO的中断类型GPIO_INTR_D...
    二月半 2025-06-09 22:37
    ESP32开发之WS2812B控制
    WS2812B数据手册重点摘录硬件电路Remote Control Transceive(RMT)概念RMT的相关API函数一段简单的控制WS2812B的应用举例总结WS2812B数据手册重点摘录WS...
    二月半 2025-06-04 09:07
    10. ESP32开发之LED闪烁和呼吸的实现
    硬件电路介绍GPIO输出模式GPIO配置过程闪烁灯的源码LED PWM的控制器(LEDC)概述LEDC配置过程及现象整体流程硬件电路介绍电路图如下:只要有硬件基础的应该都知道上图中,当GPIO4的输出...
    二月半 2025-06-02 21:24
    【Milk-V Duo 开发板】+初用体验
    许久未在面包板社区申请板卡评测了。这一次偶然最近的这款Milk-V Duo开发板正在评测。首次看到如此简单切功能强大的嵌入式平台:· 支持linux、rtos· 可接一路Camera,做人脸检测、目标...
    我要评论
    1
    14
    关闭 站长推荐上一条 /4 下一条