Inter-Intergrated Circuit driver interface.
To use the I2C driver, ensure that the correct driver library for your device is linked in and include this header file as follows:
This module serves as the main interface for applications using an underlying I2C peripheral. Its purpose is to redirect the I2C APIs to device specific driver implementations which are specified using a pointer to a I2C_FxnTable.
This section assumes that you have prior knowledge about the I2C protocol. For the full I2C-bus specification and user manual, view the UM10204 document available online.
This I2C driver is designed to operate as an I2C master. This driver does not support I2C slave mode. This driver assumes it is the only I2C master on the I2C bus. Using the I2C APIs, you can transmit and recieve data over an I2C bus. The I2C-bus specification does not define how data is to be formatted or handled. This allows for flexible implementations across different peripheral vendors. As a result, this driver only performs the exchange of data between the master and slave(s). The application is responsible for manipulating and interpretting the data.
This driver has been designed to operate in a Real-Time Operating System (RTOS) environment. This driver protects data transactions with operating system primitives supplied by the underlying RTOS.
The following code example opens an I2C instance.
In order to use the I2C APIs, the application is required to provide device-specific I2C configuration in the Board.c file. The I2C driver interface defines a configuration data structure, I2C_Config.
The application must declare an array of I2C_Config elements, named I2C_config
[]. Each element of I2C_config
[] is populated with pointers to a device specific I2C driver implementation's function table, driver object, and hardware attributes. The hardware attributes define properties such as the I2C peripheral's base address and pins. Each element in I2C_config
[] corresponds to an I2C instance, and none of the elements should have NULL
pointers.
The I2C configuration is device dependent. You will need to check the device specific I2C driver documentation. There you will find a description of the I2C hardware attributes.
I2C_init() must be called before any other I2C APIs. This function calls the device specific implementation's I2C initialization function for each element of NVS_config
[].
After initializing the I2C driver by calling I2C_init(), the application can open an I2C instance by calling I2C_open(). This function takes an index into the I2C_config
[] array and an I2C_Params structure. The I2C_Handle returned from the I2C_open() is then associated with that index into the I2C_config
[] array.
This example shows opening an I2C driver instance in callback mode with a bit rate of 400kbps.
An I2C data transfer is performed using the I2C_transfer() function. Three types of transactions are supported: write, read, and write + read. The details of each transaction are specified with an I2C_Transaction structure. Each transfer is completed before another transfer is initiated.
For write + read transactions, the specified data is first written to the peripheral, then a repeated start is sent by the driver, which initiates the read operation. This type of transfer is useful if an I2C peripheral has a pointer register that needs to be adjusted prior to reading from the referenced data register.
The below example shows sending three bytes of data to a slave peripheral at address 0x50, in blocking mode:
The next example shows reading five bytes of data from the I2C peripheral, in blocking mode:
This example shows writing two bytes and reading four bytes in a single transaction.
This final example shows usage of asynchronous callback mode, with queuing of multiple transactions. Because multiple transactions are simultaneously queued, separate I2C_Transaction structures must be used.
First, the callback function specified by I2C_Params.transferCallbackFxn is created. In this example, the I2C_Transaction will contain a custom application argument. This argument will be a semaphore handle. The I2C_Transaction.arg will point to the semaphore handle. When the callback function is called, the I2C_Transaction.arg is checked for NULL
. If this value is not NULL
, then it can be assumed the arg
is pointing to a valid semaphore handle. The semaphore handle is then used to call sem_post()
. Hypothetically, this can be used to signal transaction completion to the task(s) that queued the transaction(s).
Snippets of the task code that initiates the transactions are shown below. Note the use of multiple I2C_Transaction structures. The handle of the semaphore to be posted is specified via i2cTransaction2.arg
. I2C_transfer() is called three times to initiate each transaction. Since callback mode is used, these functions return immediately. After the transactions have been queued, other work can be done. Eventually, sem_wait()
is called causing the task to block until the transaction completes. When the transaction completes, the application's callback callback function, callbackFxn
will be called. Once callbackFxn
above posts the semaphore the task will be unblocked and can resume execution.
This top-level I2C module serves as the main interface for RTOS applications. Its purpose is to redirect the module's APIs to specific peripheral implementations which are specified using a pointer to an I2C_FxnTable.
The I2C driver interface module is joined (at link time) to an array of I2C_Config data structures named I2C_config
. I2C_config
is typically defined in the Board.c file used for the application. If there are multiple instances of I2C peripherals on the device, there will typically be multiple I2C_Config structures defined in the board file in the form of an array. Each entry in I2C_config
contains a:
void
*) data object that is associated with the I2C_FxnTablevoid
*) hardware attributes that are associated to the I2C_FxnTable #include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
Go to the source code of this file.
Data Structures | |
struct | I2C_Transaction_ |
This structure defines the I2C slave address, pointers to write and read buffers, and their associated byte counts. If no data needs to be written, the write byte count should be zero. Similarly, if no data needs to be read, the read byte count should be set to zero. More... | |
struct | I2C_Params_ |
I2C Parameters. More... | |
struct | I2C_FxnTable_ |
The definition of an I2C function table that contains the required set of functions to control a specific I2C driver implementation. More... | |
struct | I2C_Config_ |
I2C global configuration. More... | |
Macros | |
#define | I2C_CMD_RESERVED (32) |
#define | I2C_STATUS_RESERVED (-32) |
#define | I2C_STATUS_SUCCESS (0) |
Successful status code returned by I2C_control(). More... | |
#define | I2C_STATUS_ERROR (-1) |
Generic error status code returned by I2C_control(). More... | |
#define | I2C_STATUS_UNDEFINEDCMD (-2) |
An error status code returned by I2C_control() for undefined command codes. More... | |
Typedefs | |
typedef struct I2C_Config_ * | I2C_Handle |
A handle that is returned from an I2C_open() call. More... | |
typedef struct I2C_Transaction_ | I2C_Transaction |
This structure defines the I2C slave address, pointers to write and read buffers, and their associated byte counts. If no data needs to be written, the write byte count should be zero. Similarly, if no data needs to be read, the read byte count should be set to zero. More... | |
typedef enum I2C_TransferMode_ | I2C_TransferMode |
This I2C driver supports two transfer modes of operation: blocking and callback. The transfer mode is specified using the I2C_Params structure. The transfer mode defines how the I2C_transfer() function behaves for a driver instance. More... | |
typedef void(* | I2C_CallbackFxn) (I2C_Handle handle, I2C_Transaction *transaction, bool transferStatus) |
I2C callback function prototype. The application is responsible for declaring a callback function when using I2C_MODE_CALLBACK. More... | |
typedef enum I2C_BitRate_ | I2C_BitRate |
Specifies one of the standard I2C bus bit rates for I2C communication. You must check that the device specific implementation supports the desired I2C_BitRate_. More... | |
typedef struct I2C_Params_ | I2C_Params |
I2C Parameters. More... | |
typedef void(* | I2C_CancelFxn) (I2C_Handle handle) |
A function pointer to a driver-specific implementation of I2C_cancel(). More... | |
typedef void(* | I2C_CloseFxn) (I2C_Handle handle) |
A function pointer to a driver-specific implementation of I2C_close(). More... | |
typedef int_fast16_t(* | I2C_ControlFxn) (I2C_Handle handle, uint_fast16_t cmd, void *controlArg) |
A function pointer to a driver-specific implementation of I2C_control(). More... | |
typedef void(* | I2C_InitFxn) (I2C_Handle handle) |
A function pointer to a driver-specific implementation of I2C_init(). More... | |
typedef I2C_Handle(* | I2C_OpenFxn) (I2C_Handle handle, I2C_Params *params) |
A function pointer to a driver-specific implementation of I2C_open(). More... | |
typedef bool(* | I2C_TransferFxn) (I2C_Handle handle, I2C_Transaction *transaction) |
A function pointer to a driver-specific implementation of I2C_transfer(). More... | |
typedef struct I2C_FxnTable_ | I2C_FxnTable |
The definition of an I2C function table that contains the required set of functions to control a specific I2C driver implementation. More... | |
typedef struct I2C_Config_ | I2C_Config |
I2C global configuration. More... | |
Enumerations | |
enum | I2C_TransferMode_ { I2C_MODE_BLOCKING, I2C_MODE_CALLBACK } |
This I2C driver supports two transfer modes of operation: blocking and callback. The transfer mode is specified using the I2C_Params structure. The transfer mode defines how the I2C_transfer() function behaves for a driver instance. More... | |
enum | I2C_BitRate_ { I2C_100kHz = 0, I2C_400kHz = 1, I2C_1000kHz = 2, I2C_3330kHz = 3 } |
Specifies one of the standard I2C bus bit rates for I2C communication. You must check that the device specific implementation supports the desired I2C_BitRate_. More... | |
Functions | |
void | I2C_cancel (I2C_Handle handle) |
Cancel all I2C transfers. More... | |
void | I2C_close (I2C_Handle handle) |
Close an I2C peripheral specified by an I2C_Handle. More... | |
int_fast16_t | I2C_control (I2C_Handle handle, uint_fast16_t cmd, void *controlArg) |
Perform implementation-specific features on a given I2C_Handle. More... | |
void | I2C_init (void) |
Initializes the I2C module. More... | |
I2C_Handle | I2C_open (uint_least8_t index, I2C_Params *params) |
Initialize a given I2C peripheral as identified by an index value. The I2C_Params structure defines the operating mode, and any related settings. More... | |
void | I2C_Params_init (I2C_Params *params) |
Initialize an I2C_Params structure to its default values. More... | |
bool | I2C_transfer (I2C_Handle handle, I2C_Transaction *transaction) |
Perform an I2C transaction with an I2C slave peripheral. More... | |
typedef struct I2C_Config_* I2C_Handle |
A handle that is returned from an I2C_open() call.
typedef struct I2C_Transaction_ I2C_Transaction |
This structure defines the I2C slave address, pointers to write and read buffers, and their associated byte counts. If no data needs to be written, the write byte count should be zero. Similarly, if no data needs to be read, the read byte count should be set to zero.
typedef enum I2C_TransferMode_ I2C_TransferMode |
This I2C driver supports two transfer modes of operation: blocking and callback. The transfer mode is specified using the I2C_Params structure. The transfer mode defines how the I2C_transfer() function behaves for a driver instance.
typedef void(* I2C_CallbackFxn) (I2C_Handle handle, I2C_Transaction *transaction, bool transferStatus) |
I2C callback function prototype. The application is responsible for declaring a callback function when using I2C_MODE_CALLBACK.
handle | Handle to the I2C instance that called the I2C_transfer(). |
transaction | Pointer to the I2C_Transaction that just completed. |
transferStatus | Result of the I2C transfer. |
typedef enum I2C_BitRate_ I2C_BitRate |
Specifies one of the standard I2C bus bit rates for I2C communication. You must check that the device specific implementation supports the desired I2C_BitRate_.
typedef struct I2C_Params_ I2C_Params |
I2C Parameters.
I2C parameters are used with the I2C_open() call. Default values for these parameters are set using I2C_Params_init().
typedef void(* I2C_CancelFxn) (I2C_Handle handle) |
A function pointer to a driver-specific implementation of I2C_cancel().
typedef void(* I2C_CloseFxn) (I2C_Handle handle) |
A function pointer to a driver-specific implementation of I2C_close().
typedef int_fast16_t(* I2C_ControlFxn) (I2C_Handle handle, uint_fast16_t cmd, void *controlArg) |
A function pointer to a driver-specific implementation of I2C_control().
typedef void(* I2C_InitFxn) (I2C_Handle handle) |
A function pointer to a driver-specific implementation of I2C_init().
typedef I2C_Handle(* I2C_OpenFxn) (I2C_Handle handle, I2C_Params *params) |
A function pointer to a driver-specific implementation of I2C_open().
typedef bool(* I2C_TransferFxn) (I2C_Handle handle, I2C_Transaction *transaction) |
A function pointer to a driver-specific implementation of I2C_transfer().
typedef struct I2C_FxnTable_ I2C_FxnTable |
The definition of an I2C function table that contains the required set of functions to control a specific I2C driver implementation.
typedef struct I2C_Config_ I2C_Config |
I2C global configuration.
The I2C_Config structure contains a set of pointers used to characterize the I2C driver implementation.
This structure needs to be defined before calling I2C_init() and it must not be changed thereafter.
enum I2C_TransferMode_ |
This I2C driver supports two transfer modes of operation: blocking and callback. The transfer mode is specified using the I2C_Params structure. The transfer mode defines how the I2C_transfer() function behaves for a driver instance.
Enumerator | |
---|---|
I2C_MODE_BLOCKING | In blocking mode, a task calling I2C_transfer() is blocked until the transaction completes. Other tasks requesting I2C transactions while a transaction is currently taking place, are also placed into a blocked state. |
I2C_MODE_CALLBACK | In callback mode, a task calling I2C_transfer() is not blocked. The application's callback function, I2C_Params.transferCallbackFxn, is called when the transaction is complete. The callback function will be called from either a hardware or software interrupt context. This depends on the device specific driver implementation. Sequential calls to I2C_transfer() will put I2C_Transaction structures onto an internal queue that automatically starts queued transactions after the previous transaction has completed. This queuing occurs regardless of any error state from previous transactions. The application callback function will be called as each transaction is completed. |
enum I2C_BitRate_ |
Specifies one of the standard I2C bus bit rates for I2C communication. You must check that the device specific implementation supports the desired I2C_BitRate_.
Enumerator | |
---|---|
I2C_100kHz | 100kbps |
I2C_400kHz | 400kbps |
I2C_1000kHz | 1Mbps |
I2C_3330kHz | 3.33Mbps |
void I2C_cancel | ( | I2C_Handle | handle | ) |
Cancel all I2C transfers.
This function will cancel asynchronous I2C_transfer() operations, and is applicable only for I2C_MODE_CALLBACK. An in progress transfer, as well as any queued transfers will be canceled. The individual callback functions for each transfer will be called from the context that I2C_cancel() is called.
handle | An I2C_Handle returned from I2C_open() |
void I2C_close | ( | I2C_Handle | handle | ) |
Close an I2C peripheral specified by an I2C_Handle.
handle | An I2C_Handle returned from I2C_open() |
int_fast16_t I2C_control | ( | I2C_Handle | handle, |
uint_fast16_t | cmd, | ||
void * | controlArg | ||
) |
Perform implementation-specific features on a given I2C_Handle.
Commands for I2C_control() can originate from I2C.h or from implementation specific I2C.h (I2CCC26XX.h_, I2CMSP432.h_, etc.) files. While commands from I2C.h are API portable across driver implementations, not all implementations may support all these commands. Conversely, commands from driver implementation specific I2C*.h files add unique driver capabilities but are not API portable across all I2C driver implementations.
Commands supported by I2C.h follow a I2C_CMD_<cmd> naming convention.
Commands supported by I2C.h follow a I2C_CMD_<cmd> naming convention.
Each control command defines arg differently. The types of arg are documented with each command.
See I2C_control command codes for command codes.
See I2C_control return status codes for status codes.
handle | An I2C_Handle returned from I2C_open() |
cmd | I2C.h or I2C*.h command. |
controlArg | An optional R/W (read/write) command argument accompanied with cmd |
void I2C_init | ( | void | ) |
Initializes the I2C module.
I2C_config
structure must exist and be persistent before this function can be called. This function must also be called before any other I2C driver APIs. This function call does not modify any peripheral registers. I2C_Handle I2C_open | ( | uint_least8_t | index, |
I2C_Params * | params | ||
) |
Initialize a given I2C peripheral as identified by an index value. The I2C_Params structure defines the operating mode, and any related settings.
index | Logical peripheral number for the I2C indexed into the I2C_config table |
params | Pointer to a parameter block. Default values will be used if NULL is specified for params . All the fields in this structure are are considered read-only. |
NULL
on an error, or if the peripheral is already opened.void I2C_Params_init | ( | I2C_Params * | params | ) |
Initialize an I2C_Params structure to its default values.
params | A pointer to I2C_Params structure for initialization. |
Defaults values are:
bool I2C_transfer | ( | I2C_Handle | handle, |
I2C_Transaction * | transaction | ||
) |
Perform an I2C transaction with an I2C slave peripheral.
This function will perform an I2C transfer, as specified by an I2C_Transaction structure.
An I2C transaction may write data to a peripheral, or read data from a peripheral, or both write and read data, in a single transaction. If there is any data to be written, it will always be sent before any data is read from the peripheral.
The data written to the peripheral is preceded with the peripheral's 7-bit I2C slave address (with the Write bit set). After all the data has been transmitted, the driver will evaluate if any data needs to be read from the device. If yes, another START bit is sent, along with the same 7-bit I2C slave address (with the Read bit). After the specified number of bytes have been read, the transfer is ended with a NACK and a STOP bit. Otherwise, if no data is to be read, the transfer is concluded with a STOP bit.
In I2C_MODE_BLOCKING, I2C_transfer() will block thread execution until the transaction completes. Therefore, this function must only be called from an appropriate thread context (e.g., Task context for the TI-RTOS kernel).
In I2C_MODE_CALLBACK, the I2C_transfer() call does not block thread execution. Instead, a callback function (specified during I2C_open(), via the transferCallbackFxn field in the I2C_Params structure) is called when the transfer completes. Success or failure of the transaction is reported via the I2C_CallbackFxn bool argument. If a transfer is already in progress, the new transaction is put on an internal queue. The driver services the queue in a first come first served basis.
handle | An I2C_Handle |
transaction | A pointer to an I2C_Transaction. All of the fields within the transaction structure should be considered write only, unless otherwise noted in the driver implementation. |
In I2C_MODE_CALLBACK: always true. The I2C_CallbackFxn bool
argument will be true to indicate success, and false to indicate an error.