Re: [PATCH v4] DocBook: Add initial documentation for IIO

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Sorry, hit send by mistake :)


>>> +      An IIO buffer has an associated attributes directory under <filename>
>>> +      /sys/bus/iio/iio:deviceX/buffer/</filename>. Here are the existing
>>> +      attributes:
>>> +      <itemizedlist>
>>> +      <listitem>
>>> +      <emphasis>length</emphasis>, number of data samples contained by the
>>> +        buffer.
>>
>> wording is not very clean; length is is the buffer length/capacity, not
>> the number of samples currently in the buffer
>
> Oh, I see. The same wording is in the ABI file:

http://lxr.free-electrons.com/source/Documentation/ABI/testing/sysfs-bus-iio#L975

<snip>

>>> +        </listitem>
>>> +        <listitem><emphasis>bits</emphasis> is the number of bits of data
>>
>> number of data bits

Ok.

>>
>>> +        </listitem>
>>> +        <listitem><emphasis>storagebits</emphasis> is the space (after padding)
>>> +          that it occupies in the buffer.
>>
>> is the number of bits (after padding) that...

Ok.

>>
>>> +        </listitem>
>>> +        <listitem>
>>> +        <emphasis>shift</emphasis> if specified, is the shift that needs
>>> +          to be a applied prior to masking out unused bits
>>
>> that needs to be applied -- delete a

Ok.

>>
>>> +        </listitem>
>>> +        <listitem>
>>> +        <emphasis>repeat</emphasis>, specifies the number of real/storage bits
>>
>> what is real? -- undefined at this point;
>> "real/storage" doesn't make it clear if the padded or unpadded data bits
>> are repeated -- I think the later
>> maybe: "specifies the number of unpadded data repetitions"

Will fix.

>>
>>> +        repetitions. When the repeat element is 0 or 1, then the repeat
>>> +        value is omitted.
>>> +        </listitem>
>>> +        </itemizedlist>
>>> +      </listitem>
>>> +      </itemizedlist>
>>> +      For example, a driver for a 3-axis accelerometer with 12 bit
>>> +      resolution where data is stored in two 8-bits registers as
>>> +      follows:
>>> +      <programlisting>
>>> +        7   6   5   4   3   2   1   0
>>> +      +---+---+---+---+---+---+---+---+
>>> +      |D3 |D2 |D1 |D0 | X | X | X | X | (LOW byte, address 0x06)
>>> +      +---+---+---+---+---+---+---+---+
>>> +
>>> +        7   6   5   4   3   2   1   0
>>> +      +---+---+---+---+---+---+---+---+
>>> +      |D11|D10|D9 |D8 |D7 |D6 |D5 |D4 | (HIGH byte, address 0x07)
>>> +      +---+---+---+---+---+---+---+---+
>>> +      </programlisting>
>>> +
>>> +      will have the following scan element type for each axis:
>>> +      <programlisting>
>>> +      $ cat /sys/bus/iio/devices/iio:device0/scan_elements/in_accel_y_type
>>> +      le:s12/16>>4
>>> +      </programlisting>
>>> +      The userspace applications will interpret data samples read from buffer
>>
>> user space -- inconsistent
>> maybe "A user space application will..."
>> the buffer -- the
>>
>>> +      as two byte little endian signed data, that needs a 4 bits right
>>> +      shift before masking out the only 12 valid bits of real data.
>>
>> masking out the 12 valid bits of data

Agree.

