I2C in DMA mode - deadlock on I2C interrupt
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2021-06-15 9:35 AM
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....
- Labels:
-
DMA
-
I2C
-
STM32H7 Series
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2021-06-28 1:00 PM
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
Thanks
Imen
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2021-06-28 11:45 PM
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..
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2021-06-28 11:50 PM
Cube does not work for you so you have to write the I2C handling yourself.
JW
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2021-06-28 11:56 PM
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....
