【推荐阅读】

一文剖析Linux内核中内存管理

分析linux启动内核源码

关于如何快速学好,学懂Linux内核。内含学习路线

工业场合里面也有大量的模拟量和数字量之间的转换,也就是我们常说的 ADC 和 DAC。而且随着手机、物联网、工业物联网和可穿戴设备的爆发,传感器的需求只持续增强。比如手机或者手环里面的加速度计、光传感器、陀螺仪、气压计、磁力计等,这些传感器本质上都是ADC,大家注意查看这些传感器的手册,会发现他们内部都会有个 ADC,传感器对外提供 IIC或者 SPI 接口,SOC 可以通过 IIC 或者 SPI 接口来获取到传感器内部的 ADC 数值,从而得到想要测量的结果。Linux 内核为了管理这些日益增多的 ADC 类传感器,特地推出了 IIO 子系统,我们学习如何使用 IIO 子系统来编写 ADC 类传感器驱动。

1、IIO 子系统简介

IIO 全称是 Industrial I/O,翻译过来就是工业 I/O大家不要看到“工业”两个字就觉得 IIO 是只用于工业领域的。大家一般在搜索 IIO 子系统的时候,会发现大多数讲的都是 ADC,这是因为 IIO 就是为 ADC 类传感器准备的,当然了 DAC 也是可以的。大家常用的陀螺仪、加速度计、电压/电流测量芯片、光照传感器、压力传感器等内部都是有个 ADC,内部 ADC 将原始的模拟数据转换为数字量,然后通过其他的通信接口,比如 IIC、SPI 等传输给 SOC。

因此,当你使用的传感器本质是 ADC 或 DAC 器件的时候,可以优先考虑使用 IIO 驱动框架。

1、iio_dev 结构体

IIO 子系统使用结构体 iio_dev 来描述一个具体 IIO 设备,此设备结构体定义在include/linux/iio/iio.h 文件中

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_dev 首地址,如果失败就返回 NULL。

3、iio_dev 注册与注销

前面分配好 iio_dev 以后就要初始化各种成员变量,初始化完成以后就需要将 iio_dev 注册 到内核中,需要用到 iio_device_register 函数

4、iio_info

iio_dev 有个成员变量:info,为 iio_info 结构体指针变量,这个是我们在编写 IIO 驱动的时候需要着重去实现的,因为用户空间对设备的具体操作最终都会反映到 iio_info 里面。iio_info结构体定义在 include/linux/iio/iio.h 中

5、iio_chan_spec

IIO 的核心就是通道,一个传感器可能有多路数据,比如一个 ADC 芯片支持 8 路采集,那么这个 ADC 就有 8 个通道。Linux 内核使用 iio_chan_spec 结构体来描述通道,定义在 include/linux/iio/iio.h 文件中。

2、IIO 驱动框架创建

分析 IIO 子系统的时候大家应该看出了,IIO 框架主要用于 ADC 类的传感器,比如陀螺仪、加速度计、磁力计、光强度计等,这些传感器基本都是 IIC 或者 SPI 接口的。因此 IIO 驱动的基础框架就是 IIC 或者 SPI,我们可以在 IIC 或 SPI 驱动里面在加上 regmap。当然了,有些 SOC 内部的 ADC 也会使用 IIO 框架,那么这个时候驱动的基础框架就是 platfrom。

IIO 设备的申请、初始化以及注册在 probe 函数中完成,在注销驱动的时候还需要在 remove 函数中注销掉 IIO 设备、释放掉申请的一些内存。

以 SPI 接口为例,demo 如下

