news 2026/8/21 11:46:46

Linux IIO子系统

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Linux IIO子系统

因实际项目资料涉密,在此将项目中Linux common的部分和学习心得总结于此,以备时习之。(部分示例代码为脱敏经过删减和简化处理,仅供参考,请见谅!)


参考图来源于网络,侵删。

keyword:IIO、Industrial I/O、ADC、DAC

一.background

工业及消费电子(手机、物联网、可穿戴设备)中大量使用ADC将模拟物理量转为数字量。加速度计、光传感器、陀螺仪、气压计、磁力计等许多传感器内部均集成ADC,并通过IIC/SPI接口对外提供数据。同时,某些SoC也提供on chip的ADC pin。为统一管理这类ADC传感器,Linux内核推出了IIO子系统,开发者需基于IIO子系统编写驱动。

二.简介

IIO(Industrial I/O,工业输入输出)是Linux内核中专用于管理模数转换器(ADC)和数模转换器(DAC)类设备的子系统。它于2009年由Jonathan Cameron加入Linux内核,旨在为各类传感器和数据转换设备提供统一的驱动框架。当你使用的传感器本质是 ADC 或 DAC 器件时,可以优先考虑使用 IIO 驱动框架。

1.iio_dev 结构体

IIO 子系统使用结构体 iio_dev 来描述一个具体 IIO 设备,此设备结构体定义在include/linux/iio/iio.h 文件中,使用IIO子系统的外设需要根据该结构体的成员进行注册。

struct iio_dev { int modes; /* 设备支持的工作模式 */ int currentmode; /* 当前使用的工作模式 */ struct device dev; /* Linux 设备对象 */ struct iio_buffer *buffer; /* 数据缓冲区 */ int scan_bytes; /* 单次采集的总字节数 */ const unsigned long *available_scan_masks; /* 允许的通道组合掩码列表 */ const unsigned long *active_scan_mask; /* 当前启用的通道掩码 */ bool scan_timestamp; /* 是否在数据包末尾附加时间戳 */ struct iio_trigger *trig; /* 当前绑定的触发器 */ struct iio_poll_func *pollfunc; /* 触发信号到来时的回调函数 */ struct iio_chan_spec const *channels; /* 通道配置数组 */ int num_channels; /* 通道总数 */ const char *name; /* 设备名称(用户空间可见) */ const struct iio_info *info; /* 驱动功能回调函数集 */ const struct iio_buffer_setup_ops *setup_ops; /* 缓冲启用/禁用钩子 */ struct cdev chrdev; /* 字符设备 */ };

2.iio_dev 申请与释放

在使用之前要先申请 iio_dev,申请函数为 iio_device_alloc,函数原型如下:

struct iio_dev *iio_device_alloc(int sizeof_priv)

sizeof_priv:私有数据内存空间大小,一般我们会将自己定义的设备结构体变量作为 iio_dev 的私有数据,这样可以直接通过 iio_device_alloc 函数同时完成 iio_dev 和设备结构体变量的内存申请。申请成功以后使用 iio_priv 函数来得到自定义的设备结构体变量首地址。

原生IIO使用的是iio_device_alloc,这种方式方式分配的设备对象,需要手动释放(调用iio_device_free()),通常在驱动remove或probe出错时进行释放。我们也可以使用devm(device managed)机制,设备驱动无需手动释放,资源会在设备销毁时自动清理,可有效防止内存泄漏。

struct iio_dev *devm_iio_device_alloc(struct device *dev, int sizeof_priv);

此函数采用“一次分配,两块空间”的设计,在连续的内存中同时分配了struct iio_dev 和驱动私有数据(private data)的空间,这种设计能提升 CPU 缓存的利用率。

返回值:如果申请成功就返回一个指向已分配 iio_dev结构体的指针,如果失败就返回 NULL。

3.iio_info

在 iio_dev 结构体中,有一个关键成员指针 info,它指向 iio_info 结构体。iio_info 是 IIO 驱动开发中需要重点实现的部分,因为它定义了设备的具体操作接口。用户空间发起的各种访问请求,最终都会通过 VFS 层回调到 iio_info 所注册的函数中,从而实现对硬件设备的控制与数据采集。iio_info 结构体的定义位于内核源码 include/linux/iio/iio.h中。

struct iio_info { struct module *driver_module; const struct attribute_group *attrs; const struct attribute_group *event_attrs; int (*read_raw)(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long mask); int (*write_raw)(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int val, int val2, long mask); int (*write_raw_get_fmt)(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, long mask); int (*read_event_config)(struct iio_dev *indio_dev, u64 event_code); int (*write_event_config)(struct iio_dev *indio_dev, u64 event_code, int state); int (*read_event_value)(struct iio_dev *indio_dev, u64 event_code, int *val); int (*write_event_value)(struct iio_dev *indio_dev, u64 event_code, int val); int (*validate_trigger)(struct iio_dev *indio_dev, struct iio_trigger *trig); int (*update_scan_mode)(struct iio_dev *indio_dev, const unsigned long *scan_mask); int (*debugfs_reg_access)(struct iio_dev *indio_dev, unsigned reg, unsigned writeval, unsigned *readval); int (*fwnode_xlate)(struct iio_dev *indio_dev, const struct fwnode_reference_args *args); int (*hwfifo_set_watermark)(struct iio_dev *indio_dev, unsigned int val); };

