SimpleLink MCU SDK Driver APIs  tidrivers_msp43x_3_01_01_03
Data Structures | Macros | Typedefs | Enumerations | Functions
I2C.h File Reference

Detailed Description

I2C driver interface.


The I2C driver interface provides device independent APIs, data types, and macros. The I2C header file should be included in an application as follows:

#include <ti/drivers/I2C.h>

Overview

This section assumes that you have background knowledge and understanding about how the I2C protocol operates. For the full I2C specifications and user manual (UM10204), see the NXP Semiconductors website.

The I2C driver has been designed to operate as a single I2C master by performing I2C transactions between the target and I2C slave peripherals. The I2C driver does not support I2C slave mode. I2C is a communication protocol - the specifications define how data transactions are to occur via the I2C bus. The specifications do not define how data is to be formatted or handled, allowing for flexible implementations across different peripheral vendors. As a result, the I2C handles only the exchange of data (or transactions) between master and slaves. It is the left to the application to interpret and manipulate the contents of each specific I2C peripheral.

The I2C driver has been designed to operate in an RTOS environment. It protects its transactions with OS primitives supplied by the underlying RTOS.

Usage

The I2C driver includes the following APIs:

I2C Driver Configuration

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:

typedef struct I2C_Config_ {
void *object;
void const *hwAttrs;

The application must declare an array of I2C_Config elements, named I2C_config[]. Each element of I2C_config[] must be 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. There is no correlation between the index and the peripheral designation (such as I2C0 or I2C1). For example, it is possible to use I2C_config[0] for I2C1.

Because the I2C configuration is very device dependent, you will need to check the doxygen for the device specific I2C implementation. There you will find a description of the I2C hardware attributes. Please also refer to the Board.c file of any of your examples to see the I2C configuration.

Initializing the I2C Driver

I2C_init() must be called before any other I2C APIs. This function iterates through the elements of the I2C_config[] array, calling the element's device implementation I2C initialization function.

I2C Parameters

The I2C_Params structure is passed to the I2C_open() call. If NULL is passed for the parameters, I2C_open() uses default parameters. An I2C_Params structure is initialized with default values by passing it to I2C_Params_init(). Some of the I2C parameters are described below. To see brief descriptions of all the parameters, see I2C_Params.

I2C Transfer Mode

The I2C driver supports two transfer modes of operation: blocking and callback:

The transfer mode is determined by the I2C_Params.transferMode parameter passed to I2C_open(). The I2C driver defaults to blocking mode, if the application does not set it.

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.

In callback mode, an I2C_transfer() functions asynchronously, which means that it does not block a calling task's execution. In this mode, the user must set I2C_Params.transferCallbackFxn to a user- provided callback function. After an I2C transaction has completed, the I2C driver calls the user- provided callback function. If another I2C transaction is requested, the transaction is queued up. As each transfer completes, the I2C driver will call the user-specified callback function. The user callback will be called from either hardware or software interrupt context, depending upon the device implementation.

Once an I2C driver instance is opened, the only way to change the transfer mode is to close and re-open the I2C instance with the new transfer mode.

Specifying an I2C Bus Frequency

The I2C controller's bus frequency is determined by I2C_Params.bitRate passed to I2C_open(). The standard I2C bus frequencies are 100 kHz and 400 kHz, with 100 kHz being the default.

Opening the I2C Driver

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 parameters data structure. The I2C instance is specified by the index of the I2C in I2C_config[]. Only one I2C index can be used at a time; calling I2C_open() a second time with the same index previosly passed to I2C_open() will result in an error. You can, though, re-use the index if the instance is closed via I2C_close().

If no I2C_Params structure is passed to I2C_open(), default values are used. If the open call is successful, it returns a non-NULL value.

Example opening an I2C driver instance in blocking mode:

// NULL params are used, so default to blocking mode, 100 KHz
i2c = I2C_open(Board_I2C0, NULL);
if (!i2c) {
// Error opening the I2C
}

Example opening an I2C driver instance in callback mode and 400KHz bit rate:

I2C_Params params;
I2C_Params_init(&params);
params.transferCallbackFxn = myCallbackFunction;
handle = I2C_open(Board_I2C0, &params);
if (!i2c) {
// Error opening I2C
}

Transferring data

An I2C transaction with an I2C peripheral is started by calling I2C_transfer(). Three types of transactions are supported: Write, Read, or Write/Read. 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 details of each transaction are specified with an I2C_Transaction data structure. This structure defines the slave I2C address, pointers to write and read buffers, and their associated byte counts. If no data needs to be written or read, the corresponding byte counts should be set to zero.

If an I2C transaction is requested while a transaction is currently taking place, the new transaction is placed onto a queue to be processed in the order in which it was received.

The below example shows sending three bytes of data to a slave peripheral at address 0x50, in blocking mode:

unsigned char writeBuffer[3];
I2C_Transaction i2cTransaction;
i2cTransaction.slaveAddress = 0x50;
i2cTransaction.writeBuf = writeBuffer;
i2cTransaction.writeCount = 3;
i2cTransaction.readBuf = NULL;
i2cTransaction.readCount = 0;
status = I2C_transfer(i2c, &i2cTransaction);
if (!status) {
// Unsuccessful I2C transfer
}

The next example shows reading of five bytes of data from the I2C peripheral, also in blocking mode:

unsigned char readBuffer[5];
I2C_Transaction i2cTransaction;
i2cTransaction.slaveAddress = 0x50;
i2cTransaction.writeBuf = NULL;
i2cTransaction.writeCount = 0;
i2cTransaction.readBuf = readBuffer;
i2cTransaction.readCount = 5;
status = I2C_transfer(i2c, &i2cTransaction);
if (!status) {
// Unsuccessful I2C transfer
}

This example shows writing of two bytes and reading of four bytes in a single transaction.

unsigned char readBuffer[4];
unsigned char writeBuffer[2];
I2C_Transaction i2cTransaction;
i2cTransaction.slaveAddress = 0x50;
i2cTransaction.writeBuf = writeBuffer;
i2cTransaction.writeCount = 2;
i2cTransaction.readBuf = readBuffer;
i2cTransaction.readCount = 4;
status = I2C_transfer(i2c, &i2cTransaction);
if (!status) {
// Unsuccessful I2C transfer
}

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. (This is a general rule, that I2C_Transaction structures cannot be reused until it is known that the previous transaction has completed.)

First, for the callback function (that is specified in the I2C_open() call) the "arg" in the I2C_Transaction structure is a SemaphoreP_Handle; when this value is non-NULL, SemaphoreP_post() is called in the callback using the specified handle, to signal completion to the task that queued the transactions:

Void callbackFxn(I2C_Handle handle, I2C_Transaction *msg, Bool transfer) {
if (msg->arg != NULL) {
SemaphoreP_post((SemaphoreP_Handle)(msg->arg));
}
}

Snippets of the task code that initiates the transactions are shown below. Note the use of multiple I2C_Transaction structures, and passing of the handle of the semaphore to be posted 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, and then eventually SemaphoreP_pend() is called to wait for the last I2C transaction to complete. Once the callback posts the semaphore, the task will be moved to the ready state, so the task can resume execution, after the SemaphoreP_pend() call.

Void taskfxn(arg0, arg1) {
I2C_Transaction i2cTransaction0;
I2C_Transaction i2cTransaction1;
I2C_Transaction i2cTransaction2;
...
i2cTransaction0.arg = NULL;
i2cTransaction1.arg = NULL;
i2cTransaction2.arg = semaphoreHandle;
...
I2C_transfer(i2c, &i2cTransaction0);
I2C_transfer(i2c, &i2cTransaction1);
I2C_transfer(i2c, &i2cTransaction2);
...
SemaphoreP_pend(semaphoreHandle);
...
}

Implementation

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. Each entry in I2C_config contains a:

#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
Include dependency graph for I2C.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  I2C_Transaction_
 I2C transaction. 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
 I2C transaction. More...
 
typedef enum I2C_TransferMode_ I2C_TransferMode
 I2C transfer mode. More...
 
typedef void(* I2C_CallbackFxn) (I2C_Handle handle, I2C_Transaction *transaction, bool transferStatus)
 I2C callback function. More...
 
typedef enum I2C_BitRate_ I2C_BitRate
 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
}
 I2C transfer mode. More...
 
