Features Supported
- Controller and Target mode of operation
- Interrupt, Polled Mode
- Non-blocking (callback) transfers
- I2C Bus Recovery
SysConfig Features
- Note
- It is strongly recommend to use SysConfig where it is available instead of using direct SW API calls. This will help simplify the SW application and also catch common mistakes early in the development cycle.
SysConfig can be used to configure below parameters apart from common configuration like Clock,MPU,RAT and others.
- I2C module configuration parmaters like bitrate, target addresses to probe.
- I2C instances and pin configurations.
- Based on above parameters, the SysConfig generated code does below as part of Drivers_open and Drivers_close functions
- Set I2C instance parameter configuration.
Features NOT Supported
- Target mode is not supported in polling mode.
Usage Overview
API Sequence
To use the I2C LLD driver to transmit/receive data over the I2C bus, probe target and set bus frequency the application calls the following APIs:
Initializing the I2C LLD Driver
I2C_lld_init() must be called before any other I2C APIs. This function iterates till the channel count. This function uses i2c lld handle to initialize each instance.
Calling I2C_lld_init() a second time with the same handle previously passed to I2C_lld_init() will result in an error. You can, though, re-use the handle if the instance is closed via I2C_lld_deInit().
Please note that initializing I2C LLD driver is taken care by the SysConfig generated code.
I2C Transfer Mode
The I2C driver supports two transfer modes of operation: Polling and Interrupt Mode.
In Polling mode transfer can be initiated with all the polling mode APIs
In Interrupt mode Users have to register the appropriate ISR and assign a callback function before calling the interrupt mode APIs
Example Usage
Include the below file to access the APIs
#include <kernel/dpl/MutexArmP.h>
#include <kernel/nortos/dpl/r5/HwiP_armv7r_vim.h>
Instance Open Example
gI2cLldHandle0 = (
I2CLLD_Handle)(&gI2cLldObjects[CONFIG_I2CLLD0]);
Instance Close Example
Non-Blocking Transfer Example
uint8_t wrData[2U];
intrNum = gI2cLldHandle0->intrNum;
gI2cLldHandle0 = (
I2CLLD_Handle)(&gI2cLldObjects[CONFIG_I2CLLD0]);
intrNum = gI2cLldHandle0->intrNum;
intcBaseAddr = gHwiConfig.intcBaseAddr;
gI2cVimStsAddr = intcBaseAddr + (0x404u + (((intrNum)>> 5) & 0xFu) * 0x20u);
gI2cVimStsClrMask = 0x1u << ((intrNum) & 0x1Fu);
gI2cLldHandle0->transferCompleteCallback = I2C_lld_transferCompleteCallback_implementation;
HwiP_setVecAddr(intrNum, (uintptr_t)&App_I2C_ISR);
HwiP_setPri(intrNum, I2C_INTERRUPT_PRIORITY);
wrData[0U] = TPIC2810_CMD_WR_IMMEDIATE;
wrData[1U] = (uint8_t) (LED_SET_ALL);
i2cMsg.txn = &i2cTransaction;
i2cMsg.txnCount = 1U;
gI2CTransferMutex = MUTEX_ARM_LOCKED;
while(try_lock_mutex(&gI2CTransferMutex) == MUTEX_ARM_LOCKED);
{
}
HwiP_setVecAddr(intrNum, 0);
{
}
else
{
}
Non-Blocking Example transfer callback
void I2C_lld_transferCompleteCallback_implementation(
void * args,
const I2CLLD_Message * msg, int32_t transferStatus)
{
unlock_mutex(&gI2CTransferMutex);
}
Non-Blocking Example ISR CALL callback
static __attribute__((__section__(
".text.hwi"), noinline, naked, target(
"arm"), aligned(4))) void App_I2C_ISR(
void)
{
gI2cLldHandle0, \
intrNum, \
gI2cVimStsAddr, \
gI2cVimStsClrMask,
intcBaseAddr);
}
API
APIs for I2C LLD