NHS31xx SW API
i2c: I2C driver

Detailed Description

This driver provides APIs for the configuration and operation of the I2C hardware block. The I2C interface provides four operating modes:

  1. master transmitter mode
  2. master receiver mode
  3. slave transmitter mode
  4. slave receiver mode

The I2C-bus interface is byte oriented. This driver supports both polled or interrupt based operation.
This I2C block is capable of addressing four slaves.

IOCON configuration for I2C:
The I2C-bus pins (IOCON_PIO0_4 and IOCON_PIO0_5) must be configured for the I2C Standard/ Fast-mode (IOCON_FUNC_1). See IO Configuration driver iocon: IO Configuration driver for details.

I2C Clock rates:
Details on clock rates that can be used for I2C communication can be referred from SW Clock Restrictions.
Note
During driver initialization (Chip_I2C_Init), there is no implicit check that the system clock/bitrate combination meets the clock restriction requirements. It is up to the caller to ensure that the respective restrictions are met.
The I2C clock is derived from system clock. Changing the system clock frequency affects the I2C bitrate, hence it must be re-set using Chip_I2C_SetClockRate to ensure the required rate is set.
I2C Master Event Handling:
The I2C master supports two event handling mechanisms which can be configured using Chip_I2C_SetMasterEventHandler:
  1. Interrupt based handling makes use of Chip_I2C_EventHandler handler.
  2. Polling based handling makes use of Chip_I2C_EventHandlerPolling handler.
The user can also implement an own handler using Chip_I2C_SetMasterEventHandler to perform specific actions for specific events (I2C_EVENT_T).
To use this driver:
I2C Driver is initialized as follows:
  1. I2C pin functions and the I2C mode are configured using Chip_IOCON_SetPinConfig.
  2. I2C block reset signal is de-asserted using Chip_SysCon_Peripheral_DeassertReset.
  3. I2C driver is initialized using Chip_I2C_Init.
  4. I2C clock rate is set using Chip_I2C_SetClockRate.
For I2C Master transfers:
  1. Set the event handling mechanism using Chip_I2C_SetMasterEventHandler for the master.
  2. Enable the I2C interrupt in NVIC using NVIC_EnableIRQ for interrupt based event handling.
  3. Fill in I2C_XFER_T structure if Chip_I2C_MasterTransfer API is used for I2C master transfer.
  4. Use one of the appropriate Master transfer API based on the type of transfer required.
For I2C Slave transfers:
  1. Fill in I2C_XFER_T structure for the slave transfer.
  2. Use the Chip_I2C_SlaveSetup to setup the I2C slave.
  3. Enable the I2C interrupt in NVIC using NVIC_EnableIRQ.
Example 1 - Configuring I2C as Master and use transfer (send/receive) API
  • Master mode
  • System clock: 4000000 and I2C clock: 100000
  • Target SlaveAddr: 0x7f
  • Operating mode: Interrupt based
  • API used for send and receive: Chip_I2C_MasterTransfer
Note
User can select appropriate System and I2C clocks as mentioned at I2C clock rates.

Tx and Rx data structures:

uint8_t masterTxData[4] = {0x31, 0x34, 0x61, 0x95};
uint8_t masterRxData[4] = {0, 0, 0, 0};

Setup and transfer of data:

Chip_IOCON_Init(NSS_IOCON); /* Is normally already called during board initialization. */
Chip_I2C_SetMasterEventHandler(I2C0, Chip_I2C_EventHandler); /* Using the default I2C event handler */
I2C_XFER_T masterXfer;
masterXfer.slaveAddr = 0x7F;
masterXfer.rxBuff = masterRxData;
masterXfer.rxSz = sizeof(masterRxData);
masterXfer.txBuff = masterTxData;
masterXfer.txSz = sizeof(masterTxData);
I2C IRQ Handler
Note
This IRQ Handler is common for Example 1 and Example 2.
Example 2 - Configuring I2C as Slave and transfer data
  • Slave mode
  • System clock: 4000000 and I2C clock: 100000
  • SlaveAddr: 0x7f
  • Operating mode: Interrupt based
  • API used for slave setup: Chip_I2C_SlaveSetup
  • Slave event handler: Example2_I2cSlaveEventHandler
