2. I2C Adapters Concept

This section explains the procedure to enable and correctly configure the peripheral adapters for I2C functionality. The procedure is a three-step process which can be applied to almost every type of adapter including serial peripheral adapters (SPI, UART) and GPADC adapters.

'The Three-Step Process for Setting the |I2C| Adapter Mechanism'

Figure 1 The Three-Step Process for Setting the |I2C| Adapter Mechanism

2.1. Preparing the I2C Adapter

  1. The first step for configuring the I2C adapter mechanism is to enable it by defining the following macros in /config/custom_config_xxx.h file:

 * Macros for enabling I2C operations using Adapters
#define dg_configUSE_HW_I2C                     (1)
#define dg_configI2C_ADAPTER                    (1)
#define dg_configI2C_ADAPTER_SLAVE_SUPPORT      (1)

From this point onwards, the overall Adapters layer with all its integrated functionality is available.

  1. The second step is to declare IO bus as well as driver configurations for all the devices externally connected on the I2C bus. These settings are applied every time the slave I2C device is selected and used. All the configurations should be placed in platform_devices.c file.

3. Once the I2C adapter mechanism is enabled, the developer can use all the available APIs for performing I2C transactions. The following steps describe the required sequence of APIs in an application to successfully execute an I2C write/read operation.

  1. ad_i2c_open()

    Before using the I2C interface, the application task must open the device that will access the I2C block. Opening a device involves acquiring all the required resources as well as configuring the I2C controller with the target device and IO bus settings. This function returns a handler to the main flow for use in subsequent adapter functions.

    Note that this function will block until all required resources (GPIOs, DMA and I2C controller) are successfully acquired.

  2. Master initiates a write/read transaction either synchronously or asynchronously.

    After opening a device, the master task can perform any read/write I2C transaction either synchronously or asynchronously. In synchronous mode, the calling task is blocked for the duration of the write/read transaction but other tasks are not. In asynchronous mode, the calling task is not blocked by the write or read operation and thus the application task can continue with other operations while waiting for a user-defined callback function to be called, signalling the completion of the I2C transaction.

    • User-defined callback functions are called from within Interrupt Service Routine (ISR) context.

      Therefore, callback’s execution time should be as short as possible and not contain complex calculations. Please note that for as long as a system interrupt is serviced, the main application is halted.

    • Do not call asynchronous related APIs consecutively without guaranteeing that the previous asynchronous transaction is finished.

  3. Start slave transmission/reception.

    When I2C is configured in slave mode, the function ‘’ad_i2c_start_slave()’’ sets up input and/or output buffers to use for master initiated transmission and/or reception. It also specifies user callbacks that will be called when transmission or reception starts or finishes.

    If the user specifies valid (wbuf, wlen) pair, data will be sent on incoming read request from master. After reception, data_sent() callback will be called. If wbuf is NULL or wlen is 0, read_request() callback will be called to notify the user aboutmaster read request.

    If (rbuf, rlen) pair is specified, data will be received when master starts writing. When data is received, callback data_received() will be called. If rbuf is NULL or rlen is 0, data_ready() callback will be called to notify user about master write. If the user fails to read from the Rx FIFO before it becomes full then data loss may occur.

  1. ad_i2c_close()

    After all user operations are done and the device is no longer needed, it should be closed. This step involves disabling and de-initializing the I2C block used as well as releasing all the previously acquired resources.


All the write/read I2C related APIs return a code which can be used to indicate whether an I2C operation has been successfully executed or not. All the possible values are declared in HW_I2C_ABORT_SOURCE enum located in \sdk\peripherals\include\hw_i2c.h.


For more detailed information on the I2C APIs please refer to sdk\adapters\include\ad_template.h file.