Linux I2C驱动怎么写?i2c_driver和probe怎么填?用户态怎么访问?嵌入式Linux面试

浏览量:56
时间: 2026-10-07 10:02:40
一句话答案

I2C 驱动用 i2c_driver 结构体注册,id_table 或 of_match_table 匹配设备;probe 函数在设备匹配时调用,初始化硬件、创建 cdev 或 sysfs;用户态通过 /dev/i2c-X(i2c-dev)或 sysfs 访问;I2C 核心提供 i2c_transfer/i2c_smbus_* 收发函数,驱动不要直接操作寄存器。

本文概述

I2C 驱动是 Linux 字符设备常见类型,面试常考:i2c_driver、probe、设备树匹配、用户态访问。回答要给驱动框架。

核心要点

  • i2c_driver 注册:driver.name、probe、remove、id_table(传统)或 of_match_table(设备树)

  • probe 函数:i2c_check_functionality、初始化硬件、创建 cdev/sysfs、保存 client

  • 收发:i2c_transfer(通用)或 i2c_smbus_read_byte_data/i2c_smbus_write_byte_data(SMBus)

  • 设备树匹配:of_match_table 里 compatible 字符串和 dts 里一致

  • 用户态访问:/dev/i2c-X(i2c-dev,ioctl 读写)或 /sys/bus/i2c/devices/ 下的 sysfs

终端显示 Linux I2C 驱动代码,i2c_driver、probe、sysfs,i2cdetect 扫描

面试官:写一个 I2C 设备驱动的基本结构?probe 里做什么?

面试官考察点

Linux 驱动基础题。面试官看你是否写过 I2C 驱动。重点听:i2c_driver、probe、收发。

回答思路

给 i2c_driver 结构、probe 流程、收发函数、用户态访问。

参考回答

i2c_driver 结构。