Note
User can select appropriate System and I2C clocks as mentioned at I2C clock rates.

Tx, Rx and I2C transfer data structures:

uint8_t slaveTxData[4] = {0xA8, 0x01, 0xC5, 0x9D};
uint8_t slaveRxData[4] = {0, 0, 0, 0};

Slave event handler:

void Example2_I2cSlaveEventHandler(I2C_ID_T id, I2C_EVENT_T event)
{
/* Perform custom slave event handling */
}

Setup and transfer of data:

Chip_IOCON_Init(NSS_IOCON); /* Is normally already called during board initialization. */
static I2C_XFER_T slaveXfer;
slaveXfer.slaveAddr = 0x7F << 1;
slaveXfer.rxBuff = &slaveRxData[0];
slaveXfer.rxSz = sizeof(slaveRxData) + 1; /* +1: the address byte is counted but not copied to rxBuff */
slaveXfer.txBuff = &slaveTxData[0];
slaveXfer.txSz = sizeof(slaveTxData);
Chip_I2C_SlaveSetup(I2C0, I2C_SLAVE_0, &slaveXfer, Example2_I2cSlaveEventHandler, 0);

Data Structures

struct  NSS_I2C_T
 
struct  I2C_XFER_T
 

Typedefs

typedef void(* I2C_EVENTHANDLER_T) (I2C_ID_T, I2C_EVENT_T)
 

Enumerations

enum  I2C_SLAVE_ID {
  I2C_SLAVE_GENERAL,
  I2C_SLAVE_0,
  I2C_SLAVE_1,
  I2C_SLAVE_2,
  I2C_SLAVE_3,
  I2C_SLAVE_NUM_INTERFACE
}
 
enum  I2C_STATUS_T {
  I2C_STATUS_DONE,
  I2C_STATUS_NAK,
  I2C_STATUS_ARBLOST,
  I2C_STATUS_BUSERR,
  I2C_STATUS_BUSY
}
 
enum  I2C_ID_T {
  I2C0,
  I2C_NUM_INTERFACE
}
 
enum  I2C_EVENT_T {
  I2C_EVENT_WAIT = 1,
  I2C_EVENT_DONE,
  I2C_EVENT_LOCK,
  I2C_EVENT_UNLOCK,
  I2C_EVENT_SLAVE_RX,
  I2C_EVENT_SLAVE_TX
}
 

Functions

void Chip_I2C_Init (I2C_ID_T id)
 
void Chip_I2C_DeInit (I2C_ID_T id)
 
void Chip_I2C_SetClockRate (I2C_ID_T id, uint32_t clockrate)
 
uint32_t Chip_I2C_GetClockRate (I2C_ID_T id)
 
I2C_STATUS_T Chip_I2C_MasterTransfer (I2C_ID_T id, I2C_XFER_T *xfer)
 
int Chip_I2C_MasterSend (I2C_ID_T id, uint8_t slaveAddr, const uint8_t *buff, int len)
 
int Chip_I2C_MasterCmdRead (I2C_ID_T id, uint8_t slaveAddr, uint8_t *cmdBuff, uint8_t *buff, int len)
 
I2C_EVENTHANDLER_T Chip_I2C_GetMasterEventHandler (I2C_ID_T id)
 
int Chip_I2C_SetMasterEventHandler (I2C_ID_T id, I2C_EVENTHANDLER_T event)
 
int Chip_I2C_MasterRead (I2C_ID_T id, uint8_t slaveAddr, uint8_t *buff, int len)
 
void Chip_I2C_EventHandlerPolling (I2C_ID_T id, I2C_EVENT_T event)
 
void Chip_I2C_EventHandler (I2C_ID_T id, I2C_EVENT_T event)
 
void Chip_I2C_MasterStateHandler (I2C_ID_T id)
 
void Chip_I2C_Disable (I2C_ID_T id)
 
int Chip_I2C_IsMasterActive (I2C_ID_T id)
 
void Chip_I2C_SlaveSetup (I2C_ID_T id, I2C_SLAVE_ID sid, I2C_XFER_T *xfer, I2C_EVENTHANDLER_T event, uint8_t addrMask)
 
void Chip_I2C_SlaveStateHandler (I2C_ID_T id)
 
