LPC55S36 I3C Slave Issue Handling Custom CCC with No Data

取消
显示结果 
显示  仅  | 搜索替代 
您的意思是: 
已解决

LPC55S36 I3C Slave Issue Handling Custom CCC with No Data

跳至解决方案
1,378 次查看
bell_huang
Contributor III

Two LPC5536-EVK boards were connected for I3C communication, with one configured as the I3C Master and the other as the I3C Slave.
When the Master sends a custom CCC with a data length of 0, the Slave misses to receive the kI3C_SlaveCompletionEvent.

 

Notes:

  • In the sample code I provided, please refer to the I3C_BusMasterCustomCCC function, where cmd.dataSize = 0; indicates the data length.
  • The CCC waveform output from the Master has been verified and is correct.

  • If the CCC includes data with length greater than 0, the Slave is able to receive the kI3C_SlaveCompletionEvent as expected.

 

Case: data length = 1

// Private Write
transfers[7]. event: TransmitEvent
transfers[8]. event: AddressMatchEvent
transfers[9]. event: ReceiveEvent
transfers[10]. event: CompletionEvent. status: 0, count: 6

// Private Read
transfers[0]. event: TransmitEvent
transfers[1]. event: AddressMatchEvent
transfers[2]. event: ReceiveEvent
transfers[3]. event: TransmitEvent
transfers[4]. event: AddressMatchEvent
transfers[5]. event: CompletionEvent. status: 0, count: 5

// Custom CCC
transfers[0]. event: TransmitEvent
transfers[1]. event: TransmitEvent
transfers[2]. event: ReceivedCCCEvent
transfers[3]. event: AddressMatchEvent
transfers[4]. event: ReceiveEvent
transfers[5]. event: CompletionEvent. status: 0, count: 1

// Private Write
transfers[0]. event: TransmitEvent
transfers[1]. event: AddressMatchEvent
transfers[2]. event: ReceiveEvent
transfers[3]. event: CompletionEvent. status: 0, count: 6

// Private Read
transfers[0]. event: TransmitEvent
transfers[1]. event: AddressMatchEvent
transfers[2]. event: ReceiveEvent
transfers[3]. event: TransmitEvent
transfers[4]. event: AddressMatchEvent
transfers[5]. event: CompletionEvent. status: 0, count: 5

 

Case: data length = 0

// Private Write
transfers[7]. event: TransmitEvent
transfers[8]. event: AddressMatchEvent
transfers[9]. event: ReceiveEvent
transfers[10]. event: CompletionEvent. status: 0, count: 6

// Private Read
transfers[0]. event: TransmitEvent
transfers[1]. event: AddressMatchEvent
transfers[2]. event: ReceiveEvent
transfers[3]. event: TransmitEvent
transfers[4]. event: AddressMatchEvent
transfers[5]. event: CompletionEvent. status: 0, count: 5

// Private Write (mix with some events from previous Custom CCC)
transfers[0]. event: TransmitEvent
transfers[1]. event: TransmitEvent
transfers[2]. event: TransmitEvent
transfers[3]. event: ReceivedCCCEvent
transfers[4]. event: AddressMatchEvent
transfers[5]. event: ReceiveEvent
transfers[6]. event: ReceiveEvent
transfers[7]. event: CompletionEvent. status: 0, count: 0

// Private Read
transfers[0]. event: TransmitEvent
transfers[1]. event: AddressMatchEvent
transfers[2]. event: ReceiveEvent
transfers[3]. event: TransmitEvent
transfers[4]. event: AddressMatchEvent
transfers[5]. event: CompletionEvent. status: 0, count: 5

0 项奖励
回复
1 解答
873 次查看
Harry_Zhang
NXP Employee
NXP Employee

Hi @bell_huang 

Thanks for your information.

I have tested it.

I tested it based on the 

Case 2: I3C_MasterTransferNonBlocking (from fsl_i3c API)

uint8_t cmdId = 0xF0;

memset(&masterXfer, 0, sizeof(masterXfer));
masterXfer.slaveAddress = 0x7E;
masterXfer.data         = &cmdId;
masterXfer.dataSize     = 1;
masterXfer.direction    = kI3C_Write;
masterXfer.busType      = kI3C_TypeI3CSdr;
masterXfer.flags        = (uint32_t)kI3C_TransferNoStopFlag;
g_masterCompletionFlag = false;
I3C_MasterTransferNonBlocking(EXAMPLE_MASTER, &masterHandle, &masterXfer);
while (!g_masterCompletionFlag)
{
    __NOP();
}
if (g_completionStatus != kStatus_Success)
    PRINTF("I3C_MasterTransferNonBlocking Write cmdId failed: %d\r\n", g_completionStatus);


