AM263Px MCU+ SDK: I2C Low Level Driver

| AM263Px MCU+ SDK 26.00.00 |

I2C Low Level Driver

# Features Supported

- Controller and Target mode of Operation.
- Interrupt, Polled Mode.
- Non-blocking (Callback) Transfer.
- 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 parameters like bitrate, Own target address.
- 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

- DMA Mode Operation.

# 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 may call the following APIs:

- I2C_lld_init(): Initialize the I2C LLD Instance.
- I2C_lld_deInit(): De-initialize the I2C LLD instance.
- I2C_lld_Transaction_init(): Fill Default Value in Transaction object.
- I2C_lld_Message_init(): Fill Default Value in Message object.
- I2C_lld_write() / I2C_lld_writeIntr(): Write data as Controller in polling and interrupt mode respectively.
- I2C_lld_target_write() / I2C_lld_target_writeIntr(): Write data as Target in polling and interrupt mode respectively.
- I2C_lld_read() / I2C_lld_readIntr(): Read data as Controller in polling and interrupt mode respectively.
- I2C_lld_target_read() / I2C_lld_target_readIntr(): Read data as Target in polling and interrupt mode respectively.
- I2C_lld_mem_write() / I2C_lld_mem_writeIntr(): Write data to internal memory of i2c device in polling and interrupt mode respectively.
- I2C_lld_mem_read() / I2C_lld_mem_readIntr(): Read data from the internal memory of i2c device in polling and interrupt mode respectively.
- I2C_lld_transferPoll() / I2C_lld_transferIntr(): Read and Write data in polling and interrupt mode respectively.
- I2C_lld_targetTransferIntr(): Read and Write data as target device in interrupt mode.
- I2C_lld_probe(): Probe I2C Target.
- I2C_lld_setBusFrequency(): Set Bus frequency.

## Initializing the I2C LLD Driver

I2C_lld_init() must be called before any other I2C APIs. 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. Though, handle can be re-used the instance is closed using I2C_lld_deInit().

Please note that the initialization of I2C LLD instances 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 files to access the APIs

#include <kernel/dpl/DebugP.h>
#include <kernel/dpl/HwiP.h>
#include <kernel/dpl/MutexArmP.h>
#include <kernel/nortos/dpl/r5/HwiP_armv7r_vim.h>
#include <drivers/i2c/v1/lld/i2c_lld.h>

Instance Open Example

int32_t status = I2C_STS_SUCCESS;
gI2cLldHandle0 = (I2CLLD_Handle)(&gI2cLldObjects[CONFIG_I2CLLD0]);
status = I2C_lld_init(gI2cLldHandle0);
DebugP_assert(status == I2C_STS_SUCCESS);

Instance Close Example

int32_t status = I2C_STS_SUCCESS;
status = I2C_lld_deInit(gI2cLldHandle0);
DebugP_assert(status == I2C_STS_SUCCESS);

Non-Blocking Transfer Example

int32_t status = I2C_STS_SUCCESS;
uint8_t wrData[2U];
/* Interrupt configuration and registration*/
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);
DebugP_log("I2C LED Blink Test Started ...\r\n");
/* Assign Transfer Complete Callback Function */
gI2cLldHandle0->transferCompleteCallback = I2C_lld_transferCompleteCallback_implementation;
/* Register Interrupt */
HwiP_setVecAddr(intrNum, (uintptr_t)&App_I2C_ISR);
HwiP_setPri(intrNum, I2C_INTERRUPT_PRIORITY);
HwiP_enableInt(intrNum);
/* Set mask */
wrData[0U] = TPIC2810_CMD_WR_IMMEDIATE;
wrData[1U] = (uint8_t) (LED_SET_ALL);
/* Initialize transaction object */
I2C_lld_Transaction_init(&i2cTransaction);
i2cTransaction.writeBuf = &wrData[0U];
i2cTransaction.writeCount = 2U;
/* Initialize message object */
I2C_lld_Message_init(&i2cMsg);
i2cMsg.txn = &i2cTransaction;
i2cMsg.txnCount = 1U;
i2cMsg.targetAddress = deviceAddress;
/* Lock Mutex */
gI2CTransferMutex = MUTEX_ARM_LOCKED;
/* Start Transfer in interrupt Mode */
status = I2C_lld_transferIntr(gI2cLldHandle0, &i2cMsg);
/* Wait for the Mutex to Unlock */
while(try_lock_mutex(&gI2CTransferMutex) == MUTEX_ARM_LOCKED);
if(I2C_STS_SUCCESS != status)
{
DebugP_assert(FALSE); /* I2C transfer failed!! */
}
/* Deregister IRQ */
HwiP_setVecAddr(intrNum, 0);
HwiP_disableInt(intrNum);
if(I2C_STS_SUCCESS == status)
{
DebugP_log("All tests have passed!!\r\n");
}
else
{
DebugP_log("Some tests have failed!!\r\n");
}

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)
{
ISR_CALL_LEVEL_NONFLOAT_REENTRANT(I2C_lld_controllerIsr, \
gI2cLldHandle0, \
intrNum, \
gI2cVimStsAddr, \
gI2cVimStsClrMask,
intcBaseAddr);
}

# API

APIs for I2C LLD

args
void * args
Definition: hsmclient_msg.h:4
I2C_lld_Transaction_init
int32_t I2C_lld_Transaction_init(I2CLLD_Transaction *transaction)
API to set default values of I2CLLD_Transaction in transaction.
I2C_lld_Message_init
int32_t I2C_lld_Message_init(I2CLLD_Message *msg)
API to set default values of I2CLLD_Message in msg.
i2c_lld.h
I2C LLD Driver API/interface file.
HwiP_disableInt
uint32_t HwiP_disableInt(uint32_t intNum)
Disable a specific interrupt.
I2C_Transaction::writeBuf
const void * writeBuf
Definition: i2c.h:233
I2CLLD_Message
I2C Message.
Definition: i2c_lld.h:305
I2C_Transaction::targetAddress
uint32_t targetAddress
Definition: i2c.h:247
DebugP_log
#define DebugP_log(format,...)
Function to log a string to the enabled console.
Definition: DebugP.h:235
__attribute__
struct lld_sockaddr __attribute__
This is the SecureBoot Stream type which holds the data for a specific bootloader to HSM call....
HwiP.h
HwiP_enableInt
void HwiP_enableInt(uint32_t intNum)
Enable a specific interrupt.
I2C_lld_transferIntr
int32_t I2C_lld_transferIntr(I2CLLD_Handle handle, I2CLLD_Message *msg)
API to initiate a transfer from I2C in interrupt mode.
I2C_lld_init
int32_t I2C_lld_init(I2CLLD_Handle handle)
API to Initializes the I2C instance.
DebugP.h
I2C_Transaction::writeCount
size_t writeCount
Definition: i2c.h:236
I2C_lld_controllerIsr
void I2C_lld_controllerIsr(void *args)
I2C Controller ISR, can be used as IRQ handler in Controller mode.
DebugP_assert
#define DebugP_assert(expression)
Function to call for assert check.
Definition: DebugP.h:187
I2C_STS_SUCCESS
#define I2C_STS_SUCCESS
Return status when the API execution was successful.
Definition: i2c_lld.h:84
I2C_lld_deInit
int32_t I2C_lld_deInit(I2CLLD_Handle handle)
API to De-Initializes the I2C instance.
I2CLLD_Handle
struct I2CLLD_Object * I2CLLD_Handle