int Chip_I2C_IsStateChanged (I2C_ID_T id)
 

Data Structure Documentation

◆ NSS_I2C_T

struct NSS_I2C_T

I2C register block structure.

Data Fields
__IO uint32_t CONSET

I2C Control Set Register. When a one is written to a bit of this register, the corresponding bit in the I2C control register is set. Writing a zero has no effect on the corresponding bit in the I2C control register.

__I uint32_t STAT

I2C Status Register. During I2C operation, this register provides detailed status codes that allow software to determine the next action needed.

__IO uint32_t DAT

I2C Data Register. During master or slave transmit mode, data to be transmitted is written to this register. During master or slave receive mode, data that has been received can be read from this register.

__IO uint32_t ADR0

I2C Slave Address Register 0. Contains the 7-bit slave address for operation of the I2C interface in slave mode, and is not used in master mode. The least significant bit determines whether a slave responds to the General Call address.

__IO uint32_t SCLH

SCH Duty Cycle Register High Half Word. Determines the high time of the I2C clock.

__IO uint32_t SCLL

SCL Duty Cycle Register Low Half Word. Determines the low time of the I2C clock. SCLL and SCLH together determine the clock frequency generated by an I2C master and certain times used in slave mode.

__O uint32_t CONCLR

I2C Control Clear Register. When a one is written to a bit of this register, the corresponding bit in the I2C control register is cleared. Writing a zero has no effect on the corresponding bit in the I2C control register.

__IO uint32_t MMCTRL

Monitor mode control register.

__IO uint32_t ADR1

I2C Slave Address Register. Contains the 7-bit slave address for operation of the I2C interface in slave mode, and is not used in master mode. The least significant bit determines whether a slave responds to the General Call address.

__IO uint32_t ADR2

I2C Slave Address Register. Contains the 7-bit slave address for operation of the I2C interface in slave mode, and is not used in master mode. The least significant bit determines whether a slave responds to the General Call address.

__IO uint32_t ADR3

I2C Slave Address Register. Contains the 7-bit slave address for operation of the I2C interface in slave mode, and is not used in master mode. The least significant bit determines whether a slave responds to the General Call address.

__I uint32_t DATA_BUFFER

Data buffer register. The contents of the 8 MSBs of the DAT shift register will be transferred to the DATA_BUFFER automatically after every nine bits (8 bits of data plus ACK or NACK) has been received on the bus.

__IO uint32_t MASK[4]

I2C Slave address mask register

◆ I2C_XFER_T

struct I2C_XFER_T

Transfer data structure definition. For usage in master transfer, refer to Chip_I2C_MasterTransfer. For usage in slave transfer, refer to Chip_I2C_SlaveSetup.

Data Fields
uint8_t slaveAddr

7-bit I2C Slave address

const uint8_t * txBuff

Pointer to array of bytes to be transmitted

int txSz

Positive value indicating number of bytes in transmit array, if 0 only reception will be carried on

uint8_t * rxBuff

Pointer to memory where bytes received from I2C will be stored

int rxSz

Positive value indicating number of bytes to be received, if 0 only transmission will be carried on

I2C_STATUS_T status

Status of the current I2C transfer, this is read only for user

Typedef Documentation

◆ I2C_EVENTHANDLER_T

typedef void(* I2C_EVENTHANDLER_T) (I2C_ID_T, I2C_EVENT_T)

Event handler function type. Use this prototype if you want to define your own event handler using Chip_I2C_SetMasterEventHandler.

Enumeration Type Documentation

◆ I2C_SLAVE_ID

I2C Slave Identifiers.

Enumerator
I2C_SLAVE_GENERAL 

Slave ID for general calls

I2C_SLAVE_0 

Slave ID for Slave Address 0

I2C_SLAVE_1 

Slave ID for Slave Address 1

I2C_SLAVE_2 

Slave ID for Slave Address 2

I2C_SLAVE_3 

Slave ID for Slave Address 3

I2C_SLAVE_NUM_INTERFACE 

Number of slave interfaces. Not to be used as a slave ID. Use this for loops or to define array sizes.

◆ I2C_STATUS_T

I2C transfer status.

Enumerator
I2C_STATUS_DONE 

Transfer done successfully, used for Master and Slave transfers

I2C_STATUS_NAK 

