Reference#
pw_i2c: Cross-platform I2C API with interactive debugging
Overview#
pw::i2c::Address
is a helper class for representing I2C addresses.pw::i2c::Message
is a helper class for representing individual read and write components within a single i2c transaction.pw::i2c::Initiator
is the common, base driver interface for communicating with I2C devices.pw::i2c::Device
is a helper class that takes a reference to anpw::i2c::Initiator
instance and provides easier access to a single I2C device.pw::i2c::RegisterDevice
extendspw::i2c::Device
for easier access to a single I2C device’s registers.pw::i2c::I2cService
is a service for performing I2C transactions over RPC.pw::i2c::MockMessageInitiator
is a generic mocked backend forpw::i2c::Initiator
. It accepts multiplepw::i2c::MockMessageTransaction
, each of which is mock transmitted as one bus transaction.pw::i2c::MockMessageTransaction
represents a test i2c transaction. Each transaction consists of an arbitrary sequence ofpw::i2c::MockMessage
objects that are transmitted in one bus operation.pw::i2c::MockMessage
represents one read or write element of an i2c transaction.
pw::i2c::Address
#
-
class Address#
A helper class that represents I2C addresses.
An address instance remembers whether it was constructed as a seven-bit or ten-bit address. This attribute can be used by Initiators to determine the i2c addressing style to transmit.
Note: Per the above, a ten-bit constructed instance may still have an an address of seven or fewer bits.
#include "pw_i2c/address.h" constexpr pw::i2c::Address kAddress1 = pw::i2c::Address::SevenBit<0x42>(); uint8_t raw_address_1 = kAddress1.GetSevenBit(); const pw::i2c::Address kAddress2<0x200>(); // 10-bit uint16_t raw_address_2 = kAddress2.GetAddress(); // Note: kAddress2.GetSevenBit() would fail an assertion here.
Public Functions
-
explicit Address(uint16_t address)#
Creates a
pw::i2c::Address
instance from a 7 or 10 bit address.If the address argument is 7-bits or less, a 7-bit address is constructed equivalent to Address::SevenBit(address);
If the address argument is 8, 9 or 10 bits, a ten-bit address is constructed equivalent to Address::TenBit(address);
The type of address construced will affect how the i2c address is transmitted on the bus. You should always use 7-bit addresses unless you are certain you have a host and device that support 10-bit addresses.
constexpr pw::i2c::Address kAddress(0x200);
Note
This function is deprecated. You should almost certainly use either Address::SevenBit<0x1>() for addresses known at compile time, or Address::SevenBit(0x1) for addresses known at run-time.
- Parameters:
address – [in] An address no larger than 10-bits as an unsigned integer. This method does a runtime assertion to ensure that address is 10 bits or less.
- Returns:
A
pw::i2c::Address
instance.
-
uint8_t GetSevenBit() const#
Gets the 7-bit address that was provided when this instance was created.
This method does a runtime assertion to ensure that the address was constructed in 7-bit mode.
- Returns:
A 7-bit address as an unsigned integer.
-
inline uint16_t GetTenBit() const#
Gets the 10-bit address that was provided when this instance was created.
- Returns:
A 10-bit address as an unsigned integer.
-
inline uint16_t GetAddress() const#
Gets the raw address that was provided when this Address was created.
Use IsTenBit() to know whether the address should be interpreted as a 7-bit or 10-bit address.
- Returns:
A an address as an unsigned integer.
-
inline constexpr bool IsTenBit() const#
Getter for whether this object represents a Ten bit address. Note: The address itself may still be fewer than 10 bits.
- Returns:
true if the address represents a 10-bit address.
Public Static Functions
-
template<uint16_t kAddress>
static inline constexpr Address TenBit()# Creates a
pw::i2c::Address
instance for an address that’s 10 bits or less.This constant expression does a compile-time assertion to ensure that the provided address is 10 bits or less.
constexpr pw::i2c::Address kAddress = pw::i2c::Address::TenBit<0x200>();
- Returns:
A
pw::i2c::Address
instance.
-
static inline Address TenBit(uint16_t address)#
Creates a
pw::i2c::Address
instance for an address that’s 10 bits or less.This constructor does a run-time check to ensure that the provided address is 10 bits or less.
pw::i2c::Address kAddress = pw::i2c::Address::TenBit(0x200);
- Returns:
A
pw::i2c::Address
instance.
-
template<uint8_t kAddress>
static inline constexpr Address SevenBit()# Creates a
pw::i2c::Address
instance for an address that’s 7 bits or less.This constant expression does a compile-time assertion to ensure that the provided address is 7 bits or less.
constexpr pw::i2c::Address kAddress = pw::i2c::Address::SevenBit<0x42>();
- Returns:
A
pw::i2c::Address
instance.
-
static inline Address SevenBit(uint16_t address)#
Creates a
pw::i2c::Address
instance for an address that’s 7 bits or less.This constructor does a run-time check to ensure that the provided address is 7 bits or less.
pw::i2c::Address kAddress = pw::i2c::Address::SevenBit(0x42);
- Returns:
A
pw::i2c::Address
instance.
-
explicit Address(uint16_t address)#
pw::i2c::Message
#
-
class Message#
A struct that represents I2C read and write messages.
Individual messages can be accumulated into a span and transmitted in one atomic i2c transaction using an Initiator implementation.
#include "pw_i2c/message.h" constexpr auto kAddress = pw::i2c::Address::SevenBit<0x42>() constexpr chrono::SystemClock::duration kTimeout = std::chrono::duration_cast<chrono::SystemClock::duration>(100ms); const std::array<std::byte, 2> tx_buffer = {std::byte{0xCD}, std::byte{0xEF}}; std::array<std::byte, 2> rx_buffer; Vector<Message, 2> messages; if (!tx_buffer.empty()) { messages.push_back(Message::WriteMessage(kAddress, tx_buffer)); } if (!rx_buffer.empty()) { messages.push_back(Message::ReadMessage(kAddress, rx_buffer)); } initiator.TransferFor(messages, kTimeout);
Public Functions
-
inline bool IsRead() const#
Getter for whether this object represents a read operation.
- Returns:
true if the message represents a read operation.
-
inline bool IsTenBit() const#
Getter for whether this object represents an operation addressed with a ten-bit address. When true, communicate on the wire using the i2c 10-bit addressing protocol.
- Returns:
true if the message represents a 10-bit addressed operation.
-
inline bool IsWriteContinuation() const#
Getter for whether this object represents a continued write.
- Returns:
true if the message represents a continued write.
-
inline Address GetAddress() const#
Getter for the address component.
- Returns:
the Address passed into one of the constructors or factories.
-
inline ByteSpan GetMutableData() const#
Getter for the data component.
This method is only valid for Read messages and will runtime ASSERT on other messages.
- Returns:
the mutable variant of the data passed into one of the constructors or factories.
-
inline ConstByteSpan GetData() const#
Getter for the data component.
- Returns:
the data passed into one of the constructors or factories.
Public Static Functions
-
static inline constexpr Message WriteMessage(Address address, ConstByteSpan data)#
Creates a
pw::i2c::Message
instance for an i2c write message.This Message can be passed to Initiator::TransferFor().
constexpr Message kMessage = Message::WriteMessage( pw::i2c::Address::SevenBit<0x42>(), data );
- Returns:
A
pw::i2c::Message
instance.
-
static inline constexpr Message WriteMessageContinuation(ConstByteSpan data)#
Creates a
pw::i2c::Message
instance for an i2c write message without a start condition sent on the bus. Chaining one or more of these messages after a regular Write message allows the client to send non-contiguous blocks of memory as one single write message to the i2c target.Note: This message must follow another write message.
Note: No addresses is needed and no address will be transmitted. The data should immediately follow the data from the previous write message.
This Message can be passed to Initiator::TransferFor().
constexpr Message kMessage = Message::WriteMessageContinuation(data);
- Returns:
A
pw::i2c::Message
instance.
-
static inline constexpr Message ReadMessage(Address address, ByteSpan data)#
Creates a
pw::i2c::Message
instance for an i2c read message.This Message can be passed to Initiator::TransferFor().
constexpr Message kMessage = Message::ReadMessage( pw::i2c::Address::SevenBit<0x42>(), data );
- Returns:
A
pw::i2c::Message
instance.
-
inline bool IsRead() const#
pw::i2c::Initiator
#
-
class Initiator#
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.
Furthermore, devices may require specific sequences of transactions, and application logic must provide the synchronization to execute these sequences correctly.
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.Subclassed by pw::i2c::GmockInitiator, pw::i2c::LinuxInitiator, pw::i2c::MockInitiator, pw::i2c::MockMessageInitiator
Public Types
Public Functions
-
inline constexpr Initiator()#
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.
-
inline explicit constexpr Initiator(Feature supported_features)#
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);
Initiator i2c(Initiator::Feature::kTenBit | Initiator::Feature::kNoStart);
-
Status 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:
device_address – [in] The address of the I2C device.
tx_buffer – [in] The transmit buffer.
rx_buffer – [out] The receive buffer.
timeout – [in] The maximum duration to block waiting for both exclusive bus access and the completion of the I2C transaction.
- Pre:
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:
Code
Description
The transaction or transactions succeeded.
Was unable to acquire exclusive initiator access and complete the I2C transaction in time.
A NACK condition occurred, meaning the addressed device didn’t respond or was unable to process the request.
The interface isn’t initialized or enabled.
The interface doesn’t support the necessary i2c features or combination of i2c messages.
-
inline Status TransferFor(span<const Message> messages, chrono::SystemClock::duration timeout)#
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
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:
messages – [in] An array of pw::i2c::Message objects to transmit as one i2c bus transaction.
timeout – [in] The maximum duration to block waiting for both exclusive bus access and the completion of the bus transaction.
- Pre:
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:
Code
Description
The transaction succeeded.
The arguments can never be valid. For example, a WriteContinuation without a preceding Write message.
Was unable to acquire exclusive initiator access and complete the I2C transaction in time.
A NACK condition occurred, meaning the addressed device didn’t respond or was unable to process the request.
The interface isn’t initialized or enabled.
The interface doesn’t support the necessary i2c features or combination of i2c messages.
- inline 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,
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.
-
inline Status WriteFor(Address device_address, ConstByteSpan tx_buffer, chrono::SystemClock::duration timeout)#
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:
device_address – [in] The address of the I2C device.
tx_buffer – [in] The transmit buffer.
timeout – [in] The maximum duration to block waiting for both exclusive bus access and the completion of the I2C transaction.
- Pre:
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:
Code
Description
The transaction succeeded.
Was unable to acquire exclusive initiator access and complete the I2C transaction in time.
A NACK condition occurred, meaning the addressed device didn’t respond or was unable to process the request.
The interface isn’t initialized or enabled.
The interface doesn’t support the necessary i2c features or combination of i2c messages.
- inline Status WriteFor(
- Address device_address,
- const void *tx_buffer,
- size_t tx_size_bytes,
- chrono::SystemClock::duration timeout,
A variation of
pw::i2c::Initiator::WriteFor
that accepts an explicit size for the amount of bytes to write to the device.
-
inline Status ReadFor(Address device_address, ByteSpan rx_buffer, chrono::SystemClock::duration timeout)#
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:
device_address – [in] The address of the I2C device.
rx_buffer – [out] The receive buffer.
timeout – [in] The maximum duration to block waiting for both exclusive bus access and the completion of the I2C transaction.
- Pre:
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:
Code
Description
The transaction succeeded.
Was unable to acquire exclusive initiator access and complete the I2C transaction in time.
A NACK condition occurred, meaning the addressed device didn’t respond or was unable to process the request.
The interface isn’t initialized or enabled.
The interface doesn’t support the necessary i2c features or combination of i2c messages.
-
inline Status ReadFor(Address device_address, void *rx_buffer, size_t rx_size_bytes, chrono::SystemClock::duration timeout)#
A variation of
pw::i2c::Initiator::ReadFor
that accepts an explicit size for the amount of bytes to read from the device.
-
inline Status ProbeDeviceFor(Address device_address, chrono::SystemClock::duration timeout)#
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:
device_address – [in] The address of the I2C device.
timeout – [in] The maximum duration to block waiting for both exclusive bus access and the completion of the I2C transaction.
- Pre:
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:
Code
Description
The transaction succeeded.
Was unable to acquire exclusive initiator access and complete the I2C transaction in time.
A NACK condition occurred, meaning the addressed device didn’t respond or was unable to process the request.
The interface isn’t initialized or enabled.
The interface doesn’t support the necessary i2c features or combination of i2c messages.
-
inline constexpr Initiator()#
pw::i2c::Device
#
-
class Device#
The common interface for generic I2C devices. Reads and writes arbitrary chunks of data over an I2C bus to an I2C device. This class contains
pw::i2c::Address
and wraps thepw::i2c::Initiator
API. Only works with devices that have a single device address.pw::i2c::Device
is intended to represent ownership of a specific responder. Individual transactions are atomic but there’s no synchronization for sequences of transactions. Therefore, shared access should be faciliated with higher-level application abstractions. To help enforce this,pw::i2c::Device
instances are only movable and not copyable.Subclassed by pw::i2c::RegisterDevice
Public Functions
-
inline constexpr Device(Initiator &initiator, Address device_address)#
Creates a
pw::i2c::Device
instance.The address for the I2C device is set in this constructor and can’t be modified later.
- Parameters:
initiator – [in] A reference to a
pw::i2c::Initiator
instance.device_address – [in] The address of the I2C device.
- Returns:
A
pw::i2c::Device
instance.
-
inline Status TransferFor(span<const Message> messages, chrono::SystemClock::duration timeout)#
-
inline Status WriteReadFor(ConstByteSpan tx_buffer, ByteSpan rx_buffer, chrono::SystemClock::duration timeout)#
- inline Status WriteReadFor(
- const void *tx_buffer,
- size_t tx_size_bytes,
- void *rx_buffer,
- size_t rx_size_bytes,
- chrono::SystemClock::duration timeout,
Wraps the 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.
-
inline Status WriteFor(ConstByteSpan tx_buffer, chrono::SystemClock::duration timeout)#
Wraps
pw::i2c::Initiator::WriteFor
.
-
inline Status WriteFor(const void *tx_buffer, size_t tx_size_bytes, chrono::SystemClock::duration timeout)#
Wraps the variation of
pw::i2c::Initiator::WriteFor
that accepts an explicit size for the amount of bytes to write to the device.
-
inline Status ReadFor(ByteSpan rx_buffer, chrono::SystemClock::duration timeout)#
Wraps
pw::i2c::Initiator::ReadFor
.
-
inline Status ReadFor(void *rx_buffer, size_t rx_size_bytes, chrono::SystemClock::duration timeout)#
Wraps the variation of
pw::i2c::Initiator::ReadFor
that accepts an explicit size for the amount of bytes to read from the device.
-
inline Status ProbeFor(chrono::SystemClock::duration timeout)#
-
inline constexpr Device(Initiator &initiator, Address device_address)#
pw::i2c::RegisterDevice
#
See Configure and read an I2C device’s registers for example usage of
pw::i2c::RegisterDevice
.
-
class RegisterDevice : public pw::i2c::Device#
The common interface for I2C register devices. Contains methods to help read and write the device’s registers.
Warning
This interface assumes that you know how to consult your device’s datasheet to determine correct address sizes, data sizes, endianness, etc.
Public Functions
- inline constexpr RegisterDevice(
- Initiator &initiator,
- Address address,
- endian register_address_order,
- endian data_order,
- RegisterAddressSize register_address_size,
This constructor specifies the endianness of the register address and data separately. If your register address and data have the same endianness and you’d like to specify them both with a single argument, see the other
pw::i2c::RegisterDevice
constructor.- Parameters:
initiator – [in] A
pw::i2c::Initiator
instance for the bus that the device is on.address – [in] The address of the I2C device.
register_address_order – [in] The endianness of the register address.
data_order – [in] The endianness of the data.
register_address_size – [in] The size of the register address.
-
inline constexpr RegisterDevice(Initiator &initiator, Address address, endian order, RegisterAddressSize register_address_size)#
This constructor specifies the endianness of the register address and data with a single argument. If your register address and data have different endianness, use the other
pw::i2c::RegisterDevice
constructor.- Parameters:
initiator – [in] A
pw::i2c::Initiator
instance for the bus that the device is on.address – [in] The address of the I2C device.
order – [in] The endianness of both the register address and register data.
register_address_size – [in] The size of the register address.
- inline Status WriteRegisters(
- uint32_t register_address,
- ConstByteSpan register_data,
- ByteSpan buffer,
- chrono::SystemClock::duration timeout,
Writes data to multiple contiguous registers starting at a specific register. This method is byte-addressable.
register_address
andregister_data
use the endianness that was provided when thispw::i2c::RegisterDevice
instance was constructed.- Parameters:
register_address – [in] The register address to begin writing at.
register_data – [in] The data to write. Endianness is taken into account if the data is 2 or 4 bytes.
buffer – [in] A buffer for constructing the write data. The size of this buffer must be at least as large as the size of
register_address
plus the size ofregister_data
.timeout – [in] The maximum duration to block waiting for both exclusive bus access and the completion of the I2C transaction.
- Pre:
This method assumes that you’ve verified that your device supports bulk writes and that
register_data
is a correct size for your device.- Returns:
Code
Description
The bulk write was successful.
Unable to acquire exclusive bus access and complete the transaction in time.
The interface is not initialized or enabled.
An issue occurred while building
register_data
.register_address
is larger than the 10-bit address space.The size of
buffer
is less than the size ofregister_address
plus the size ofregister_data
.The device took too long to respond to the NACK.
- inline Status WriteRegisters8(
- uint32_t register_address,
- span<const uint8_t> register_data,
- ByteSpan buffer,
- chrono::SystemClock::duration timeout,
Variant of
pw::i2c::RegisterDevice::WriteRegisters()
that requiresregister_data
to be exactly 8 bits.
- inline Status WriteRegisters16(
- uint32_t register_address,
- span<const uint16_t> register_data,
- ByteSpan buffer,
- chrono::SystemClock::duration timeout,
Variant of
pw::i2c::RegisterDevice::WriteRegisters()
that requiresregister_data
to be exactly 16 bits.
- inline Status WriteRegisters32(
- uint32_t register_address,
- span<const uint32_t> register_data,
- ByteSpan buffer,
- chrono::SystemClock::duration timeout,
Variant of
pw::i2c::RegisterDevice::WriteRegisters()
that requiresregister_data
to be exactly 32 bits.
-
Status ReadRegisters(uint32_t register_address, ByteSpan return_data, chrono::SystemClock::duration timeout)#
Reads data from multiple contiguous registers starting from a specific offset or register. This method is byte-addressable.
register_address
andreturn_data
use the endianness that was provided when thispw::i2c::RegisterDevice
instance was constructed.- Parameters:
register_address – [in] The register address to begin reading at.
return_data – [out] The area to read the data into. The amount of data that will be read is equal to the size of this span. Endianness is taken into account if this span is 2 or 4 bytes.
timeout – [in] The maximum duration to block waiting for both exclusive bus access and the completion of the I2C transaction.
- Pre:
This method assumes that you’ve verified that your device supports bulk reads and that
return_data
is a correct size for your device.- Returns:
Code
Description
The bulk read was successful.
Unable to acquire exclusive bus access and complete the transaction in time.
The interface is not initialized or enabled.
An issue occurred while building
return_data
.register_address
is larger than the 10-bit address space.The device took too long to respond to the NACK.
-
inline Status ReadRegisters8(uint32_t register_address, span<uint8_t> return_data, chrono::SystemClock::duration timeout)#
Variant of
pw::i2c::RegisterDevice::ReadRegisters()
that requiresreturn_data
to be exactly 8 bits.
-
inline Status ReadRegisters16(uint32_t register_address, span<uint16_t> return_data, chrono::SystemClock::duration timeout)#
Variant of
pw::i2c::RegisterDevice::ReadRegisters()
that requiresreturn_data
to be exactly 16 bits.
-
inline Status ReadRegisters32(uint32_t register_address, span<uint32_t> return_data, chrono::SystemClock::duration timeout)#
Variant of
pw::i2c::RegisterDevice::ReadRegisters()
that requiresreturn_data
to be exactly 32 bits.
-
inline Status WriteRegister(uint32_t register_address, std::byte register_data, chrono::SystemClock::duration timeout)#
Sends a register address to write to and then writes to that address.
register_address
andregister_data
use the endianness that was provided when thispw::i2c::RegisterDevice
instance was constructed.- Parameters:
register_address – [in] The register address to write to.
register_data – [in] The data that should be written at the address. The maximum allowed size is 4 bytes.
timeout – [in] The maximum duration to block waiting for both exclusive bus access and the completion of the I2C transaction.
- Pre:
This method assumes that you’ve verified that
register_data
is a correct size for your device.- Returns:
Code
Description
The write was successful.
Unable to acquire exclusive bus access and complete the transaction in time.
The interface is not initialized or enabled.
An issue occurred while writing the data.
register_address
is larger than the 10-bit address space.The device took too long to respond to the NACK.
-
inline Status WriteRegister8(uint32_t register_address, uint8_t register_data, chrono::SystemClock::duration timeout)#
Variant of
pw::i2c::RegisterDevice::WriteRegister()
that writes exactly 8 bits.
-
inline Status WriteRegister16(uint32_t register_address, uint16_t register_data, chrono::SystemClock::duration timeout)#
Variant of
pw::i2c::RegisterDevice::WriteRegister()
that writes exactly 16 bits.
-
inline Status WriteRegister32(uint32_t register_address, uint32_t register_data, chrono::SystemClock::duration timeout)#
Variant of
pw::i2c::RegisterDevice::WriteRegister()
that writes exactly 32 bits.
-
inline Result<std::byte> ReadRegister(uint32_t register_address, chrono::SystemClock::duration timeout)#
Sends a register address to read from and then reads from that address.
register_address
and the return data use the endianness that was provided when thispw::i2c::RegisterDevice
instance was constructed.- Parameters:
register_address – [in] The register address to read.
timeout – [in] The maximum duration to block waiting for both exclusive bus access and the completion of the I2C transaction.
- Pre:
This method assumes that you’ve verified that the return data size is a correct size for your device.
- Returns:
Code
Description
Returns the register data.
Unable to acquire exclusive bus access and complete the transaction in time.
The interface is not initialized or enabled.
An issue occurred while building the return data.
register_address
is larger than the 10-bit address space.The device took too long to respond to the NACK.
-
inline Result<uint8_t> ReadRegister8(uint32_t register_address, chrono::SystemClock::duration timeout)#
Variant of
pw::i2c::RegisterDevice::ReadRegister()
that returns exactly 8 bits.
-
inline Result<uint16_t> ReadRegister16(uint32_t register_address, chrono::SystemClock::duration timeout)#
Variant of
pw::i2c::RegisterDevice::ReadRegister()
that returns exactly 16 bits.
-
inline Result<uint32_t> ReadRegister32(uint32_t register_address, chrono::SystemClock::duration timeout)#
Variant of
pw::i2c::RegisterDevice::ReadRegister()
that returns exactly 32 bits.
pw::i2c::I2cService
#
-
class I2cService : public pw_rpc::pwpb::I2c::Service<I2cService>#
RPC service for performing I2C transactions.
Public Types
-
using InitiatorSelector = pw::Function<Initiator*(size_t pos)>#
A callback that returns a
pw::i2c::Initiator
instance for the given bus index position ornullptr
if the position is not valid for this I2C device.
Public Functions
-
inline explicit I2cService(InitiatorSelector &&initiator_selector)#
Creates an I2cService instance.
-
using InitiatorSelector = pw::Function<Initiator*(size_t pos)>#
pw::i2c::MockMessageInitiator
#
-
class MockMessageInitiator : public pw::i2c::Initiator#
A generic mocked backend for
pw::i2c::Initiator
that’s specifically designed to make it easier to develop I2C device drivers.pw::i2c::MessageMockInitiator
compares actual I2C transactions against expected transactions. The expected transactions are represented as a list ofpw::i2c::MockMessageTransaction
instances that are passed as arguments in thepw::i2c::MessageMockInitiator
constructor. Each consecutive call topw::i2c::MockMessageInitiator
iterates to the next expected transaction.pw::i2c::MockMessageInitiator::Finalize()
indicates whether the actual transactions matched the expected transactions.pw::i2c::MessageMockInitiator
is intended to be used within GoogleTest tests. See pw_unit_test .#include <chrono> #include "pw_bytes/array.h" #include "pw_i2c/address.h" #include "pw_i2c/initiator_message_mock.h" #include "pw_i2c/message.h" #include "pw_result/result.h" #include "pw_unit_test/framework.h" using namespace std::chrono_literals; namespace { TEST(I2CTestSuite, I2CReadRegisterTestCase) { constexpr Address kTestDeviceAddress = Address::SevenBit<0x3F>(); constexpr auto kExpectedWrite1 = bytes::Array<0x42>(); constexpr auto kExpectedRead1 = bytes::Array<1, 2>(); auto expected_transactions = MakeExpectedTransactionArray({ MockMessageTransaction( OkStatus(), MakeExpectedMessageArray({ MockWriteMessage(OkStatus(), kTestDeviceAddress, kExpectedWrite1), MockReadMessage(OkStatus(), kTestDeviceAddress, kExpectedRead1), }), kI2cTransactionTimeout), }); MockMessageInitiator initiator(expected_transactions); std::array<std::byte, kExpectedRead1.size()> read1; EXPECT_EQ(initiator.WriteReadFor(kTestDeviceAddress, kExpectedWrite1, read1, kI2cTransactionTimeout), OkStatus()); EXPECT_TRUE(pw::containers::Equal(read1, kExpectedRead1)); EXPECT_EQ(initiator.Finalize(), OkStatus()); } }
Public Functions
-
inline Status Finalize() const#
Indicates whether the actual I2C transactions matched the expected transactions. Should be called at the end of the test.
- Returns:
Code
Description
The actual transactions matched the expected transactions.
The mocked set of transactions hasn’t been exhausted.
-
~MockMessageInitiator() override#
Runs
pw::i2c::MessageMockInitiator::Finalize()
regardless of whether it was already optionally finalized.
-
inline Status Finalize() const#
pw::i2c::MockMessageTransaction
#
-
class MockMessageTransaction#
Represents a list of MockMessages that make up one i2c transaction. An i2c transaction can consist of any arbitrary combination of i2c read and write messages that are transmitted sequentially and without releasing the bus with an i2c Stop condition.
Public Functions
-
inline std::optional<chrono::SystemClock::duration> timeout() const#
Gets the minimum duration to wait for a blocking I2C transaction.
-
inline std::optional<chrono::SystemClock::duration> timeout() const#
pw::i2c::MockMessage
#
-
class MockMessage#
Base class for creating expected individual Messages that make up a MockMessageTransaction instance. For read-only, write-only, or probe messages, improve code readability by using one of the following helpers instead:
pw::i2c::MockReadMessage
pw::i2c::MockWriteMessage
pw::i2c::MockProbeMessage
pw::i2c::MockReadMessage
#
-
constexpr MockMessage pw::i2c::MockReadMessage(Status expected_return_value, Address address, ConstByteSpan data_buffer)#
pw::i2c::MockWriteMessage
#
-
constexpr MockMessage pw::i2c::MockWriteMessage(Status expected_return_value, Address address, ConstByteSpan data_buffer)#
pw::i2c::MockProbeMessage
#
-
constexpr MockMessage pw::i2c::MockProbeMessage(Status expected_return_value, Address address)#