I2C Master Asynchronous Driver

In Inter-Integrated Circuit (I2C) master asynchronous driver, a callback function can be registered in the driver by the application and triggered when the transfer done. It provides an interface to read/write the data from/to the slave device.

The stop condition is automatically controlled by the driver if the I/O write and read functions are used, but can be manually controlled by using the i2c_m_async_transfer function.

Often a master accesses different information in the slave by accessing different registers in the slave. This is done by first sending a message to the target slave containing the register address, followed by a repeated start condition (no stop condition in between) ending with transferring register data. This scheme is supported by the i2c_m_async_cmd_write and i2c_m_async_cmd_read function, but limited to 8-bit register addresses.

Transfer callbacks are executed at the end of a full transfer, that is, when a complete message with address is either sent or read from the slave. When the i2c_m_async_transfer function is used the TX and RX callbacks are triggered regardless if a stop condition is generated at the end of the message.

The TX and RX callbacks are reused for the cmd functions and are triggered at the end of a full register write or read, that is, after the register address has been written to the slave and data has been transferred to or from the master.

The error callback is executed as soon as an error is detected, the error situation can both be detected while processing an interrupt or detected by the hardware which may trigger a special error interrupt. In situations where errors are detected by the software, there will be a slight delay from the error occurs until the error callback is triggered due to software processing.

I2C Modes (standard mode/fastmode+/highspeed mode) can only be selected in START. If the SCL frequency (baudrate) has changed run-time, make sure to stick within the SCL clock frequency range supported by the selected mode. The requested SCL clock frequency is not validated by the i2c_m_async_set_baudrate function against the selected I2C mode.

Summary of the API's Functional Features

The API provides functions to:
  • Initialize and deinitialize the driver and associated hardware

  • Register I/O descriptor

  • Enable or disable I2C master

  • Hookup callback handlers on TX complete, RX complete, or error events

  • Set the address of slave device

  • Read/Write message to/from the slave

Summary of Configuration Options

Below is a list of the main I2C master parameters that can be configured in START. Many of these parameters are used by the i2c_m_async_init function when initializing the driver and underlying hardware. Most of the initial values can be overridden and changed runtime by calling the appropriate API functions, such as i2c_m_async_set_baudrate.
  • Set I2C bus clock speed

  • Which clock source is used

Driver Implementation Description

After I2C hardware initialization, the i2c_m_async_get_io_descriptor function is needed to register an I/O descriptor. Then enable the I2C hardware, and use the i2c_m_async_register_callback to register callback function for RX/TX complete. After that, the application needs to set the slave address by the i2c_m_async_set_slaveaddr function. At the end, start the read/write operation.

Limitations

  • System Management Bus (SMBus) not supported

  • Power Management Bus (PMBus) not supported

  • The register value for the requested I2C speed is calculated and placed in the correct register, but not validated if it works correctly with the clock/prescaler settings used for the module. To validate the I2C speed setting use the formula found in the configuration file for the module. Selectable speed is automatically limited within the speed range defined by the I2C mode selected

Example of Usage

The following shows a simple example of using the I2C master. The I2C master must have been initialized by i2c_m_async_init. This initialization will configure the operation of the I2C master.

The example registers an I/O descriptor and enables the hardware. Then it registers a callback for TX complete, sets the slave address, finally starts a writing operation.

          static uint8_t I2C_0_example_str[12] = "Hello World!";
          void I2C_0_tx_complete(struct i2c_m_async_desc *const i2c)
          {
          }
          void I2C_0_example(void)
          {
              struct io_descriptor *I2C_0_io;
              i2c_m_async_get_io_descriptor(&I2C_0, &I2C_0_io);
              i2c_m_async_enable(&I2C_0);
              i2c_m_async_register_callback(&I2C_0, I2C_M_ASYNC_TX_COMPLETE, (FUNC_PTR)I2C_0_tx_complete);
              i2c_m_async_set_slaveaddr(&I2C_0, 0x12, I2C_M_SEVEN);
              io_write(I2C_0_io, I2C_0_example_str, 12);
          }
        

Dependencies

  • The I2C master peripheral and its related I/O lines and clocks

  • The NVIC must be configured so that I2C interrupt requests are periodically serviced