cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F4xx: I2C multiple slaves, very strange behavior

ittokor
Associate II
Posted on October 16, 2014 at 12:25

Hello all,

I'm attempting to talk to two devices, a barometer (MS5611) and a magnetometer (HMC5883L), using I2C with DMA on an STM32F4. The barometer runs on a timer (10ms), while the magnetometer runs through an interrupt line.

The slaves work well together, communicating only when the other isn't as verified by a logic analyzer. However, occasionally (~ every 20 secs), when the MCU attempts to write to the barometer the start condition is immediately followed by a stop condition. No address is sent, it is a void message! I have attached pictures below.

I2C working nicely until the last part:

0690X00000605B8QAI.png

Zoom in on the last three communications. The first is a barometer write followed by read. The second is a magnetometer interrupt triggering a write followed by read. The last is the faulty barometer communication.

0690X00000605BDQAY.png

This is a close-up of the last faulty communication. You can see that SDA is low for 4us, which is slightly longer than usual.

0690X00000605BIQAY.png

This issue causes the I2C to timeout at the I2C_WaitOnMasterAddressFlagUntilTimeout function.

I do not believe this is associated with DMA as I am using CubeMX code, where the Addressing phase occurs before any DMA communication.

I have also tried adding an EEPROM (4FC128) as a third slave. The eeprom exhibited the same problem. Only the Magnetometer does not exhibit this, making me think it might be causing the problem?

Any help with this strange issue would be appreciated.</map></div>

#flag #i2c #dma #address #sda-low
17 REPLIES 17
graffiti
Associate III
Posted on October 27, 2014 at 13:50

waiting on TxE AND BTF before setting STOP bit when sending makes no difference, I still get the problem.

waiting on TxE AND BTF before setting STOP bit when receiving hangs, as TxE is never set.

Posted on October 27, 2014 at 14:45

Ok, so we are talking about reception now, through the ''blocking'' HAL_I2C_Master_Receive().

Can't this be a scenario to failure:

- HAL_I2C_Master_Receive() is called with Size == 1

- address is sent through I2C_MasterRequestRead()

-

    if(Size == 1)

    {

      /* Disable Acknowledge */

      hi2c->Instance->CR1 &= ~I2C_CR1_ACK;

      /* Clear ADDR flag */

      __HAL_I2C_CLEAR_ADDRFLAG(hi2c);

      /* Generate Stop */

      hi2c->Instance->CR1 |= I2C_CR1_STOP;

  }

[...] while (size) loop

      if(Size == 1)

        {

          /* Wait until RXNE flag is set */

          if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_RXNE, RESET, Timeout) != HAL_OK)

          {

            return HAL_TIMEOUT;

          }

          /* Read data from DR */

          (*pData++) = hi2c->Instance->DR;

          Size--;

        }

[immediately after this exits from loop]

    /* Disable Pos */

    hi2c->Instance->CR1 &= ~I2C_CR1_POS;

What if at the moment when this last line reads from _CR1, STOP is not cleared yet, and gets rewritten just after cleared?

Could you please try to add a check for ''is STOP already cleared'' just before this line?

Jan

graffiti
Associate III
Posted on October 27, 2014 at 15:06

Wow, yes, that's exactly the problem!

Adding this code just before the read-modify-write, triggers the trap after 20 seconds or so...

//check for r-m-w problem

 

    if((I2C_CR1_STOP & hi2c->Instance->CR1) != (I2C_CR1_STOP & hi2c->Instance->CR1))

 

    {

 

    printf(''read-modify-write trap\n'');

 

    }

Thank you so much! If someone from ST is reading this (are you ST Jan?), maybe this can be patched in the next release of the HAL drivers?

graffiti
Associate III
Posted on October 27, 2014 at 15:36

Hmm, unfortunately there is more.

Waiting for the STOP bit to be cleared at that point (and also before CR1 register is modified in HAL_I2C_Master_Transmit) improves the situation, but hasn't solved it completely. I now get about 25000 read/writes on the i2c bus (over about 3-4 minutes) but then the STOP bit doesn't get cleared! (and I hang waiting for it to clear).

I am out of time today, but will continue checking tomorrow, thanks for the pointers Jan. And to the OP, sorry for somewhat hijacking the thread, but I suspect your issues are the same, but in the DMA versions of the i2c HAL code.

Thanks, Kieran.
ittokor
Associate II
Posted on October 27, 2014 at 16:11

By ''NACK reception'' do you mean the slave not acknowledging? If so, it has been some time since I last tested this, but I am almost positive that for me it occurs even if the slave has previously acknowledged me.

-Checking for BTF AND TxE has no effect.

-Implementing a check for a stop bit before a sending a start seems to fix the issue.

Apologies for the lack of more information, I have since moved on to other problems. Once I get back the logic analyzer, I will update with more information.

graffiti
Associate III
Posted on October 27, 2014 at 20:42

My understanding of NACK reception is that the last byte of a Master Receive is not acknowledged. I believe this is normal with i2c, and the master sending a STOP with NO acknowledge is how the slave knows not to send any more bytes.

I have a second i2c bus with two devices to which I only ever transmit, and have never experienced this problem on that bus. That leads me to suspect that it's the receives that are somehow screwing things up.

ittokor
Associate II
Posted on October 28, 2014 at 14:59

Then yes, I do believe that the error only occurs after NACK reception so you may be onto something. Just note that it occurs after a NACK reception from either slave (this makes sense since the master is in charge of sending the NACK).

ittokor
Associate II
Posted on November 14, 2014 at 16:12

graffiti, have you had any success getting to the root of the issue?