嵌入式linux IIO驱动
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 文件中,结构体内容如下(有省略):
我们需要看一下比较重要的几个成员变量:
第 477 行,modes 为设备支持的模式,可选择的模式如下图所示,我们通常选择的是第一个模式
第 478 行,currentmode 为当前模式。
第 483 行,buffer 为缓冲区。
第 484 行,buffer_list 为当前匹配的缓冲区列表。
第 485 行,scan_bytes 为捕获到,并且提供给缓冲区的字节数。
第 488 行,available_scan_masks 为可选的扫描位掩码,使用触发缓冲区的时候可以通过设置掩码来确定使能哪些通道,使能以后的通道会将捕获到的数据发送到 IIO 缓冲区。
第 490 行,active_scan_mask 为缓冲区已经开启的通道掩码。只有这些使能了的通道数据才能被发送到缓冲区。
第 491 行,scan_timestamp 为扫描时间戳,如果使能以后会将捕获时间戳放到缓冲区里面。
第 493 行,trig 为 IIO 设备当前触发器,当使用缓冲模式的时候。
第 494 行,pollfunc 为一个函数,在接收到的触发器上运行。
第 496 行,channels 为 IIO 设备通道,为 iio_chan_spec 结构体类型,后面会详细讲解 IIO通道。
第 497 行,num_channels 为 IIO 设备的通道数。
第 501 行,name 为 IIO 设备名字。
可以看出 iio_buffer_setup_ops 里面都是一些回调函数,在使能或禁用缓冲区的时候会调用这些函数。如果未指定的话就默认使用 iio_triggered_buffer_setup_ops。
2,iio_dev申请与释放
在使用之前肯定要先申请iio_dev,申请函数为iio_device_alloc,函数原型如下:
sizeof_priv:私有数据内存空间大小,一般我们会将我们自己定义的设备结构体变量作为iio_dev的私有数据,这样可以直接通过iio_device_alloc函数同时完iio_dev和设备结构体变量的内存申请。申请成功后,我们可以私有iio_priv函数来得到自定义的设备结构体变量首地址。
返回值:如果申请成功就返回iio_dev首地址,失败返回NULL
一般iio_device_alloc和iio_priv之间的配合使用如下:
第 1 行,icm20608_dev 是自定义的设备结构体。
也可以使用devm_iio_device_alloc来分配iio_dev,这样就不需要我们手动调用iio_device_free函数来完成iio_dev的释放工作。
3,iio_dev注册和注销
前面分配好iio_dev以后就要初始化各种成员变量,初始化完成以后就需要将iio_dev祖册到内核中,需要用到iio_device_register函数,函数原型如下:
indio_dev:需要注册的iio_dev
返回值:0,成功;其他值,失败;
注销iio_dev对应的iio_device_unregister函数,函数原型如下:
iio_info
iio_dev有一个成员变量:info,为iio_info结构体指针变量,这个是我们在编写IIO驱动的时候需要去实现的,因为用户空间对设备的具体操作都会反映到iio_info里面。iio_info结构体定义在include/linux/iio/iio.h 中,结构体定义如下:
第 355 行,attrs 是通用的设备属性。
mask:掩码,用于指定我们读取的是什么数据,比如ICM20608这样的传感器,他既有原始的测量数据,比如 X,Y,Z 轴的陀螺仪、加速度计等。也有测量范围值,或者分辨率,比如加速度计测量范围设置为(正负)16g,那么分辨率就是32/65536=0.000488,我们只有读出原始值,分辨率。linux内核使用 IIO_CHAN_INFO_RAW 和 IIO_CHAN_INFO_SCALE 这两个宏来表示原始值以及分辨率,这两个宏就是掩码。至于每个通道可以采用哪几种掩码,这个在我们初始化通道的时候需要驱动编写人员设置好。掩码有很多种,稍后讲解 IIO 通道的时候详细讲解!
第 376 行的 write_raw_get_fmt 用于设置用户空间向内核空间写入的数据格式,write_raw_get_fmt 函数决定了 wtite_raw 函数中 val 和 val2 的意义也就是上面表中的组合形式。比如我们需要在应用程序中设置ICM20608加速度计的量程为(正负)8g,那么分辨率就是16/65536=0.000244,我们再write_raw_get_fmt函数里面设置加速度计的护具格式为IIO_VAL_INT_PLUS_MICRO。那么我们再应用程序向指定文件写入0.000244以后,最终传递给内核驱动的就是0.000244*1000000=244,也就是write_raw函数的val参数为0,val2参数为244。(主要就是内核空间和用户空间之间不能传递小数,前面的组合形式都是为了将小数扩大进行两者之间的传输,当设置为上面表中的组合形式,那么小数就会被自动扩大成整数进行两着之间传输,传入完成后内核空间或者用户空间自动将其变为小数)
iio_chan_spec
IIO的核心就是通道,一个传感器可能有多路数据,比如一个ADC芯片支持8路采集,那么这个ADC就有8个通道。例如ICM20608,这是一个六轴传感器,可以输出三轴陀螺仪(X、Y、Z)、三轴加速度计(X、Y、Z)和一路温度,也就是一共有7路数据,因此就有7个通道。
Linux 内核使用 iio_chan_spec 结构体来描述通道,定义在 include/linux/iio/iio.h 文件中,内容如下:
第 224 行,type 为通道类型, iio_chan_type 是一个枚举类型,列举出了可以选择的通道类型,定义在 include/uapi/linux/iio/types.h 文件里面,内容如下:
像是ICM20608,是一种复合类型的了,陀螺仪部分是 IIO_ANGL_VEL 类型加速度计部分是 IIO_ACCEL 类型,温度部分就是 IIO_TEMP。
比如ICM20608的加速度计部分,类型设置为IIO_ACCEL,X,Y,Z这三个轴就用channel2的通道修饰符来区分。IIO_MOD_X、IIO_MOD_Y、IIO_MOD_Z 就分别对应 X、Y、Z 这三个轴。通道修饰符主要是影响 sysfs 下的通道文件名字,后面我们会讲解 sysfs 下通道文件名字组成形式。
第 227 行的 address 成员变量用户可以自定义,但是一般会设置为此通道对应的芯片数据寄存器地址 。比如 ICM20608 的加速度计 X 轴这个通道,它的数据首地址就是 0X3B。address 也可以用作其他功能,自行选择,也可以不使用 address,一切以实 际情况为准。
第 228 行,当使用触发缓冲区的时候,scan_index 是扫描索引。
第 229~236,scan_type 是一个结构体,描述了扫描数据在缓冲区中的存储格式。我们依次来看一下 scan_type 各个成员变量的涵义:
.sign:如果为‘u’表示数据为无符号类型,为‘s’的话为有符号类型。
.realbits:数据真实的有效位数,比如很多传感器说的 10 位 ADC,其真实有效数据就是 10 位。
.storagebits:存储位数,有效位数+填充位。比如有些传感器 ADC 是 12 位的,那么我们存储的话肯定要用到 2 个字节,也就是 16 位,这 16 位就是存储位数。
.shift: 右移位数,也就是存储位数和有效位数不一致的时候,需要右移的位数,这个参数不总是需要,一切以实际芯片的数据手册位数。
.repeat:实际或存储位的重复数量。
.endianness: 数据的大小端模式,可设置为 IIO_CPU、IIO_BE(大端)或 IIO_LE(小端)。
比如ICM20608加速度计的X,Y,Z这三个轴,在sysfs下这三个轴肯定是对应三个不同的文件,我们通过读取这三个文件就能得到每个轴的原始数据。IIO_CHAN_INFO_RAW这个属性表示原始数据,当我们配置X,Y,Z,这是三个通道的时候,在info_mask_separate中使能IIO_CHAN_INFO_RAW这个属性,那么就表示在sysfs下生成三个不同的文件分别对应X,Y,Z轴,这三个轴的IIO_CHAN_INFO_RAW属性是相互独立的。
第 238 行,info_mask_shared_by_type 标记导出的信息由相同类型的通道共享。也就是 .type 成员变量相同的通道。比如 ICM20608 加速度计的 X、Y、Z 轴他们的 type 都是 IIO_ACCEL,也就是类型相同。而这三个轴的分辨率(量程)是一样的,那么在配置这三个通道的时候就可以在 info_mask_shared_by_type 中使能 IIO_CHAN_INFO_SCALE 这个属性,表示这三个通道的分辨率是共用的,这样在 sysfs 下就会只生成一个描述分辨率的文件,这三个通道都可以使用这一个分辨率文件。
第 248 行,output 表示为输出通道。
IIO驱动框架搭建
由上面分析IIO子系统的时候大家已经看出来了,IIO驱动框架主要是用于ADC类的传感器,比如陀螺仪、加速度计、磁力计、光强度计等,这些传感器基本都是 IIC 或者 SPI 接口的。因此 IIO 驱动的基础框架就是 IIC 或者 SPI。有些 SOC 内部的 ADC 也会使用 IIO 框架,那么这个时候驱动的基础框架 就是 platfrom。
首先我们需要搭建SPI(IIC)驱动框架,当设备和驱动匹配成功之后,probe函数就会执行。
IIO 设备申请与初始化
IIO 设备的申请、初始化以及注册在 probe 函数中完成,在注销驱动的时候还需要在 remove函数中注销掉 IIO 设备、释放掉申请的一些内存。
嵌入式linux IIO驱动相关推荐
- linux cached释放_正点原子Linux第四十一章嵌入式Linux LED驱动开发实验
1)资料下载:点击资料即可下载 2)对正点原子Linux感兴趣的同学可以加群讨论:935446741 3)关注正点原子公众号,获取最新资料更新 第四十一章嵌入式Linux LED驱动开发实验 上一章我 ...
- linux内核创建字符节点,Tiny6410学习ing—(四)、嵌入式Linux内核驱动进阶—(7)、高级字符设备驱动(自动创建节点)—#931...
按照国嵌的视频教程上来说的,最后就是-自动创建设备文件! 其实我感觉以前完全可以直接是手动创建了设备文件,然后就可以直接讲述自动创建设备文件,为啥非要拖到最后来讲述,我也就不清楚了!! 不管了,写完收 ...
- STM32MP157驱动开发——Linux IIO驱动(上)
STM32MP157驱动开发--Linux IIO驱动(上 ) 0.前言 一.IIO 子系统简介 1.iio_dev 结构体 2.iio_dev 申请与释放 3.iio_dev 注册与注销 4.iio ...
- 【正点原子Linux连载】第四十一章 嵌入式Linux LED驱动开发实验 -摘自【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.0
1)实验平台:正点原子阿尔法Linux开发板 2)平台购买地址:https://item.taobao.com/item.htm?id=603672744434 2)全套实验源码+手册+视频下载地址: ...
- 嵌入式linux设备驱动开发,嵌入式Linux设备驱动开发简介.pdf
清远见--嵌入式培训专家 http :// "黑色经典"系列之<嵌入式Linux 应用程序开发详解> 11 章 嵌入式Linux 设备驱动开发 本章目标 本书从 6 章 ...
- 有限状态机的嵌入式Linux按键驱动设计(转载)
本文转载自边缘之火<有限状态机的嵌入式Linux按键驱动设计(转载)> 原文链接: http://www.eccn.com/design_2010052509381340.htm 秦国栋 ...
- STM32MP157驱动开发——Linux IIO驱动(下)
STM32MP157驱动开发--Linux IIO驱动(下) 0.前言 一.IIO 触发缓冲区 1.IIO 触发器 2.申请触发器 3.释放触发器 4.注册触发器 5.注销触发器 6. IIO 缓冲区 ...
- 【正点原子MP157连载】第二十一章 嵌入式Linux LED驱动开发实验-摘自【正点原子】STM32MP1嵌入式Linux驱动开发指南V1.7
1)实验平台:正点原子STM32MP157开发板 2)购买链接:https://item.taobao.com/item.htm?&id=629270721801 3)全套实验源码+手册+视频 ...
- 嵌入式 Linux 内核驱动开发【The first day: 36093万字】
嵌入式 Linux 内核驱动开发[1] 嵌入式 Linux 内核驱动开发前言 第1章 Linux 内核裁剪和定制 [1]Linux 内核开发简介 [2] Linux 源码阅读工具 [1.2.1]Sou ...
最新文章
- EEPlat vs saleforce 配置 Knowledge Article 演示样例
- PE文件结构 - 数据目录表学习
- Python Flask web 项目零改动迁移至阿里云函数计算
- 掌握这 25 条小贴士,快速提升数据可视化能力!
- 统计字符串每个字符出现的次数
- POJ 1581 优先队列 priority_queue -- 比赛胜者求解
- 微信或正测试“发送语音过程”转文字功能 部分安卓用户可用
- 中判断字符串是否为空_自己动手编写VBA代码,判断一个工作表是否为空,然后删除它...
- 管理感悟:谈谈用户和需求
- mysql data masking_Percona8.0.17的数据屏蔽插件的使用
- ios 热更新可行性分析
- PIC单片机-Mplab的使用与实践
- 按键精灵---后台按键及鼠标操作
- php 调用 百度句法分析,【原创源码】百度新版翻译API调用使用范例
- final_cut_pro基础
- 石器时代地图->魔力宝贝地图
- Kotlin 之 lateinit关键字 与lazy
- 最新弹幕播放器源码/支持对接苹果+蓝光接口API
- JMeter BeanShell 应用
- 金蟾论金:4.13黄金探底回升收复跌势、晚间黄金走势分析指导
热门文章
- 1、Mac如何剪切文件
- vue keys detected: '1111'. This may cause an update error.
- SharePoint Log分析 —— HRESULT: 0x8007007E
- 如何用PS(photoshop)给照片加文字
- 分析称惠普赶走前任CEO赫德堪比苹果赶走乔布斯
- s1 Linux 硬件基础
- Windows系统下布置Redis服务器
- 汽车电瓶电压12V验证
- java 拼音_GitHub - promeG/TinyPinyin: 适用于Java和Android的快速、低内存占用的汉字转拼音库。...
- leetcode 58. 最后一个单词的长度(Length of Last Word)