uint8_t data[10];
memset(data, 0, sizeof(data));
data[0] = 0x01;
data[1] = 0x02;
data[2] = 0x03;

memset(&masterXfer, 0, sizeof(masterXfer));
masterXfer.slaveAddress = slaveAddr;
masterXfer.data         = data;
masterXfer.dataSize     = 0;
masterXfer.direction    = kI3C_Write;
masterXfer.busType      = kI3C_TypeI3CSdr;
masterXfer.flags        = (uint32_t)kI3C_TransferRepeatedStartFlag;
g_masterCompletionFlag = false;
I3C_MasterTransferNonBlocking(EXAMPLE_MASTER, &masterHandle, &masterXfer);
while (!g_masterCompletionFlag)
{
    __NOP();
}
if (g_completionStatus != kStatus_Success)
    PRINTF("I3C_MasterTransferNonBlocking Write data failed: %d\r\n", g_completionStatus);

I can reproduce this issue.

So i try to add some debug code.

In fsl_i3c.c

Harry_Zhang_0-1754386837044.png

When Master send the RepeatStart. it will enter while(1);

And i checked the logic analyze.

Harry_Zhang_1-1754387004620.png

The waveform is correct.

So currently, when you want to write date through nonblocking. The SDK only support the DataSize >0.

May I ask if you have datasize=0 with write  based on the nonblocking Related requirements?

If yes, you need modify related code.

BR

Harry

 

 

 

在原帖中查看解决方案

0 项奖励
回复
6 回复数
1,298 次查看
Harry_Zhang
NXP Employee
NXP Employee

Hi @bell_huang 

Can you share your project so that I can reproduce this issue more easily?

BR

Harry

0 项奖励
回复
1,275 次查看
bell_huang
Contributor III

Hi @Harry_Zhang ,

Test steps:

(1) Reset slave board

(2) Reset master board

    At this step, it can be observed that after the Slave receives the CCC, the callback does not trigger the kI3C_SlaveCompletionEvent.

(3, Optional) Click SW3 on master board

    Master read register

 

Also check out the configuration of CCC data length in I3C_BusMasterCustomCCC function of master code:

cmd.dataSize = 1;

 

==============================

Case: data length = 1

 

--- Master log ---

data: 0x0

Write Custom CCC

Click SW3 to start
data: 0x65 // ---> Indicate that the slave received CCC successfully, so that the master can read the correct value

 

--- Slave log ---

transfers[0]. event: TransmitEvent
transfers[1]. event: TransmitEvent
transfers[2]. event: TransmitEvent
transfers[3]. event: TransmitEvent
transfers[4]. event: TransmitEvent
transfers[5]. event: TransmitEvent
transfers[6]. event: TransmitEvent
transfers[7]. event: TransmitEvent
transfers[8]. event: AddressMatchEvent
transfers[9]. event: ReceiveEvent
transfers[10]. event: TransmitEvent
transfers[11]. event: AddressMatchEvent
transfers[12]. event: CompletionEvent. status: 0, count: 0

transfers[0]. event: TransmitEvent
transfers[1]. event: TransmitEvent
transfers[2]. event: ReceivedCCCEvent
transfers[3]. event: AddressMatchEvent
transfers[4]. event: ReceiveEvent
transfers[5]. event: CompletionEvent. status: 0, count: 1 // ---> Received kI3C_SlaveCompletionEvent after received CCC event

 

// After clicked on master SW3

transfers[0]. event: TransmitEvent
transfers[1]. event: AddressMatchEvent
transfers[2]. event: ReceiveEvent
transfers[3]. event: TransmitEvent
transfers[4]. event: AddressMatchEvent
transfers[5]. event: CompletionEvent. status: 0, count: 0

 

==============================

Case: data length = 0

 

--- Master log ---

data: 0x0

Write Custom CCC

Click SW3 to start
data: 0x90 // ---> Wrong value

 

--- Slave log ---

transfers[0]. event: TransmitEvent
transfers[1]. event: TransmitEvent
transfers[2]. event: TransmitEvent
transfers[3]. event: TransmitEvent
transfers[4]. event: TransmitEvent
transfers[5]. event: TransmitEvent
transfers[6]. event: TransmitEvent
transfers[7]. event: TransmitEvent
transfers[8]. event: AddressMatchEvent
transfers[9]. event: ReceiveEvent
transfers[10]. event: TransmitEvent
transfers[11]. event: AddressMatchEvent
transfers[12]. event: CompletionEvent. status: 0, count: 0

 

