RT685 I3C port in I2C mode - interrupt not occuring

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

RT685 I3C port in I2C mode - interrupt not occuring

Jump to solution
1,119 Views
dash
Contributor II

I have the I3C port in I2C mode. Polling mode iworks correctly, but I can not get interrupts to trigger.

 

static void i3c_master_ibi_callback(I3C_Type *base,
                                    i3c_master_handle_t *handle,
                                    i3c_ibi_type_t ibiType,
                                    i3c_ibi_state_t ibiState);
static void i3c_master_callback(I3C_Type *base, i3c_master_handle_t *handle, status_t status, void *userData);

/*******************************************************************************
 * Variables
 ******************************************************************************/
uint8_t g_master_txBuff[I3C_DATA_LENGTH];
uint8_t g_master_rxBuff[I3C_DATA_LENGTH];
i3c_master_config_t masterConfig;
i3c_master_transfer_t masterXfer;
uint8_t g_master_ibiBuff[10];
i3c_master_handle_t g_i3c_m_handle;
const i3c_master_transfer_callback_t masterCallback = {
    .slave2Master = NULL, .ibiCallback = i3c_master_ibi_callback, .transferComplete = i3c_master_callback};
volatile bool g_masterCompletionFlag = false;
volatile bool g_ibiWonFlag           = false;
volatile status_t g_completionStatus = kStatus_Success;
#define I3C_TIME_OUT_INDEX 100000000U


static void i3c_master_ibi_callback(I3C_Type *base,
                                    i3c_master_handle_t *handle,
                                    i3c_ibi_type_t ibiType,
                                    i3c_ibi_state_t ibiState)
{
    switch (ibiType)
    {
        case kI3C_IbiNormal:
            if (ibiState == kI3C_IbiDataBuffNeed)
            {
                handle->ibiBuff = g_master_ibiBuff;
            }
            else
            {
                /* Handle ibi data*/
            }
            break;

        default:
            assert(false);
            break;
    }
}

static void i3c_master_callback(I3C_Type *base, i3c_master_handle_t *handle, status_t status, void *userData)
{
    /* Signal transfer success when received success status. */
    if (status == kStatus_Success)
    {
        g_masterCompletionFlag = true;
    }

    if (status == kStatus_I3C_IBIWon)
    {
        g_ibiWonFlag = true;
    }

    g_completionStatus = status;
}

uint8_t imuGetRegCountNonBlocking(uint8_t subAdr, uint8_t * pVal, int count)
{
	status_t result = kStatus_Success;

	memset(&masterXfer, 0, sizeof(masterXfer));
    masterXfer.slaveAddress   = I3C_MASTER_SLAVE_ADDR_7BIT>>1;
    masterXfer.direction      = kI3C_Read;
    masterXfer.busType        = kI3C_TypeI2C;
    masterXfer.subaddress     = subAdr;
    masterXfer.subaddressSize = 1;
    masterXfer.data           = pVal;
    masterXfer.dataSize       = count;
    masterXfer.flags          = kI3C_TransferDefaultFlag; // kI3C_TransferDefaultFlag;

    result = I3C_MasterTransferNonBlocking(I3C_MASTER_BASE, &g_i3c_m_handle, &masterXfer);
    if (result != kStatus_Success)
    {
        PRINTF("Receive error 0x%02.2X\r\n", result);
    }
	return result;
}

/* Wait for transfer completed. */
uint8_t imuCheckCompletion(void)
{
	static uint32_t timeout = 0U;
	if  ((!g_ibiWonFlag) && (!g_masterCompletionFlag) && (g_completionStatus == kStatus_Success) &&
       (++timeout < I3C_TIME_OUT_INDEX))
	{
		return 0;
	}
	else
	{
		timeout = 0U;
		if ((g_completionStatus != kStatus_Success) || (timeout == I3C_TIME_OUT_INDEX))
		{
			return -1;
		}
	    g_masterCompletionFlag = false;
	}
	return 1;
}

/* init code */
    /* Attach main clock to I3C, 297MHz / 4 = 74.25MHz. */
    CLOCK_AttachClk(kMAIN_CLK_to_I3C_CLK);
    CLOCK_SetClkDiv(kCLOCK_DivI3cClk, 4);

    I3C_MasterGetDefaultConfig(&masterConfig);
    masterConfig.enableMaster = kI3C_MasterOn;
    masterConfig.baudRate_Hz.i2cBaud = I3C_MASTER_I2C_BAUDRATE;
    I3C_MasterInit(I3C_MASTER_BASE, &masterConfig, I3C_MASTER_CLOCK_FREQUENCY);

#ifdef IMU_INTERRUPT
    /* Create I3C handle. */
    I3C_MasterTransferCreateHandle(I3C_MASTER_BASE, &g_i3c_m_handle, &masterCallback, NULL);
#endif

/* runtime code */
			imuGetRegCountNonBlocking(LSM6DSV16X_FIFO_STATUS1, &((uint8_t *)&diff)[0], 2);
			while (imuCheckCompletion() == 0);

 

 

