大家好!我是大聪明-PLUS!
设备树
这里我要特别强调一下为节点设置标签的功能,如果您有许多类似的设备,此功能尤其适用。您可以随时在每个 iio:device 的 of_node 目录中查看节点中设置的当前值 - /sys/bus/iio/devices/iio\:device0/of_node/。
测量通道类型
许多以前作为独立实体存在的传感器已迁移到 IIO 基础架构,因此几乎任何测量类型都可以在 iio_chan_type 枚举中找到。详情可在此处找到: iio_event_monitor。
数据格式
IIO 可以向我们报告数据传输的格式iio-buffer-sysfs-interface。
`[be|le]:[s|u]bits/storagebitsXrepeat[>>shift]`
icm20608 的实例:
`# cat /sys/bus/iio/devices/iio\:device0/scan_elements/*_type
be:s16/16>>0
be:s16/16>>0
be:s16/16>>0
be:s16/16>>0
be:s16/16>>0
be:s16/16>>0
le:s64/64>>0`
到这里,一切都或多或少清楚了:
- 首先是字节顺序 le 或 be,我们必须确保顺序与我们的体系结构或我们选择的字节顺序相匹配
- 然后是类型 - 有符号或无符号,分别为 s 或 u
- 然后是值的长度(以位为单位),/ 之后是包含该值的字段的长度,同样以位为单位,是字节位数的倍数
- 最后要改变的是
也就是说,如果我们将两个四位值打包到同一个字段中,我们将看到以下内容:
`be:u4/8>>0
be:u4/8>>4`
倒数第二个字段(在实际示例中未显示)是重复的 - 如果它大于 1,则会立即传输一个维度数组。
缩放和偏移
正如我之前所说,读取的原始数据必须转化为一般形式:
`/sys/bus/iio/devices/iio:deviceX/in_*_raw
/sys/bus/iio/devices/iio:deviceX/in_*_offset
/sys/bus/iio/devices/iio:deviceX/in_*_scale`
一般来说,转换的形式为 (raw + offset)*scale;对于某些传感器类型,可能没有偏移。
如何使用sysfs接口进行简单的ADC转换
iio_simple_dummy
对于研究和测试,iio_simple_dummy可能很有用------它是一个内核模块,可以为以下通道模拟抽象的 IIO 设备:
- IIO_电压
- IIO_加速
- IIO_ACTIVITY
iio_simple_dummy 结构
iio_simple_dummy
自由主义
如果您觉得上述内容很复杂, Analog Devices 的libiio可以为您提供帮助。
除了处理诸如整理频道格式或打开/关闭频道等日常事务之外。
它具有一个有趣的特性,即能够作为服务器/客户端工作,在这种情况下,带有传感器的设备充当数据服务器,而客户端可以位于 Linux、Windows 或 Mac 机器上,并通过 USB、以太网或串行连接。
连接到远程 iiod 节点:
在远程:
`host # iiod`
在本地:
`local $ iio_info -n [host_address]
local $ iio_attr -u ip:[host_address] -d
local $ iio_readdev -u ip:[host_address] -b 256 -s 0 icm20608`
不使用 libiio 进行工作
我不会涉及 sysfs 的平凡工作,因此一般来说,阅读时您需要执行以下操作:
- 搜索设备,这里我们关注的是/sys/bus/iio/iio:deviceN/name,分别/sys/bus/iio/iio:deviceN会匹配/dev/iio:deviceN
- 初始化 /sys/bus/iio/iio:deviceN/scan_elements/ 中的通道,我们将仅接收在 *_en 中订购的通道的测量值
- 初始化缓冲区 /sys/bus/iio/iio:deviceN/enable
该示例显示了工作所需的最低限度。
结论
如果我们不想使用 libiio,就必须自己做。
计算每个通道偏移量的简单代码:
`
if (bytes % length == 0)
offset = bytes;
else
offset = bytes - bytes % length + length;
bytes = offset + length;`
在没有 libiio 的情况下以及相反的情况下,测量都必须达到其最终形式:
- 使字节顺序与正在使用的字节顺序一致
- 移至所需值
- 切掉多余的
- 如果是签名的,则执行符号扩展(Sign extension)
- 如果有偏移,则在应用比例之前添加它
- 如果有尺度,则应用尺度
` input = is_be ? betoh(input) : letoh(input);
input >>= shift;
input &= BIT_MASK(bits);
value = is_signed ? (float)sext(input, bits) : (float)input;
if(with_offset) value += offset;
if(with_scale) value *= scale;`
注意:示例中显示的 Sign 扩展是最简单的、不可移植的版本。
使用 libiio
关于读取数据的替代机制的几句话
作为数据访问的替代方案,提出了一个原型,允许将数据从设备缓冲区直接移动到用户缓冲区,即所谓的零拷贝机制。
所有这些都与处理高速数据流的方法有关。
方法比较(演示文稿摘要):
解决方案一------区块
- 将多个维度组合成一个块
- 每个块生成一个中断
- 降低管理成本
- 块大小必须是可配置的
- 允许用户应用程序在延迟和开销之间进行选择
解决方案二:DMA + mmap()
- 使用 DMA 将数据从设备移动到专用内存块。
- 使用 mmap() 从用户空间访问内存
- 避免复制数据
- 用户空间中的"免费"解复用
在我看来,这是 SDR 的一个绝佳解决方案。
从我与作者的通信中,我了解到此功能将包含在官方核心中,尽管不是当前的形式并且何时发布尚不清楚。