Skip to main content

I2c

Struct I2c 

Source
pub struct I2c<I2CX, SDA, SCL> { /* private fields */ }
Expand description

A configured I²C master, owning the peripheral and its two pins.

Both lines are open-drain and need a pull-up.

Implementations§

Source§

impl<I2CX, SDA, SCL> I2c<I2CX, SDA, SCL>
where I2CX: Instance, SDA: SdaPin<I2CX>, SCL: SclPin<I2CX>,

Source

pub fn new( rcu: &mut Rcu, i2c: I2CX, sda_pin: SDA, scl_pin: SCL, mode: I2cMode, ) -> Self

Enables the peripheral’s clock, resets it and applies mode.

The pins must already be open-drain in this I²C’s alternate function; release hands them back.

§Panics

If pclk1 is too slow for mode (2 / 8 / 24 MHz), or if mode’s frequency is unreachable from it.

Source

pub fn release(self, rcu: &mut Rcu) -> (I2CX, SDA, SCL)

Waits for a requested STOP to reach the bus, then returns the peripheral and both pins, disabled, with its interrupts off and its clock stopped.

Source§

impl<I2CX, SDA, SCL> I2c<I2CX, SDA, SCL>
where I2CX: Instance,

Source

pub fn is_busy(&self) -> bool

Whether the bus is in use, by another master or by a transaction of this one (I2CBSY).

Source

pub fn sbsend(&self) -> bool

START has gone out and the bus is waiting for the address (SBSEND).

Source

pub fn addsend(&self) -> bool

The addressed device answered; the data phase opens on clear_addsend (ADDSEND).

Source

pub fn tbe(&self) -> bool

DATA will take the next byte (TBE).

True whenever nothing is queued, so a handler listening for it must stop once it has nothing left to send.

Source

pub fn btc(&self) -> bool

The byte behind the one in DATA has arrived whole, and the peripheral holds SCL until software catches up (BTC).

Source

pub fn rbne(&self) -> bool

A received byte is waiting in DATA (RBNE).

Source

pub fn wait_idle(&self)

Blocks until the bus is free.

Only the first START needs this: I2CBSY stays set while this master owns the bus, so waiting again before a repeated START would wait forever.

Source

pub fn write_start(&mut self)

Raises START, which goes out as soon as the bus is free.

On a bus this master already holds it is a repeated START, and the transaction continues without a STOP in between.

Source

pub fn write_addr(&mut self, address: u8, read: bool)

Puts the address into DATA with read as its direction bit.

Also the second half of clearing SBSEND, the first being the read of STAT0 that observed it.

§Panics

If address does not fit in seven bits.

Source

pub fn write_byte(&mut self, byte: u8)

Puts one byte into DATA, which also clears TBE.

Source

pub fn read_byte(&mut self) -> u8

Takes the received byte out of DATA, which also clears RBNE.

Source

pub fn write_stop(&mut self)

Releases the bus with a STOP condition.

Every path out of a transaction goes through here, failures included: a skipped STOP leaves the master holding SCL, and the bus never goes idle again.

Source

pub fn clear_addsend(&mut self)

Clears ADDSEND, which releases the bus into the data phase.

Goes down on a read of STAT0 then a read of STAT1, in that order; skipping either leaves the transfer stalled.

Source

pub fn set_acken(&mut self, ack: bool)

Acknowledges or refuses the byte currently on the wire (ACKEN).

It governs the byte already being clocked in, so the NAK that ends a read has to stand one byte early — before ADDSEND is cleared on a one-byte read, and before the last BTC otherwise.

Source

pub fn set_poap(&mut self, next: bool)

Moves the acknowledge one byte further along (POAP), for the two-byte read where both bytes must be taken after the NAK is already placed.

Like ACKEN it must stand before the START that begins the read.

Source

pub fn write(&mut self, address: u8, bytes: &[u8]) -> Result<(), Error>

Writes bytes to the device at address, framed by START and STOP.

address is the plain 7-bit value from the datasheet; the direction bit is appended here. Blocks until the last byte is out and acknowledged, so the bus is idle on return.

§Errors

Error::NoAcknowledge if nothing answers the address — with NoAcknowledgeSource::Address, which is how a bus scan finds devices — or the device refuses a byte; Error::Bus or Error::ArbitrationLoss on a bus fault.

§Panics

If address does not fit in seven bits (10-bit addressing is not supported). Checked before the bus is touched.

Source

pub fn read(&mut self, address: u8, bytes: &mut [u8]) -> Result<(), Error>

Reads bytes.len() bytes from the device at address, framed by START and STOP.

An empty bytes is a no-op: a zero-byte transfer has no acknowledge to end on.

§Errors

As for write; only the address can go unanswered.

§Panics

If address does not fit in seven bits.

Source

pub fn write_read( &mut self, address: u8, write: &[u8], read: &mut [u8], ) -> Result<(), Error>

Writes write, then reads into read, joined by a repeated START.