>>
>>> +    </para>
>>> +    <para>
>>> +      For implementing buffer support a driver should initialize the following
>>> +      fields in <type>iio_chan_spec</type> definition:
>>> +      <programlisting>
>>> +          struct iio_chan_spec {
>>> +              /* other members */
>>> +              int scan_index
>>> +              struct {
>>> +                  char sign;
>>> +                  u8 realbits;
>>> +                  u8 storagebits;
>>> +                  u8 shift;
>>> +                  u8 repeat;
>>> +                  enum iio_endian endianness;
>>> +              } scan_type;
>>> +          };
>>> +      </programlisting>
>>> +      The driver implementing the accelerometer described above will
>>> +      have the following channel definition:
>>> +      <programlisting>
>>> +      struct struct iio_chan_spec accel_channels[] = {
>>> +          {
>>> +            .type = IIO_ACCEL,
>>> +            .modified = 1,
>>> +            .channel2 = IIO_MOD_X,
>>> +            /* other stuff here */
>>> +            .scan_index = 0,
>>> +            .scan_type = {
>>> +              .sign = 's',
>>> +              .realbits = 12,
>>> +              .storgebits = 16,
>>> +              .shift = 4,
>>> +              .endianness = IIO_LE,
>>> +            },
>>> +        }
>>> +        /* similar for Y and  Z axis */
>>
>> two spaces before Z
>> maybe: "similar for Y (with channel2 = IIO_MOD_Y, scan_index = 1) and Z
>> (with channel2 = IIO_MOD_Z, scan_index=2) axis"

Ok.

>>
>>> +    }
>>> +    </programlisting>
>>> +    </para>
>>> +    <para>
>>> +    Here <emphasis> scan_index </emphasis> defines the relative order in which
>>
>> why relative?
>> it is simply the order
>>
>>> +    the enabled channels are placed inside the buffer. Channels with a lower
>>> +    scan_index will be placed before channels with a higher index. Each
>>> +    channel needs to have a unique scan_index.
>>> +    </para>
>>> +    <para>
>>> +    It is important to realize that the scan_index does not define the
>>> +    absolute position in the buffer. E.g. a channel with the scan_index = 3
>>> +    will not be at offset 3 bytes or 3 words, but rather will be placed in the
>>> +    buffer after any channel with a scan_index lower than 3 and before
>>> +    any channel with a scan_index larger than 3.
>>
>> I'd drop the paragraph above, this is just confusing; better mention that
>> there are padding rules (e.g. for the timestamp channel) and it follows
>> that the scan_index is not a byte offset into the buffer

Will try to add a better wording for this, although it looks clear enough to me.

>>
>>> +    Furthermore the scan indices do not have to be consecutive. E.g. A
>>> +    channel spec array that defines 3 channels with the indices 1, 2 and 3 is
>>> +    just as valid as a channel spec that uses the indices 100, 200, 300. The
>>> +    relative order of the channels will be the same.
>>> +    </para>
>>> +    <para>
>>> +    Setting scan_index to -1 can be used to indicate that the specific
>>> +    channel does not support buffered capture. In this case no entries will
>>> +    be created for the channel in the scan_elements directory.
>>> +    </para>
>>> +    </sect2>
>>> +  </sect1>
>>> +
>>> +  <sect1 id="iiotrigger"> <title> Industrial I/O triggers  </title>
>>> +!Finclude/linux/iio/trigger.h iio_trigger
>>> +!Edrivers/iio/industrialio-trigger.c
>>> +    <para>
>>> +      In many situations it is useful for a driver to be able to
>>> +      capture data based on some external event (trigger) as opposed
>>> +      to periodically polling for data. An IIO trigger can be provided
>>> +      by a device driver that also has an IIO device based on hardware
>>> +      generated events (e.g. data ready or threshold exceeded) or
>>> +      provided by a separate driver from an independent interrupt
>>> +      source (e.g. GPIO line connected to some external system, timer
>>> +      interrupt or user space reading a specific file in sysfs). A
>>
>> writing a specific file
Ok.

>>
>>> +      trigger may initialize data capture for a number of sensors and
>>
>> initiate -- not initialize

:)

>>
>>> +      also it may be completely unrelated to the sensor itself.
>>> +    </para>
>>> +
>>> +    <sect2 id="iiotrigsysfs"> <title> IIO trigger sysfs interface </title>
>>> +      There are two locations in sysfs related to triggers:
>>> +      <itemizedlist>
>>> +        <listitem><filename>/sys/bus/iio/devices/triggerY</filename>,
>>> +          this file is created once an IIO triggered is registered with
>>
>> an IIO trigger

Ok.

>>
>>> +          the IIO core and corresponds to trigger with index Y. Because
>>> +          triggers can be very different depending on type there are few
>>> +          standard attributes that we can describe here:
>>> +          <itemizedlist>
>>> +            <listitem>
>>> +              <emphasis>name</emphasis>, trigger name that can be later
>>> +                used to for association with a device.
>>
>> used for association

:), ok.

