LPC55S36, I3C RSTDAA issue

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

LPC55S36, I3C RSTDAA issue

Jump to solution
3,102 Views
bell_huang
Contributor III

I'm running I3C on LPC5536-EVK and find out that I3C_BusMasterResetDAA(RSTDAA) doesn't seem to work for any of the sensors.

When we call I3C_BusMasterResetDAA, then It's always stuck for a while. We can see it stuck at fsl_component_i3c_adapter.c -> I3CMasterAdapterTransfer -> while (!g_masterCompletionFlag). The timeout for this call takes about 20 seconds.

This issue can be reproduced in Building an I3C Sensor Network Using LPC553x/LPC55S3x example. Add I3C_BusMasterResetDAA after the ICM42688P device enters I3C mode. See the attachment i3c_sensor_network.c.

 

if (demo_icm42688pDev != NULL ) {
  icm42688p_sensorAddr = demo_icm42688pDev->info.dynamicAddr;
  PRINTF("\r\nICM42688 Dynamic addresses is %d\r\n", icm42688p_sensorAddr);

  status_t result = I3C_BusMasterResetDAA(&demo_masterDev, icm42688p_sensorAddr);
  if (result != kStatus_Success)
  {
      PRINTF("I3C_BusMasterResetDAA failed\r\n");
      return false;
  }
  PRINTF("Finished\r\n");
}

while(1);

 

According to MIPI I3C® v1.0 (2016) . The format of a direct RSTDAA shall be:

1. S

2. 0x7E

3. 0x86 (Direct RSTDAA CCC)

4. SR

5. 0x09 (The dynamic address in this example)

6. P

bell_huang_0-1707097102939.png

However, we observe that the wavelet has a redundant byte after the Slave Addr.

1. S

2. 0x7E

3. 0x86 (Direct RSTDAA CCC)

4. SR

5. 0x09 (The dynamic address in this example)

6. 0x00 (A redundant byte)

7. P

RSTDAA_1.png

RSTDAA_2.png

RSTDAA_3.png

RSTDAA_4.png

Tags (1)
0 Kudos
Reply
1 Solution
2,385 Views
Pavel_Hernandez
NXP TechSupport
NXP TechSupport

Hello, sorry for the late response, I was waiting for more information from the internal department.

After a quick debug I found there's a bug in the I3C driver which can't handle write transactions with no data payload properly. I have provided a quick fix for this issue by checking the payload length and transition the state into STOP when no data needs to be sent by a write transaction. 

Please note this is a quick fix just for the case you are experiencing, so this may not cover all cases but I believe similar checks may be added to other state transitions. Please verify whether this fixes the problem and check for formal SDK team's solution.

As a side note, this Direct RSTDAA CCC shall not be used by us (host) since it has been deprecated in I3C specification 1.1. The scenario 2 you mentioned above also should not be used for CCCs like this, and is not complies with I3C specification, since there is a distinctive different between device address and data bytes: the address checks for ACK using open-drain fashion while data bytes not.

Best regards,
Pavel

View solution in original post

0 Kudos
Reply
20 Replies
3,031 Views
Pavel_Hernandez
NXP TechSupport
NXP TechSupport

Hello, sorry for the late response, I am following your case, the driver of I3C seems good. I could not modify our EVK, but my recommendation is to review if other commands work if yes that confirms the I3C is good, and the device is not responding well with that command.

Best regards,
Pavel

0 Kudos
Reply
2,979 Views
bell_huang
Contributor III

Hi Pavel,

Broadcast RSTDAA works fine for any sensors, but Direct RSTDAA does not.

See the wavelet of Direct RSTDAA of LPC55S36:

(1) S

(2) 0x7E

(3) 0x86 (Direct RSTDAA CCC)

(4) SR

(5) 0x09 (The dynamic address in this example)

(6) 0x00 (A redundant byte)

(7) P

From (1) to (5), devie responds well. However, the device is not responsable to respond (6) according to MIPI I3C® v1.0 (2016) . 

Untitled.png

Not only ICM42688P, but any other device (including P3T1175) has the same situation.

Based on the two points mentioned above, I think the problem should be with the EVK or SDK, not the device.

 

