Linux I²C 驱动 & 模拟 I²C 总线开发

一、 Linux I²C 驱动模型简介

1. 三大核心结构

结构体作用
i2c_adapter表示一条 I²C 总线(硬件或虚拟)
i2c_client表示挂在总线上的一个 I²C 设备
i2c_driver表示驱动程序,用于识别并驱动 i2c_client

二、 I²C 驱动与设备匹配机制

方式一:通过设备树匹配

✅ 设备树节点
&i2c0 {
    ap3216c@1e {
        compatible = "lite-on,ap3216c";
        reg = <0x1e>;
    };
};
✅ 驱动中匹配方式
static const struct of_device_id of_match_ids_ap3216c[] = {
    { .compatible = "lite-on,ap3216c" },
    { }
};

static struct i2c_driver i2c_ap3216c_driver = {
    .driver = {
        .name = "ap3216c", // 也可用于调试信息显示
        .of_match_table = of_match_ids_ap3216c,
    },
    .probe = ap3216c_probe,
    .remove = ap3216c_remove,
    .id_table = ap3216c_ids,
};

⚠️ 驱动中的 .name 不直接参与匹配,但用于日志和 fallback 名称识别。(会在某些兜底机制(fallback)中参与匹配)


方式二:手动注册 i2c_client

适用于平台不支持设备树或快速调试场景。

static struct i2c_board_info board_info = {
    I2C_BOARD_INFO("ap3216c", 0x1e),
};

struct i2c_adapter *adapter = i2c_get_adapter(0);
struct i2c_client *client = i2c_new_device(adapter, &board_info);

匹配依赖 i2c_device_id

static const struct i2c_device_id ap3216c_ids[] = {
    { "ap3216c", 0 },
    { }
};

三、 GPIO 模拟 I²C(Bit-Banging)

1. 原理:用 GPIO 手动控制 SDA/SCL 电平

  • SDA、SCL 都是 GPIO
  • 使用 udelay() 控制时序
  • 可封装 start() / stop() / send_byte() / recv_byte() 等函数

2. 优点与缺点

优点缺点
不依赖硬件控制器占用 CPU
简单、通用时序受限,效率低

3. 示例函数框架(伪代码)

void i2c_start(void) {
    sda_high(); scl_high(); udelay(5);
    sda_low();  udelay(5);
    scl_low();  udelay(5);
}

void i2c_stop(void) {
    sda_low();  scl_high(); udelay(5);
    sda_high(); udelay(5);
}

4. 利用 Linux i2c-gpio 框架

DTS 配置
i2c_gpio: i2c-gpio {
    compatible = "i2c-gpio";
    gpios = <&gpio1 10 GPIO_ACTIVE_HIGH>, <&gpio1 11 GPIO_ACTIVE_HIGH>; // SDA, SCL
    i2c-gpio,delay-us = <5>;
};
自动创建 /dev/i2c-X 节点
modprobe i2c-gpio-custom bus0=0,10,11

四、 软件模拟 I²C 总线(虚拟 I²C)

✅ 1. 本质:注册一个自定义的 i2c_adapter,告诉内核“这是条 I²C 总线”

g_adapter = kzalloc(...);
g_adapter->algo = &i2c_bus_virtual_algo;
i2c_add_adapter(g_adapter);  // 内核正式登记这条总线

✅ 2. 定义通信算法 i2c_algorithm

const struct i2c_algorithm i2c_bus_virtual_algo = {
	.master_xfer    = i2c_bus_virtual_master_xfer,  // 收发数据的函数
	.functionality  = i2c_bus_virtual_func,
};

这告诉内核这条“虚拟 I²C 总线”怎么通信、支持哪些功能。


✅ 3. 配合设备树创建总线和子设备

i2c_bus_virtual@0 {
    compatible = "100ask,i2c-bus-virtual";
    #address-cells = <1>;
    #size-cells = <0>;

    eeprom@50 {
        compatible = "atmel,24c02";
        reg = <0x50>;
    };
};

✅ 4. 驱动行为流程总结

步骤描述
1设备树中匹配 compatible
2platform 驱动注册触发 probe
3在 probe 中创建 i2c_adapter 并注册
4内核根据设备树中挂载的子节点创建 i2c_client
5i2c_driver 匹配到 i2c_client,调用对应 probe
6数据读写通过 master_xfer 模拟转发到软件逻辑中

✅ 五、统一总结一句话:

只要你实现了并注册了 i2c_adapter,无论底层是硬件、GPIO、甚至纯软件模拟,Linux 内核就认为你提供了一条合法的 I²C 总线。


小结对比表:各种 I²C 实现方式

实现方式控制方式是否真实硬件是否注册 i2c_adapter场景推荐
硬件 I²CSoC 控制器正式产品
GPIO 模拟 I²C控制 GPIO是(通过 i2c-gpio没有硬件 I²C
软件虚拟 I²C纯软件逻辑测试、模拟器、教学
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值