0 Kudos
1 Solution
1,060 Views
dash
Contributor II

Turns out I had an unrelated bug in my code causing me not to see the interrupt. Sorry for the waste of your time. Looking at nvic showed the interrupt being captured.

Yes I2C mode interrupts work on the I3C port.

View solution in original post

0 Kudos
3 Replies
1,061 Views
dash
Contributor II

Turns out I had an unrelated bug in my code causing me not to see the interrupt. Sorry for the waste of your time. Looking at nvic showed the interrupt being captured.

Yes I2C mode interrupts work on the I3C port.

0 Kudos
1,110 Views
Dezheng_Tang
NXP Employee
NXP Employee

I don't have the second rt600 EVK board with me. So, I tried to communicate with a on-board ICM42688 sensor, the interrupt does fire. In I3C_MasterTransferCreateHandle(), it installs MasterTransferHandleIRQ which is the ISR. If you happen to go in there, the interrupt ISR is working.

void I3C_MasterTransferCreateHandle(I3C_Type *base, i3c_master_handle_t *handle,
const i3c_master_transfer_callback_t *callback, void *userData)
{
.......

    /* Set irq handler. */
    s_i3cMasterIsr = I3C_MasterTransferHandleIRQ;

}

There could be a problem in I3C_RunTransferStateMachine() that the state machine is not working right in I2C interrupt mode. I will get back to you tomorrow.

 

 

 

 

1,100 Views
Dezheng_Tang
NXP Employee
NXP Employee

I used I3C driver from RT6xx SDK and communicated with the on-board ICM42688 sensor using I2c (RT6xx Audio EVK), it works fine.

Here are the change needed,

(1) masterXfer.busType = kI3C_TypeI3CSdr;
to
masterXfer.busType = kI3C_TypeI2C;

(2) Defined by the user, i3c_master_callback is needed. Our example works as seen below.

(3) Sensor Address must be 7-bit I2C address.

sensorConfig.sensorAddress = STATIC_I2C_ADDR;

(4) Call I3C_MasterTransferNonBlocking(EXAMPLE_MASTER, &g_i3c_m_handle, &masterXfer);

I monitored the bus, SCL and SDA are shown correctly. So, our SDK I3C handler handles both I2C and I3C correctly..

 Your parameter change looks good, the problem was, even if you give the wrong I2C slave address, interrupt should fire and your code should break in the beginning of the ISR. Since you mentioned that you didn't get any interrupt, please check NVIC if there is anything pending.


/*******************************************************************************
* Definitions
******************************************************************************/
#define EXAMPLE_MASTER I3C
#define EXAMPLE_I2C_BAUDRATE 400000
#define I3C_MASTER_CLOCK_FREQUENCY CLOCK_GetI3cClkFreq()
#define SENSOR_ADDR 0x09U
#define STATIC_I2C_ADDR 0x69U
#define I3C_TIME_OUT_INDEX 100000000U

/*******************************************************************************
* Prototypes
******************************************************************************/
static void i3c_master_ibi_callback(I3C_Type *base,
i3c_master_handle_t *handle,
i3c_ibi_type_t ibiType,
i3c_ibi_state_t ibiState);
static void i3c_master_callback(I3C_Type *base, i3c_master_handle_t *handle, status_t status, void *userData);
/*******************************************************************************
* Variables
******************************************************************************/
i3c_master_handle_t g_i3c_m_handle;
uint8_t g_ibiBuff[10U];
static uint8_t g_ibiUserBuff[10U];
static uint8_t g_ibiUserBuffUsed = 0;
static volatile bool g_masterCompletionFlag = false;
static volatile bool g_ibiWonFlag = false;
static volatile status_t g_completionStatus = kStatus_Success;
icm42688p_handle_t icmp42688p_handle;
/*******************************************************************************
* Code
******************************************************************************/
status_t I3C_WriteSensor(uint8_t deviceAddress, uint8_t regAddress, uint8_t *regData, size_t dataSize)
{
i3c_master_transfer_t masterXfer;
status_t result = kStatus_Success;
g_ibiWonFlag = false;
g_masterCompletionFlag = false;
g_completionStatus = kStatus_Success;

memset(&masterXfer, 0, sizeof(masterXfer));

/* Set register data */
masterXfer.slaveAddress = deviceAddress;
masterXfer.direction = kI3C_Write;
// masterXfer.busType = kI3C_TypeI3CSdr;
masterXfer.busType = kI3C_TypeI2C;
masterXfer.subaddress = regAddress;
masterXfer.subaddressSize = 1;
masterXfer.data = regData;
masterXfer.dataSize = dataSize;
masterXfer.flags = kI3C_TransferDefaultFlag;

result = I3C_MasterTransferNonBlocking(EXAMPLE_MASTER, &g_i3c_m_handle, &masterXfer);
if (kStatus_Success != result)
{
return result;
}

uint32_t timeout = 0U;
/* Wait for transfer completed. */
while ((!g_ibiWonFlag) && (!g_masterCompletionFlag))
{
timeout++;
if ((g_completionStatus != kStatus_Success) || (timeout > I3C_TIME_OUT_INDEX))
{
break;
}
__NOP();
}
result = g_completionStatus;
if (timeout == I3C_TIME_OUT_INDEX)
{
result = kStatus_Timeout;
}

return result;
}