0 Kudos
Reply
2,919 Views
Pavel_Hernandez
NXP TechSupport
NXP TechSupport

Hello, sorry for the late response, I have some observations about the code you modified, seems good until line 221, I suggest using it at the most possible as the example shows, and add lines 221 to 225.

We analyzed the code and I suggest doing a test on your board.

On the function (I3C_MasterAdapterTransmitCCC) when the RSTDAA is on line 444 seems the function does a broadcast and then sends the code for the directs does not find anything.

Could you let me know about works if you comment the lines 444 o 454?

Best regards,
Pavel

0 Kudos
Reply
2,904 Views
bell_huang
Contributor III

Hi @Pavel_Hernandez,

We add lines 221 to 225 back, the result of RSTDAA has no difference. We removed lines 221 to 225 because we can observe cleaner wavelet.

 

/* Set higher PP Baudrate higher for data communication after DAA. */
i3c_baudrate_hz_t   baudrate_config;
baudrate_config.i3cPushPullBaud  = 10000000ULL;
baudrate_config.i3cOpenDrainBaud = 4000000ULL;
I3C_MasterSetBaudRate(EXAMPLE_MASTER, &baudrate_config, I3C_MASTER_CLOCK_FREQUENCY);

 

In fsl_component_i3c_adapter.c -> I3C_MasterAdapterTransmitCCC. In line 444, although I3C_BUS_BROADCAST_ADDR has the word broadcast. Here it mean a value of 0x7E, not doing a broadcast. I3C CCC commands start with 0x7E, so both the Broadcast command and Direct command will have 0x7E at the beginning. Folloing 0x7E, the Broadcast RSTDAA is 0x06, and the Direct RSTDAA is 0x86. You can refer to the definition of RSTDAA in MIPI I3C® v1.0 (2016).

bell_huang_1-1708482550574.png

bell_huang_2-1708483562477.png

If we comment the lines 444 to 454, 0x7E 0x86 does not appear. Therefore it will not be an RSTDAA command.

testRSTDAA_1.png

testRSTDAA_2.png

0 Kudos
Reply
2,854 Views
Pavel_Hernandez
NXP TechSupport
NXP TechSupport

Hello, thanks for following our instructions, we will investigate more, and when I have more details, I will contact you.

Best regards,
Pavel

0 Kudos
Reply
2,810 Views
Pavel_Hernandez
NXP TechSupport
NXP TechSupport

Hello, sorry for the late response I get more details from my team,

This is the code to implement the RSTDAA command.

    /* Reset dynamic address. */
    result = I3C_WriteSensor(0x7E, 0x06, NULL, 0);

The 0x7E is reserved byte, the CCC is 0x06 RSTDAA command. Pls refer to example i3cmaster_read_sensor_icm4268p in SDK example for lpc5536.

Best regards,
Pavel

0 Kudos
Reply
2,795 Views
bell_huang
Contributor III

Hi @Pavel_Hernandez,

Could you check is it valid to call I3C_WriteSensor(0x7E, 0x06, NULL, 0) ? The type of first parameter shall be i3c_device_t*. And 0x06 is Broadcast RSTDAA, the problem in previous discussion is Direct RSTDAA which is 0x86.

 

status_t I3C_WriteSensor(i3c_device_t *device_handle, uint8_t regAddress, uint8_t *regData, size_t dataSize)
{
}

 

 

0 Kudos
Reply
2,782 Views
Pavel_Hernandez
NXP TechSupport
NXP TechSupport

Hello, sorry I misspelled.

uint8_t slaveAdd;
slaveAdd=SLAVEADDRESS<<1;
result = I3C_WriteSensor(0x7E, 0x86, &slaveAdd, 1);

Best regards,
Pavel

 

0 Kudos
Reply
2,757 Views
bell_huang
Contributor III

Hi @Pavel_Hernandez ,

This does not work. As I said, the first parameter of I3C_WriteSensor should be i3c_device_t*. It is weird to regard 0x7E as a pointer.

bell_huang_0-1709514834404.pngbell_huang_1-1709514840872.png

0 Kudos
Reply
2,727 Views
Pavel_Hernandez
NXP TechSupport
NXP TechSupport

