This driver provides APIs for the configuration and operation of the I2C hardware block. The I2C interface provides four operating modes:
- master transmitter mode
- master receiver mode
- slave transmitter mode
- 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:
- Interrupt based handling makes use of Chip_I2C_EventHandler handler.
- 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:
- I2C pin functions and the I2C mode are configured using Chip_IOCON_SetPinConfig.
- I2C block reset signal is de-asserted using Chip_SysCon_Peripheral_DeassertReset.
- I2C driver is initialized using Chip_I2C_Init.
- I2C clock rate is set using Chip_I2C_SetClockRate.
For I2C Master transfers:
- Set the event handling mechanism using Chip_I2C_SetMasterEventHandler for the master.
- Enable the I2C interrupt in NVIC using NVIC_EnableIRQ for interrupt based event handling.
- Fill in I2C_XFER_T structure if Chip_I2C_MasterTransfer API is used for I2C master transfer.
- Use one of the appropriate Master transfer API based on the type of transfer required.
For I2C Slave transfers:
- Fill in I2C_XFER_T structure for the slave transfer.
- Use the Chip_I2C_SlaveSetup to setup the I2C slave.
- 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:
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:
Setup and transfer of data:
slaveXfer.
rxBuff = &slaveRxData[0];
slaveXfer.
rxSz =
sizeof(slaveRxData) + 1;
slaveXfer.
txBuff = &slaveTxData[0];
slaveXfer.
txSz =
sizeof(slaveTxData);
|
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
} |
|
|
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) |
|
◆ 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
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
|
◆ I2C_EVENTHANDLER_T
◆ 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
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
|
◆ Chip_I2C_Init()
Initializes the NSS_I2C peripheral with specified parameter.
- Parameters
-
id | : I2C peripheral ID (I2C0) |
◆ Chip_I2C_DeInit()
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()
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()
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()
Set function that must handle I2C events
- Parameters
-
- 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()
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()
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()
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()
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.