3. Analyzing The Demonstration Example

This section analyzes an application example which demonstrates using the I2C adapters. The example is based on the freertos_retarget sample code found in the SDK. It adds an additional freeRTOS task which is responsible for controlling an external I2C module, connected on I2C1 bus. It also enables the wake-up timer for handling external events. Both synchronous and asynchronous I2C operations are demonstrated.

3.1. Application Structure

  1. The key goal of this demonstration is for the device to perform a few I2C operations following an event. For demonstration purposes, the K1 button on the Pro DevKit has been configured as a wake-up input pin. For more detailed information on how to configure and set a pin for handling external events, read the External Interruption tutorial. At each external event (produced at every K1 button press), a dedicated callback function named wkup_cb() is triggered. In this function, a variable named i2c_status is toggled. It can take two different values which are interpreted as follows:

  • i2c_status = 1
    • An asynchronous I2C write operation is attempted. A whole page of 64 bytes is written in EEPROM starting from the physical address 0x0000. Note that the page size of an EEPROM is device-specific and we recommend reading the manufacturer datasheet for more information on this. At the end of the transaction, a debugging message is printed on the serial console indicating whether or not the I2C operation was successfully executed.
'EEPROM Write SW FSM - Main Execution Path'

Fig. 8 EEPROM Write SW FSM - Main Execution Path

  • i2c_status = 0
    • Depending on the value of the I2C_ASYNC_EN macro, a synchronous or asynchronous I2C read operation is attempted. A whole page of 64 bytes is read from EEPROM starting from the physical address 0x0000. In fact, the program attempts to read the previously written data in EEPROM. At the end of the transaction, a debugging message is printed on the serial console indicating whether or not the I2C operation was successfully executed. In addition, a data integrity check is performed and a corresponding debugging message is also printed on the serial console.
'EEPROM Read SW FSM - Main Execution Path'

Fig. 9 EEPROM Read SW FSM - Main Execution Path

  1. The I2C_ASYNC_EN macro can be used to enable asynchronous I2C read operations. As described in I2C Transactions, developers must not call asynchronous related APIs without guaranteeing that the previous asynchronous transaction is finished. To ensure this, after calling the ad_i2c_async_transact() function, the code waits for the arrival of a signal, indicating the end of the current I2C operation.
'EEPROM Async Read SW FSM - Callback Function Execution Path'

Fig. 10 EEPROM Asynch Read SW FSM - Callback function Execution Path

  1. At this point, it is important to highlight one peculiarity encountered in EEPROM devices. Data sent from a master device to an EEPROM slave device is actually written in EEPROM cells after a STOP condition is issued by the master. At this point, the EEPROM starts its write cycle for storing the previous written data to its memory cells. This means that the code should not continue with the next write/read cycle without guaranteeing that the EEPROM device is ready to handle a new command. To ensure this, the function poll_ack() is called after a successful I2C write operation. For more information on how to poll the EEPROM device to check its readiness, read the Acknowledge Polling section in the manufacturer datasheet.

Note

The 24LC256 EEPROM module has been selected for demonstration purposes only. Providing complete drivers for this module is out of the scope of this tutorial.