Hello, sorry I have the other version of the example.

Pavel_Hernandez_0-1709765574827.png

I3C_WriteSensor(&demo_masterDev, 0x86, &slaveAdd, 1)

 

Let me know if you have more questions. 

Best regards,
Pavel

 

0 Kudos
Reply
2,600 Views
bell_huang
Contributor III

Hi @Pavel_Hernandez ,

Do you have any updates for this message ?

0 Kudos
Reply
2,716 Views
bell_huang
Contributor III

Hi @Pavel_Hernandez ,

I3C_WriteSensor(&demo_masterDev, 0x86, &slaveAdd, 1) doesn't work in i3c_sensor_network example. The first byte it drives is 0x08 and then NACK.

bell_huang_0-1709861784917.png

bell_huang_1-1709861804018.png

 

I3C_WriteSensor in i3c_sensor_network example is very different from in i3c_master_read_sensor_icm42688p example. In i3c_sensor_network example:

(1) The first parameter i3c_device_t of I3C_WriteSensor determines what it drives the first byte as the slave address.

(2) In this example, the dynamic address of demo_masterDev is assigned to 0x08, and the dynamic address of demo_icm42688pDev is assigned to 0x09.

That's the reason that I3C_WriteSensor(&demo_masterDev, 0x86, &slaveAdd, 1) drives the first byte 0x08, not 0x7E.

-------------------------------------------------------------------------------------------------------------------------------------

I test I3C_WriteSensor(0x7E, 0x86, &slaveAdd, 1) in i3c_master_read_sensor_icm42688p example, and it does not work too. Please refer to the attachment i3c_master_read_sensor_icm42688p.c for this test.

If we call I3C_WriteSensor(0x7E, 0x06, NULL, 0) for Broadcast RSTDAA, then it can read WHO_AM_I value using I2C.

 

/* Broadcast RSTDAA */
result = I3C_WriteSensor(0x7E, 0x06, NULL, 0);
if (result != kStatus_Success)
{
    PRINTF("Broadcast RSTDAA failed\r\n");
    return -1;
}

/* I2C Read WHO_AM_I */
uint8_t whoAmI = 0;
i3c_master_transfer_t xfer = {};
xfer.slaveAddress   = 0x69;
xfer.subaddress     = WHO_AM_I;
xfer.subaddressSize = 1;
xfer.data           = &whoAmI;
xfer.dataSize       = 1;
xfer.direction      = kI3C_Read;
xfer.busType        = kI3C_TypeI2C;
xfer.flags          = (uint32_t)kI3C_TransferDefaultFlag;
result = I3C_MasterTransferBlocking(EXAMPLE_MASTER, &xfer);
if (result != kStatus_Success)
{
    PRINTF("I2C Read WHO_AM_I failed\r\n");
    return -1;
}
PRINTF("WHO_AM_I = 0x%02X\r\n", whoAmI);

 

bell_huang_2-1709862835744.png

 

But if we call I3C_WriteSensor(0x7E, 0x86, &targetAddr, 1) for Direct RSTDAA, then it fails to read value using I2C. It means that the device does not be reset to I2C mode.

 

/* Direct RSTDAA */
uint8_t targetAddr = slaveAddr << 1;
result = I3C_WriteSensor(0x7E, 0x86, &targetAddr, 1);
if (result != kStatus_Success)
{
    PRINTF("Direct RSTDAA failed\r\n");
    return -1;
}

/* I2C Read WHO_AM_I */
uint8_t whoAmI = 0;
i3c_master_transfer_t xfer = {};
xfer.slaveAddress   = 0x69;
xfer.subaddress     = WHO_AM_I;
xfer.subaddressSize = 1;
xfer.data           = &whoAmI;
xfer.dataSize       = 1;
xfer.direction      = kI3C_Read;
xfer.busType        = kI3C_TypeI2C;
xfer.flags          = (uint32_t)kI3C_TransferDefaultFlag;
result = I3C_MasterTransferBlocking(EXAMPLE_MASTER, &xfer);
if (result != kStatus_Success)
{
    PRINTF("I2C Read WHO_AM_I failed\r\n");
    return -1;
}
PRINTF("WHO_AM_I = 0x%02X\r\n", whoAmI);

 

