cancel
Showing results for 
Search instead for 
Did you mean: 

I2C in DMA mode - deadlock on I2C interrupt

Jaroslaw Karwik
Associate II

Has anyone have similiar issues ? I got I2C DMA writes working nicely on table, but in real application there are disturbances which cause false start condition on the bus.

This happen when I2C HAL driver has "lock" on I2C handle - so incoming interrupt hangs in forever loop as the code always returns empty when faces locked handle. But the interrupt is not serviced, so it is executed forever....

4 REPLIES 4
Imen.D
ST Employee

Hello @Jaroslaw Karwik​ ,

Have a look at this FAQ STM32 I2C does not work which describes few tips related to I2C.

There are several I2C examples within STM32Cube MCU package. You can refer to the one example relevant to the device that you are using

For Example:

STM32Cube_FW_F4_V1.26.1\Projects\STM32F4-Discovery\Examples\I2C

Hope this helps you!

Imen

When your question is answered, please close this topic by clicking "Accept as Solution".
Thanks
Imen
Jaroslaw Karwik
Associate II

My working code is based on on such example.

I basically call library function - the code is provided by STM32CubeIDE

HAL_I2C_Mem_Write_DMA(hi2c, DevAddr, WriteAddr, I2C_MEMADD_SIZE_8BIT, (uint8_t*)pBuffer, *NumByteToWrite);

And this - in case of disturbances - hangs whole software.

Simple , non interrupt version works:

HAL_I2C_Mem_Write(hi2c, DevAddr, WriteAddr, I2C_MEMADD_SIZE_8BIT, (uint8_t*)pBuffer, *NumByteToWrite,50);

As far as I can see there is bug in the code - it goes like this:

  • Normal code enters code within __HAL_LOCK(hi2c); ...... __HAL_UNLOCK(hi2c) - it happens when my code executes write
  • Disturbance causes i2c interrupt ( I am not 100% sure looks like erroneous start condition on the bus due electrical spike which surpasses filtering)
  • Interrupt code is called ( HAL_I2C_EV_IRQHandler() and later one of subroutines - like HAL_I2C_Master_Seq_Transmit_DMA() )
  • The code - in the interrupt reaches __HAL_LOCK() ... which fails - as there is already lock from normal code.
  • The failure causes immediate return - the interrupt is not serviced ( and as result - it stays )
  • The CPU triggers the interrupt again - as it was not serviced - this causes deadlock

The __HAL_LOCK() in the interrupt code is really bad design choice. It is asking for troubles like that in all other peripherals as well..

Cube does not work for you so you have to write the I2C handling yourself.

JW

Jaroslaw Karwik
Associate II

I know.

In few cases I already have my own drivers based on LL.

Just I2C hardware is so overcomplicated that I decided to stay with standard non-interrupt code.

I decided to post my question as warning - this problem started happening after testing whole setup on the table and only in my client's final setup - where 2x 10kW electrical engines cause large mess when started. Not a nice surprise in final test phase....