Necesitamos hablar sobre Linux IIO

IIO (Industrial I / O) es un subsistema del kernel de Linux para convertidores de analógico a digital (ADC), convertidores de digital a analógico (DAC) y varios tipos de sensores. Puede utilizarse en dispositivos industriales de alta velocidad. También incluye una API incorporada para otros controladores.





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:



IIO types



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.



IIO Triggered Buffers





"" , 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



IIO sysfs trigger



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)



iio-trig-interrupt



, . 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



iio-trig-sysfs



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



iio-trig-loop



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


The iio_simple_dummy Anatomy



iio_simple_dummy



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



libiio-loop.c

.



:



#    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.



, , .



4.19 5.4.









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://events19.linuxfoundation.org/wp-content/uploads/2017/12/Bandan-Das_Drone_SITL_bringup_with_the_IIO_framework.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.



Perdón por los enlaces, no pude hacer que se vieran como deberían en la rebaja y no estoy seguro de por qué.



Se solucionó el espacio - gracias Exosfera - Formateé incorrectamente los enlaces.




All Articles