// ---> Miss kI3C_SlaveCompletionEvent here after receiving CCC event.

 

// After clicked on master SW3

transfers[0]. event: TransmitEvent
transfers[1]. event: TransmitEvent
transfers[2]. event: TransmitEvent
transfers[3]. event: AddressMatchEvent
transfers[4]. event: ReceivedCCCEvent
transfers[5]. event: ReceiveEvent
transfers[6]. event: TransmitEvent
transfers[7]. event: ReceivedCCCEvent
transfers[8]. event: AddressMatchEvent
transfers[9]. event: CompletionEvent. status: 7904
transfers[10]. event: TransmitEvent
transfers[11]. event: CompletionEvent. status: 0, count: 5

0 项奖励
回复
968 次查看
Harry_Zhang
NXP Employee
NXP Employee

Hi @bell_huang 

Would it be possible to make minimal modifications based on the i3c SDK example to verify the this functionality?

Additionally, could you provide the waveform data?

BR

Harry

0 项奖励
回复
952 次查看
bell_huang
Contributor III

I tried simplifying my example to be even more minimal than the SDK example.
I found that the issue occurs on the Master side, rather than on the Slave side as originally assumed.

In summary, when implementing a Custom CCC with no data on the Master, using I3C_MasterTransferBlocking works correctly. However, when using I3C_MasterTransferNonBlocking, the waveform is incorrect.

The expected waveform sequence for a Custom CCC is: 0x7E -> 0xF0 (Custom CCC) -> 0x09 (Slave Address). Below, I only show the waveform for the Slave Address. The following three cases use the same Slave driver, but different Master driver APIs.

Test steps:

(1) Reset Slave

(2) Reset Master

(3) Click Master SW3

 

Case 1: I3C_MasterTransferBlocking (from fsl_i3c API)
-> The waveform is correct.

uint8_t cmdId = 0xF0;

memset(&masterXfer, 0, sizeof(masterXfer));
masterXfer.slaveAddress = 0x7E;
masterXfer.data         = &cmdId;
masterXfer.dataSize     = 1;
masterXfer.direction    = kI3C_Write;
masterXfer.busType      = kI3C_TypeI3CSdr;
masterXfer.flags        = (uint32_t)kI3C_TransferNoStopFlag;
result                  = I3C_MasterTransferBlocking(EXAMPLE_MASTER, &masterXfer);
if (result != kStatus_Success)
    PRINTF("I3C_MasterTransferBlocking Write cmdId failed: %d\r\n", result);

uint8_t data[10];
memset(data, 0, sizeof(data));
data[0] = 0x01;
data[1] = 0x02;
data[2] = 0x03;

memset(&masterXfer, 0, sizeof(masterXfer));
masterXfer.slaveAddress = slaveAddr;
masterXfer.data         = data;
masterXfer.dataSize     = 0;
masterXfer.direction    = kI3C_Write;
masterXfer.busType      = kI3C_TypeI3CSdr;
masterXfer.flags        = (uint32_t)kI3C_TransferRepeatedStartFlag;
result                  = I3C_MasterTransferBlocking(EXAMPLE_MASTER, &masterXfer);
if (result != kStatus_Success)
    PRINTF("I3C_MasterTransferBlocking Write data failed: %d\r\n", result);

bell_huang_0-1753928201436.png

 

Case 2: I3C_MasterTransferNonBlocking (from fsl_i3c API)
-> The Slave Address sent is incorrect, resulting in a NACK.

uint8_t cmdId = 0xF0;

memset(&masterXfer, 0, sizeof(masterXfer));
masterXfer.slaveAddress = 0x7E;
masterXfer.data         = &cmdId;
masterXfer.dataSize     = 1;
masterXfer.direction    = kI3C_Write;
masterXfer.busType      = kI3C_TypeI3CSdr;
masterXfer.flags        = (uint32_t)kI3C_TransferNoStopFlag;
g_masterCompletionFlag = false;
I3C_MasterTransferNonBlocking(EXAMPLE_MASTER, &masterHandle, &masterXfer);
while (!g_masterCompletionFlag)
{
    __NOP();
}
if (g_completionStatus != kStatus_Success)
    PRINTF("I3C_MasterTransferNonBlocking Write cmdId failed: %d\r\n", g_completionStatus);


uint8_t data[10];
memset(data, 0, sizeof(data));
data[0] = 0x01;
data[1] = 0x02;
data[2] = 0x03;