status_t I3C_ReadSensor(uint8_t deviceAddress, uint8_t regAddress, uint8_t *regData, size_t dataSize)
{
i3c_master_transfer_t masterXfer;
status_t result = kStatus_Success;
g_ibiWonFlag = false;
g_masterCompletionFlag = false;
g_completionStatus = kStatus_Success;

memset(&masterXfer, 0, sizeof(masterXfer));

/* Set register data */
masterXfer.slaveAddress = deviceAddress;
masterXfer.direction = kI3C_Read;
// masterXfer.busType = kI3C_TypeI3CSdr;
masterXfer.busType = kI3C_TypeI2C;

masterXfer.subaddress = regAddress;
masterXfer.subaddressSize = 1;
masterXfer.data = regData;
masterXfer.dataSize = dataSize;
masterXfer.flags = kI3C_TransferDefaultFlag;

result = I3C_MasterTransferNonBlocking(EXAMPLE_MASTER, &g_i3c_m_handle, &masterXfer);

uint32_t timeout = 0U;
/* Wait for transfer completed. */
while ((!g_ibiWonFlag) && (!g_masterCompletionFlag))
{
timeout++;
if ((g_completionStatus != kStatus_Success) || (timeout > I3C_TIME_OUT_INDEX))
{
break;
}
__NOP();
}
result = g_completionStatus;
if (timeout == I3C_TIME_OUT_INDEX)
{
result = kStatus_Timeout;
}

return result;
}

static void i3c_master_ibi_callback(I3C_Type *base,
i3c_master_handle_t *handle,
i3c_ibi_type_t ibiType,
i3c_ibi_state_t ibiState)
{
switch (ibiType)
{
case kI3C_IbiNormal:
if (ibiState == kI3C_IbiDataBuffNeed)
{
handle->ibiBuff = g_ibiBuff;
}
else
{
memcpy(g_ibiUserBuff, (void *)handle->ibiBuff, handle->ibiPayloadSize);
g_ibiUserBuffUsed = handle->ibiPayloadSize;
}
break;

default:
assert(false);
break;
}
}

static void i3c_master_callback(I3C_Type *base, i3c_master_handle_t *handle, status_t status, void *userData)
{
/* Signal transfer success when received success status. */
if (status == kStatus_Success)
{
g_masterCompletionFlag = true;
}

if (status == kStatus_I3C_IBIWon)
{
g_ibiWonFlag = true;
}

g_completionStatus = status;
}

static const i3c_master_transfer_callback_t masterCallback = {
.slave2Master = NULL, .ibiCallback = i3c_master_ibi_callback, .transferComplete = i3c_master_callback};

/*!
* @brief Main function
*/
int main(void)
{
i3c_master_config_t masterConfig;
status_t result = kStatus_Success;

/* Attach main clock to I3C, 500MHz / 20 = 25MHZ. */
CLOCK_AttachClk(kMAIN_CLK_to_I3C_CLK);
CLOCK_SetClkDiv(kCLOCK_DivI3cClk, 20);

BOARD_InitBootPins();
BOARD_BootClockRUN();
BOARD_InitDebugConsole();

PRINTF("\r\nI3C master read sensor data example.\r\n");

I3C_MasterGetDefaultConfig(&masterConfig);
masterConfig.baudRate_Hz.i2cBaud = EXAMPLE_I2C_BAUDRATE;
masterConfig.baudRate_Hz.i3cPushPullBaud = 12500000U;
masterConfig.baudRate_Hz.i3cOpenDrainBaud = 4000000U;
masterConfig.enableOpenDrainStop = false;
I3C_MasterInit(EXAMPLE_MASTER, &masterConfig, I3C_MASTER_CLOCK_FREQUENCY);

I3C_MasterTransferCreateHandle(EXAMPLE_MASTER, &g_i3c_m_handle, &masterCallback, NULL);

#if I2C_SENSOR_READING
icm42688p_config_t sensorConfig;
sensorConfig.Sensor_WriteTransfer = (sensor_write_transfer_func_t)I3C_WriteSensor;
sensorConfig.Sensor_ReadTransfer = (sensor_read_transfer_func_t)I3C_ReadSensor;
sensorConfig.sensorAddress = STATIC_I2C_ADDR;
sensorConfig.isReset = true;

result = ICM42688P_Init(&icmp42688p_handle, &sensorConfig);
if (result != kStatus_Success)
{
PRINTF("\r\nSensor reset failed.\r\n");
return -1;
}
result = ICM42688P_EnableSensors(&icmp42688p_handle);
if (result != kStatus_Success)
{
PRINTF("\r\nSensor enable failed.\r\n");
return -1;
}

#endif