/* 自定义设备结构体 */
struct xxx_dev { struct spi_device *spi; /* spi 设备 */struct regmap *regmap; /* regmap */struct regmap_config regmap_config;struct mutex lock;
};/*
* 通道数组
*/
static const struct iio_chan_spec xxx_channels[] = {};/*
* @description : 读函数,当读取 sysfs 中的文件的时候最终此函数会执行,
* :此函数里面会从传感器里面读取各种数据,然后上传给应用。
* @param - indio_dev : IIO 设备
* @param - chan : 通道
* @param - val : 读取的值,如果是小数值的话,val 是整数部分。
* @param - val2 : 读取的值,如果是小数值的话,val2 是小数部分。
* @param - mask : 掩码。
* @return : 0,成功;其他值,错误
*/
static int xxx_read_raw(struct iio_dev *indio_dev,struct iio_chan_spec const *chan,int *val, int *val2, long mask)
{return 0;
} /*
* @description : 写函数,当向 sysfs 中的文件写数据的时候最终此函数
* :会执行,一般在此函数里面设置传感器,比如量程等。
* @param - indio_dev : IIO 设备
* @param - chan : 通道
* @param - val : 应用程序写入值,如果是小数的话,val 是整数部分。
* @param - val2 : 应用程序写入值,如果是小数的话,val2 是小数部分。
* @return : 0,成功;其他值,错误
*/
static int xxx_write_raw(struct iio_dev *indio_dev,struct iio_chan_spec const *chan,int val, int val2, long mask)
{return 0;
}/*
* @description : 用户空间写数据格式,比如我们在用户空间操作 sysfs 来设
* :置传感器的分辨率,如果分辨率带小数,那么这个小数传递到
* : 内核空间应该扩大多少倍,此函数就是用来设置这个的。
* @param - indio_dev : iio_dev
* @param - chan : 通道
* @param - mask : 掩码
* @return : 0,成功;其他值,错误
*/
static int xxx_write_raw_get_fmt(struct iio_dev *indio_dev,struct iio_chan_spec const *chan, long mask)
{return 0;
}/*
* 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,
};/*
* @description : spi 驱动的 probe 函数,当驱动与
* 设备匹配以后此函数就会执行
* @param - spi : spi 设备
*
*/
static int xxx_probe(struct spi_device *spi)
{int ret;struct xxx_dev *data;struct iio_dev *indio_dev;/* 1、申请 iio_dev 内存 */indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*data));if (!indio_dev)return -ENOMEM;/* 2、获取 xxx_dev 结构体地址 */data = iio_priv(indio_dev);data->spi = spi;spi_set_drvdata(spi, indio_dev);mutex_init(&data->lock);/* 3、初始化 iio_dev 成员变量 */indio_dev->dev.parent = &spi->dev;indio_dev->info = &xxx_info;indio_dev->name = "xxx";indio_dev->modes = INDIO_DIRECT_MODE; /* 直接模式 /indio_dev->channels = xxx_channels;indio_dev->num_channels = ARRAY_SIZE(xxx_channels);iio_device_register(indio_dev);/* 4、regmap 相关设置 *//* 5、SPI 相关设置*//* 6、芯片初始化 */return 0;}/*
* @description : spi 驱动的 remove 函数,移除 spi 驱动的时候此函数会执行
* @param - spi : spi 设备
* @return : 0,成功;其他负值,失败
*/
static int xxx_remove(struct spi_device *spi)
{struct iio_dev *indio_dev = spi_get_drvdata(spi);struct xxx_dev *data;data = iio_priv(indio_dev); ;/* 1、其他资源的注销以及释放 *//* 2、注销 IIO */iio_device_unregister(indio_dev);return 0;
}

3、使能内核 IIO 相关配置

Linux 内核默认使能了 IIO 子系统,但是有一些 IIO 模块没有选择上,这样会导致我们编译 驱动的时候会提示某些 API 函数不存在,需要使能的项目如下:

-> Device Drivers -> Industrial I/O support (IIO [=y])-> [*]Enable buffer support within IIO //选中-> <*>Industrial I/O buffering based on kfifo //选中

IIO 驱动框架提供了 sysfs 接口,因此加载成功以后我们可以在用户空间访问对应的 sysfs 目录项,进入目录“/sys/bus/iio/devices/”目录里面,此目录下都是 IIO 框架设备。


