Industrial I/O (IIO) 深度解析:Linux 内核的传感器框架
一、IIO 是什么?
Industrial I/O (IIO) 是 Linux 内核中一个专门用于传感器和转换器的子系统框架。它提供了一套标准化的接口,用于连接和管理各类工业级传感器,包括但不限于:
- 运动传感器:加速度计、陀螺仪、磁力计
- 环境传感器:温度、湿度、气压、光照
- 化学传感器:气体检测、pH值传感器
- 生物传感器:心率监测、血氧饱和度
- 转换器:ADC(模数转换器)、DAC(数模转换器)
IIO 的设计目标是解决嵌入式系统中传感器集成碎片化的问题。在 IIO 出现之前,传感器驱动分散在内核各处(input、hwmon、misc等),导致:
- 用户空间访问接口不统一
- 驱动程序重复开发
- 缺乏高级功能支持(如硬件缓冲、事件处理)
二、IIO 架构设计
内核空间架构
核心组件
- IIO 设备驱动:与物理硬件交互
- IIO 核心:提供注册、缓冲区、事件等基础设施
- IIO 触发器:控制数据采集时机
- IIO 缓冲区:批量数据存储
- IIO 通道:传感器数据通道抽象
三、IIO 用户空间接口
IIO 通过多种方式向用户空间提供访问接口:
1. Sysfs 接口
路径:/sys/bus/iio/devices/
/sys/bus/iio/devices/ ├── iio:device0 │├── name │├── in_accel_x_raw │├── in_accel_y_raw │├── in_accel_z_raw │├── in_accel_scale │├── in_temp_raw │├── in_temp_offset │└── triggers └── iio_sysfs_trigger └── trigger0常用属性:
*_raw:原始传感器数据*_scale:比例因子(将原始值转换为工程单位)*_offset:校准偏移量sampling_frequency:采样频率
2. 字符设备接口
路径:/dev/iio:deviceX
- 用于高效读取缓冲数据
- 支持 poll/select 异步通知
- 直接访问原始二进制数据
3. Debugfs 接口
路径:/sys/kernel/debug/iio/
- 提供调试信息
- 显示设备注册状态
- 查看缓冲区使用情况
四、IIO 核心概念详解
1. 通道(Channels)
通道是 IIO 的基本数据单元,代表传感器的单个测量值。每个通道有以下属性:
| 属性 | 描述 | 示例 |
|---|---|---|
| 类型 | 测量类型 | accel, gyro, temp |
| 索引 | 通道索引 | x, y, z 或 0,1,2 |
| 修饰符 | 附加信息 | ambient, ir, processed |
通道类型示例代码:
staticconststructiio_chan_specbme280_channels[]={{.type=IIO_TEMP,.info_mask_separate=BIT(IIO_CHAN_INFO_RAW)|BIT(IIO_CHAN_INFO_SCALE),.scan_index=0,.scan_type={.sign='s',.realbits=14,.storagebits=16,.shift=2,},},{.type=IIO_PRESSURE,.info_mask_separate=BIT(IIO_CHAN_INFO_RAW)|BIT(IIO_CHAN_INFO_SCALE),.scan_index=1,// ...},// ...};2. 触发器(Triggers)
触发器决定数据采集的时机:
| 触发类型 | 描述 | 典型应用 |
|---|---|---|
| 软件触发 | 按需采集 | 用户空间控制 |
| 硬件触发 | 外部事件触发 | 中断驱动采集 |
| 定时触发 | 周期性采集 | 连续监测 |
创建硬件触发示例:
staticirqreturn_tsensor_trigger_handler(intirq,void*p){structiio_poll_func*pf=p;structiio_dev*indio_dev=pf->indio_dev;// 读取传感器数据read_sensor_data();// 通知 IIO 核心iio_push_to_buffers(indio_dev,sensor_data);returnIRQ_HANDLED;}3. 缓冲区(Buffers)
用于高效处理批量数据:
五、IIO 设备驱动开发
1. 设备注册流程
staticintsensor_probe(structplatform_device*pdev){structiio_dev*indio_dev;structsensor_data*data;// 分配 IIO 设备indio_dev=devm_iio_device_alloc(&pdev->dev,sizeof(*data));if(!indio_dev)return-ENOMEM;data=iio_priv(indio_dev);// 初始化设备indio_dev->name="my-sensor";indio_dev->info=&sensor_info;indio_dev->channels=sensor_channels;indio_dev->num_channels=ARRAY_SIZE(sensor_channels);indio_dev->modes=INDIO_DIRECT_MODE|INDIO_BUFFER_TRIGGERED;// 配置硬件sensor_hw_init(data);// 注册设备returndevm_iio_device_register(&pdev->dev,indio_dev);}2. 核心数据结构
iio_info 结构体:
staticconststructiio_infosensor_info={.read_raw=sensor_read_raw,.write_raw=sensor_write_raw,.read_event_config=sensor_read_event_config,.write_event_config=sensor_write_event_config,.validate_trigger=sensor_validate_trigger,};iio_dev 结构体:
structiio_dev{conststructiio_info*info;// 操作函数集structiio_buffer*buffer;// 数据缓冲区structlist_headtrig_list;// 触发器列表conststructiio_chan_spec*channels;// 通道定义intnum_channels;// 通道数量unsignedlongmodes;// 工作模式// ...};六、IIO 用户空间编程
1. 使用 sysfs 读取数据
# 查看可用设备$ls/sys/bus/iio/devices/ iio:device0iio:device1trigger0# 读取温度值$cat/sys/bus/iio/devices/iio:device0/in_temp_raw24560$cat/sys/bus/iio/devices/iio:device0/in_temp_scale0.03125# 计算实际温度:24560 * 0.03125 = 767.5 m°C2. 使用 libiio 库编程
#include<iio.h>intmain(){// 创建上下文structiio_context*ctx=iio_create_default_context();// 查找设备structiio_device*dev=iio_context_find_device(ctx,"bme280");// 查找通道structiio_channel*temp_chan=iio_device_find_channel(dev,"temp",false);// 读取数据floattemp;iio_channel_attr_read_float(temp_chan,"raw",&temp);// 应用校准floatscale,offset;iio_channel_attr_read_float(temp_chan,"scale",&scale);iio_channel_attr_read_float(temp_chan,"offset",&offset);floatcalibrated=temp*scale+offset;printf("Temperature: %.2f°C\n",calibrated);iio_context_destroy(ctx);return0;}3. 高级特性:缓冲数据采集
// 设置缓冲区structiio_buffer*buf=iio_device_create_buffer(dev,1024,false);// 启用通道iio_channel_enable(temp_chan);iio_channel_enable(humidity_chan);// 开始采集iio_buffer_refill(buf);// 阻塞等待数据// 处理数据void*start,*end;ptrdiff_tstep;iio_buffer_step(buf,&step);iio_buffer_start(buf,&start);iio_buffer_end(buf,&end);for(void*ptr=start;ptr<end;ptr+=step){int16_t*data=ptr;floattemp=data[0]*0.03125;floathumidity=data[1]*0.001;// ...}七、IIO 高级功能
1. 事件检测
支持阈值、运动检测等事件:
// 设置阈值事件echo1000>/sys/bus/iio/devices/iio:device0/events/in_accel_x_thresh_rising_value// 监听事件structiio_event_dataevent;while(read(event_fd,&event,sizeof(event))>0){if(event.id==IIO_EV_CODE_ACCEL_X_THRESH){printf("X-axis threshold exceeded!\n");}}2. 硬件滤波
配置传感器内置滤波器:
# 查看可用滤波器$cat/sys/bus/iio/devices/iio:device0/filter_low_pass_3db_frequency_available0.1131030100# 设置滤波器echo10>/sys/bus/iio/devices/iio:device0/filter_low_pass_3db_frequency3. 多设备同步
使用硬件触发器同步多个传感器:
# 创建触发器echo100>/sys/bus/iio/devices/trigger0/sampling_frequency# 绑定设备到触发器echotrigger0>/sys/bus/iio/devices/iio:device0/trigger/current_triggerechotrigger0>/sys/bus/iio/devices/iio:device1/trigger/current_trigger八、IIO 工具集
| 工具名称 | 功能描述 | 示例用法 |
|---|---|---|
| iio_info | 查看设备信息 | iio_info -u local: |
| iio_readdev | 读取设备数据 | iio_readdev -b 1024 iio:device0 |
| iio_writedev | 写入设备数据 | iio_writedev -s 0.5 iio:device0 voltage0 |
| iio_attr | 操作设备属性 | iio_attr -c iio:device0 in_accel_x scale |
| iio_event_monitor | 监视 IIO 事件 | iio_event_monitor -n iio:device0 |
九、IIO 在嵌入式系统中的应用案例
1. 无人机飞行控制器
传感器配置:
- 加速度计:200Hz 采样率
- 陀螺仪:8kHz 采样率
- 使用硬件触发器同步采样
2. 工业环境监测
// 创建多传感器监测系统structiio_context*ctx=network_context_create("192.168.1.100");// 分布式传感器列表constchar*sensors[]={"floor1-temp","floor1-humidity","floor2-temp","floor2-humidity","outside-temp","outside-pressure"};// 批量读取数据for(inti=0;i<ARRAY_SIZE(sensors);i++){structiio_device*dev=iio_context_find_device(ctx,sensors[i]);// 读取并处理数据}十、IIO 最佳实践
- 通道设计原则:
- 每个物理量使用独立通道
- 提供原始数据和工程单位转换
- 明确定义数据精度和范围
- 性能优化:
- 使用 DMA 缓冲区减少 CPU 开销
- 启用传感器硬件滤波
- 合理设置采样率平衡功耗与性能
- 电源管理:
// 实现挂起/恢复回调staticconststructdev_pm_opssensor_pm_ops={.suspend=sensor_suspend,.resume=sensor_resume,};- 调试技巧:
# 启用 IIO 调试echo1>/sys/module/iio/parameters/debug# 查看内核日志dmesg|grepiio总结
IIO 子系统为 Linux 生态系统提供了强大的传感器集成能力:
- 统一框架:标准化各类传感器接口
- 灵活架构:支持从简单数据读取到高速流处理
- 丰富工具:提供完整的用户空间工具链
- 跨平台:从微控制器到服务器级系统均可使用
“IIO 是 Linux 传感器领域的通用语言,它将硬件多样性与软件统一性完美结合。掌握 IIO,意味着你能让任何传感器在 Linux 系统中‘开口说话’。” —— Jonathan Cameron, IIO 维护者
通过本文,您已全面了解:
- IIO 架构与核心概念
- 驱动开发与用户空间编程
- 高级特性与优化技巧
- 实际应用场景与最佳实践
这些知识将帮助您在嵌入式系统和物联网项目中高效集成各类传感器设备。