cancel
Showing results for 
Search instead for 
Did you mean: 

Potential bug in I2C HAL layer (STM32Cube_FW_F4_V1.25.0) in I2C_MemoryTransmit_TXE_BTF() ?

TKube.1
Associate II

Details:

MasterMode: HAL_I2C_MODE_MEM

Clockspeed 400kb/s

Symptoms:

In Master-MODE_MEM after memory address has been sent a repeated start should be sent (in I2C_MemoryTransmit_TXE_BTF()) before the switch to read. However if the ISR is handled quickly the code will be triggered twice (= two START conditions after each other) and the slave device will answer with a NAK.

0693W000003PfNcQAK.png

If I added debug code (I2C event logger) the problem went away which made me feel it was a timing issue. So I analysed the code more and found that a the event handler HAL_I2C_EV_IRQHandler() can be triggered multiple times for the same event.

So I modified the code and incremented eventcount to stop the code from executing twice:

In MemoryTransmit_TXE_BTF()...

..else if (hi2c->EventCount == 2U)

 {

   if (hi2c->State == HAL_I2C_STATE_BUSY_RX)

   {

     /* Generate Restart */

     hi2c->direction = I2C_Direction_Receiver;

     hi2c->Instance->CR1 |= I2C_CR1_START;

     // TK 20200818- FIX for dual start instead of single for re-start

     // inc eventcount makes so that code only executes once

      hi2c->EventCount++;

   }

   else ....

And it seems to work as intended:

0693W000003PfOuQAK.png

Is there anyone else that has seen the same problem ?

/Tony

6 REPLIES 6
Amel NASRI
ST Employee

Hi @TKube.1​ ,

To more understand conditions when this problem occurs, may you check the flags set in SR1 register each time HAL_I2C_EV_IRQHandler() is executed?

Thanks.

-Amel

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

TKube.1
Associate II

I2C bus @400kb, read *one* byte in memory mode from slave 0x6B.

Bottom row is a GPIO that I bring high when entering HAL_I2C_EV_IRQHandler() and low when I exit.

Added event log code to HAL_I2C_EV_IRQHandler(): #if DEBUG_I2C_EVENTS

if(evtCnt < (MAXBUF))lastEvtBuf[evtCnt++] = (sr1itflags | (sr2itflags<<16)) & 0x00FFFFFF;

if(evtCnt >= MAXBUF)evtCnt = 0;

#endif

A normal sequence:

0693W000002lD6EQAU.png

And error sequence:

0693W000002lD6OQAU.png

I'm not really sure but it seems that, when the double start occurs, there is a slight delay for the ISR handling of Master mode byte transmitted (0x00070084) event, this generates two starts and consequently the event Master mode receiver mode selected (0x00030002) is not triggered.

Please let me know if you need anything more. I'm not sure its a bug, but with my change it seems to work so-far.

/Tony

TKube.1
Associate II

Sorry, there was a problem with the last image, here it is:0693W000002lD9mQAE.png

TKube.1
Associate II

And here is a zoomed in view to see the phases if ISR handler and the double start:

0693W000002lDFGQA2.png

It looks like the second start is actually triggered before START released event (0x0030001).

I tried to make a better image with both a normal sequence and one with the double start, I think I got the states correct but its a bit perplexing, but it might be of interest.

0693W000002lYBeQAM.png

I'm sorry I think I got the states of the normal sequence one step incorrect (its a bit hard to match manually).

I think this might be more correct:

0693W000002lYUCQA2.png