type
Post
date
Mar 3, 2026
slug
linux_drivers_iio_subsystem
category
🥳嵌入式Linux开发
icon
password
为什么需要IIO子系统架构总览核心数据结构关键结构体说明设备注册流程数据读取流程单次读取(Direct Mode)缩放因子(Scaling)源码要点分析关键文件iio_chan_spec 通道描述实例DHT11 驱动实例分析硬件协议驱动私有数据结构probe 函数分析read_raw 核心读取逻辑中断处理函数数据解码platform_driver 注册DHT11 驱动完整数据流用户空间使用单次读取Triggered Buffer 采样(需支持的设备)设计理念回顾与常见陷阱关键要点常见陷阱
Linux内核的 Industrial I/O(IIO)子系统 是专门为传感器类设备设计的统一框架。它填补了
hwmon(低采样率系统监控)与 input(人机交互输入设备)之间的空白,为 ADC、DAC、加速度计、陀螺仪、温湿度传感器、光传感器、气压计等提供标准化的驱动接口。IIO子系统自 Linux 2.6.32 进入 staging,后在 Linux 3.x 正式合入主线,至 Linux 5.x 已经非常成熟,是嵌入式Linux中传感器驱动开发的 事实标准。
为什么需要IIO子系统
在IIO出现之前,传感器驱动分散在多个子系统中:
- hwmon:面向低采样率的系统监控传感器(风扇转速、CPU温度),不适合高速ADC
- input:面向人机交互设备(键盘、鼠标、触摸屏),Android早期滥用它来处理传感器
- 自定义字符设备:各驱动各自为政,接口不统一
IIO的设计目标:
- 统一的用户空间接口:所有传感器通过 sysfs 和字符设备提供一致的访问方式
- 灵活的采样机制:支持单次读取(direct mode)和连续采样(triggered buffer)
- 可组合的触发器模型:设备A的触发器可以驱动设备B采样
- 标准的数据格式描述:通道类型、缩放因子、数据位宽等均有规范
架构总览
IIO子系统由四个核心概念组成:
- IIO Device:对应一个硬件传感器,产生采样数据
- IIO Trigger:触发采样的信号源(硬件中断、定时器、软件触发)
- IIO Buffer:存储连续采样数据的缓冲区
- IIO Event:阈值检测器,当数据超出设定范围时产生事件
核心数据结构
关键结构体说明
struct iio_dev:IIO设备的核心结构,由devm_iio_device_alloc()分配。驱动私有数据通过iio_priv()获取
struct iio_info:操作函数集,最重要的是read_raw()回调
struct iio_chan_spec:通道描述符,定义传感器能测量的物理量类型(IIO_TEMP、IIO_HUMIDITYRELATIVE、IIO_VOLTAGE等)
struct iio_trigger:触发器抽象,可跨设备共享
struct iio_buffer:连续采样的数据缓冲区,通常使用 kfifo 实现
设备注册流程
数据读取流程
单次读取(Direct Mode)
用户通过 sysfs 读取单个通道值时,IIO核心调用驱动的
read_raw() 回调:缩放因子(Scaling)
read_raw() 的返回值类型决定了数据的表示方式:返回值类型 | 含义 | 最终值计算 |
IIO_VAL_INT | 整数 | value = val |
IIO_VAL_INT_PLUS_MICRO | 整数+微小数 | value = val + val2 × 10⁻⁶ |
IIO_VAL_FRACTIONAL | 分数 | value = val / val2 |
IIO_VAL_FRACTIONAL_LOG2 | 对数分数 | value = val / 2^val2 |
源码要点分析
关键文件
文件路径 | 功能说明 |
drivers/iio/industrialio-core.c | IIO核心,设备注册/注销、sysfs接口创建 |
drivers/iio/industrialio-buffer.c | Buffer框架,连续采样数据管理 |
drivers/iio/industrialio-trigger.c | Trigger框架,触发器注册与分发 |
drivers/iio/industrialio-event.c | Event框架,阈值事件处理 |
drivers/iio/buffer/kfifo_buf.c | kfifo缓冲区实现 |
include/linux/iio/iio.h | 核心头文件,iio_dev / iio_info / iio_chan_spec 定义 |
include/linux/iio/trigger.h | 触发器相关结构体和API |
include/linux/iio/buffer.h | 缓冲区相关结构体和API |
drivers/iio/humidity/dht11.c | DHT11温湿度传感器驱动(本文分析对象) |
iio_chan_spec 通道描述实例
以DHT11驱动为例,它定义了两个通道——温度和相对湿度:
IIO_CHAN_INFO_PROCESSED表示驱动返回的是 已处理 的值(单位为毫摄氏度 / 千分之一%RH),而非原始ADC码值
- 每个通道在 sysfs 中分别生成:
in_temp_input和in_humidityrelative_input
DHT11 驱动实例分析
源码位置:drivers/iio/humidity/dht11.c
作者:Harald Geyer
许可证:GPL v2
DHT11 是一款常见的低成本温湿度传感器,使用 单总线协议(类似1-Wire,但非标准)通过一根GPIO数据线传输数据。它是学习IIO驱动的理想入门实例,因为它不涉及I2C/SPI总线复杂性,专注于IIO框架本身。
硬件协议
驱动私有数据结构
设计要点:
- 使用
completion机制在中断上下文通知进程上下文数据就绪
timestamp实现 2秒数据缓存,避免过于频繁地访问传感器(DHT11采样间隔需≥2秒)
edges[]数组记录每个边沿的精确时间戳,用于后续解码
probe 函数分析
关键流程:
devm_iio_device_alloc() → 硬件初始化 → 填充 iio_dev → devm_iio_device_register()read_raw 核心读取逻辑
这是整个驱动最关键的函数,实现了完整的 触发采样 → 中断收集边沿 → 解码数据 流程:
中断处理函数
IRQ handler 非常简洁——仅记录边沿时间戳和GPIO电平:
数据解码
platform_driver 注册
设备树节点示例:
DHT11 驱动完整数据流
用户空间使用
单次读取
Triggered Buffer 采样(需支持的设备)
设计理念
Linux IIO子系统的设计体现了以下核心理念:
- 统一抽象:将千差万别的传感器设备统一到
iio_dev+iio_chan_spec模型下,用户空间无需关心底层硬件差异
- 关注点分离:Device、Trigger、Buffer、Event 四者独立注册、可自由组合。设备A的触发器可以驱动设备B采样,体现了 Linux 内核一贯的"机制与策略分离"思想
- sysfs 自描述:通道类型、数据格式(
scan_type)、缩放因子均通过 sysfs 暴露,用户空间可自动解析而无需硬编码
- devm 资源管理:
devm_iio_device_alloc()/devm_iio_device_register()利用设备资源管理框架,避免手动释放资源的遗漏
- 最小驱动原则:DHT11驱动仅约 340 行代码即完成了完整功能——IIO框架承担了 sysfs 创建、字符设备管理、数据格式化等所有通用工作
回顾与常见陷阱
关键要点
- IIO 填补了 hwmon 和 input 之间的传感器驱动空白
- 四大核心概念:Device + Trigger + Buffer + Event
read_raw()是最核心的回调,返回值类型决定数据的缩放方式
- 通道的
info_mask_separate与info_mask_shared_by_type决定 sysfs 文件的共享方式
INDIO_DIRECT_MODE用于按需单次采样,Triggered Buffer 用于连续高速采样
常见陷阱
- 忘记互斥保护:IIO sysfs 接口不阻止并发读取,驱动必须自行加锁
- 时钟分辨率问题:DHT11 依赖微秒级时间戳解码,系统时钟分辨率 >34μs 时无法正常工作
IIO_CHAN_INFO_RAWvsIIO_CHAN_INFO_PROCESSED:RAW 返回原始值(需配合 SCALE),PROCESSED 返回最终值。混淆会导致数据偏差
- Trigger 与 Direct Mode 互斥:大多数设备不能同时支持两种模式,需用
iio_device_claim_direct_mode()保护
- devm 注册顺序:
devm_iio_device_register()应在所有初始化完成后最后调用,因为注册后用户空间立即可访问
- Author:felixfixit
- URL:http://www.felixmicrospace.top/article/linux_drivers_iio_subsystem
- Copyright:All articles in this blog, except for special statements, adopt BY-NC-SA agreement. Please indicate the source!