NAK received during transfer, used for Master transfer

I2C_STATUS_ARBLOST 

Arbitration lost during transfer, used for Master transfer

I2C_STATUS_BUSERR 

Bus error in I2C transfer, used for Master transfer

I2C_STATUS_BUSY 

I2C is busy doing transfer, used for Master and Slave transfers

◆ I2C_ID_T

enum I2C_ID_T

I2C interface IDs.

Enumerator
I2C0 

ID I2C0, all Chip functions will take this as the first parameter

I2C_NUM_INTERFACE 

Number of I2C interfaces in the chip, must never be used for calling any Chip functions

◆ I2C_EVENT_T

I2C events. Provides information on the type of event to the event handler functions (I2C_EVENTHANDLER_T).

Enumerator
I2C_EVENT_WAIT 

I2C Wait event, triggered when waiting for the status (I2C_STATUS_T) to update

I2C_EVENT_DONE 

Done event that wakes up Wait event, triggered when master transactions for slave are completed

I2C_EVENT_LOCK 

Re-entrancy lock event for I2C transfer, triggered at the beginning of a Master transfer

I2C_EVENT_UNLOCK 

Re-entrancy unlock event for I2C transfer, triggered on completion of a Master transfer

I2C_EVENT_SLAVE_RX 

Slave receive event, triggered on reception of data in Slave

I2C_EVENT_SLAVE_TX 

Slave transmit event, triggered after data transmitted from Slave

Function Documentation

◆ Chip_I2C_Init()

void Chip_I2C_Init ( I2C_ID_T  id)

Initializes the NSS_I2C peripheral with specified parameter.

Parameters
id: I2C peripheral ID (I2C0)

◆ Chip_I2C_DeInit()

void Chip_I2C_DeInit ( I2C_ID_T  id)

De-initializes the I2C peripheral registers to their default reset values

Parameters
id: I2C peripheral ID (I2C0)

◆ Chip_I2C_SetClockRate()

void Chip_I2C_SetClockRate ( I2C_ID_T  id,
uint32_t  clockrate 
)

Set up clock rate for NSS_I2C peripheral.

Parameters
id: I2C peripheral ID (I2C0)
clockrate: Target clock rate value to initialize I2C peripheral (Hz)
Note
Parameter clockrate for I2C0 must be from 1000 up to 400000 (1 KHz to 400 KHz), as I2C0 supports Fast Mode.
Refer to I2C clock rates for I2C clock restrictions.

◆ Chip_I2C_GetClockRate()

uint32_t Chip_I2C_GetClockRate ( I2C_ID_T  id)

Get current clock rate for NSS_I2C peripheral.

Parameters
id: I2C peripheral ID (I2C0)
Returns
The current I2C peripheral clock rate

◆ Chip_I2C_MasterTransfer()

I2C_STATUS_T Chip_I2C_MasterTransfer ( I2C_ID_T  id,
I2C_XFER_T xfer 
)

Transmit and Receive data in master mode

Parameters
id: I2C peripheral selected (I2C0)
xfer: Pointer to a I2C_XFER_T structure. Details of structure members is captured below:
  • slaveAddr : 7-Bit slave address to which the master will do the transfer, bit0 to bit6 should have the address and bit7 is ignored.
  • txBuff : pointer to the memory from which to pick the data to be transfered to slave
  • txSz : number of bytes to send
  • rxBuff : pointer to the memory where data received from slave is to be stored
  • rxSz : number of bytes to get from slave
Refer to I2C_XFER_T for additional information.
Returns
Any of I2C_STATUS_T values, I2C_XFER_T.txSz will have number of bytes not sent due to error, I2C_XFER_T.rxSz will have the number of bytes yet to be received.
Note
During the transfer, program execution (like event handler) must not change the content of the memory pointed to by xfer.
Alternate implementations for Master transfers can be referred from Chip_I2C_MasterSend and Chip_I2C_MasterRead.

◆ Chip_I2C_MasterSend()

int Chip_I2C_MasterSend ( I2C_ID_T  id,
uint8_t  slaveAddr,
const uint8_t *  buff,
int  len 
)

Transmit data to I2C slave using I2C Master mode