static const struct of_device_id my_i2c_of_match[] = {
  { .compatible = "vendor,mychip" },
  { /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, my_i2c_of_match);

static struct i2c_driver my_i2c_driver = {
  .driver = {
    .name = "my_i2c_chip",
    .of_match_table = my_i2c_of_match,
  },
  .probe = my_i2c_probe,
  .remove = my_i2c_remove,
  .id_table = my_i2c_id, // 可选,传统匹配
};
module_i2c_driver(my_i2c_driver);

probe 函数流程。

  1. i2c_check_functionality(client, I2C_FUNC_I2C) 检查适配器能力;

  2. 读取设备 ID 寄存器,确认硬件存在(可选但推荐);

  3. 分配私有数据结构(devm_kzalloc),保存 client;

  4. 初始化硬件(复位、配置寄存器);

  5. 注册字符设备 cdev 或 sysfs 属性,让用户态访问;

  6. i2c_set_clientdata(client, data) 保存私有数据。

static int my_i2c_probe(struct i2c_client *client){
  struct my_data *data;
  data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
  data->client = client;
  i2c_set_clientdata(client, data);
  // 初始化硬件、注册 cdev/sysfs
  return 0;
}

I2C 收发函数。

函数用途
i2c_transfer(client, msgs, num)通用 I2C 收发,支持多消息组合(写寄存器+读)
i2c_smbus_read_byte_data(client, reg)读 1 字节寄存器
i2c_smbus_write_byte_data(client, reg, val)写 1 字节寄存器
i2c_smbus_read_word_data读 2 字节
i2c_smbus_read_i2c_block_data读块数据(最多 32 字节)

// 读寄存器 reg 的值
u8 val = i2c_smbus_read_byte_data(client, reg);

// 写寄存器
i2c_smbus_write_byte_data(client, reg, val);

// 通用 i2c_transfer(写 reg 然后读 N 字节)
struct i2c_msg msgs[2];
u8 reg_addr = 0x10;
u8 buf[4];
msgs[0].addr = client->addr; msgs[0].flags = 0;
msgs[0].buf = &reg_addr; msgs[0].len = 1;
msgs[1].addr = client->addr; msgs[1].flags = I2C_M_RD;
msgs[1].buf = buf; msgs[1].len = 4;
i2c_transfer(client->adapter, msgs, 2);

用户态访问。

  • /dev/i2c-X:i2c-dev 驱动提供,open + ioctl(I2C_RDWR/I2C_SMBUS) 读写,不需要写内核驱动;

  • sysfs:驱动在 /sys/bus/i2c/devices/X-YYYY/ 下创建属性文件,cat/echo 读写;

  • 字符设备 /dev/mychip:驱动注册 cdev,用户态 read/write/ioctl;

  • i2c-tools:i2cdetect(扫描)、i2cget(读)、i2cset(写)、i2cdump(dump)。

注意。

  • I2C 地址 7 位(0x08~0x77),驱动里写 7 位地址(不包含读写位);

  • probe 失败要回滚已分配资源(devm_ 自动管理);

  • remove 里释放资源、注销 cdev/sysfs;

  • 多实例支持:同一个驱动可以匹配多个同型号设备(不同地址),用 client 区分。

面试官可能追问

追问 1:设备树里 I2C 设备怎么写?
在 i2c 控制器节点下加子节点:compatible、reg(7位地址)。例如 eeprom@50 { compatible="atmel,24c02"; reg=<0x50>; }。内核通过 of_match_table 匹配。
追问 2:i2c_transfer 和 i2c_smbus_* 区别?
i2c_transfer 是通用 I2C 协议,支持任意消息组合;i2c_smbus_* 是 SMBus 协议子集,简单但有限(块最多 32 字节)。大多数 I2C 设备兼容 SMBus,用 smbus 函数更简单。
追问 3:probe 里怎么确认硬件存在?
读设备 ID 寄存器(很多芯片有 WHO_AM_I 寄存器),和预期值比较。不匹配就返回 -ENODEV。防止设备不存在时驱动加载成功。
追问 4:用户态不写驱动能访问 I2C 吗?
可以,用 /dev/i2c-X + ioctl,或 i2c-tools。适合简单调试和少量数据。复杂协议(如传感器连续采样)还是写驱动更好。
追问 5:I2C 总线和 SPI 驱动框架区别?
I2C 用 i2c_driver/i2c_client,SPI 用 spi_driver/spi_device。结构类似,都是 probe/remove + 设备树匹配。SPI 收发用 spi_write/spi_read/spi_sync。

常见失分表达

✗ 驱动里直接操作 I2C 控制器寄存器 — 应该用 i2c_transfer/smbus 函数,跨平台兼容。直接操作寄存器不可移植。
✗ probe 不检查设备 ID — 设备不存在时也加载成功,后续读写出错。
✗ I2C 地址包含读写位 — 驱动用 7 位地址,内核自动加读写位。写成 8 位会地址错误。

准备动作

1
写过一个简单 I2C 驱动(传感器/EEPROM)
2
了解 i2c_driver 和 probe
3
用过 i2c-tools 调试

核心关键词

Linux I2C驱动i2c_driverprobei2c_transfersysfsi2c-dev设备树


声明:本网站所收集的部分公开资料来源于互联网,转载的目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。仅供学习交流使用,不构成商业目的。版权归原作者所有,如果您发现网站上有侵犯您的知识产权的作品,请与我们取得联系,我们会及时删除。侵权投诉
相关推荐HOT
技术岗谈薪时怎样问清楚薪资结构?工程师谈薪注意事项指南

分类:面试技巧与通用知识经验级别:基础难度:★★☆题型:谈薪策略技术岗面试:谈薪与薪资结构注意事项指南本文概述技术工程师谈薪不能只问"月薪多少",必须搞清楚完整... 详情>>

2026-08-08 15:17:33
PCB S参数仿真怎么做与结果解读?PCB仿真工程师面试高速信号完整性核心考点

PCB仿真中等偏难技术面试中级经验本文概述S参数(散射参数)是描述高速互连网络传输和反射特性的重要工具,S11表示回波损耗(反射),S21表示插入损耗(传输)。... 详情>>

2026-08-27 12:14:50
工程师面试前准备清单:从材料到心态全流程指南

分类:面试准备技巧经验级别:通用难度:基础题型:面试清单📖 本文概述工程师面试前的准备工作直接影响面试表现。本文把准备事项分为材料、技术、后勤、心态四大模块,... 详情>>

2026-08-04 15:54:13
射频滤波器怎么选?LC/SAW/腔体滤波器区别?插损和带外抑制怎么平衡?射频面试

一句话答案滤波器类型:LC(低成本、低Q、大体积)、SAW/BAW(小体积、高Q、固定频率)、腔体(高Q、大功率、大体积贵)、LTCC(集成小体积);选型看频率... 详情>>

2026-09-24 09:23:24
PCB串扰仿真是怎么做的?3W规则有效性验证与远端近端串扰分析

本文概述串扰是高速PCB信号完整性的三大核心问题(反射、串扰、电源完整性)之一,也是PCB仿真工程师面试的高频考点。本文从互容和互感耦合的物理原理出发,系统讲解... 详情>>

2026-08-28 15:10:11
开班信息