bell_huang_4-1709863228631.png
bell_huang_3-1709863214104.png

 

0 Kudos
Reply
2,745 Views
Pavel_Hernandez
NXP TechSupport
NXP TechSupport

Hello, sorry you are right let me review this information with the team.

Best regards,
Pavel

0 Kudos
Reply
2,512 Views
Pavel_Hernandez
NXP TechSupport
NXP TechSupport

Hello, I have more comments from the team, In I3C Specification v1.1, the Direct RSTDAA CCC is deprecated and should not be used by controllers, and shall not be used against v1.1 target.

Have you tried using Broadcast RSTDAA CCC on the device to check whether this can reset target's address?

Let me know your comments.

Best regards,
Pavel

0 Kudos
Reply
2,420 Views
bell_huang
Contributor III

Hi @Pavel_Hernandez,

Thanks for response.

I did notice that Direct RSTDAA CCC has been deprecated since v1.1 of the I3C specification. Since I have a device that is v1.0 compatible, I would like to test Direct RSTDAA on the LPC55S36 if possible.
As mentioned before, Broadcast RSTDAA works fine for any sensors, but Direct RSTDAA does not.
These days I have tried and found out the workaround for Direct RSTDAA, which can successfully get a single device out of the I3C. I can provide the code if you need it.

bell_huang_0-1711076416340.png


-------------------------------------------------------------
Anyway, I also found another problem, I can create a new topic/case if needed.

Refer to attachment i3c_sensor_network.c modified from i3c_sensor_network example. If we call I3C_BusMasterGetDeviceInfo(), then it will casue SDA been pulled low.

if (demo_icm42688pDev != NULL ) {
    icm42688p_sensorAddr = demo_icm42688pDev->info.dynamicAddr;
    PRINTF("ICM42688 Dynamic addresses is %d\r\n", icm42688p_sensorAddr);

    SDK_DelayAtLeastUs(1000000, SystemCoreClock);

    i3c_device_information_t devInfo = {};
    devInfo.dynamicAddr = icm42688p_sensorAddr;
    result = I3C_BusMasterGetDeviceInfo(&demo_masterDev, icm42688p_sensorAddr, &devInfo);
    if (result != kStatus_Success)
    {
        PRINTF("I3C_BusMasterGetDeviceInfo failed\r\n");
        while(1);
    }
}

bell_huang_1-1711076772351.png

 

The I3C_BusMasterGetDeviceInfo() contains six I3C CCCs: GETPID, GETBCR, GETDCR, GETMRL, GETMWL, GETHDRCAP. To simplify this problem, just run three of the commands GETBCR, GETDCR, GETMRL and you will be able to reproduce it.

if (demo_icm42688pDev != NULL ) {
    icm42688p_sensorAddr = demo_icm42688pDev->info.dynamicAddr;
    PRINTF("ICM42688 Dynamic addresses is %d\r\n", icm42688p_sensorAddr);

    SDK_DelayAtLeastUs(1000000, SystemCoreClock);

    i3c_device_information_t devInfo = {};
    devInfo.dynamicAddr = icm42688p_sensorAddr;
    
    // GETBCR (0x8E)
    extern status_t I3C_BusMasterGetBCR(i3c_device_t *master, i3c_device_information_t *info);
    result = I3C_BusMasterGetBCR(&demo_masterDev, &devInfo);
    if (result != kStatus_Success)
    {
        PRINTF("I3C_BusMasterGetPID failed\r\n");
        while(1);
    }

    // GETDCR (0x8F)
    extern status_t I3C_BusMasterGetDCR(i3c_device_t *master, i3c_device_information_t *info);
    result = I3C_BusMasterGetDCR(&demo_masterDev, &devInfo);
    if (result != kStatus_Success)
    {
        PRINTF("I3C_BusMasterGetDCR failed\r\n");
        while(1);
    }

    // GETMRL (0x8C)
    extern status_t I3C_BusMasterGetMaxReadLength(i3c_device_t *master, i3c_device_information_t *info);
    result = I3C_BusMasterGetMaxReadLength(&demo_masterDev, &devInfo);
    if (result != kStatus_Success)
    {
        PRINTF("I3C_BusMasterGetMaxReadLength failed\r\n");
        while(1);
    }
}

