当前位置: 首页 > news >正文

驱动开发硬核特训 · Day 30(上篇):深入理解 I2C 总线驱动模型(以 at24 EEPROM 为例)

作者:嵌入式Jerry
视频教程请关注 B 站:“嵌入式Jerry”


一、写在前面

在上一阶段我们已经深入理解了字符设备驱动与设备模型之间的结合方式、sysfs 的创建方式以及平台驱动模型的实际运用。今天我们迈入总线驱动模型的世界,聚焦于 I2C 总线驱动模型,并选取一个典型、真实且广泛使用的驱动设备 —— at24 EEPROM,进行完整分析。

本篇内容将从 I2C 总线模型的架构出发,讲清楚:

  • 驱动如何注册到 I2C 总线上?
  • I2C client 是如何匹配的?
  • at24 是如何成为标准驱动代表的?
  • 如何配置设备树节点?
  • 如何验证实际读写?

并配套提供真实代码与调试示例。


二、I2C 总线驱动模型架构简介

在 Linux 内核中,I2C 总线驱动模型是基于总线-设备-驱动的三层结构之上实现的:

        I2C 总线(i2c_adapter) ←→  I2C 设备(i2c_client) ←→  I2C 驱动(i2c_driver)
  • i2c_adapter:抽象了一个物理 I2C 控制器(主机控制器)
  • i2c_client:抽象了挂在某条 adapter 上的 I2C 外设
  • i2c_driver:抽象了对某种类型 I2C 设备的驱动代码

这和设备模型中的 bus_typedevicedevice_driver 是一致的,i2c-core 就是 bus_type 的实现,负责完成 match 和 probe。


在这里插入图片描述

三、典型案例介绍:at24 EEPROM

我们选择 i2c 子系统中的一个经典外设:at24 系列 EEPROM。它们遵循 I2C 协议,容量常见为 16Kbit/32Kbit/64Kbit,支持页写和顺序读。

在 Linux 内核中,驱动文件为:

drivers/misc/eeprom/at24.c

其本质是一个标准 i2c_driver 驱动。


四、设备树配置

在 NXP i.MX8MP 平台中,at24 EEPROM 可以通过设备树添加,典型配置如下:

&i2c3 {status = "okay";clock-frequency = <400000>;eeprom@50 {compatible = "atmel,24c16";reg = <0x50>;pagesize = <16>;};
};

解释:

  • compatible:用于匹配驱动
  • reg:I2C 地址(7 位)
  • pagesize:页写大小(单位:字节)

五、驱动入口分析

at24.c 中的核心驱动结构如下:

