Pigweed
 
Loading...
Searching...
No Matches
pw::i2c::Initiator Class Reference

The common, base driver interface for initiating thread-safe transactions with devices on an I2C bus. Other documentation may call this style of interface an I2C "master", "central", or "controller". More...

#include <initiator.h>

Inheritance diagram for pw::i2c::Initiator:
pw::i2c::GmockInitiator pw::i2c::LinuxInitiator pw::i2c::MockInitiator pw::i2c::MockMessageInitiator

Public Types

enum class  Feature : int { kStandard = 0 , kTenBit = (1 << 0) , kNoStart = (1 << 1) }
 Defined set of supported i2c features.
 

Public Member Functions

constexpr Initiator ()
 
constexpr Initiator (Feature supported_features)
 
Status WriteReadFor (Address device_address, ConstByteSpan tx_buffer, ByteSpan rx_buffer, chrono::SystemClock::duration timeout)
 
Status TransferFor (span< const Message > messages, chrono::SystemClock::duration timeout)
 
Status WriteReadFor (Address device_address, const void *tx_buffer, size_t tx_size_bytes, void *rx_buffer, size_t rx_size_bytes, chrono::SystemClock::duration timeout)
 
Status WriteFor (Address device_address, ConstByteSpan tx_buffer, chrono::SystemClock::duration timeout)
 
Status WriteFor (Address device_address, const void *tx_buffer, size_t tx_size_bytes, chrono::SystemClock::duration timeout)
 
Status ReadFor (Address device_address, ByteSpan rx_buffer, chrono::SystemClock::duration timeout)
 
Status ReadFor (Address device_address, void *rx_buffer, size_t rx_size_bytes, chrono::SystemClock::duration timeout)
 
Status ProbeDeviceFor (Address device_address, chrono::SystemClock::duration timeout)
 

Detailed Description

The common, base driver interface for initiating thread-safe transactions with devices on an I2C bus. Other documentation may call this style of interface an I2C "master", "central", or "controller".

pw::i2c::Initiator isn't required to support 10-bit addressing. If only 7-bit addressing is supported, pw::i2c::Initiator fails a runtime assertion if given a Message with the kTenBitAddress flag, or when given an address that is out of 7-bit address range.

The implementer of TransferFor() (or DoWriteReadFor()) is responsible for ensuring thread safety and enabling functionality such as initialization, configuration, enabling and disabling, unsticking SDA, and detecting device address registration collisions.

Note
pw::i2c::Initiator uses internal synchronization, so it's safe to initiate transactions from multiple threads. Each call to this class will be executed in a single bus transaction using repeated starts.

Furthermore, devices may require specific sequences of transactions, and application logic must provide the synchronization to execute these sequences correctly.

Constructor & Destructor Documentation

◆ Initiator() [1/2]

constexpr pw::i2c::Initiator::Initiator ( )
inlineconstexpr

Construct Initiator with default features.

Note: this constructor enables kTenBit because the older implementation enabled it by default. Most users will not need kTenBit enabled.

◆ Initiator() [2/2]

constexpr pw::i2c::Initiator::Initiator ( Feature  supported_features)
inlineexplicitconstexpr

Construct Initiator with defined set of features.

Supported features are defined in the Feature enum.

Note: to support only the required features, you should specify Initiator(Initiator::Feature::kStandard).

Initiator i2c(Initiator::Feature::kStandard);
The common, base driver interface for initiating thread-safe transactions with devices on an I2C bus....
Definition: initiator.h:49
Initiator i2c(Initiator::Feature::kTenBit |
Initiator::Feature::kNoStart);

Member Function Documentation

◆ DoWriteReadFor()

virtual Status pw::i2c::Initiator::DoWriteReadFor ( Address  ,
ConstByteSpan  ,
ByteSpan  ,
chrono::SystemClock::duration   
)
inlineprivatevirtual

Reimplemented in pw::i2c::LinuxInitiator.

◆ ProbeDeviceFor()

Status pw::i2c::Initiator::ProbeDeviceFor ( Address  device_address,
chrono::SystemClock::duration  timeout 
)
inline

Probes the device for an I2C ACK after only writing the address. This is done by attempting to read a single byte from the specified device.

