Skip to main content

Module bus

Module bus 

Source
Expand description

One I2C bus, shared by a program and every driver on it.

A driver takes its bus by value, which is the right shape on a microcontroller: the program owns the peripheral and hands it over once. A program on a host works differently. A gateway keeps several parts on /dev/i2c-1, gives the same bus to a driver for each, and looks at the bus itself between reads. A language binding needs the same, since it cannot give a driver a Rust type at all. I2cBus is a handle to one bus that clones cheaply: every clone reaches the same bus, and one transfer runs at a time.

Behind the handle is one of three things:

  • The kernel’s adapter, opened with I2cBus::open. Only Linux has one.
  • Simulated parts, I2cBus::simulated, each answering at its own address from its registers the way a sim::I2cPart does. A transfer to an address no part holds is not acknowledged, as on a real bus.
  • A script, I2cBus::scripted, that plays one conversation and refuses any other, the way an I2cScript does.

A driver also takes a delay. I2cBus::delay gives it one that suits the bus: the process sleeps when real parts are on the other end, and carries straight on when simulated or scripted ones are, since there is nothing to wait for. Either way the wait is counted, and I2cBus::waited_micros is the total, so a test checks that a driver waited as long as its datasheet asks without the test taking that long.

§Examples

use pamoja_hal::bus::I2cBus;
use pamoja_hal::i2c::I2c;
use pamoja_hal::sim::I2cPart;

// Two parts on one bus, each holding the id its datasheet gives: a BME280, whose chip
// id register reads 0x60, and a TMP117, whose 16-bit device id register reads 0x0117.
const BME280: u8 = 0x76;
const BME280_CHIP_ID_REGISTER: u8 = 0xD0;
const TMP117: u8 = 0x48;
const TMP117_DEVICE_ID_REGISTER: u8 = 0x0F;
let bus = I2cBus::simulated([
    I2cPart::new(BME280).holding(BME280_CHIP_ID_REGISTER, &[0x60]),
    I2cPart::new(TMP117).holding(TMP117_DEVICE_ID_REGISTER, &0x0117u16.to_be_bytes()),
]);

// A clone is what a driver is given; the program keeps the original.
let mut driver = bus.clone();
let mut id = [0u8; 1];
driver.write_read(BME280, &[BME280_CHIP_ID_REGISTER], &mut id)?;
assert_eq!(id, [0x60]);

// Nothing answers at the BME280's other address.
assert!(driver.write_read(BME280 + 1, &[BME280_CHIP_ID_REGISTER], &mut id).is_err());
assert_eq!(bus.transfers(), 2);

Structs§

BusDelay
The delay a driver on an I2cBus waits with, from I2cBus::delay.
I2cBus
One I2C bus, reached by every clone of this handle.
NotSimulated
A part was put on a bus that is not simulated.

Enums§

BusError
Why a transfer on an I2cBus failed.
BusKind
What answers on an I2cBus.
OpenError
Why an I2C adapter could not be opened.