Parameters
id: I2C peripheral ID (I2C0)
slaveAddr: Slave address to which the data be written
buff: Pointer to buffer having the array of data
len: Number of bytes to be transfered from buff
Returns
Number of bytes successfully transfered

◆ Chip_I2C_MasterCmdRead()

int Chip_I2C_MasterCmdRead ( I2C_ID_T  id,
uint8_t  slaveAddr,
uint8_t *  cmdBuff,
uint8_t *  buff,
int  len 
)

Transfer a command to slave and receive data from slave after a repeated start

Parameters
id: I2C peripheral ID (I2C0)
slaveAddr: Slave address of the I2C device
cmdBuff: Pointer to command buffer of size one byte
buff: Pointer to memory that will hold the data received
len: Number of bytes to receive
Returns
Number of bytes successfully received
Note
This is a specific implementation of Master transfer where a specific command can be send by the Master to invoke a pre-defined behavior from the Slave.

◆ Chip_I2C_GetMasterEventHandler()

I2C_EVENTHANDLER_T Chip_I2C_GetMasterEventHandler ( I2C_ID_T  id)

Get pointer to current function handling the events

Parameters
id: I2C peripheral ID (I2C0)
Returns
Pointer to function handing events of I2C
Note
The user can also implement an own handler using Chip_I2C_SetMasterEventHandler API.

◆ Chip_I2C_SetMasterEventHandler()

int Chip_I2C_SetMasterEventHandler ( I2C_ID_T  id,
I2C_EVENTHANDLER_T  event 
)

Set function that must handle I2C events

Parameters
id: I2C peripheral ID (I2C0)
event: Pointer to function that will handle the event, I2C_EVENTHANDLER_T
Returns
1 when successful, 0 when a transfer is on going with its own event handler
Note
event should not be NULL
Live swap of event handlers is not tested.

◆ Chip_I2C_MasterRead()

int Chip_I2C_MasterRead ( I2C_ID_T  id,
uint8_t  slaveAddr,
uint8_t *  buff,
int  len 
)

Receive data from I2C slave using I2C Master mode

Parameters
id: I2C peripheral ID (I2C0)
slaveAddr: Slave address from which data be read
buff: Pointer to memory where data read be stored
len: Number of bytes to read from slave
Returns
Number of bytes read successfully

◆ Chip_I2C_EventHandlerPolling()

void Chip_I2C_EventHandlerPolling ( I2C_ID_T  id,
I2C_EVENT_T  event 
)

Default event handler for polling operation

Parameters
id: I2C peripheral ID (I2C0)
event: Event ID of the event that called the function
Note
This is the default handler for polling mode where only the I2C_EVENT_WAIT state is handled.

◆ Chip_I2C_EventHandler()

void Chip_I2C_EventHandler ( I2C_ID_T  id,
I2C_EVENT_T  event 
)

Default event handler for interrupt based operation

Parameters
id: I2C peripheral ID (I2C0)
event: Event ID of the event that called the function
Note
This is the default handler for interrupt mode where only the I2C_EVENT_WAIT state is handled.

◆ Chip_I2C_MasterStateHandler()

void Chip_I2C_MasterStateHandler ( I2C_ID_T  id)

I2C Master transfer state change handler

Parameters
id: I2C peripheral ID (I2C0)
Note
In case of interrupt based operation, this function is to be invoked from the interrupt handler. For the polling based operation, this function is implicitly invoked from Chip_I2C_EventHandlerPolling.

◆ Chip_I2C_Disable()

void Chip_I2C_Disable ( I2C_ID_T  id)

Disable I2C peripheral's operation

Parameters
id: I2C peripheral ID (I2C0)

◆ Chip_I2C_IsMasterActive()

int Chip_I2C_IsMasterActive ( I2C_ID_T  id)

Checks if master transfer in progress

Parameters
id: I2C peripheral ID (I2C0)
Returns
1 if master transfer in progress, 0 for slave transfer
Note
This API is generally used in interrupt handler of the application to decide whether to call master state handler or to call slave state handler

◆ Chip_I2C_SlaveSetup()

void Chip_I2C_SlaveSetup ( I2C_ID_T  id,
I2C_SLAVE_ID  sid,
I2C_XFER_T xfer,
I2C_EVENTHANDLER_T  event,
uint8_t  addrMask 
)