This is how a register-addressed device is read: the write phase moves its pointer, the read phase takes what the pointer names. A write then a read puts a STOP in between, which some devices treat as the end of the register access.

An empty read degenerates to write, an empty write to read.

§Errors

As for write, from either phase.

§Panics

If address does not fit in seven bits.

Source

pub fn take_error(&mut self) -> Option<Error>

Returns the pending error, if any, and clears it.

The acknowledge for Event::Error: the flag is what holds the interrupt request up, so a handler that skips this re-enters forever. One error per call — with two pending, the second survives for the next. A NACK reports NoAcknowledgeSource::Unknown, the phase it arrived in being known only to whoever drives the transaction.

Source

pub fn listen(&mut self, event: Event)

Raises an interrupt on event, which still has to be unmasked in the NVIC.

Event::Byte raises EVIE along with BUFIE, so it covers Event::Protocol too.

Source

pub fn unlisten(&mut self, event: Event)

Stops raising an interrupt on event.

Event::Protocol takes BUFIE down with it: byte events cannot stand on their own in hardware. Dropping only those is unlisten(Event::Byte).

Source

pub fn is_listening(&self, event: Event) -> bool

Whether event is being listened for.

Source

pub fn start_write( self, address: u8, buf: &'static [u8], ) -> WriteTransfer<I2CX, SDA, SCL>

Starts a write of buf to address, to be driven by interrupts.

Takes the peripheral with it; both come back from release. An empty buf still addresses the device, which is how a bus scan probes for one. Blocks only until the bus is free, then raises START and returns.

Arms the interrupts itself and keeps re-arming them as the phases change, so listen beforehand is neither needed nor respected.

§Panics

If address does not fit in seven bits.

Source

pub fn start_read( self, address: u8, buf: &'static mut [u8], ) -> ReadTransfer<I2CX, SDA, SCL>

Starts a read of buf.len() bytes from address, to be driven by interrupts.

Takes the peripheral with it; both come back from release. An empty buf finishes immediately without touching the bus — a zero-byte read has no acknowledge to end on. Blocks only until the bus is free, then raises START and returns.

Arms the interrupts itself and keeps re-arming them as the phases change, so listen beforehand is neither needed nor respected.

§Panics

If address does not fit in seven bits.

Trait Implementations§

Source§

impl<I2CX, SDA, SCL> ErrorType for I2c<I2CX, SDA, SCL>
where I2CX: Instance,

Source§

type Error = Error

Error type
Source§

impl<I2CX, SDA, SCL> I2c for I2c<I2CX, SDA, SCL>
where I2CX: Instance,

Source§

fn transaction( &mut self, address: u8, operations: &mut [Operation<'_>], ) -> Result<(), Error>

Per the trait’s contract: neighbouring operations of the same direction join into one addressed phase, a change of direction inserts a repeated START, and only the end carries a STOP.

§Panics

If address does not fit in seven bits, or if a Read is followed by further operations — ending a read early needs a repeated START in place of its STOP, which the read sequences here do not express. [Write.., Read] works.

Source§

fn read(&mut self, address: u8, bytes: &mut [u8]) -> Result<(), Error>

Reads enough bytes from slave with address to fill read. Read more
Source§

fn write(&mut self, address: u8, bytes: &[u8]) -> Result<(), Error>

Writes bytes to slave with address address. Read more
Source§

fn write_read( &mut self, address: u8, bytes: &[u8], buffer: &mut [u8], ) -> Result<(), Error>

Writes bytes to slave with address address and then reads enough bytes to fill read in a single transaction. Read more

Auto Trait Implementations§

§

impl<I2CX, SDA, SCL> Freeze for I2c<I2CX, SDA, SCL>
where I2CX: Freeze, SDA: Freeze, SCL: Freeze,

§

impl<I2CX, SDA, SCL> RefUnwindSafe for I2c<I2CX, SDA, SCL>
where I2CX: RefUnwindSafe, SDA: RefUnwindSafe, SCL: RefUnwindSafe,

§

impl<I2CX, SDA, SCL> Send for I2c<I2CX, SDA, SCL>
where I2CX: Send, SDA: Send, SCL: Send,

§

impl<I2CX, SDA, SCL> Sync for I2c<I2CX, SDA, SCL>
where I2CX: Sync, SDA: Sync, SCL: Sync,

§

impl<I2CX, SDA, SCL> Unpin for I2c<I2CX, SDA, SCL>
where I2CX: Unpin, SDA: Unpin, SCL: Unpin,

§

impl<I2CX, SDA, SCL> UnsafeUnpin for I2c<I2CX, SDA, SCL>
where I2CX: UnsafeUnpin, SDA: UnsafeUnpin, SCL: UnsafeUnpin,

§

impl<I2CX, SDA, SCL> UnwindSafe for I2c<I2CX, SDA, SCL>
where I2CX: UnwindSafe, SDA: UnwindSafe, SCL: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.