Low-level I2C peripheral driver. More...
Low-level I2C peripheral driver.
This interface provides a simple abstraction to use the MCUs I2C peripherals. It provides support for 7-bit and 10-bit addressing and can be used for different kind of register addressing schemes.
Example for reading a 8-bit register on a device, using a 10-bit device address and 8-bit register addresses and using a RESTART condition (CAUTION: this example does not check any return values...):
Example for writing a 16-bit register with 16-bit register addressing and 7-bit device addressing:
The I2C signal lines SDA/SCL need external pull-up resistors which connect the lines to the positive voltage supply Vcc. The I2C driver implementation should enable the pin's internal pull-up resistors. There are however some use cases for which the internal pull resistors are not strong enough and the I2C bus will show faulty behavior. This can for example happen when connecting a logic analyzer which will raise the capacitance of the bus. In this case you should make sure you connect external pull-up resistors to both I2C bus lines.
The minimum and maximum resistances are computed by:
where:
Supply voltage, Low level voltage, Low level output current, Signal rise time, Bus capacitance
The pull-up resistors depend on the bus speed. Some typical values are:
Normal mode: 10kΩ
Fast mode: 2kΩ
Fast plus mode: 2kΩ
For more details refer to section 7.1 in:
http://www.nxp.com/documents/user_manual/UM10204.pdf
The I2C interface realizes a transaction-based access scheme to the bus. From a power management perspective, we can leverage this by only powering on the I2C peripheral while it is actually used, that is inside an i2c_acquire() - i2c_release() block.
After initialization, the I2C peripheral should be powered off (e.g. through peripheral clock gating). It should only be powered on once a transaction on the I2C bus starts, namely in the i2c_acquire() function. Once the transaction is finished, the corresponding I2C peripheral should be powered off again in the i2c_release() function.
If the implementation puts the active thread to sleep while a transfer is in progress (e.g. when using DMA), the implementation might need to block certain power states.
Files | |
file | i2c.h |
Low-level I2C peripheral driver interface definition. | |
Macros | |
#define | I2C_READ (0x0001) |
Read bit needs to be set when reading. | |
#define | I2C_10BIT_MAGIC (0xF0u) |
Special bit pattern indicating a 10 bit address is used. | |
Functions | |
void | i2c_init (i2c_t dev) |
Initialize the given I2C bus. | |
void | i2c_init_pins (i2c_t dev) |
Initialize the used I2C bus pins. | |
void | i2c_deinit_pins (i2c_t dev) |
Change the pins of the given I2C bus back to plain GPIO functionality. | |
gpio_t | i2c_pin_sda (i2c_t dev) |
Get the SDA pin of the given I2C bus. | |
gpio_t | i2c_pin_scl (i2c_t dev) |
Get the SCL pin of the given I2C bus. | |
void | i2c_acquire (i2c_t dev) |
Get mutually exclusive access to the given I2C bus. | |
void | i2c_release (i2c_t dev) |
Release the given I2C device to be used by others. | |
int | i2c_read_reg (i2c_t dev, uint16_t addr, uint16_t reg, void *data, uint8_t flags) |
Convenience function for reading one byte from a given register address. | |
int | i2c_read_regs (i2c_t dev, uint16_t addr, uint16_t reg, void *data, size_t len, uint8_t flags) |
Convenience function for reading several bytes from a given register address. | |
int | i2c_read_byte (i2c_t dev, uint16_t addr, void *data, uint8_t flags) |
Convenience function for reading one byte from a device. | |
int | i2c_read_bytes (i2c_t dev, uint16_t addr, void *data, size_t len, uint8_t flags) |
Convenience function for reading bytes from a device. | |
int | i2c_write_byte (i2c_t dev, uint16_t addr, uint8_t data, uint8_t flags) |
Convenience function for writing a single byte onto the bus. | |
int | i2c_write_bytes (i2c_t dev, uint16_t addr, const void *data, size_t len, uint8_t flags) |
Convenience function for writing several bytes onto the bus. | |
int | i2c_write_reg (i2c_t dev, uint16_t addr, uint16_t reg, uint8_t data, uint8_t flags) |
Convenience function for writing one byte to a given register address. | |
int | i2c_write_regs (i2c_t dev, uint16_t addr, uint16_t reg, const void *data, size_t len, uint8_t flags) |
Convenience function for writing data to a given register address. | |
enum | i2c_speed_t { I2C_SPEED_LOW = 0 , I2C_SPEED_NORMAL , I2C_SPEED_FAST , I2C_SPEED_FAST_PLUS , I2C_SPEED_HIGH } |
Default mapping of I2C bus speed values. More... | |
enum | i2c_flags_t { I2C_ADDR10 = 0x01 , I2C_REG16 = 0x02 , I2C_NOSTOP = 0x04 , I2C_NOSTART = 0x08 } |
I2C transfer flags. More... | |
typedef uint_fast8_t | i2c_t |
Default i2c_t type definition. | |
#define | I2C_DEV(x) (x) |
Default I2C device access macro. | |
#define | I2C_UNDEF (UINT_FAST8_MAX) |
Default I2C undefined value. | |
#define I2C_10BIT_MAGIC (0xF0u) |
Special bit pattern indicating a 10 bit address is used.
Should only be used internally in CPU driver implementations, this is not intended to be used by applications.
#define I2C_READ (0x0001) |
#define I2C_UNDEF (UINT_FAST8_MAX) |
enum i2c_flags_t |
enum i2c_speed_t |
void i2c_acquire | ( | i2c_t | dev | ) |
Get mutually exclusive access to the given I2C bus.
In case the I2C device is busy, this function will block until the bus is free again.
[in] | dev | I2C device to access |
void i2c_deinit_pins | ( | i2c_t | dev | ) |
Change the pins of the given I2C bus back to plain GPIO functionality.
The pin mux of the SDA and SCL pins of the bus will be changed back to default (GPIO) mode and the I2C bus is powered off. This allows to use the I2C pins for another function and return to I2C functionality again by calling i2c_init_pins()
If you want the pin to be in a defined state, call gpio_init() on it.
The bus MUST not be acquired before initializing it, as this is handled internally by the i2c_deinit function!
Calls to i2c_acquire() will block until i2c_init_pins() is called.
[in] | dev | the device to de-initialize |
void i2c_init | ( | i2c_t | dev | ) |
Initialize the given I2C bus.
The given I2C device will be initialized with the parameters as specified in the boards periph_conf.h, using the pins and the speed value given there.
The bus MUST not be acquired before initializing it, as this is handled internally by the i2c_init function!
[in] | dev | the device to initialize |
void i2c_init_pins | ( | i2c_t | dev | ) |
Initialize the used I2C bus pins.
After calling i2c_init, the pins must be initialized (i.e. spi_init is calling this function internally). In normal cases, this function will not be used. But there are some devices (e.g. ATECC608A), that use I2C bus lines also for other purposes and need the option to dynamically re-configure one or more of the used pins.
[in] | dev | I2C device the pins are configure for |
gpio_t i2c_pin_scl | ( | i2c_t | dev | ) |
Get the SCL pin of the given I2C bus.
[in] | dev | The device to query |
gpio_t i2c_pin_sda | ( | i2c_t | dev | ) |
Get the SDA pin of the given I2C bus.
[in] | dev | The device to query |
int i2c_read_byte | ( | i2c_t | dev, |
uint16_t | addr, | ||
void * | data, | ||
uint8_t | flags | ||
) |
Convenience function for reading one byte from a device.
[in] | dev | I2C peripheral device |
[in] | addr | 7-bit or 10-bit device address (right-aligned) |
[out] | data | memory location to store received data |
[in] | flags | optional flags (see i2c_flags_t) |
int i2c_read_bytes | ( | i2c_t | dev, |
uint16_t | addr, | ||
void * | data, | ||
size_t | len, | ||
uint8_t | flags | ||
) |
Convenience function for reading bytes from a device.
[in] | dev | I2C peripheral device |
[in] | addr | 7-bit or 10-bit device address (right-aligned) |
[out] | data | memory location to store received data |
[in] | len | the number of bytes to read into data |
[in] | flags | optional flags (see i2c_flags_t) |
int i2c_read_reg | ( | i2c_t | dev, |
uint16_t | addr, | ||
uint16_t | reg, | ||
void * | data, | ||
uint8_t | flags | ||
) |
Convenience function for reading one byte from a given register address.
[in] | dev | I2C peripheral device |
[in] | reg | register address to read from (8- or 16-bit, right-aligned) |
[in] | addr | 7-bit or 10-bit device address (right-aligned) |
[out] | data | memory location to store received data |
[in] | flags | optional flags (see i2c_flags_t) |
int i2c_read_regs | ( | i2c_t | dev, |
uint16_t | addr, | ||
uint16_t | reg, | ||
void * | data, | ||
size_t | len, | ||
uint8_t | flags | ||
) |
Convenience function for reading several bytes from a given register address.
[in] | dev | I2C peripheral device |
[in] | reg | register address to read from (8- or 16-bit, right-aligned) |
[in] | addr | 7-bit or 10-bit device address (right-aligned) |
[out] | data | memory location to store received data |
[in] | len | the number of bytes to read into data |
[in] | flags | optional flags (see i2c_flags_t) |
void i2c_release | ( | i2c_t | dev | ) |
Release the given I2C device to be used by others.
[in] | dev | I2C device to release |
int i2c_write_byte | ( | i2c_t | dev, |
uint16_t | addr, | ||
uint8_t | data, | ||
uint8_t | flags | ||
) |
Convenience function for writing a single byte onto the bus.
[in] | dev | I2C peripheral device |
[in] | addr | 7-bit or 10-bit device address (right-aligned) |
[in] | data | byte to write to the device |
[in] | flags | optional flags (see i2c_flags_t) |
int i2c_write_bytes | ( | i2c_t | dev, |
uint16_t | addr, | ||
const void * | data, | ||
size_t | len, | ||
uint8_t | flags | ||
) |
Convenience function for writing several bytes onto the bus.
[in] | dev | I2C peripheral device |
[in] | addr | 7-bit or 10-bit device address (right-aligned) |
[in] | data | array holding the bytes to write to the device |
[in] | len | the number of bytes to write |
[in] | flags | optional flags (see i2c_flags_t) |
int i2c_write_reg | ( | i2c_t | dev, |
uint16_t | addr, | ||
uint16_t | reg, | ||
uint8_t | data, | ||
uint8_t | flags | ||
) |
Convenience function for writing one byte to a given register address.
[in] | dev | I2C peripheral device |
[in] | reg | register address to read from (8- or 16-bit, right-aligned) |
[in] | addr | 7-bit or 10-bit device address (right-aligned) |
[in] | data | byte to write |
[in] | flags | optional flags (see i2c_flags_t) |
int i2c_write_regs | ( | i2c_t | dev, |
uint16_t | addr, | ||
uint16_t | reg, | ||
const void * | data, | ||
size_t | len, | ||
uint8_t | flags | ||
) |
Convenience function for writing data to a given register address.
[in] | dev | I2C peripheral device |
[in] | reg | register address to read from (8- or 16-bit, right-aligned) |
[in] | addr | 7-bit or 10-bit device address (right-aligned) |
[out] | data | memory location to store received data |
[in] | len | the number of bytes to write |
[in] | flags | optional flags (see i2c_flags_t) |