Setup a slave I2C device

Parameters
id: I2C peripheral ID (I2C0)
sid: I2C Slave peripheral ID (I2C_SLAVE_ID)
xfer: Pointer to transfer structure (I2C_XFER_T). Details of structure members is captured below:
  • slaveAddr : 7 bit Slave address (from bit1 to bit7), bit0 when set enables general call handling. This along with addrMask will be used to match the slave address.
  • txBuff : pointer to valid buffers where slave can send data from
  • txSz : size of txBuff
  • rxBuff : pointer to valid buffers where slave can receive data from
  • rxSz : size of rxBuff
event: Event handler for slave transfers (I2C_EVENTHANDLER_T)
addrMask: Address mask to use along with slave address, see notes below for more info
Note
Parameter xfer should point to a valid I2C_XFER_T structure object.
Function pointed to by event will be called for the following events: Bit-0 of the parameter addrMask is reserved and should always be 0. Any bit (BIT1 to BIT7) set in addrMask will make the corresponding bit in I2C_XFER_T.slaveAddr as don't care, that is, if I2C_XFER_T.slaveAddr is (0x10 << 1) and addrMask is (0x03 << 1) then 0x10, 0x11, 0x12, 0x13 will all be considered as valid slave addresses for the registered slave. Upon receiving any event I2C_XFER_T.slaveAddr (BIT1 to BIT7) will hold the actual address which was received from master.

General Call Handling
Slave can receive data from master using general call address (0x00). General call handling must be setup as given below
  • Call Chip_I2C_SlaveSetup() with argument sid as I2C_SLAVE_GENERAL
  • To handle General Call only (No other slaves are configured)
    • Call Chip_I2C_SlaveSetup() with sid as I2C_SLAVE_X (X=0,1,2,3)
    • setup xfer with slaveAddr member set to 0, event is ignored hence can be NULL
    • provide addrMask (typically 0, if not you better be knowing what you are doing)
  • To handle General Call when other slave is active
    • Call Chip_I2C_SlaveSetup() with sid as I2C_SLAVE_X (X=0,1,2,3)
    • setup xfer with slaveAddr member set to 7-Bit Slave address [from Bit1 to 7]
    • Set Bit0 of xfer->slaveAddr as 1
    • Provide appropriate addrMask
    • Argument event must point to function, that handles events from actual slaveAddress and not the GC
Warning
If the slave has only one byte left in its I2C_XFER_T.txBuff, once that byte is transfered to master the event handler will be called for event I2C_EVENT_DONE. If the master attempts to read more bytes in the same transfer then the slave hardware will send 0xFF to master till the end of transfer, event handler will not be called to notify this. For more info see section below

Last data handling in slave
If the user wants to implement a slave which will read a byte from a specific location over and over again whenever master reads the slave. If the user initializes the I2C_XFER_T.txBuff as the location to read the byte from and I2C_XFER_T.txSz as 1, then say, if master reads one byte; slave will send the byte read from I2C_XFER_T.txBuff and will call the event handler with I2C_EVENT_DONE. If the master attempts to read another byte instead of sending the byte read from I2C_XFER_T.txBuff the slave hardware will send 0xFF and no event will occur. To handle this issue, slave should set I2C_XFER_T.txSz to 2, in which case when master reads the byte event handler will be called with I2C_EVENT_SLAVE_TX, in which the slave implementation can reset the buffer and size back to original location (i.e, I2C_XFER_T.txBuff–, I2C_XFER_T.txSz++), if the master reads another byte in the same transfer, byte read from I2C_XFER_T.txBuff will be sent and I2C_EVENT_SLAVE_TX will be called again, and the process repeats.

◆ Chip_I2C_SlaveStateHandler()

void Chip_I2C_SlaveStateHandler ( I2C_ID_T  id)

I2C Slave event handler

Parameters
id: I2C peripheral ID (I2C0)

◆ Chip_I2C_IsStateChanged()

int Chip_I2C_IsStateChanged ( I2C_ID_T  id)

I2C peripheral state change checking

Parameters
id: I2C peripheral ID (I2C0)
Returns
1 if I2C peripheral id has changed its state, 0 if there is no state change
Note
This function is applicable for polling mode and must be used by the application when the polling has to be done based on state change.