memset(&masterXfer, 0, sizeof(masterXfer));
masterXfer.slaveAddress = slaveAddr;
masterXfer.data         = data;
masterXfer.dataSize     = 0;
masterXfer.direction    = kI3C_Write;
masterXfer.busType      = kI3C_TypeI3CSdr;
masterXfer.flags        = (uint32_t)kI3C_TransferRepeatedStartFlag;
g_masterCompletionFlag = false;
I3C_MasterTransferNonBlocking(EXAMPLE_MASTER, &masterHandle, &masterXfer);
while (!g_masterCompletionFlag)
{
    __NOP();
}
if (g_completionStatus != kStatus_Success)
    PRINTF("I3C_MasterTransferNonBlocking Write data failed: %d\r\n", g_completionStatus);

bell_huang_1-1753928285555.png

 

If you change dataSize from 0 to 1, the waveform of Slave Address will be correct.

bell_huang_2-1753928603654.png

 

 

Case 3: I3C_BusMasterSendCCC (from fsl_component_i3c_adapter API)
-> Internally uses I3C_MasterTransferNonBlocking, so the behavior is the same as Case 2.

uint8_t cmdId = 0xF0;

i3c_ccc_cmd_t cmd = {0};
uint8_t data[10];
memset(data, 0, sizeof(data));
data[0] = 0x01;
data[1] = 0x02;
data[2] = 0x03;

cmd.isRead   = false;
cmd.cmdId    = 0xF0;
cmd.destAddr = slaveAddr;
cmd.data     = data;
cmd.dataSize = 0;
status_t result = I3C_BusMasterSendCCC(&masterDev, &cmd);
if (result != kStatus_Success)
    PRINTF("I3C_BusMasterSendCCC failed: %d\r\n", result);

 

0 项奖励
回复
874 次查看
Harry_Zhang
NXP Employee
NXP Employee

Hi @bell_huang 

Thanks for your information.

I have tested it.

I tested it based on the 

Case 2: I3C_MasterTransferNonBlocking (from fsl_i3c API)

uint8_t cmdId = 0xF0;

memset(&masterXfer, 0, sizeof(masterXfer));
masterXfer.slaveAddress = 0x7E;
masterXfer.data         = &cmdId;
masterXfer.dataSize     = 1;
masterXfer.direction    = kI3C_Write;
masterXfer.busType      = kI3C_TypeI3CSdr;
masterXfer.flags        = (uint32_t)kI3C_TransferNoStopFlag;
g_masterCompletionFlag = false;
I3C_MasterTransferNonBlocking(EXAMPLE_MASTER, &masterHandle, &masterXfer);
while (!g_masterCompletionFlag)
{
    __NOP();
}
if (g_completionStatus != kStatus_Success)
    PRINTF("I3C_MasterTransferNonBlocking Write cmdId failed: %d\r\n", g_completionStatus);


uint8_t data[10];
memset(data, 0, sizeof(data));
data[0] = 0x01;
data[1] = 0x02;
data[2] = 0x03;

memset(&masterXfer, 0, sizeof(masterXfer));
masterXfer.slaveAddress = slaveAddr;
masterXfer.data         = data;
masterXfer.dataSize     = 0;
masterXfer.direction    = kI3C_Write;
masterXfer.busType      = kI3C_TypeI3CSdr;
masterXfer.flags        = (uint32_t)kI3C_TransferRepeatedStartFlag;
g_masterCompletionFlag = false;
I3C_MasterTransferNonBlocking(EXAMPLE_MASTER, &masterHandle, &masterXfer);
while (!g_masterCompletionFlag)
{
    __NOP();
}
if (g_completionStatus != kStatus_Success)
    PRINTF("I3C_MasterTransferNonBlocking Write data failed: %d\r\n", g_completionStatus);

I can reproduce this issue.

So i try to add some debug code.

In fsl_i3c.c

Harry_Zhang_0-1754386837044.png

When Master send the RepeatStart. it will enter while(1);

And i checked the logic analyze.

Harry_Zhang_1-1754387004620.png

The waveform is correct.

So currently, when you want to write date through nonblocking. The SDK only support the DataSize >0.

May I ask if you have datasize=0 with write  based on the nonblocking Related requirements?

If yes, you need modify related code.

BR

Harry

 

 

 

0 项奖励
回复
862 次查看
bell_huang
Contributor III

Hi @Harry_Zhang ,

I’m not sure how to modify the code related to the non-blocking function. Fortunately, it is confirmed that the blocking function works correctly, so for now, I will use I3C_MasterTransferBlocking to implement the Custom CCC.

Since I typically use the higher-level API (fsl_component_i3c_adapter), it would be ideal if the NXP SDK team could address this issue in a future update. Once it is fixed, I will switch back to using I3C_BusMasterSendCCC for Custom CCC implementation.

0 项奖励
回复