一文带你深入了解Linux IIO 子系统相关推荐

  1. 【转】 linux iio子系统

    原文网址:http://blog.csdn.net/tsy20100200/article/details/47101661 最近由于工作的需要,接触了Linux iio子系统,对于这个目录其实以前是 ...

  2. Linux的iio数据流程,linux iio子系统

    转自http://blog.csdn.net/tsy20100200/article/details/47101661 最近由于工作的需要,接触了Linux iio子系统,对于这个目录其实以前是很少接 ...

  3. LINUX IIO子系统分析之一 IIO子系统概述

    从本章开始,我们进行IIO子系统专栏的分析文档,本次IIO子系统专栏分析文档大概包含如下几章: 一. IIO子系统概述 二.IIO子系统相关数据结构分析 三.iio trigger 介绍 四.iio ...

  4. LINUX IIO子系统分析之五IIO BUFFER子模块实现分析

    上一章我们介绍了iio子系统中的iio event模块,本章我们将介绍iio buffer模块,iio buffer主要用于连续数据采集与缓存功能.IIO buffer模块借助IIO DEVICE字符 ...

  5. LINUX IIO子系统分析之二 IIO子系统相关数据结构分析

    上一章我们简要说明了IIO子系统的架构,本章我们通过数据结构的定义,分析IIO子系统的设计实现,本章的主要内容如下: 一.IIO子系统各数据结构说明 二.数据结构间的关联说明 一.IIO子系统各数据结 ...

  6. LINUX IIO子系统分析之七 虚拟iio device驱动实现

    前面几章我们基本完成了IIO子系统的所有内容,而该章即为本专栏的结束篇,主要用来实现一个虚拟的IIO DEVICE DRIVER,本章的内容主要包括如下几部分: 一. 虚拟IIO DEVICE的说明 ...

  7. LINUX IIO子系统分析之四 IIO EVENT介绍

    上一章我们介绍了iio子系统中的iio trigger模块,本章我们将介绍iio event模块,iio event主要用于阈值监测.自由落体监测等监测功能.因为IIO EVENT涉及IIO DEVI ...

  8. LINUX IIO子系统分析之六 iio device的驱动开发流程说明

    前面五章我们基本上把IIO 子系统的内部设计实现均作了说明,本章我们将说明iio device的驱动开发流程,本章的主要内容大致安排如下: 一.IIO子系统的关键技术点总结 二.IIO DEVICE的 ...

  9. linux IIO子系统使用说明

    新的内核将ADC/DAC/G_sensor这样的设备统一成IIO子系统,用户层通过访问IIO的接口来实现如ADC的触发.采样等操作. 下面给出IIO接口用户层的接口使用实例(以ADC的采样为例) 1. ...

最新文章

  1. 多任务训练的模式结构扩散
  2. mysql cluster 外键_Mysql外键约束
  3. 固有属性与自定义属性
  4. postman数据保存在哪里_快速掌握接口测试利器Postman
  5. 变压器绕组降低邻近效应_高功率UPS性能提升,规格/重量显著降低
  6. mysql 查询索引
  7. Fbinst增强版 命令详解
  8. 科海思除镍树脂CH-90Na
  9. 小白盒子无线打印服务器,玩转无线打印、共享打印机,蒲公英X1盒子和小白学习盒子谁更好...
  10. python-求m+mm+mmm+mmmm+ ...
  11. 统计分析用户信息量的工具Flurry的使用
  12. 疫情当下,选择代理加盟互联网广告项目的优势
  13. 高端数据中心交换机散热系统大比拼
  14. Acrel-2000Z变电站综合自动化系统
  15. vsftpd服务的黑名单和白名单
  16. 获取 ProgramData 文件夹路径
  17. mui上拉加载不好使
  18. android 图库显示,【Android】 保存图片到系统图库, 并立即显示在图库中
  19. 初识web服务器(汤姆猫)HTTP
  20. 每日一问 --欧拉公式是什么?

热门文章

  1. C语言深度剖析笔记1
  2. Elasticsearch 6.4 ingest-attachment对office文件IK分词器全文检索(1) HttpAPI使用
  3. 格兰杰因果检验准备-平稳性检验-Eviews
  4. 每日10行代码82:网上购物活动满减凑单计算器
  5. Docker入门实战看这篇就够了(最新详细以及踩过的坑)
  6. Hitting the database(Chapter 5 of Spring In Action)
  7. python爬虫捕鱼网站_古法捕鱼,千年绝技
  8. win10强制关闭飞行模式_让你的电脑1台变n台 win10自带虚拟机Hyper-V讲解
  9. Tomcat with muti instance
  10. android 移除子view,android-从父视图中移除视图与隐藏视图