Day 27 - SPI Sensor Driver (Dual-Bus Architecture)¶
Overview¶
This day extends the existing I2C-based sensor driver to support SPI, while keeping a shared sensor core layer.
Goal:
- Reuse the same mysensor_core
- Add a new SPI transport layer
- Verify Device Tree + SPI driver binding
- Ensure compatibility with STM32 fake sensor (SPI slave)
Architecture¶
Application / hwmon │ mysensor_core (bus-agnostic) │ ┌───────────────┬───────────────┐ │ │ │ I2C bus SPI bus (future: UART, etc.) mysensor_i2c mysensor_spi
Key Design Concepts¶
1. Bus Abstraction Layer¶
Core does not depend on I2C/SPI directly.
Example:
struct mysensor_bus_ops {
int (*read_reg)(void *ctx, u8 reg, u8 *val);
int (*write_reg)(void *ctx, u8 reg, u8 val);
};
Each bus driver provides its own implementation.
2. SPI Protocol Design (STM32 fake sensor)¶
SPI is full-duplex and frame-based.
Read operation requires two transfers:
1st frame (command) MOSI: [0x80 | reg] [0x00]
2nd frame (fetch data) MOSI: [NOP] [0x00] MISO: [xx] [value]
3. Why spi_write_then_read() is NOT suitable¶
spi_write_then_read() performs:
- write phase
- separate read phase
But STM32 slave expects:
- fixed 2-byte full-duplex frames
Therefore must use:
4. SPI Transfer Implementation¶
Each read consists of 2 transfers:
cs_change = 1 is used to separate frames.
5. Device Tree Binding¶
Example:
Driver must provide:
of_match_tablespi_device_id(recommended)
6. spidev Conflict¶
Default Raspberry Pi enables:
This conflicts with custom driver using same CS.
Solution:
7. Boot vs Runtime Overlay¶
- Boot-time:
/boot/firmware/config.txt - Runtime:
dtoverlaycommand
SPI driver should use boot-time overlay for stability.
8. Verification Strategy¶
Do NOT rely only on dmesg.
Correct validation order:
/sys/bus/spi/devices/- driver bind
- hwmon output
- sensor data
Debug Lessons Learned¶
Chip ID = 0x00¶
Cause: - wrong SPI transfer pattern
Fix:
- switch to spi_sync + 2-phase transfer
"chipselect already in use"¶
Cause: - spidev occupying CS0
Fix: - disable spidev
temp1_input returns -EAGAIN¶
Cause: - cache not ready - no IRQ, polling disabled
Fix: - enable polling
Summary¶
- SPI bus successfully integrated into existing architecture
- Core layer reused without modification
- Device Tree binding validated
- STM32 SPI slave protocol aligned with Linux SPI driver
This confirms the design is scalable to multiple transport layers.