嵌入式学习-I2C子系统(2)

<驱动开发>

一、i2c子系统框架

1.1 工作原理

1.2 分配i2c_driver对象

#include <linux/i2c.h>

struct i2c_driver {

    int (*probe)(struct i2c_client *client, const struct i2c_device_id *id);  //匹配成功执行probe函数

    int (*remove)(struct i2c_client *client);//分离时执行remove函数

    struct device_driver driver; //父类

    const struct i2c_device_id *id_table; //idtable匹配

};

struct device_driver {

        const char    *name; //名字

        const struct of_device_id  *of_match_table; //设备树匹配

};       

1.3 注册

i2c_add_driver(struct i2c_driver *driver);

1.4 注销

void i2c_del_driver(struct i2c_driver *driver);

1.5 一键注册宏

module_i2c_driver(i2c_driver结构体变量名字)

1.5 代码实例

#include <linux/init.h>

#include <linux/module.h>

#include <linux/i2c.h>

int si7006_probe(struct i2c_client *client, const struct i2c_device_id *id)

{

    //设备驱动层和总线驱动层匹配成功执行函数

    printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);

    return 0;

}

int si7006_remove(struct i2c_client *client)

{

    //设备驱动层和总线驱动层分离执行函数

    printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);

    return 0;

}

const struct of_device_id ofmatch[] = {

    {.compatible = "hqyj,si7006"},

    {},

};

//分配i2c_driver对象

struct i2c_driver si7006 = {

    .probe = si7006_probe,

    .remove = si7006_remove,

    .driver = {

        .name  = "hahaha",

        .of_match_table = ofmatch,

    },

};

//一键注册i2c子系统宏

module_i2c_driver(si7006);

MODULE_LICENSE("GPL");

二、i2c子系统设备树编写

2.1 硬件电路图连接

2.2 分析内核设备树

linux@ubuntu:~/linux-5.10.61/arch/arm/boot/dts$ vi stm32mp151.dtsi

        i2c1: i2c@40012000 { =========> 节点取别名 i2c1 = i2c@40012000

            compatible = "st,stm32mp15-i2c";  =========> 厂商固定含义键

            reg = <0x40012000 0x400>; =========> 寄存器地址,以及地址长度固定固定含义键

            #address-cells = <1>;

            #size-cells = <0>;

            status = "disabled";  =========> 工作状态没有使能

        };

2.3 分析内核帮助文档

1、参考帮助文档得到如下信息

    linux@ubuntu:~/linux-5.10.61/Documentation/devicetree/bindings/i2c$ vi i2c-s3c2410.txt

    si7006@40 {

            compatible = "hqyj,si7006"; =========> 和设备驱动层匹配固定含义键

            reg = <0x40>;  =========> 从机地址

        };

2、在内核中,查看在其他文件中如何引用i2c1节点

    linux@ubuntu:~/linux-5.10.61$ grep "&i2c1" * -nR

    linux@ubuntu:~/linux-5.10.61$ vi arch/arm/boot/dts/stm32mp15xx-dkx.dtsi +206

    &i2c1 {                                                                                                                             

        pinctrl-names = "default", "sleep"; =========> 设置引脚复用功能模式

        pinctrl-0 = <&i2c1_pins_a>; =========> ?????????查看i2c1_pins_a这个节点作用?????????

        pinctrl-1 = <&i2c1_sleep_pins_a>;  =========> 休眠状态

        //设置i2c控制器上升沿和下降沿时间

        i2c-scl-rising-time-ns = <100>; // 上升沿时间

        i2c-scl-falling-time-ns = <7>;  // 下降沿时间

        status = "okay";    //工作状态okay

        //删除键值对信息

        /delete-property/dmas;

        /delete-property/dma-names;

    };

3、 在内核中,查看在其他文件中引用i2c1_pins_a节点作用? 

    查找结果:arch/arm/boot/dts/stm32mp15-pinctrl.dtsi:436:    i2c1_pins_a: i2c1-0 {

436    i2c1_pins_a: i2c1-0 {

437        pins {

438            pinmux = <STM32_PINMUX('D', 12, AF5)>, /* I2C1_SCL */

439                  <STM32_PINMUX('F', 15, AF5)>; /* I2C1_SDA */

440            bias-disable;

441            drive-open-drain;

442            slew-rate = <0>;

443        };

444    };

========================================================================================================

453    i2c1_pins_b: i2c1-1 {

454        pins {

455            pinmux = <STM32_PINMUX('F', 14, AF5)>, /* I2C1_SCL */

456                  <STM32_PINMUX('F', 15, AF5)>; /* I2C1_SDA */

457            bias-disable;

458            drive-open-drain;

459            slew-rate = <0>;

460        };

461    };

1.4 编写i2c设备树

1.添加设备树目录:linux@ubuntu:~/linux-5.10.61/arch/arm/boot/dts$ vi stm32mp157a-fsmp1a.dts


    &i2c1 {                                                                                                                             

        pinctrl-names = "default", "sleep";

        pinctrl-0 = <&i2c1_pins_b>;

        pinctrl-1 = <&i2c1_sleep_pins_b>;

        //设置i2c控制器上升沿和下降沿时间

        i2c-scl-rising-time-ns = <100>; // 上升沿时间

        i2c-scl-falling-time-ns = <7>;  // 下降沿时间

        status = "okay";    //工作状态okay

        //删除键值对信息

        /delete-property/dmas;

        /delete-property/dma-names;

        si7006@40 {

            compatible = "hqyj,si7006";

            reg = <0x40>;

        };

    };

2、编译拷贝

    linux@ubuntu:~/linux-5.10.61$ make dtbs

      DTC    arch/arm/boot/dts/stm32mp157a-fsmp1a.dtb

    linux@ubuntu:~/linux-5.10.61$ cp arch/arm/boot/dts/stm32mp157a-fsmp1a.dtb ~/tftpboot/

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容