bell_huang_2-1711077636831.png

 

The program will be stuck at fsl_component_i3c_adapter.c -> I3CMasterAdapterTransfer() until timeout. after timeout, any I3C Read/Write will fail because the SDA is pulled low.

bell_huang_3-1711077887798.png

 

 

 

0 Kudos
Reply
2,386 Views
Pavel_Hernandez
NXP TechSupport
NXP TechSupport

Hello, sorry for the late response, I was waiting for more information from the internal department.

After a quick debug I found there's a bug in the I3C driver which can't handle write transactions with no data payload properly. I have provided a quick fix for this issue by checking the payload length and transition the state into STOP when no data needs to be sent by a write transaction. 

Please note this is a quick fix just for the case you are experiencing, so this may not cover all cases but I believe similar checks may be added to other state transitions. Please verify whether this fixes the problem and check for formal SDK team's solution.

As a side note, this Direct RSTDAA CCC shall not be used by us (host) since it has been deprecated in I3C specification 1.1. The scenario 2 you mentioned above also should not be used for CCCs like this, and is not complies with I3C specification, since there is a distinctive different between device address and data bytes: the address checks for ACK using open-drain fashion while data bytes not.

Best regards,
Pavel

0 Kudos
Reply
2,284 Views
bell_huang
Contributor III

Hi @Pavel_Hernandez,

Thanks for the provided quick fix.

I apply i3c_quickfix.patch and then I3C_BusMasterResetDAA(&demo_masterDev, icm42688p_sensorAddr) can issue the correct Direct RSTDAA.

bell_huang_0-1711347039524.png

The above test was done at a baud rate of OpenDrain=4MHz & Push-Pull=10MHz. However, if I keep the baud rate at OpenDrain=400KHz & Push-Pull=2MHz, then the SDA is pulled low after a direct RSTDAA. I guess there could be another potential bug?

 

#define EXAMPLE_I2C_BAUDRATE       400000

// ...

/* In order to start sensor network discovery, depending on the sensors on the network,
initiate PP baudrate needs to be slow. PP Baudrate can be set to higher after the discovery is done. */
busConfig.i3cPushPullBaudRate  = 2000000ULL;
busConfig.i3cOpenDrainBaudRate = EXAMPLE_I2C_BAUDRATE;
I3C_BusCreate(&demo_i3cBus, &busConfig);

// ...

/* Set higher PP Baudrate higher for data communication after DAA. */
//i3c_baudrate_hz_t   baudrate_config;
//baudrate_config.i3cPushPullBaud  = 10000000ULL;
//baudrate_config.i3cOpenDrainBaud = 4000000ULL;
//I3C_MasterSetBaudRate(EXAMPLE_MASTER, &baudrate_config, I3C_MASTER_CLOCK_FREQUENCY);

 

bell_huang_1-1711347577591.png

-------------------------------------------------------------

Scenario 2

I don't get that I cannot use I3C_BusMasterGetDeviceInfo() or GETBCR/GETDCR/GETMRL like this. As I known Direct GETBCR/GETDCR/GETMRL are still available in I3C specification 1.1. Cannot I issue these commands at random time?

bell_huang_2-1711347904755.png

bell_huang_3-1711347925861.png

0 Kudos
Reply
2,265 Views
Pavel_Hernandez
NXP TechSupport
NXP TechSupport

Hello, I recommend waiting for the next release this is the answered from the internal department... as I mentioned before, the patch provided is a quick fix for one of the many cases when a write occurs with empty data. I didn't touch other part of the driver so it's totally possible for me to miss some state machine transitions. 

Best regards,
Pavel

0 Kudos
Reply
2,260 Views
bell_huang
Contributor III

Hi @Pavel_Hernandez,

Thank you for your great support, I will wait for the release of that fix.

0 Kudos
Reply
3,065 Views
Pavel_Hernandez
NXP TechSupport
NXP TechSupport

Hello, my name is Pavel, and I will be supporting your case, let me get into your case and when I have more information, I will contact you.

Best regards,
Pavel

 

0 Kudos
Reply