Warning
This method is not compatible with all devices. For example, some I2C devices require a device_address in W mode before they can ack the device_address in R mode. In this case, use WriteReadFor or TransferFor to read a register with known value.
Parameters
[in]device_addressThe address of the I2C device.
[in]timeoutThe maximum duration to block waiting for both exclusive bus access and the completion of the I2C transaction.
Precondition
The provided address must be supported by the initiator. I.e. don't use a 10-bit address if the initiator only supports 7-bit addresses. This method fails a runtime assertion if this precondition isn't met.
Returns
embed:rst:leading-asterisk
 
* 
*  .. pw-status-codes::
* 
*     OK: The transaction succeeded.
* 
*     DEADLINE_EXCEEDED: Was unable to acquire exclusive initiator access
*     and complete the I2C transaction in time.
* 
*     UNAVAILABLE: A NACK condition occurred, meaning the addressed device
*     didn't respond or was unable to process the request.
* 
*     FAILED_PRECONDITION: The interface isn't initialized or enabled.
* 
*     UNIMPLEMENTED: The interface doesn't support the necessary i2c
*     features or combination of i2c messages.
* 
*  

◆ ReadFor() [1/2]

Status pw::i2c::Initiator::ReadFor ( Address  device_address,
ByteSpan  rx_buffer,
chrono::SystemClock::duration  timeout 
)
inline

Reads bytes from an I2C device.

The signal on the bus should look like this:

START + I2C_ADDRESS + READ(1) + RX_BUFFER_BYTES + STOP
Parameters
[in]device_addressThe address of the I2C device.
[out]rx_bufferThe receive buffer.
[in]timeoutThe maximum duration to block waiting for both exclusive bus access and the completion of the I2C transaction.
Precondition
The provided address must be supported by the initiator. I.e. don't use a 10-bit address if the initiator only supports 7-bit addresses. This method fails a runtime assertion if this precondition isn't met.
Returns
embed:rst:leading-asterisk
 
* 
*  .. pw-status-codes::
* 
*     OK: The transaction succeeded.
* 
*     DEADLINE_EXCEEDED: Was unable to acquire exclusive initiator access
*     and complete the I2C transaction in time.
* 
*     UNAVAILABLE: A NACK condition occurred, meaning the addressed device
*     didn't respond or was unable to process the request.
* 
*     FAILED_PRECONDITION: The interface isn't initialized or enabled.
* 
*     UNIMPLEMENTED: The interface doesn't support the necessary i2c
*     features or combination of i2c messages.
* 
*  

◆ ReadFor() [2/2]

Status pw::i2c::Initiator::ReadFor ( Address  device_address,
void *  rx_buffer,
size_t  rx_size_bytes,
chrono::SystemClock::duration  timeout 
)
inline

A variation of pw::i2c::Initiator::ReadFor that accepts an explicit size for the amount of bytes to read from the device.

◆ TransferFor()

Status pw::i2c::Initiator::TransferFor ( span< const Message messages,
chrono::SystemClock::duration  timeout 
)
inline

Performs multiple arbitrary reads and writes to an I2C device as one atomic transaction. Each part of the transaction is referred to as a "message".

For a series of 0...N messages, the signal on the bus for the atomic transaction of two messages should look like this:

START + #0.I2C_ADDRESS + #0.WRITE/READ(0/1) + #0.BYTES +
START + #1.I2C_ADDRESS + #1.WRITE/READ(0/1) + #1.BYTES +
...
START + #N.I2C_ADDRESS + #N.WRITE/READ(0/1) + #N.BYTES + STOP
Parameters
[in]messagesAn array of pw::i2c::Message objects to transmit as one i2c bus transaction.

For each Message msg in messages:

If msg.GetAddress().IsTenBit() is true:

  • The implementation should transmit that message using the 10-bit addressing scheme defined in the i2c spec.
  • The implementation should CHECK or return an error if 10-bit addressing is unsupported.

If msg.GetAddress().IsWriteContinuation() is true:

  • The implementation should transmit this message without a start condition or address.
  • The implementation should CHECK or return an error if the hardware or initiator does not support this feature.
Parameters
[in]timeoutThe maximum duration to block waiting for both exclusive bus access and the completion of the bus transaction.
Precondition
The provided addresses of each message must be supported by the initiator, Don't use a 10-bit address if the initiator only supports 7-bit addresses. This method fails a runtime assertion if this precondition isn't met.
Returns
embed:rst:leading-asterisk
 