enum  I2C_BitRate_ {
  I2C_100kHz = 0,
  I2C_400kHz = 1
}
 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 struct to its defaults. More...
 
bool I2C_transfer (I2C_Handle handle, I2C_Transaction *transaction)
 Perform an I2C transaction with an I2C slave peripheral. More...
 

Typedef Documentation

typedef struct I2C_Config_* I2C_Handle

A handle that is returned from an I2C_open() call.

I2C transaction.

This structure defines an I2C transaction. It specifies the buffer(s) and buffer size(s) to be written to and/or read from an I2C slave peripheral. arg is an optional user-supplied argument that will be passed to the user-supplied callback function when the I2C driver is in I2C_MODE_CALLBACK. nextPtr is a pointer used internally by the driver for queuing of multiple transactions; this value must never be modified by the user application.

I2C transfer mode.

I2C_MODE_BLOCKING blocks task execution while an I2C transfer is in progress. I2C_MODE_CALLBACK does not block task execution, but calls a callback function when the I2C transfer has completed.

typedef void(* I2C_CallbackFxn) (I2C_Handle handle, I2C_Transaction *transaction, bool transferStatus)

I2C callback function.

User-definable callback function prototype. The I2C driver will call this callback upon transfer completion, specifying the I2C handle for the transfer (as returned from I2C_open()), the pointer to the I2C_Transaction that just completed, and the return value of I2C_transfer(). Note that this return value will be the same as if the transfer were performed in blocking mode.