4.iio_chan_spec

IIO 子系统的核心抽象是**通道**,它代表传感器设备的一个独立数据采集维度。一个物理传感器可能包含多个功能单元,产生多路相互独立但有内在关联的数据。例如:
- 三轴加速度计包含 X、Y、Z 三个通道;
- 8 通道 ADC 芯片提供 8 个模拟输入通道;
- 温湿度传感器通常包含温度(temperature)和湿度(humidity)两个通道。

在 Linux 内核中,每个通道由 `struct iio_chan_spec` 结构体描述。该结构体定义了通道的类型、编号、数据类型、是否可读写以及数值转换关系等关键属性。其定义位于内核源码 `include/linux/iio/iio.h` 文件中。

驱动开发者在实现 IIO 驱动时,需要为设备的所有通道构造一个 `iio_chan_spec` 数组,并将其赋值给 `iio_dev` 结构体的 `channels` 成员,同时通过 `num_channels` 指定通道数量。内核和用户空间将依据这些通道定义来解析、展示和访问多路传感器数据。

三.IIO framework (platform)

IIO 框架主要用于 ADC 类的传感器,比如陀螺仪、加速度计、磁力计、光强度计等,这些传感器基本都是 IIC 或者 SPI 接口的。因此IIO 驱动的基础框架就是 IIC 或者 SPI,我们可以在 IIC 或 SPI 驱动里面在加上 regmap。当然了,有些 SOC 内部的 ADC 也会使用 IIO 框架,那么这个时候驱动的基础框架就是 platfrom(为使用dev-bus-drv模型,MTK的某些STB SoC就是如此)。​

1.iio_dev 结构体

/* 自定义设备结构体 */ struct xxx_dev { struct device *dev; struct iio_dev *indio_dev; void __iomem *xxx int irq; ... };

2.通道数组

static const struct iio_chan_spec xxx_channels[] = { };

3.读函数

当读取 sysfs 中的文件的时候最终此函数会执行,此函数里面会从传感器里面读取各种数据,然后上传给应用。

static int xxx_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int val, int val2, long mask) { return 0; }

4.写函数

static int xxx_write_raw_get_fmt(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, long mask) { return 0; }

5.iio_info 结构体变量

static const struct iio_info xxx_info = { .read_raw = xxx_read_raw, .write_raw = xxx_write_raw, .write_raw_get_fmt = xxx_write_raw_get_fmt, .write_event_value = xxx_write_event_value, .read_event_value = xxx_read_event_value, .write_event_config = xxx_write_event_config, .read_event_config = xxx_read_event_config, };

6.driver probe func

按需实现,在dev与drv match成功后调用

static int xxx_probe(struct platform_device *pdev) { }

7.driver remove func

按需实现,在设备卸载时调用

static int xxx_remove(struct platform_device *pdev) { }
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/21 11:44:54

LangChain架构演进:基于MCP与LangGraph构建现代化AI智能体

如果你最近关注AI应用开发,可能会发现一个现象:很多教程还在教你用LangChain的旧版API写Agent,但GitHub上活跃的项目和最新的官方文档,已经悄悄转向了一套更模块化、更工程化的新范式。你跟着旧教程写的代码跑不通,查错…

作者头像 李华
网站建设 2026/8/21 11:43:56

研发效能平台的智能化改造要点

研发效能平台的智能化改造要点编校说明:本文为技术讨论稿;文中的案例、数据、阈值和运行环境如未附原始记录,均应视为示例。发布前请用实际项目配置、测试方法和结果替换,或删去无法核验的内容。问题与适用范围 微服务网关在流量高…

作者头像 李华
网站建设 2026/8/21 11:38:55

华为eNSP核心命令全解析:从入门到实战的网络工程师必备指南

大家好,我是专注于网络技术分享的博主。在网络工程师的学习和工作中,华为 eNSP(Enterprise Network Simulation Platform)是绕不开的经典模拟器。很多朋友在入门时,面对繁杂的命令行界面和众多的命令,常常感…

作者头像 李华
网站建设 2026/8/21 11:37:24

无人机+自组网:背负式单兵自组网电台技术详解

无人机背负式单兵自组网电台技术背负式单兵自组网电台属于宽带无线 MESH‑Ad Hoc 分布式通信系统,单兵背负携带;无人机搭载轻量化机载自组网电台作为空中移动中继,构建空‑地一体化立体自组网,解决山地、楼宇、废墟、丛林等地形遮…

作者头像 李华
网站建设 2026/8/21 11:37:21

Genspark AI Workspace 6.0:从AI工具到AI操作系统的范式转变

如果你是一名开发者,最近可能已经感受到了一个明显的变化:AI 正在从“聊天机器人”和“代码补全工具”,快速演变为一个能深度介入你整个工作流的“智能工作空间”。过去,我们可能需要频繁地在 IDE、终端、文档、浏览器、项目管理工…

作者头像 李华