IIO (Industrial I / O) is a subsystem of the Linux kernel for analog to digital converters (ADC), digital to analog converters (DAC), and various types of sensors. Can be used on high speed industrial devices. It also includes a built-in API for other drivers.
Industrial I/O Linux ( ) , . , sysfs devfs.
IIO:
- /
IIO :
- (: )
- - , DFSDM (, , )
- , TIM LPTIM
- SPI I2C
IIO , , ...
IIO
/ :
# https://www.kernel.org/doc/Documentation/i2c/dev-interface
open("/dev/i2c-1", O_RDWR);
# https://www.kernel.org/doc/Documentation/spi/spidev.rst
open("/dev/spidev2.0", O_RDWR);
, :
— ?
"" ( ).
IIO - , - poll .
IIO — .
.
IIO
sysfs ( ):
# cat /sys/bus/iio/devices/iio\:device0/in_accel_x_raw
-493
"" , .
read():
#
(cd /sys/bus/iio/devices/iio:device0/scan_elements/ && for file in *_en; do echo 1 > $file; done)
:
int fd = open("/dev/iio:device0");
read(fd, buffer, scan_size);
# scan_size , 1 /sys/bus/iio/devices/iio:device0/scan_elements/*_en
scan_size, "" , , .
IIO struct iio_chan_spec:
BME280
/* https://elixir.bootlin.com/linux/v5.9-rc1/source/drivers/iio/pressure/bmp280-core.c#L132*/
static const struct iio_chan_spec bmp280_channels[] = {
{
.type = IIO_PRESSURE,
.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
},
{
.type = IIO_TEMP,
.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
},
{
.type = IIO_HUMIDITYRELATIVE,
.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
},
};
, , — .
Linux , .
, kfifo .
, , , .
. , , , , , .
, CLOCK_REALTIME.
"" , user space.
, .
:
# cat /sys/bus/iio/devices/iio\:device0/trigger/current_trigger
icm20608-dev0
# echo > /sys/bus/iio/devices/iio\:device0/trigger/current_trigger
# cat /sys/bus/iio/devices/iio\:device0/trigger/current_trigger
# echo "icm20608-dev0" > /sys/bus/iio/devices/iio\:device0/trigger/current_trigger
Official Trigger Documentation
Industrial IIO configfs support
Triggered buffer support trigger buffer support for IIO subsystem of Linux device driver
Device owned triggers
, device tree:
icm20608: imu@0 {
...
interrupt-parent = <&gpio5>;
interrupts = <11 IRQ_TYPE_EDGE_RISING>;
...
};
:
cat /sys/bus/iio/devices/trigger0/name
icm20608-dev0
gpio, , .
Interrupt triggers (also known as gpio trigger)
, . gpio, .
, maintainer'a IIO Jonathan Cameron, .
— Triggered buffer support trigger buffer support for IIO subsystem of Linux device driver
.
:
[v3,1/6] dt-bindings: iio: introduce trigger providers, consumers
device tree :
trig0: interrupt-trigger0 {
#io-trigger-cells = <0>;
compatible = "interrupt-trigger";
interrupts = <11 0>;
interrupt-parent = <&gpioa>;
};
sysfs trigger
sysfs — , .
:
# echo 10 > /sys/bus/iio/devices/iio_sysfs_trigger/add_trigger
"sysfstrig%d", .
High resolution timer trigger
1 .
# mkdir /sys/kernel/config/iio/triggers/hrtimer/my_trigger_name
# cat /sys/bus/iio/devices/trigger4/name
my_trigger_name
# cat /sys/bus/iio/devices/trigger4/sampling_frequency
100
— "" SoC.
loop trigger
PATCH v1 5/5 iio:pressure:ms5611: continuous sampling support
.
. :
iio:trigger: Experimental kthread tight loop trigger.
DT, , .
Device tree
label , , of_node iio:device — /sys/bus/iio/devices/iio\:device0/of_node/.
— https://elixir.bootlin.com/linux/v5.9-rc1/source/Documentation/devicetree/bindings/iio
, IIO, enum 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 c
- — , s u
- / ,
:
be:u4/8>>0
be:u4/8>>4
repeat — 1 .
Scaling and offset
:
/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, offset'a .
How to do a simple ADC conversion using the sysfs interface
iio_simple_dummy
iio_simple_dummy — IIO :
- IIO_VOLTAGE
- IIO_ACCEL
- IIO_ACTIVITY
libiio
— libiio Analog Devices.
, / .
/, , Linux, Windows Mac , USB, Ethernet Serial.
iiod:
On remote :
host # iiod
On local :
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
Matlab, .
, libiio .
https://github.com/maquefel/icm20608-iio
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
.
E libiio.
https://elixir.bootlin.com/linux/v5.9-rc1/source/drivers/iio/industrialio-buffer.c#L574
:
# bytes -
# length -
# offset -
if (bytes % length == 0)
offset = bytes;
else
offset = bytes - bytes % length + length;
bytes = offset + length;
libiio, :
- , (Sign extension)
- offset,
- scale,
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 extension) . SignExtend.
libiio
:
# uri
# uri = "ip:127.0.0.1"
# uri = "local:"
# uri = "usb:"
ctx = iio_create_context_from_uri(uri);
#
# device = icm20608
dev = iio_context_find_device(ctx, device);
#
nb_channels = iio_device_get_channels_count(dev);
#
for(int i = 0; i < nb_channels; i++)
iio_channel_enable(iio_device_get_channel(dev, i));
# buffer_size = SAMPLES_PER_READ, ( )
buffer = iio_device_create_buffer(dev, buffer_size, false);
#
iio_buffer_set_blocking_mode(buffer, true);
while(true) {
#
iio_buffer_refill(buffer);
# - libiio
# "" ,
#
# ssize_t print_sample(const struct iio_channel *chn, void *buffer, size_t bytes, __notused void *d)
# const struct iio_channel *chn -
# void *buffer -
# size_t bytes -
# __notused void *d - iio_buffer_foreach_sample
iio_buffer_foreach_sample(buffer, print_sample, NULL);
}
#
iio_buffer_destroy(buffer);
#
iio_context_destroy(ctx);
, , Zero-Copy.
.
( ):
—
— DMA + mmap()
- DMA
- mmap()
- ""
High-speed Data Acquisition
using the
Linux Industrial IO framework
SDR.
, , .
https://bootlin.com/pub/conferences/2012/fosdem/iio-a-new-subsystem/iio-a-new-subsystem.pdf
https://archive.fosdem.org/2012/schedule/event/693/127_iio-a-new-subsystem.pdf
https://programmer.group/5cbf67db154ab.html
https://elinux.org/images/b/ba/ELC_2017_-_Industrial_IO_and_You-_Nonsense_Hacks%21.pdf
https://elinux.org/images/8/8d/Clausen--high-speed_data_acquisition_with_the_linux_iio_framework.pdf
https://linux.ime.usp.br/~marcelosc/2019/09/Simple-IIO-driver
P.S.
Sorry for the links, I couldn't get them to look like they should in markdown, and I'm not sure why.
Space was solved - thanks Exosphere - I incorrectly formatted the links.