S32 LPI2C Stop vs Start Repeat

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

S32 LPI2C Stop vs Start Repeat

Jump to solution
701 Views
cctp
Contributor II

Hello, I was hoping someone could help me with an issue with the LPI2C Driver in the S32K148 SDK. I'm using an I2C multiplexer in order to interface with several devices with the same address, but the multiplexer needs an I2C STOP packet before it will actually activate and switch devices.

The issue here is if I try to send I2C packets too quickly, the driver appears to convert my STOP packets into START_REPEAT packets, which the multiplexer will not respond to.

I suspect this may have something to do with the hardware FIFO trying to optimize / consolidate packets. Is there a way I could disable this behavior? Or failing that, detect when the bus is fully stopped?


Minimal example code:

while (true) {
    size_t buffer_size = 1;

    // Select each I2C Mux output in sequence
    for (int i = 0; i < 4; i+=1) {
        masterTxBuffer[0] = 1 << i;
        LPI2C_DRV_MasterSendDataBlocking(INST_LPI2C1, masterTxBuffer, buffer_size, true, 1000);
    }

    for (volatile int i = 0; i < 2000; i++ ) {} // wait a bit

    // Select each I2C Mux output in sequence, with a delay
    // This works
    for (int i = 0; i < 4; i+=1) {
        masterTxBuffer[0] = 1 << i;
        LPI2C_DRV_MasterSendDataBlocking(INST_LPI2C1, masterTxBuffer, buffer_size, true, 1000);
        for (volatile int i = 0; i < 1000; i++ ) {} // wait a bit so a stop is sent
    }

    // wait a bit
    for (int i = 0; i < 100000; i++ ) {}
}


I've attached the view from my digital logic analyzer -- as you can see adding the short busy wait allows the Mux to take affect.

Thanks.

 

Tags (2)
1 Solution
670 Views
cctp
Contributor II

Hi Daniel, thank you for the response.

I'm using the 4.0.3 version of the SDK. This is with S32 Design Studio version 3.4 -- I read somewhere on this forum that is the latest version that is compatible with the S32K1 family of chips.

I've experimented a fair bit with both the public interface for the driver as well as directly reading some of the registers defined in the reference manual. Using the non-blocking interface in combination with a `while (LPI2C_DRV_MasterGetTransferStatus() == STATUS_BUSY)` gives the same results, with STOP only appearing after forcing a delay. The return value of the function call is `STATUS_SUCCESS` either way. (Unless the device is busy of course)

Additionally, if I call the LPI2C_DRV_MasterSendDataBlocking(..., sendStop=false, ...), the START_REPEAT packets still appear for sequential transmits, even though there is no terminating stop bit at the end of the four packets.

I'm seeing some information about a hardware FIFO that all of these commands are being written to, but I'm unable to find any documentation on how it works.


UPDATE:
Was in the middle of writing this out and I figured out a solution, the `STOP detect flag` of the MSR register (Section 52.4.1.5 in the reference manual). I had previously tried this, but had erroneously used I2C0 instead of I2C1. Waiting for this flag after the first transmit can tell me if the stop packet has sent, and lets the mux activate before sending subsequent packets.

// Wait for LPI2C1 MSR STOP Condition
while ((LPI2C1->MSR & (0x1 << 9)) == 0) {}


Thank you for the help!

View solution in original post

0 Kudos
4 Replies
671 Views
cctp
Contributor II

Hi Daniel, thank you for the response.

I'm using the 4.0.3 version of the SDK. This is with S32 Design Studio version 3.4 -- I read somewhere on this forum that is the latest version that is compatible with the S32K1 family of chips.

I've experimented a fair bit with both the public interface for the driver as well as directly reading some of the registers defined in the reference manual. Using the non-blocking interface in combination with a `while (LPI2C_DRV_MasterGetTransferStatus() == STATUS_BUSY)` gives the same results, with STOP only appearing after forcing a delay. The return value of the function call is `STATUS_SUCCESS` either way. (Unless the device is busy of course)

Additionally, if I call the LPI2C_DRV_MasterSendDataBlocking(..., sendStop=false, ...), the START_REPEAT packets still appear for sequential transmits, even though there is no terminating stop bit at the end of the four packets.

I'm seeing some information about a hardware FIFO that all of these commands are being written to, but I'm unable to find any documentation on how it works.


UPDATE:
Was in the middle of writing this out and I figured out a solution, the `STOP detect flag` of the MSR register (Section 52.4.1.5 in the reference manual). I had previously tried this, but had erroneously used I2C0 instead of I2C1. Waiting for this flag after the first transmit can tell me if the stop packet has sent, and lets the mux activate before sending subsequent packets.

// Wait for LPI2C1 MSR STOP Condition
while ((LPI2C1->MSR & (0x1 << 9)) == 0) {}


Thank you for the help!

0 Kudos
610 Views
nxf78987
NXP Employee
NXP Employee

Hello @cctp,

In the SDK driver, there is a static inline function - LPI2C_Get_SlaveSTOPDetectEvent() which is called by Slave_Handler to check the stop bit, but the user can't call this function.

So, there is no way to replace your solution with any functions in the driver. Therefore, you can use the while() loop as your solution if you want to do that.

Best regards,

Dan

649 Views
danielmartynek
NXP TechSupport
NXP TechSupport

Hi @cctp,

It is pending on feedback from the SDK development team.

 

Regards,

Daniel

674 Views
danielmartynek
NXP TechSupport
NXP TechSupport

Hello @cctp,

What release of the SDK do you use?

The blocking function should return only after the STOP condition has been sent (sendStop == 1).

Can you read the return status?

Have you tried the non-blocking LPI2C_DRV_MasterSendData() with LPI2C_DRV_MasterGetTransferStatus()?

 

Regards,

Daniel

0 Kudos