Skip to content

Day36 - IIO Triggered Buffer (User-Space Controlled Data Flow)

Overview

This day introduces the IIO triggered buffer model, transforming the driver from:

Direct mode (read_raw via sysfs)

into:

Event-driven streaming (IRQ → trigger → buffer → /dev/iio:deviceX)

The key concept:

👉 User space controls data flow, not the driver


Architecture

Previous (Day34–35)

User → read sysfs
driver read_raw()
I2C read sensor

Day36 (Triggered Buffer)

Sensor → DRDY IRQ
    IRQ handler
    iio_trigger_poll()
    pollfunc (driver)
    iio_push_to_buffers()
    /dev/iio:deviceX
        User space

Key Components

1. Trigger

  • Represents data-ready event source
  • Can be:

  • GPIO interrupt

  • timer
  • external trigger

Example:

myadc_iio-dev0

2. Buffer

  • Kernel-side FIFO (kfifo)
  • Stores sample frames
  • Exposed via:
/dev/iio:deviceX

3. Scan Elements

Define:

  • which channels are included
  • ordering in buffer frame

Example:

in_voltage0 → scan_index = 0
in_voltage1 → scan_index = 1
in_voltage2 → scan_index = 2

Important Design Principle

⚠️ User-space owns configuration

Component Controlled by
scan elements user space
trigger binding user space
buffer enable user space
data read user space

👉 Driver must NOT enforce policy


Why driver cannot auto-enable buffer

Because:

  1. multiple devices may share trigger
  2. user decides sampling strategy
  3. kernel separates mechanism vs policy

User-Space Control Flow

Step 1 - Enable scan elements

echo 1 > scan_elements/in_voltage0_en
echo 1 > scan_elements/in_voltage1_en
echo 1 > scan_elements/in_voltage2_en

Step 2 - Bind trigger

echo myadc_iio-dev0 > trigger/current_trigger

Step 3 - Configure buffer

echo 16 > buffer/length

Step 4 - Enable buffer

echo 1 > buffer/enable

Step 5 - Read data

cat /dev/iio:device0

Step 6 - Cleanup (IMPORTANT)

echo 0 > buffer/enable
echo "" > trigger/current_trigger

Sample Frame Layout

For this driver:

[ch0][ch1][ch2]
 2B   2B   2B

Total:

6 bytes per sample

Data Format Example

f0 02 54 03 b8 03

Decoded:

Channel Value
ch0 0x02F0 (752)
ch1 0x0354 (852)
ch2 0x03B8 (952)

Driver Responsibilities

Driver MUST:

  • define channels
  • implement read_raw()
  • implement trigger handler
  • push data into buffer

Driver MUST NOT:

  • enable buffer
  • bind trigger
  • decide sampling policy

Trigger Handler Flow

trigger fires
→ pollfunc executes
→ read sensor channels
→ push sample
→ notify done

Common Pitfalls

1. Missing scan_index

Duplicate scan index → -EINVAL

2. Buffer still enabled

rmmod: module in use

Fix:

echo 0 > buffer/enable

3. Trigger not detached

driver cannot unload

Fix:

echo "" > trigger/current_trigger

4. IRQ works but no data

Check:

  • trigger binding
  • buffer enable
  • scan elements

Comparison with Previous Days

Feature Day34 Day35 Day36
sysfs read
IRQ
buffer
streaming
user control low medium high

Key Learning

1. Separation of concerns

  • driver = data provider
  • user space = data controller

2. Trigger decoupling

  • sensor event ≠ data read
  • trigger connects them

3. Buffer = streaming interface

  • replaces repeated sysfs reads
  • supports high-rate sampling

Next Step

Day37:

  • timestamp channel
  • variable scan mask support
  • userspace parsing tool
  • performance tuning