>>
>>> +            </listitem>
>>> +            <listitem>
>>> +            <emphasis>sampling_frequency</emphasis>, some timer based
>>> +              triggers use this attribute to specify the frequency for
>>> +              trigger calls.
>>> +            </listitem>
>>> +          </itemizedlist>
>>> +        </listitem>
>>> +        <listitem>
>>> +          <filename>/sys/bus/iio/devices/iio:deviceX/trigger/</filename>, this
>>> +          directory is created once the device supports a triggered
>>> +          buffer. We can associate a trigger with our device by writing
>>> +            trigger's name in the<filename>current_trigger</filename> file.
>>
>> the trigger's name -- the
>> the <filename> -- add space before tag
>>
>>> +        </listitem>
>>> +      </itemizedlist>
>>> +    </sect2>
>>> +
>>> +    <sect2 id="iiotrigattr"> <title> IIO trigger setup</title>
>>> +
>>> +    <para>
>>> +      Let's see a simple example of how to setup a trigger to be used
>>> +      by a driver.
>>> +
>>> +      <programlisting>
>>> +      struct iio_trigger_ops trigger_ops = {
>>> +          .set_trigger_state = sample_trigger_state,
>>> +          .validate_device = sample_validate_device,
>>> +      }
>>> +
>>> +      struct iio_trigger *trig;
>>> +
>>> +      /* first, allocate memory for our trigger */
>>> +      trig = iio_trigger_alloc(dev, "trig-%s-%d", name, idx);
>>> +
>>> +      /* setup trigger operations field */
>>> +      trig->ops = &amp;trigger_ops;
>>> +
>>> +      /* now register the trigger with the IIO core */
>>> +      iio_trigger_register(trig);
>>> +      </programlisting>
>>> +    </para>
>>> +    </sect2>
>>> +
>>> +    <sect2 id="iiotrigsetup"> <title> IIO trigger ops</title>
>>> +!Finclude/linux/iio/trigger.h iio_trigger_ops
>>> +     <para>
>>> +        Notice that a trigger has a set of operations attached:
>>> +        <itemizedlist>
>>> +        <listitem>
>>> +          <function>set_trigger_state</function>, switch the trigger on/off
>>> +          on demand.
>>> +        </listitem>
>>> +        <listitem>
>>> +          <function>validate_device</function>, function to validate the
>>> +          device when the current trigger gets changed.
>>> +        </listitem>
>>> +        </itemizedlist>
>>> +      </para>
>>> +    </sect2>
>>> +  </sect1>
>>> +  <sect1 id="iiotriggered_buffer">
>>> +    <title> Industrial I/O triggered buffers </title>
>>> +    <para>
>>> +    Now that we know what buffers and triggers are let's see how they
>>> +    work together.
>>> +    </para>
>>> +    <sect2 id="iiotrigbufsetup"> <title> IIO triggered buffer setup</title>
>>> +!Edrivers/iio/industrialio-triggered-buffer.c
>>> +!Finclude/linux/iio/iio.h iio_buffer_setup_ops
>>> +
>>> +
>>> +    <para>
>>> +    A typical triggered buffer setup looks like this:
>>> +    <programlisting>
>>> +    const struct iio_buffer_setup_ops sensor_buffer_setup_ops = {
>>> +      .preenable    = sensor_buffer_preenable,
>>> +      .postenable   = sensor_buffer_postenable,
>>> +      .postdisable  = sensor_buffer_postdisable,
>>> +      .predisable   = sensor_buffer_predisable,
>>> +    };
>>> +
>>> +    irqreturn_t sensor_iio_pollfunc(int irq, void *p)
>>> +    {
>>> +        pf->timestamp = iio_get_time_ns();
>>> +        return IRQ_WAKE_THREAD;
>>> +    }
>>> +
>>> +    irqreturn_t sensor_trigger_handler(int irq, void *p)
>>> +    {
>>> +        u16 buf[8];
>>
>> int i = 0;
>>
>>> +
>>> +        /* read data for each active channel */
>>> +        for_each_set_bit(bit, active_scan_mask, masklength)
>>> +            buf[i++] = sensor_get_data(bit)
>>> +
>>> +        iio_push_to_buffers_with_timestamp(indio_dev, buffer, timestamp);
>>
>> buf -- not buffer
ok.

>>
>>> +
>>> +        iio_trigger_notify_done(trigger);
>>
>> return IRQ_HANDLED;

ok.

>>
>>> +    }
>>> +
>>> +    /* setup triggered buffer, usually in probe function */
>>> +    iio_triggered_buffer_setup(indio_dev, sensor_iio_polfunc,
>>> +                               sensor_trigger_handler,
>>> +                               sensor_buffer_setup_ops);
>>> +    </programlisting>
>>> +    </para>
>>> +    The important things to notice here are:
>>> +    <itemizedlist>
>>> +    <listitem><function> iio_buffer_setup_ops</function>, the buffer setup
>>> +    functions to be called at predefined points in buffer configuration
>>
>> the buffer configuration -- the

ok.
--
To unsubscribe from this list: send the line "unsubscribe linux-iio" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Input]     [Linux Kernel]     [Linux SCSI]     [X.org]

  Powered by Linux