I2C
Overview
Note
The terminology used in Zephyr I2C APIs follows that of the NXP I2C Bus Specification Rev 7.0. These changed from previous revisions as of its release October 1, 2021.
I2C (Inter-Integrated Circuit, pronounced “eye squared see”) is a commonly-used two-signal shared peripheral interface bus. Many system-on-chip solutions provide controllers that communicate on an I2C bus. Devices on the bus can operate in two roles: as a “controller” that initiates transactions and controls the clock, or as a “target” that responds to transaction commands. A I2C controller on a given SoC will generally support the controller role, and some will also support the target mode. Zephyr has API for both roles.
I2C Controller API
Zephyr’s I2C controller API is used when an I2C peripheral controls the bus, in particularly the start and stop conditions and the clock. This is the most common mode, used to interact with I2C devices like sensors and serial memory.
This API is supported in all in-tree I2C peripheral drivers and is considered stable.
I2C Target API
Zephyr’s I2C target API is used when an I2C peripheral responds to transactions initiated by a different controller on the bus. It might be used for a Zephyr application with transducer roles that are controlled by another device such as a host processor.
This API is supported in very few in-tree I2C peripheral drivers. The API is considered experimental, as it is not compatible with the capabilities of all I2C peripherals supported in controller mode.
Configuration Options
Related configuration options:
API Reference
- group i2c_interface
I2C Interface.
Defines
-
I2C_SPEED_STANDARD
I2C Standard Speed: 100 kHz
-
I2C_SPEED_FAST
I2C Fast Speed: 400 kHz
-
I2C_SPEED_FAST_PLUS
I2C Fast Plus Speed: 1 MHz
-
I2C_SPEED_HIGH
I2C High Speed: 3.4 MHz
-
I2C_SPEED_ULTRA
I2C Ultra Fast Speed: 5 MHz
-
I2C_SPEED_DT
Device Tree specified speed
-
I2C_SPEED_SHIFT
-
I2C_SPEED_SET(speed)
-
I2C_SPEED_MASK
-
I2C_SPEED_GET(cfg)
-
I2C_ADDR_10_BITS
Use 10-bit addressing. DEPRECATED - Use I2C_MSG_ADDR_10_BITS instead.
-
I2C_MODE_CONTROLLER
Peripheral to act as Controller.
-
I2C_MODE_MASTER
- Deprecated:
Use I2C_MODE_CONTROLLER instead.
-
I2C_DT_SPEC_GET_ON_I3C(node_id)
Structure initializer for i2c_dt_spec from devicetree (on I3C bus)
This helper macro expands to a static initializer for a
struct i2c_dt_spec
by reading the relevant bus and address data from the devicetree.- Parameters
node_id – Devicetree node identifier for the I2C device whose struct i2c_dt_spec to create an initializer for
-
I2C_DT_SPEC_GET_ON_I2C(node_id)
Structure initializer for i2c_dt_spec from devicetree (on I2C bus)
This helper macro expands to a static initializer for a
struct i2c_dt_spec
by reading the relevant bus and address data from the devicetree.- Parameters
node_id – Devicetree node identifier for the I2C device whose struct i2c_dt_spec to create an initializer for
-
I2C_DT_SPEC_GET(node_id)
Structure initializer for i2c_dt_spec from devicetree.
This helper macro expands to a static initializer for a
struct i2c_dt_spec
by reading the relevant bus and address data from the devicetree.- Parameters
node_id – Devicetree node identifier for the I2C device whose struct i2c_dt_spec to create an initializer for
-
I2C_DT_SPEC_INST_GET(inst)
Structure initializer for i2c_dt_spec from devicetree instance.
This is equivalent to
I2C_DT_SPEC_GET(DT_DRV_INST(inst))
.- Parameters
inst – Devicetree instance number
-
I2C_MSG_WRITE
Write message to I2C bus.
-
I2C_MSG_READ
Read message from I2C bus.
-
I2C_MSG_STOP
Send STOP after this message.
-
I2C_MSG_RESTART
RESTART I2C transaction for this message.
Note
Not all I2C drivers have or require explicit support for this feature. Some drivers require this be present on a read message that follows a write, or vice-versa. Some drivers will merge adjacent fragments into a single transaction using this flag; some will not.
-
I2C_MSG_ADDR_10_BITS
Use 10-bit addressing for this message.
Note
Not all SoC I2C implementations support this feature.
-
I2C_TARGET_FLAGS_ADDR_10_BITS
Target device responds to 10-bit addressing.
-
I2C_DEVICE_DT_DEFINE(node_id, init_fn, pm, data, config, level, prio, api, ...)
Like DEVICE_DT_DEFINE() with I2C specifics.
Defines a device which implements the I2C API. May generate a custom device_state container struct and init_fn wrapper when needed depending on I2C
CONFIG_I2C_STATS
.- Parameters
node_id – The devicetree node identifier.
init_fn – Name of the init function of the driver.
pm – PM device resources reference (NULL if device does not use PM).
data – Pointer to the device’s private data.
config – The address to the structure containing the configuration information for this instance of the driver.
level – The initialization level. See SYS_INIT() for details.
prio – Priority within the selected initialization level. See SYS_INIT() for details.
api – Provides an initial pointer to the API function struct used by the driver. Can be NULL.
-
I2C_DEVICE_DT_INST_DEFINE(inst, ...)
Like I2C_DEVICE_DT_DEFINE() for an instance of a DT_DRV_COMPAT compatible.
- Parameters
inst – instance number. This is replaced by
DT_DRV_COMPAT(inst)
in the call to I2C_DEVICE_DT_DEFINE().... – other parameters as expected by I2C_DEVICE_DT_DEFINE().
Typedefs
-
typedef void (*i2c_callback_t)(const struct device *dev, int result, void *data)
I2C callback for asynchronous transfer requests.
- Param dev
I2C device which is notifying of transfer completion or error
- Param result
Result code of the transfer request. 0 is success, -errno for failure.
- Param data
Transfer requester supplied data which is passed along to the callback.
-
typedef int (*i2c_target_write_requested_cb_t)(struct i2c_target_config *config)
Function called when a write to the device is initiated.
This function is invoked by the controller when the bus completes a start condition for a write operation to the address associated with a particular device.
A success return shall cause the controller to ACK the next byte received. An error return shall cause the controller to NACK the next byte received.
- Param config
the configuration structure associated with the device to which the operation is addressed.
- Return
0 if the write is accepted, or a negative error code.
-
typedef int (*i2c_target_write_received_cb_t)(struct i2c_target_config *config, uint8_t val)
Function called when a write to the device is continued.
This function is invoked by the controller when it completes reception of a byte of data in an ongoing write operation to the device.
A success return shall cause the controller to ACK the next byte received. An error return shall cause the controller to NACK the next byte received.
- Param config
the configuration structure associated with the device to which the operation is addressed.
- Param val
the byte received by the controller.
- Return
0 if more data can be accepted, or a negative error code.
-
typedef int (*i2c_target_read_requested_cb_t)(struct i2c_target_config *config, uint8_t *val)
Function called when a read from the device is initiated.
This function is invoked by the controller when the bus completes a start condition for a read operation from the address associated with a particular device.
The value returned in
*val
will be transmitted. A success return shall cause the controller to react to additional read operations. An error return shall cause the controller to ignore bus operations until a new start condition is received.- Param config
the configuration structure associated with the device to which the operation is addressed.
- Param val
pointer to storage for the first byte of data to return for the read request.
- Return
0 if more data can be requested, or a negative error code.
-
typedef int (*i2c_target_read_processed_cb_t)(struct i2c_target_config *config, uint8_t *val)
Function called when a read from the device is continued.
This function is invoked by the controller when the bus is ready to provide additional data for a read operation from the address associated with the device device.
The value returned in
*val
will be transmitted. A success return shall cause the controller to react to additional read operations. An error return shall cause the controller to ignore bus operations until a new start condition is received.- Param config
the configuration structure associated with the device to which the operation is addressed.
- Param val
pointer to storage for the next byte of data to return for the read request.
- Return
0 if data has been provided, or a negative error code.
-
typedef int (*i2c_target_stop_cb_t)(struct i2c_target_config *config)
Function called when a stop condition is observed after a start condition addressed to a particular device.
This function is invoked by the controller when the bus is ready to provide additional data for a read operation from the address associated with the device device. After the function returns the controller shall enter a state where it is ready to react to new start conditions.
- Param config
the configuration structure associated with the device to which the operation is addressed.
- Return
Ignored.
Functions
-
static inline bool i2c_is_ready_dt(const struct i2c_dt_spec *spec)
Validate that I2C bus is ready.
- Parameters
spec – I2C specification from devicetree
- Return values
true – if the I2C bus is ready for use.
false – if the I2C bus is not ready for use.
-
static inline void i2c_xfer_stats(const struct device *dev, struct i2c_msg *msgs, uint8_t num_msgs)
Updates the i2c stats for i2c transfers.
- Parameters
dev – I2C device to update stats for
msgs – Array of struct i2c_msg
num_msgs – Number of i2c_msgs
-
int i2c_configure(const struct device *dev, uint32_t dev_config)
Configure operation of a host controller.
- Parameters
dev – Pointer to the device structure for the driver instance.
dev_config – Bit-packed 32-bit value to the device runtime configuration for the I2C controller.
- Return values
0 – If successful.
-EIO – General input / output error, failed to configure device.
-
int i2c_get_config(const struct device *dev, uint32_t *dev_config)
Get configuration of a host controller.
This routine provides a way to get current configuration. It is allowed to call the function before i2c_configure, because some I2C ports can be configured during init process. However, if the I2C port is not configured, i2c_get_config returns an error.
i2c_get_config can return cached config or probe hardware, but it has to be up to date with current configuration.
- Parameters
dev – Pointer to the device structure for the driver instance.
dev_config – Pointer to return bit-packed 32-bit value of the I2C controller configuration.
- Return values
0 – If successful.
-EIO – General input / output error.
-ERANGE – Configured I2C frequency is invalid.
-ENOSYS – If get config is not implemented
-
int i2c_transfer(const struct device *dev, struct i2c_msg *msgs, uint8_t num_msgs, uint16_t addr)
Perform data transfer to another I2C device in controller mode.
This routine provides a generic interface to perform data transfer to another I2C device synchronously. Use i2c_read()/i2c_write() for simple read or write.
The array of message msgs must not be NULL. The number of message num_msgs may be zero,in which case no transfer occurs.
Note
Not all scatter/gather transactions can be supported by all drivers. As an example, a gather write (multiple consecutive
i2c_msg
buffers all configured forI2C_MSG_WRITE
) may be packed into a single transaction by some drivers, but others may emit each fragment as a distinct write transaction, which will not produce the same behavior. See the documentation ofstruct i2c_msg
for limitations on support for multi-message bus transactions.- Parameters
dev – Pointer to the device structure for an I2C controller driver configured in controller mode.
msgs – Array of messages to transfer.
num_msgs – Number of messages to transfer.
addr – Address of the I2C target device.
- Return values
0 – If successful.
-EIO – General input / output error.
-
static inline int i2c_transfer_dt(const struct i2c_dt_spec *spec, struct i2c_msg *msgs, uint8_t num_msgs)
Perform data transfer to another I2C device in controller mode.
This is equivalent to:
i2c_transfer(spec->bus, msgs, num_msgs, spec->addr);
- Parameters
spec – I2C specification from devicetree.
msgs – Array of messages to transfer.
num_msgs – Number of messages to transfer.
- Returns
a value from i2c_transfer()
-
int i2c_recover_bus(const struct device *dev)
Recover the I2C bus.
Attempt to recover the I2C bus.
- Parameters
dev – Pointer to the device structure for an I2C controller driver configured in controller mode.
- Return values
0 – If successful
-EBUSY – If bus is not clear after recovery attempt.
-EIO – General input / output error.
-ENOSYS – If bus recovery is not implemented
-
static inline int i2c_target_register(const struct device *dev, struct i2c_target_config *cfg)
Registers the provided config as Target device of a controller.
Enable I2C target mode for the ‘dev’ I2C bus driver using the provided ‘config’ struct containing the functions and parameters to send bus events. The I2C target will be registered at the address provided as ‘address’ struct member. Addressing mode - 7 or 10 bit - depends on the ‘flags’ struct member. Any I2C bus events related to the target mode will be passed onto I2C target device driver via a set of callback functions provided in the ‘callbacks’ struct member.
Most of the existing hardware allows simultaneous support for controller and target mode. This is however not guaranteed.
- Parameters
dev – Pointer to the device structure for an I2C controller driver configured in target mode.
cfg – Config struct with functions and parameters used by the I2C driver to send bus events
- Return values
0 – Is successful
-EINVAL – If parameters are invalid
-EIO – General input / output error.
-ENOSYS – If target mode is not implemented
-
static inline int i2c_target_unregister(const struct device *dev, struct i2c_target_config *cfg)
Unregisters the provided config as Target device.
This routine disables I2C target mode for the ‘dev’ I2C bus driver using the provided ‘config’ struct containing the functions and parameters to send bus events.
- Parameters
dev – Pointer to the device structure for an I2C controller driver configured in target mode.
cfg – Config struct with functions and parameters used by the I2C driver to send bus events
- Return values
0 – Is successful
-EINVAL – If parameters are invalid
-ENOSYS – If target mode is not implemented
-
int i2c_target_driver_register(const struct device *dev)
Instructs the I2C Target device to register itself to the I2C Controller.
This routine instructs the I2C Target device to register itself to the I2C Controller via its parent controller’s i2c_target_register() API.
- Parameters
dev – Pointer to the device structure for the I2C target device (not itself an I2C controller).
- Return values
0 – Is successful
-EINVAL – If parameters are invalid
-EIO – General input / output error.
-
int i2c_target_driver_unregister(const struct device *dev)
Instructs the I2C Target device to unregister itself from the I2C Controller.
This routine instructs the I2C Target device to unregister itself from the I2C Controller via its parent controller’s i2c_target_register() API.
- Parameters
dev – Pointer to the device structure for the I2C target device (not itself an I2C controller).
- Return values
0 – Is successful
-EINVAL – If parameters are invalid
-
static inline int i2c_write(const struct device *dev, const uint8_t *buf, uint32_t num_bytes, uint16_t addr)
Write a set amount of data to an I2C device.
This routine writes a set amount of data synchronously.
- Parameters
dev – Pointer to the device structure for an I2C controller driver configured in controller mode.
buf – Memory pool from which the data is transferred.
num_bytes – Number of bytes to write.
addr – Address to the target I2C device for writing.
- Return values
0 – If successful.
-EIO – General input / output error.
-
static inline int i2c_write_dt(const struct i2c_dt_spec *spec, const uint8_t *buf, uint32_t num_bytes)
Write a set amount of data to an I2C device.
This is equivalent to:
i2c_write(spec->bus, buf, num_bytes, spec->addr);
- Parameters
spec – I2C specification from devicetree.
buf – Memory pool from which the data is transferred.
num_bytes – Number of bytes to write.
- Returns
a value from i2c_write()
-
static inline int i2c_read(const struct device *dev, uint8_t *buf, uint32_t num_bytes, uint16_t addr)
Read a set amount of data from an I2C device.
This routine reads a set amount of data synchronously.
- Parameters
dev – Pointer to the device structure for an I2C controller driver configured in controller mode.
buf – Memory pool that stores the retrieved data.
num_bytes – Number of bytes to read.
addr – Address of the I2C device being read.
- Return values
0 – If successful.
-EIO – General input / output error.
-
static inline int i2c_read_dt(const struct i2c_dt_spec *spec, uint8_t *buf, uint32_t num_bytes)
Read a set amount of data from an I2C device.
This is equivalent to:
i2c_read(spec->bus, buf, num_bytes, spec->addr);
- Parameters
spec – I2C specification from devicetree.
buf – Memory pool that stores the retrieved data.
num_bytes – Number of bytes to read.
- Returns
a value from i2c_read()
-
static inline int i2c_write_read(const struct device *dev, uint16_t addr, const void *write_buf, size_t num_write, void *read_buf, size_t num_read)
Write then read data from an I2C device.
This supports the common operation “this is what I want”, “now give
it to me” transaction pair through a combined write-then-read bus transaction.
- Parameters
dev – Pointer to the device structure for an I2C controller driver configured in controller mode.
addr – Address of the I2C device
write_buf – Pointer to the data to be written
num_write – Number of bytes to write
read_buf – Pointer to storage for read data
num_read – Number of bytes to read
- Return values
0 – if successful
negative – on error.
-
static inline int i2c_write_read_dt(const struct i2c_dt_spec *spec, const void *write_buf, size_t num_write, void *read_buf, size_t num_read)
Write then read data from an I2C device.
This is equivalent to:
i2c_write_read(spec->bus, spec->addr, write_buf, num_write, read_buf, num_read);
- Parameters
spec – I2C specification from devicetree.
write_buf – Pointer to the data to be written
num_write – Number of bytes to write
read_buf – Pointer to storage for read data
num_read – Number of bytes to read
- Returns
a value from i2c_write_read()
-
static inline int i2c_burst_read(const struct device *dev, uint16_t dev_addr, uint8_t start_addr, uint8_t *buf, uint32_t num_bytes)
Read multiple bytes from an internal address of an I2C device.
This routine reads multiple bytes from an internal address of an I2C device synchronously.
Instances of this may be replaced by i2c_write_read().
- Parameters
dev – Pointer to the device structure for an I2C controller driver configured in controller mode.
dev_addr – Address of the I2C device for reading.
start_addr – Internal address from which the data is being read.
buf – Memory pool that stores the retrieved data.
num_bytes – Number of bytes being read.
- Return values
0 – If successful.
-EIO – General input / output error.
-
static inline int i2c_burst_read_dt(const struct i2c_dt_spec *spec, uint8_t start_addr, uint8_t *buf, uint32_t num_bytes)
Read multiple bytes from an internal address of an I2C device.
This is equivalent to:
i2c_burst_read(spec->bus, spec->addr, start_addr, buf, num_bytes);
- Parameters
spec – I2C specification from devicetree.
start_addr – Internal address from which the data is being read.
buf – Memory pool that stores the retrieved data.
num_bytes – Number of bytes to read.
- Returns
a value from i2c_burst_read()
-
static inline int i2c_burst_write(const struct device *dev, uint16_t dev_addr, uint8_t start_addr, const uint8_t *buf, uint32_t num_bytes)
Write multiple bytes to an internal address of an I2C device.
This routine writes multiple bytes to an internal address of an I2C device synchronously.
Warning
The combined write synthesized by this API may not be supported on all I2C devices. Uses of this API may be made more portable by replacing them with calls to i2c_write() passing a buffer containing the combined address and data.
- Parameters
dev – Pointer to the device structure for an I2C controller driver configured in controller mode.
dev_addr – Address of the I2C device for writing.
start_addr – Internal address to which the data is being written.
buf – Memory pool from which the data is transferred.
num_bytes – Number of bytes being written.
- Return values
0 – If successful.
-EIO – General input / output error.
-
static inline int i2c_burst_write_dt(const struct i2c_dt_spec *spec, uint8_t start_addr, const uint8_t *buf, uint32_t num_bytes)
Write multiple bytes to an internal address of an I2C device.
This is equivalent to:
i2c_burst_write(spec->bus, spec->addr, start_addr, buf, num_bytes);
- Parameters
spec – I2C specification from devicetree.
start_addr – Internal address to which the data is being written.
buf – Memory pool from which the data is transferred.
num_bytes – Number of bytes being written.
- Returns
a value from i2c_burst_write()
-
static inline int i2c_reg_read_byte(const struct device *dev, uint16_t dev_addr, uint8_t reg_addr, uint8_t *value)
Read internal register of an I2C device.
This routine reads the value of an 8-bit internal register of an I2C device synchronously.
- Parameters
dev – Pointer to the device structure for an I2C controller driver configured in controller mode.
dev_addr – Address of the I2C device for reading.
reg_addr – Address of the internal register being read.
value – Memory pool that stores the retrieved register value.
- Return values
0 – If successful.
-EIO – General input / output error.
-
static inline int i2c_reg_read_byte_dt(const struct i2c_dt_spec *spec, uint8_t reg_addr, uint8_t *value)
Read internal register of an I2C device.
This is equivalent to:
i2c_reg_read_byte(spec->bus, spec->addr, reg_addr, value);
- Parameters
spec – I2C specification from devicetree.
reg_addr – Address of the internal register being read.
value – Memory pool that stores the retrieved register value.
- Returns
a value from i2c_reg_read_byte()
-
static inline int i2c_reg_write_byte(const struct device *dev, uint16_t dev_addr, uint8_t reg_addr, uint8_t value)
Write internal register of an I2C device.
This routine writes a value to an 8-bit internal register of an I2C device synchronously.
Note
This function internally combines the register and value into a single bus transaction.
- Parameters
dev – Pointer to the device structure for an I2C controller driver configured in controller mode.
dev_addr – Address of the I2C device for writing.
reg_addr – Address of the internal register being written.
value – Value to be written to internal register.
- Return values
0 – If successful.
-EIO – General input / output error.
-
static inline int i2c_reg_write_byte_dt(const struct i2c_dt_spec *spec, uint8_t reg_addr, uint8_t value)
Write internal register of an I2C device.
This is equivalent to:
i2c_reg_write_byte(spec->bus, spec->addr, reg_addr, value);
- Parameters
spec – I2C specification from devicetree.
reg_addr – Address of the internal register being written.
value – Value to be written to internal register.
- Returns
a value from i2c_reg_write_byte()
-
static inline int i2c_reg_update_byte(const struct device *dev, uint8_t dev_addr, uint8_t reg_addr, uint8_t mask, uint8_t value)
Update internal register of an I2C device.
This routine updates the value of a set of bits from an 8-bit internal register of an I2C device synchronously.
Note
If the calculated new register value matches the value that was read this function will not generate a write operation.
- Parameters
dev – Pointer to the device structure for an I2C controller driver configured in controller mode.
dev_addr – Address of the I2C device for updating.
reg_addr – Address of the internal register being updated.
mask – Bitmask for updating internal register.
value – Value for updating internal register.
- Return values
0 – If successful.
-EIO – General input / output error.
-
static inline int i2c_reg_update_byte_dt(const struct i2c_dt_spec *spec, uint8_t reg_addr, uint8_t mask, uint8_t value)
Update internal register of an I2C device.
This is equivalent to:
i2c_reg_update_byte(spec->bus, spec->addr, reg_addr, mask, value);
- Parameters
spec – I2C specification from devicetree.
reg_addr – Address of the internal register being updated.
mask – Bitmask for updating internal register.
value – Value for updating internal register.
- Returns
a value from i2c_reg_update_byte()
-
void i2c_dump_msgs(const char *name, const struct i2c_msg *msgs, uint8_t num_msgs, uint16_t addr)
Dump out an I2C message.
Dumps out a list of I2C messages. For any that are writes (W), the data is displayed in hex.
It looks something like this (with name “testing”):
D: I2C msg: testing, addr=56 D: W len=01: D: contents: D: 06 |. D: W len=0e: D: contents: D: 00 01 02 03 04 05 06 07 |........ D: 08 09 0a 0b 0c 0d |......
- Parameters
name – Name of this dump, displayed at the top.
msgs – Array of messages to dump.
num_msgs – Number of messages to dump.
addr – Address of the I2C target device.
-
struct i2c_dt_spec
- #include <i2c.h>
Complete I2C DT information.
- Param bus
is the I2C bus
- Param addr
is the target address
-
struct i2c_msg
- #include <i2c.h>
One I2C Message.
This defines one I2C message to transact on the I2C bus.
Note
Some of the configurations supported by this API may not be supported by specific SoC I2C hardware implementations, in particular features related to bus transactions intended to read or write data from different buffers within a single transaction. Invocations of i2c_transfer() may not indicate an error when an unsupported configuration is encountered. In some cases drivers will generate separate transactions for each message fragment, with or without presence of I2C_MSG_RESTART in flags.
-
struct i2c_target_callbacks
- #include <i2c.h>
Structure providing callbacks to be implemented for devices that supports the I2C target API.
This structure may be shared by multiple devices that implement the same API at different addresses on the bus.
-
struct i2c_target_config
- #include <i2c.h>
Structure describing a device that supports the I2C target API.
Instances of this are passed to the i2c_target_register() and i2c_target_unregister() functions to indicate addition and removal of a target device, respective.
Fields other than
node
must be initialized by the module that implements the device behavior prior to passing the object reference to i2c_target_register().Public Members
-
sys_snode_t node
Private, do not modify
-
uint8_t flags
Flags for the target device defined by I2C_TARGET_FLAGS_* constants
-
uint16_t address
Address for this target device
-
const struct i2c_target_callbacks *callbacks
Callback functions
-
sys_snode_t node
-
struct i2c_device_state
- #include <i2c.h>
I2C specific device state which allows for i2c device class specific additions.
-
I2C_SPEED_STANDARD