|
|
|
# IIO
|
|
|
|
|
|
|
|
## Version
|
|
|
|
|
|
|
|
This section refers to the code available in Linux-3.1. Previously, I
|
|
|
|
studied and commented on version 2.6.39, but the code has significantly
|
|
|
|
improved since that release.
|
|
|
|
|
|
|
|
## Documentation
|
|
|
|
|
|
|
|
The IIO documentation is available in the kernel staging tree at
|
|
|
|
`iio/Documentation/`. The documentation provides an overview of the main
|
|
|
|
features and a quick indication of the functions to use for a rapid
|
|
|
|
test.
|
|
|
|
|
|
|
|
Documentation does not provides a full guide to writing an IIO driver;
|
|
|
|
for further information you need to read the drivers already developed
|
|
|
|
for IIO and use them as examples. Another source of information are the
|
|
|
|
dummy files developed to understand how to write an IIO driver.
|
|
|
|
|
|
|
|
Documentation does not provide an exhaustive description of the
|
|
|
|
mechanisms implement in the IIO core, buffers and triggers; again, for a
|
|
|
|
deeper knowledge you need to see all the code which is not always well
|
|
|
|
commented.
|
|
|
|
|
|
|
|
## Device Organization
|
|
|
|
|
|
|
|
IIO is organized as two levels: device and channels.
|
|
|
|
|
|
|
|
- **device** is the top level of the hierarchy and it represents the
|
|
|
|
acquisition chip. A device is described by the structures `iio_info`
|
|
|
|
and `iio_dev`.
|
|
|
|
|
|
|
|
<!-- end list -->
|
|
|
|
|
|
|
|
- **channel** is part of device; it represents a single acquisition
|
|
|
|
source of the device. A channel is described by the
|
|
|
|
iio\_chan\_spec structure.
|
|
|
|
|
|
|
|
IIO allocates a char device region of 256 minors; IIO assigns a minor
|
|
|
|
for each device registered, so there is only one char special file for
|
|
|
|
each device, so you can register a maximum of 256 devices.
|
|
|
|
|
|
|
|
The char device management use a single char device file for each
|
|
|
|
device. The main purpose of this file is accessing the buffer from user
|
|
|
|
space; another use is delivering events.
|
|
|
|
|
|
|
|
## Aim and Features
|
|
|
|
|
|
|
|
The main purpose of IIO is providing support for analogue input devices,
|
|
|
|
typically connected through I2C or SPI; there is no support at all for
|
|
|
|
output signals. In this release there are no specific functionality to
|
|
|
|
handle digital signals, but it is not forbidden.
|
|
|
|
|
|
|
|
Channels specificity is the focus of the IIO hierarchy and the core.
|
|
|
|
Channels must have a specified type which can be only one that IIO has
|
|
|
|
defined: accelerometers, inclinometers, temperature sensors, and similar
|
|
|
|
well-defined use classes. These devices are usually based on SPI or I2C,
|
|
|
|
and this is the main IIO target. Again, IIO builds the sysfs name with
|
|
|
|
these devices in mind, so it provides modifiers for the three axis of an
|
|
|
|
accelerometers or a gyroscope, or for the light of a light sensor.
|
|
|
|
|
|
|
|
I think that IIO target is not the *industrial* sector intended as a
|
|
|
|
serious industrial setup with a complex sensors network, but only basic
|
|
|
|
acquisition systems for small industrial applications or personal
|
|
|
|
equipments, as well as the sensors included in atypical PC.
|
|
|
|
|
|
|
|
The functionality provided by IIO framework is aimed to create a
|
|
|
|
standard interface for driver development for acquisition chips; part of
|
|
|
|
this interface are triggers, buffers, events and sysfs. Events and sysfs
|
|
|
|
management is integrated within the IIO core, which exports utility
|
|
|
|
functions towards low-level drivers. Buffers and triggers follow the
|
|
|
|
modular approach so each developer can implement his/her buffers or
|
|
|
|
triggers and use them with IIO. Some buffer and trigger implementations
|
|
|
|
are already developed and are available in the kernel configuration;
|
|
|
|
developers with no special needs can use them.
|
|
|
|
|
|
|
|
In a context where data transfers are several mega-samples per second,
|
|
|
|
it's important to have meta-information about samples. Meta-information
|
|
|
|
allows a delayed analysis of the streams, and a logging activity about
|
|
|
|
the acquisitions. IIO does not provide this important feature; the only
|
|
|
|
meta-information exported to user space is in the so-called *events*
|
|
|
|
which are not really useful for logging or delayed analysis.
|
|
|
|
|
|
|
|
## Over Engineering
|
|
|
|
|
|
|
|
IIO sometimes suffers from over-engineering. Four examples are:
|
|
|
|
|
|
|
|
- IIO sysfs attributes accept floating point numbers in input; then
|
|
|
|
kernel can handle only integer values so IIO must convert
|
|
|
|
a float number ASCII string into two integer variables: the integral
|
|
|
|
part and the fractional part. All this conversion is useless because
|
|
|
|
the kernel can not handle floating point values. Only integer values
|
|
|
|
should be allowed, using very fine granularity (e.g., micro-volts).
|
|
|
|
|
|
|
|
<!-- end list -->
|
|
|
|
|
|
|
|
- The sysfs attribute system is centralized into IIO, it creates and
|
|
|
|
destroys attributes and calculates a name for each of them. The name
|
|
|
|
is calculated from the channel features by the concatenation of some
|
|
|
|
suffixes and prefixes, thus can create very long names. A sysfs name
|
|
|
|
should be small and it should not describe the channel features.
|
|
|
|
|
|
|
|
<!-- end list -->
|
|
|
|
|
|
|
|
- each channel has 2 different indexes; one is the `scan_index` which
|
|
|
|
is used to order channels in *scans* within a buffer (a *scan* is a
|
|
|
|
set of channels to acquire); the other one, `channel`, is the
|
|
|
|
channel index on device, but if the `indexed` flag is false, then
|
|
|
|
`channel` is just a numerical name. Using two indexes is generally
|
|
|
|
not needed: a single index should be enough for both purposes; if a
|
|
|
|
device scans its channels in a different order from channel indexes,
|
|
|
|
then you should change channel indexes to meet the scan order, which
|
|
|
|
is more important than channel order.
|
|
|
|
|
|
|
|
<!-- end list -->
|
|
|
|
|
|
|
|
- IIO channels provide different precision formats and a function to
|
|
|
|
query the device about this; format precision is applied to the
|
|
|
|
fractional part. In my opinion, a framework should not handle these
|
|
|
|
details because it is a needless overhead for low-level drivers, the
|
|
|
|
framework itself and user-space. The precision may change among
|
|
|
|
devices, so each part of the acquisition system must handle this
|
|
|
|
possibility. With a fixed precision format, the meaning of each data
|
|
|
|
item in each part of the acquisition system is well known, so it is
|
|
|
|
easy to handle; if a different precision format is absolutely
|
|
|
|
required,
|
|
|
|
low-level drivers or user-space can change it, but not the
|
|
|
|
framework.
|
|
|
|
|
|
|
|
## IIO Interfaces
|
|
|
|
|
|
|
|
### IIO Buffer Interface
|
|
|
|
|
|
|
|
The IIO buffer interface has three main structures:
|
|
|
|
|
|
|
|
- `*iio_buffer_setup_ops*`. They are used when a buffer instance is
|
|
|
|
enabled or disabled.
|
|
|
|
|
|
|
|
<!-- end list -->
|
|
|
|
|
|
|
|
- `*iio_buffer_access_funcs*`. It contains the buffer operations used
|
|
|
|
to gain access to the buffer.
|
|
|
|
|
|
|
|
<!-- end list -->
|
|
|
|
|
|
|
|
- `*iio_buffer*`. It is the general descriptor of a buffer. It
|
|
|
|
contains the information about the buffer status, about
|
|
|
|
channels scan and the pointers to the buffer functions, both setup
|
|
|
|
and access. Developers can also add here buffer specific sysfs
|
|
|
|
attributes.
|
|
|
|
|
|
|
|
The IIO buffer interface provides the file operations for all the
|
|
|
|
buffers, and does not allow developers to define their own. The file
|
|
|
|
operations provided by IIO are really simple; for data transfer only
|
|
|
|
`read()` function is available, and it is just a wrap function around
|
|
|
|
the buffer operation `read_first_n()`, so developers when implement this
|
|
|
|
buffer operation must bear in mind that is a file operation.
|
|
|
|
`read_first_n()` is effectively the `read()` file operations but with a
|
|
|
|
subset of parameters, so limiting functionality and making it difficult
|
|
|
|
to recognize without reading the IIO core.
|
|
|
|
|
|
|
|
IIO does not handle buffer reference counting; it asks to the buffer
|
|
|
|
developers to implement an *use counter* of the buffer. IIO uses
|
|
|
|
`mark_in_use()` and `unmark_in_use()` from `iio_buffer_access_funcs`
|
|
|
|
functions to check if buffer is in use or not. IIO buffer interface does
|
|
|
|
not handle any concurrency issue and leaves them to developers of each
|
|
|
|
individual buffer implementation.
|
|
|
|
|
|
|
|
IIO does not allow users to change the buffer implementation in use; a
|
|
|
|
low-level driver chooses which implementation uses and can not be
|
|
|
|
changed.
|
|
|
|
|
|
|
|
The IIO buffer interface handles an individual sample or a group of
|
|
|
|
samples from different channels; such group is called a *scan*. The
|
|
|
|
buffer operation `store_to()` accepts a single scan to store in the
|
|
|
|
buffer; the read operations `read_last()` and
|
|
|
|
`read_first_n()` return a single scan and `n` scans, respectively.
|
|
|
|
|
|
|
|
For our purpose this buffer interface is not good. In our main case
|
|
|
|
buffer handles millions of samples for second and we can not waste time
|
|
|
|
on the single sample, but we need to move large amount of samples
|
|
|
|
between user space and devices. Again, it is useful to have flexibility
|
|
|
|
in choosing the buffer type. IIO does not currently provide such
|
|
|
|
flexibility.
|
|
|
|
|
|
|
|
### IIO Trigger Interface
|
|
|
|
|
|
|
|
IIO trigger interface has two main structures:
|
|
|
|
|
|
|
|
\* `*iio_trigger_ops*`. It is the container for the triggers functions
|
|
|
|
which are handled by IIO.
|
|
|
|
|
|
|
|
\* `*iio_trigger*`. It is the general descriptor of a trigger. It
|
|
|
|
contains information about trigger and a pointer to the trigger
|
|
|
|
functions. In IIO triggers are devices, so trigger implementations can
|
|
|
|
use `device` functionality; for example to define trigger specific sysfs
|
|
|
|
attributes. These sysfs attributes can not be declared in `iio_trigger`
|
|
|
|
but developers must use `device` by adding new attribute to
|
|
|
|
`iio_trigger->dev->groups`
|
|
|
|
|
|
|
|
\* `*iio_poll_func*`. It is a structure which contains the functions to
|
|
|
|
run on trigger fire.
|
|
|
|
|
|
|
|
A specific trigger can be associated to an IIO device by registering a
|
|
|
|
new trigger and set it in `iio_device->trig`. A generic trigger suitable
|
|
|
|
for different IIO device should be declared as separate module; but the
|
|
|
|
IIO mechanism to associate a trigger to a device it is no intuitive, and
|
|
|
|
it can discourage developers to create independent modules for triggers.
|
|
|
|
|
|
|
|
IIO takes track of all the registered triggers to allow users to change
|
|
|
|
the current trigger through sysfs by naming it. This operation is
|
|
|
|
possible only if the IIO device has the `INDIO_BUFFER_TRIGGERED` mode
|
|
|
|
enable. When the trigger implementation is an independent module, it
|
|
|
|
must provides the functions to add and remove instances of itself. A
|
|
|
|
trigger instance is the only object that an IIO device can use. The
|
|
|
|
instance management take place on user space side, so it is the user
|
|
|
|
that creates an instance and associates it to the device.
|
|
|
|
|
|
|
|
When an user tries to associate a trigger instance to an IIO device, IIO
|
|
|
|
makes a double check: it verifies if trigger is compatible with the
|
|
|
|
device in use, and it verifies if the device is compatible with the
|
|
|
|
requested trigger; if both trigger and device are compatible, framework
|
|
|
|
assigns the trigger to device.
|
|
|
|
|
|
|
|
It is not explicit, but events can be used to configure a trigger value.
|
|
|
|
Event attributes have their own methods to read and write; these methods
|
|
|
|
access to the value used as reference to generate the event. For
|
|
|
|
example, for the threshold event the value is the threshold limit for
|
|
|
|
trigger.
|
|
|
|
|
|
|
|
### SYSFS Interface
|
|
|
|
|
|
|
|
In the last release IIO creates the common attributes but lefts to
|
|
|
|
developers the freedom to add their own; the IIO sysfs interface is
|
|
|
|
built on `device` which creates the sysfs tree prepared by IIO.
|
|
|
|
|
|
|
|
In IIO Developers can declare their attributes for event, buffer,
|
|
|
|
trigger and device, but not for channels. This can works for small chip,
|
|
|
|
but acquisition boards can have many register for each channel and it is
|
|
|
|
desirable that a framework allows developers to add attributes on
|
|
|
|
channel level.
|
|
|
|
|
|
|
|
The attributes provided by IIO have an `address` field which should be
|
|
|
|
used to set up the device register addresses correspondent to the
|
|
|
|
attributes; IIO uses the field to store the bit flag which generate the
|
|
|
|
sysfs attribute and don't allow developer to specify a valid address.
|
|
|
|
Developers are free to use `address` to store a valid address, but only
|
|
|
|
for their own attributes.
|
|
|
|
|
|
|
|
IIO base its sysfs attributes interface on `device` interface, so it is
|
|
|
|
not semaphored. Concurrent processes can try to change the same
|
|
|
|
attribute at the same time with unpredictable result.
|
|
|
|
|
|
|
|
### Events Interface
|
|
|
|
|
|
|
|
The events interface aim is to provide events notification to user
|
|
|
|
space. They are typically used to notify when trigger fires or when
|
|
|
|
hardware interrupt occurs. IIO defines a few kind of events; developers
|
|
|
|
can add their own.
|
|
|
|
|
|
|
|
IIO manage the events with a list. The `iio_push_event()` function add a
|
|
|
|
new occurred event to the list; the function is used
|
|
|
|
by the low-level drivers. The `read()` `file_operations` extracts an
|
|
|
|
event from the event list with FIFO policy and copy it to user space.
|
|
|
|
|
|
|
|
The `file_operations` to gain access to events are hide behind the
|
|
|
|
`ioctl()`; `ioctl()` calls `anon_inode_get_fd()` which create a `file`
|
|
|
|
without an inode, so without consume minors. This choice forces users to
|
|
|
|
use specific programs to read the events.
|
|
|
|
|
|
|
|
IIO allows the driver to push events although char device file is not
|
|
|
|
open; when char device file is open and it is going to be closed, IIO
|
|
|
|
flush the detected events list. This is incorrect because this procedure
|
|
|
|
deletes events which are not returned to user space. IIO applies two
|
|
|
|
opposite policies: it allows to enqueue events when file is closed; but
|
|
|
|
it flush the events list on close.
|
|
|
|
|
|
|
|
## Use IIO From User Space
|
|
|
|
|
|
|
|
IIO communicate with user-space via char device and SYSFS interface. The
|
|
|
|
main purpose of SYSFS interface is to configure driver options; it is
|
|
|
|
also used to acquire a single sample from a device channel without
|
|
|
|
buffer. Char devices are used to fetch data from a buffer and from the
|
|
|
|
event list.
|
|
|
|
|
|
|
|
There is not an official user-space library for IIO programs
|
|
|
|
development.
|
|
|
|
|
|
|
|
## Developing a Driver
|
|
|
|
|
|
|
|
The aim of this paragraph it is not to provide a full guide to develop a
|
|
|
|
driver within IIO, because each device has different features and
|
|
|
|
requires different driver implementation. This is a rapid introduction
|
|
|
|
for a fast test of IIO.
|
|
|
|
|
|
|
|
The minimum lines of code to get work a low-level driver with IIO,
|
|
|
|
requires to implement the IIO functions in `iio_info` and an array of
|
|
|
|
`iio_chan_spec`, respectively to implement the device operations and to
|
|
|
|
describe the device channels; then register the device in IIO.
|
|
|
|
|
|
|
|
For example, for a simple acquisition chip the `read_raw()`
|
|
|
|
implementation can be enough; this operation acquires a value from
|
|
|
|
device, so it implements the low-level communication between kernel and
|
|
|
|
device; the value can be both a configuration value or a sample, the
|
|
|
|
mask parameter specifies which value acquire. You can implement the
|
|
|
|
other operations if your driver need them. Driver specific sysfs
|
|
|
|
attributes can be also defined within `iio_info->attrs`.
|
|
|
|
|
|
|
|
The IIO targets are the SPI and I2C devices, so you have to create the
|
|
|
|
driver for the bus in use and then register it. The driver method
|
|
|
|
`probe()` must be used for IIO initialization and registration, and the
|
|
|
|
driver method `remove()` to un-register from IIO and free data.
|
|
|
|
|
|
|
|
To register a device in IIO you have to follow the following steps in
|
|
|
|
the exact order:
|
|
|
|
|
|
|
|
\* allocate an `iio_device` with `iio_allocate_device()`.
|
|
|
|
|
|
|
|
\* fill the `iio_device` fields and private date if it is needed.
|
|
|
|
|
|
|
|
\* configure an `iio_buffer` with one of the available implementations
|
|
|
|
or your own one.
|
|
|
|
|
|
|
|
\* register the configured `iio_buffer` with `iio_buffer_register()`
|
|
|
|
|
|
|
|
\* register the `iio_device` with `iio_device_register()`
|
|
|
|
|
|
|
|
The registrations `iio_buffer_register()` and `iio_device_register()`
|
|
|
|
must be executed in this exact order, otherwise the sysfs creation is
|
|
|
|
wrong; there is not error or message to warn you about this.
|
|
|
|
|
|
|
|
## Compare with Requirements
|
|
|
|
|
|
|
|
The following table shows how the [Requirements](Requirements) list
|
|
|
|
items are supported by COMEDI.
|
|
|
|
|
|
|
|
<table>
|
|
|
|
<tbody>
|
|
|
|
<tr class="odd">
|
|
|
|
<td><strong>requirements</strong></td>
|
|
|
|
<td><strong>IIO</strong></td>
|
|
|
|
<td><strong>Note</strong></td>
|
|
|
|
</tr>
|
|
|
|
<tr class="even">
|
|
|
|
<td>Digital/Analog I/O</td>
|
|
|
|
<td>no</td>
|
|
|
|
<td>There is no output, only analogue signal are explicit support.</td>
|
|
|
|
</tr>
|
|
|
|
<tr class="odd">
|
|
|
|
<td>TDC and DTC</td>
|
|
|
|
<td>no</td>
|
|
|
|
<td>There is no explicit support.</td>
|
|
|
|
</tr>
|
|
|
|
<tr class="even">
|
|
|
|
<td>One-shot, burst, and streaming support</td>
|
|
|
|
<td>yes</td>
|
|
|
|
<td></td>
|
|
|
|
</tr>
|
|
|
|
<tr class="odd">
|
|
|
|
<td>Layered structure</td>
|
|
|
|
<td>half</td>
|
|
|
|
<td>The layer structure is thought for small chips, so it provide only two level: device and channels</td>
|
|
|
|
</tr>
|
|
|
|
<tr class="even">
|
|
|
|
<td>No hard limits on the number of bits or channels</td>
|
|
|
|
<td>no</td>
|
|
|
|
<td>The numer of device is limited to 256</td>
|
|
|
|
</tr>
|
|
|
|
<tr class="odd">
|
|
|
|
<td>High-data rate, little storage overhead</td>
|
|
|
|
<td>no</td>
|
|
|
|
<td>IIO buffer interface handle data sample by sample, we need to handle very large amout of samples</td>
|
|
|
|
</tr>
|
|
|
|
<tr class="even">
|
|
|
|
<td>Easy and general configuration</td>
|
|
|
|
<td>no</td>
|
|
|
|
<td>General application</td>
|
|
|
|
</tr>
|
|
|
|
<tr class="odd">
|
|
|
|
<td>Offset, gain, number of bits, ...</td>
|
|
|
|
<td>no</td>
|
|
|
|
<td>A different set is considered "common" and does not have always the same name in each devices</td>
|
|
|
|
</tr>
|
|
|
|
<tr class="even">
|
|
|
|
<td>Extensibility</td>
|
|
|
|
<td>yes</td>
|
|
|
|
<td></td>
|
|
|
|
</tr>
|
|
|
|
<tr class="odd">
|
|
|
|
<td>Little code overhead</td>
|
|
|
|
<td>yes</td>
|
|
|
|
<td></td>
|
|
|
|
</tr>
|
|
|
|
<tr class="even">
|
|
|
|
<td>Centralized semaphores</td>
|
|
|
|
<td>no</td>
|
|
|
|
<td>IIO handle semaphores only for internal use and for standard syfs attribute. Each implementations (driver, buffer, trigger) must handle with semaphores.</td>
|
|
|
|
</tr>
|
|
|
|
<tr class="odd">
|
|
|
|
<td>Flexible buffer management</td>
|
|
|
|
<td>no</td>
|
|
|
|
<td>IIO buffer interface handle data sample by sample, we need to handle very large amout of samples</td>
|
|
|
|
</tr>
|
|
|
|
<tr class="even">
|
|
|
|
<td>Device-driven data transfers</td>
|
|
|
|
<td>yes</td>
|
|
|
|
<td></td>
|
|
|
|
</tr>
|
|
|
|
<tr class="odd">
|
|
|
|
<td>Hardware time stamps</td>
|
|
|
|
<td>half</td>
|
|
|
|
<td>IIO make assumption on timestamp; it is a 64bit signed integer which represent nanoseconds</td>
|
|
|
|
</tr>
|
|
|
|
</tbody>
|
|
|
|
</table>
|
|
|
|
|