Linux IIO研究(二)

大家好!我是大聪明-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 的一个绝佳解决方案。

从我与作者的通信中,我了解到此功能将包含在官方核心中,尽管不是当前的形式并且何时发布尚不清楚。

相关推荐
_dindong4 小时前
Linux网络编程:Socket编程预备
linux·运维·网络·学习
deng-c-f4 小时前
Linux C/C++ 学习日记(25):KCP协议:普通模式与极速模式
linux·学习·kcp
Net_Walke4 小时前
【Linux系统】系统编程
linux·运维·服务器
_dindong4 小时前
Linux网络编程:宏观网络体系
linux·网络·笔记·学习
猫林老师4 小时前
OpenHarmony南向开发环境搭建 - 深入理解Ubuntu、DevEco Device Tool与HPM
linux·运维·ubuntu·harmonyos·openharmony
爱装代码的小瓶子5 小时前
Linux下的权限与文件
linux·运维·服务器
ggaofeng6 小时前
linux中mount的本质是什么?自己如何实现一个伪文件系统
linux·mount·自己实现伪文件系统
敲上瘾6 小时前
Linux系统C++开发环境搭建工具(二)—— etcd 使用指南
linux·c++·etcd
励志不掉头发的内向程序员6 小时前
【Linux系列】解码 Linux 内存地图:从虚拟到物理的寻宝之旅
linux·运维·服务器·开发语言·学习