LPI2C protection

cancel
Showing results for 
Search instead for 
Did you mean: 

LPI2C protection

320 Views
m_mishrikey
Contributor II

I am making a large number of i2c calls.  Sometimes this works okay, but often the bus will hang and the program gets stuck.  

There should not be any gaps in the data below.  My theory is that some interrupt is occuring, and if the interrupt occurs at some unfortunate moment, the i2c traffic gets messed up:

m_mishrikey_0-1599879699307.png

So I wanted to try protecting the i2c call by disabling unrelated interrupts, then reenabling them.  

ENABLE_INTERRUPTS() and DISABLE_INTERRUPTS() set primask, which would not be good because the i2c still needs to function.  

Then I thought I could use BASEPRI, but I am not sure how to set this through the SDK (or otherwise).  

 

Related question - I was experimenting with blocking and non-blocking variants of the receive code. 

m_mishrikey_1-1599880321567.png

I have blockng and non-blocking versions of both the send and the receive.  If I understand correctly, the non-blocking still blocks the program in a sense, but gives you the option to do something inside the {} brackets while you're waiting.   

I wonder if there is a safer way to handle this code.  If anything happens to the bus, you will get stuck in the while busy loop forever.  But if you use the blocking calls, and change the max wait time to something finite, you should return something to the calling function so they know to retry.  is there a try/catch way to handle these i2c calls?

 

 

 

0 Kudos
3 Replies

280 Views
danielmartynek
NXP TechSupport
NXP TechSupport

Hello,

Instead of the LPI2C_DRV_MasterGetTransferStatus() function, you can use a callback function which is then called from the LPI2C_DRV_MasterIRQHandler().

The callback function takes i2c_master_event_t as an argument.

callbacks.h

danielmartynek_0-1600251361896.png

If using a higher interrupt level for the LPI2C is not enough, you can use the BASEPRI.

The BASEPRI register is in the same format as the interrupt priority registers.

danielmartynek_1-1600252132482.png

For example, interrupt priority level 2:

S32_NVIC->IP[xx] = 0x20;

To set BASEPRI to the same level use something like this:

__asm__("MOV R0, 0x20");
__asm__("MSR BASEPRI, R0");

 

Regards,

Daniel

 

 

 

 

 

 

 

0 Kudos

304 Views
m_mishrikey
Contributor II

Follow-up question.  

Does S32K SDK have some form of deadlock recovery such as described by TomE here?

https://community.nxp.com/t5/i-MX-Processors/I2C-reset/m-p/253182

There is also a nice description of what to try here:

https://community.nxp.com/t5/Kinetis-Microcontrollers/I2C-device-dead-lock-recovery/m-p/304368

It would be great if the SDK already had what is needed!

 

0 Kudos

280 Views
danielmartynek
NXP TechSupport
NXP TechSupport

Hi,

The LPI2C module does not have such a recovery feature and therefore the SDK does not support it either.

It would need to be a function of the pin_mux driver, I guess, as it would be performed with GPIOs.

 

You can refer to this AN4803 I2C Non-Blocking Communication as well.

https://www.nxp.com/docs/en/application-note/AN4803.pdf

I2C restore function definition

 

Regards,

Daniel

0 Kudos