Parameters
I2C_HandleI2C_Handle
I2C_Transaction*Address of the I2C_Transaction
boolResult of the I2C transfer
typedef enum I2C_BitRate_ I2C_BitRate

I2C bitRate.

Specifies one of the standard I2C bus bit rates for I2C communications. The default is I2C_100kHz.

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().

If I2C_TransferMode is set to I2C_MODE_BLOCKING, I2C_transfer() function calls will block thread execution until the transaction has completed. In this case, the transferCallbackFxn parameter will be ignored.

If I2C_TransferMode is set to I2C_MODE_CALLBACK, I2C_transfer() will not block thread execution, but it will call the function specified by transferCallbackFxn upon transfer completion. Sequential calls to I2C_transfer() in I2C_MODE_CALLBACK will put the 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.

I2C_BitRate specifies the I2C bus rate used for I2C communications.

See also
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.

See also
I2C_init()

Enumeration Type Documentation

I2C transfer mode.

I2C_MODE_BLOCKING blocks task execution while an I2C transfer is in progress. I2C_MODE_CALLBACK does not block task execution, but calls a callback function when the I2C transfer has completed.

Enumerator
I2C_MODE_BLOCKING 

I2C_transfer() blocks execution

I2C_MODE_CALLBACK 

I2C_transfer() does not block

I2C bitRate.

Specifies one of the standard I2C bus bit rates for I2C communications. The default is I2C_100kHz.

Enumerator
I2C_100kHz 
I2C_400kHz 

Function Documentation

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.

Precondition
I2C_Transfer() has been called.
Parameters
handleAn I2C_Handle returned from I2C_open()
Note
Different I2C slave devices will behave differently when an in-progress transfer fails and needs to be canceled. The slave may need to be reset, or there may be other slave-specific steps that can be used to successfully resume communication.
See also
I2C_transfer()
void I2C_close ( I2C_Handle  handle)

Close an I2C peripheral specified by an I2C_Handle.

Precondition
I2C_open() has been called.
Parameters
handleAn I2C_Handle returned from I2C_open()
See also
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.

Precondition
I2C_open() has to be called first.
Parameters
handleAn I2C_Handle returned from I2C_open()
cmdI2C.h or I2C*.h command.
controlArgAn optional R/W (read/write) command argument accompanied with cmd
Returns
Implementation-specific return codes. Negative values indicate unsuccessful operations.
See also
I2C_open()
void I2C_init ( void  )

Initializes the I2C module.

Precondition
The 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.

Precondition
The I2C controller has been initialized, via a previous call to I2C_init()
Parameters
indexLogical peripheral number for the I2C indexed into the I2C_config table
paramsPointer to a parameter block. Default values will be used if NULL is specified for params. All the fields in this structure are are considered RO (read-only).
Returns
An I2C_Handle on success, or NULL on an error, or if the peripheral is already opened.
See also
I2C_init()
I2C_close()
void I2C_Params_init ( I2C_Params params)

Initialize an I2C_Params struct to its defaults.

Parameters
paramsA pointer to I2C_Params structure for initialization

Defaults values are: transferMode = I2C_MODE_BLOCKING transferCallbackFxn = NULL bitRate = I2C_100kHz

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 callback function's 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.

Parameters
handleAn I2C_Handle
transactionA 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.
Note
The I2C_Transaction structure must persist unmodified until the corresponding call to I2C_transfer() has completed.
Returns
In I2C_MODE_BLOCKING: true for a successful transfer; false for an error (for example, an I2C bus fault (NACK)).

In I2C_MODE_CALLBACK: always true. The transferCallbackFxn's bool argument will be true to indicate success, and false to indicate an error.

See also
I2C_open
Copyright 2016, Texas Instruments Incorporated