static const struct of_device_id at24_of_match[] = {{ .compatible = "atmel,24c16", .data = (void *)AT24_DEVICE_MAGIC },{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, at24_of_match);static struct i2c_driver at24_driver = {.driver = {.name = "at24",.of_match_table = of_match_ptr(at24_of_match),},.probe_new = at24_probe,.remove = at24_remove,.id_table = at24_ids,
};
module_i2c_driver(at24_driver);

🔍 核心点解析:

  • 使用 of_match_table 进行设备树匹配;
  • 使用 module_i2c_driver 宏注册;
  • probe 函数负责初始化工作,注册字符设备。

六、字符设备注册逻辑

at24 实现为字符设备,允许用户从 /dev 直接读写 EEPROM 数据。

ret = devm_device_add_groups(&client->dev, at24_groups);
cdev_init(&at24->cdev, &at24_fops);
ret = cdev_add(&at24->cdev, at24->devt, 1);
device_create(...);

最终会创建出:

/dev/eeprom
/sys/class/eeprom/eeprom0

文件操作如下:

static const struct file_operations at24_fops = {.owner = THIS_MODULE,.llseek = no_llseek,.read = at24_read,.write = at24_write,.open = at24_open,
};

七、匹配过程剖析

整个驱动匹配过程:

  1. at24 驱动通过 of_match_table 注册支持 "atmel,24c16"
  2. i2c-core 扫描设备树时发现此节点
  3. 创建 i2c_client,并匹配 i2c_driver
  4. 调用 at24_probe(),完成驱动绑定

八、调试验证操作

加载驱动后会创建字符设备:

ls /dev/eeprom

我们可以直接写入:

echo "hello" > /dev/eeprom

再读取:

hexdump -C /dev/eeprom

若权限不足,可添加 udev 规则或通过 root 权限访问。


九、at24 驱动完整结构总览

+-----------------------------+
|        I2C Adapter         |
|   (控制器,如i.MX8MP)   |
+-------------+-------------+|v
+-------------+-------------+
|         I2C Client        | ←─────────────── 由设备树注册
|     i2c_client @ 0x50     |
+-------------+-------------+|v
+-------------+-------------+
|         I2C Driver        | ←─────────────── drivers/misc/eeprom/at24.c
|       i2c_driver: at24    |
+-------------+-------------+|v
+-------------+-------------+
|       Character Device    | ←─────────────── /dev/eeprom
|    file_operations: fops  |
+---------------------------+

🔟 总结与思考

通过 at24 EEPROM 的驱动分析,我们掌握了 I2C 总线驱动模型的完整机制:

关键组成说明
i2c_adapter控制器抽象,如 i2c3
i2c_client挂载在 adapter 上的设备
i2c_driver与 client 匹配的驱动
device tree提供匹配入口
字符设备提供用户访问接口

相比 platform 模型,I2C 总线驱动具有自动枚举能力,更适合标准器件(如 EEPROM、音频 codec、传感器等)。


✅ 今日任务巩固

  1. I2C 总线模型中,clientdriver 如何匹配?
  2. at24 驱动中,字符设备注册在哪个函数中?
  3. 如何通过设备树指定 I2C 地址与页大小?
  4. EEPROM 驱动是否需要实现 read/write
  5. 与 platform_driver 模型的区别有哪些?

📢 后续预告

在下一篇(Day 30 下篇)中,我们将围绕 lm48100q 音频 codec 展开,深入讲解 音频子系统 + I2C 驱动模型 的高级应用与集成技巧,敬请期待!


本文由 嵌入式Jerry 原创发布,转载请注明出处
视频教程请关注 B 站:“嵌入式Jerry”

http://www.xdnf.cn/news/336727.html

相关文章:

  • Dynamic Causal Modeling在医疗AI领域的编程案例与应用研究
  • 〖 Linux 〗解决 VS Code 远程连接服务器的常见问题
  • iPhone手机连接WiFi异常解决方法
  • 【hadoop】案例:Sqoop迁移仓库数据
  • 5、开放式PLC梯形图编程组件 - /自动化与控制组件/open-plc-programming
  • Lua学习笔记
  • 无刷电机控制算法策略
  • AI驱动的制造工艺:系统化探索与创新
  • 【hadoop】Hbase java api 案例
  • 【嵌入式开发-CAN】
  • 美化IDEA注释:Idea 中快捷键 Ctrl + / 自动注释的缩进(避免添加注释自动到行首)以及 Ctrl + Alt + l 全局格式化代码的注释缩进
  • Java 异常
  • 深入理解 Docker 网络原理:构建高效、灵活的容器网络
  • 缓存局部性保留
  • 【Python】PDF文件处理(PyPDF2、borb、fitz)
  • 2022年8月,​韩先超对中移信息进行微服务架构原理(Docker+k8s+DevOps+Go等)培训
  • MYSQL的行级锁到底锁的是什么东西
  • iOS 模块化开发流程
  • DeepSeek多尺度数据:无监督与原则性诊断方案全解析
  • 查看jdk是否安装并且配置成功?(Android studio安装前的准备)
  • Vue3 + Node.js 实现客服实时聊天系统(WebSocket + Socket.IO 详解)
  • 大模型深度思考与ReAct思维方式对比
  • Linux下部署Keepalived
  • Oracle免费认证来袭
  • 计算机学习路线与编程语言选择(信息差)
  • 排序算法-选择排序
  • 计算机网络常识:缓存、长短连接 网络初探、URL、客户端与服务端、域名操作 tcp 三次握手 四次挥手
  • v-model原理详解
  • Java 对象克隆(Object Cloning)详解
  • 【统计学基础】随机抽样的特点