* 
*  .. pw-status-codes::
* 
*     OK: The transaction succeeded.
* 
*     INVALID_ARGUMENT: The arguments can never be valid. For example,
*     a WriteContinuation without a preceding Write message.
* 
*     DEADLINE_EXCEEDED: Was unable to acquire exclusive initiator access
*     and complete the I2C transaction in time.
* 
*     UNAVAILABLE: A NACK condition occurred, meaning the addressed device
*     didn't respond or was unable to process the request.
* 
*     FAILED_PRECONDITION: The interface isn't initialized or enabled.
* 
*     UNIMPLEMENTED: The interface doesn't support the necessary i2c
*     features or combination of i2c messages.
* 
*  

◆ WriteFor() [1/2]

Status pw::i2c::Initiator::WriteFor ( Address  device_address,
const void *  tx_buffer,
size_t  tx_size_bytes,
chrono::SystemClock::duration  timeout 
)
inline

A variation of pw::i2c::Initiator::WriteFor that accepts an explicit size for the amount of bytes to write to the device.

◆ WriteFor() [2/2]

Status pw::i2c::Initiator::WriteFor ( Address  device_address,
ConstByteSpan  tx_buffer,
chrono::SystemClock::duration  timeout 
)
inline

Write bytes to the I2C device.

The signal on the bus should look like this:

START + I2C_ADDRESS + WRITE(0) + TX_BUFFER_BYTES + STOP
Parameters
[in]device_addressThe address of the I2C device.
[in]tx_bufferThe transmit buffer.
[in]timeoutThe maximum duration to block waiting for both exclusive bus access and the completion of the I2C transaction.
Precondition
The provided address must be supported by the initiator. I.e. don't use a 10-bit address if the initiator only supports 7-bit addresses. This method fails a runtime assertion if this precondition isn't met.
Returns
embed:rst:leading-asterisk
 
* 
*  .. pw-status-codes::
* 
*     OK: The transaction succeeded.
* 
*     DEADLINE_EXCEEDED: Was unable to acquire exclusive initiator access
*     and complete the I2C transaction in time.
* 
*     UNAVAILABLE: A NACK condition occurred, meaning the addressed device
*     didn't respond or was unable to process the request.
* 
*     FAILED_PRECONDITION: The interface isn't initialized or enabled.
* 
*     UNIMPLEMENTED: The interface doesn't support the necessary i2c
*     features or combination of i2c messages.
* 
*  

◆ WriteReadFor() [1/2]

Status pw::i2c::Initiator::WriteReadFor ( Address  device_address,
const void *  tx_buffer,
size_t  tx_size_bytes,
void *  rx_buffer,
size_t  rx_size_bytes,
chrono::SystemClock::duration  timeout 
)
inline

A variation of pw::i2c::Initiator::WriteReadFor that accepts explicit sizes for the amount of bytes to write to the device and read from the device.

◆ WriteReadFor() [2/2]

Status pw::i2c::Initiator::WriteReadFor ( Address  device_address,
ConstByteSpan  tx_buffer,
ByteSpan  rx_buffer,
chrono::SystemClock::duration  timeout 
)

Writes bytes to an I2C device and then reads bytes from that same device as one atomic I2C transaction.

The signal on the bus for the atomic transaction should look like this:

START + I2C_ADDRESS + WRITE(0) + TX_BUFFER_BYTES +
START + I2C_ADDRESS + READ(1) + RX_BUFFER_BYTES + STOP
Parameters
[in]device_addressThe address of the I2C device.
[in]tx_bufferThe transmit buffer.
[out]rx_bufferThe receive buffer.
[in]timeoutThe maximum duration to block waiting for both exclusive bus access and the completion of the I2C transaction.
Precondition
The provided address must be supported by the initiator. I.e. don't use a 10-bit address if the initiator only supports 7-bit addresses. This method fails a runtime assertion if this precondition isn't met.
Returns
embed:rst:leading-asterisk
 
* 
*  .. pw-status-codes::
* 
*     OK: The transaction or transactions succeeded.
* 
*     DEADLINE_EXCEEDED: Was unable to acquire exclusive initiator access
*     and complete the I2C transaction in time.
* 
*     UNAVAILABLE: A NACK condition occurred, meaning the addressed device
*     didn't respond or was unable to process the request.
* 
*     FAILED_PRECONDITION: The interface isn't initialized or enabled.
* 
*     UNIMPLEMENTED: The interface doesn't support the necessary i2c
*     features or combination of i2c messages.
* 
*  

The documentation for this class was generated from the following file: