Skip to content

Day37 – IIO FIFO Mode with Watermark Interrupt

Overview

In Day36, the driver used a per-sample interrupt model:

IRQ → pollfunc → read single sample → push buffer

This approach is simple but inefficient:

  • High interrupt frequency
  • Low I2C transfer efficiency
  • High CPU overhead

FIFO-Based Design

To improve efficiency, FIFO buffering is introduced:

Sensor:
  accumulate multiple samples in FIFO

When FIFO >= watermark:
  → trigger IRQ

Driver:
  → read multiple samples in one burst
  → push multiple frames into IIO buffer

FIFO Architecture

STM32 Sensor
 ├─ FIFO buffer (64 bytes)
 ├─ FIFO_COUNT
 ├─ FIFO_DATA
 ├─ FIFO_WATERMARK
 └─ IRQ_ACTIVE

IRQ Design

IRQ is a global interrupt state, not FIFO-specific.

Non-FIFO mode

IRQ_ACTIVE = DATA_READY

FIFO mode

IRQ_ACTIVE = (FIFO_COUNT >= WATERMARK)

IRQ Edge Behavior

Proper IRQ requires level transition:

FIFO >= watermark → IRQ assert
Driver drains FIFO → FIFO < watermark → IRQ deassert

Without deassert:

  • IRQ stays high
  • No new interrupts
  • Driver stalls

Linux IIO Data Flow (FIFO)

IRQ (GPIO)
 → iio_trigger_poll()
 → pollfunc
 → read FIFO_COUNT
 → read FIFO_DATA (burst)
 → unpack frames
 → iio_push_to_buffers()

SMBus Limitation

i2c_smbus_read_i2c_block_data():
  max ≈ 32 bytes

FIFO frame:

4 channels × 2 bytes = 8 bytes

Maximum frames per read:

32 / 8 = 4 frames

Driver must limit read size accordingly.


FIFO Drain Strategy

Critical logic:

do {
    read FIFO
} while (IRQ_ACTIVE);

Goal:

One IRQ → drain FIFO below watermark

IIO Design Principle

Driver = mechanism
User-space = policy

Driver responsibilities:

  • read data
  • push buffer

User-space responsibilities:

  • enable scan elements
  • bind trigger
  • enable buffer