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
ittokor
Associate II
Posted on October 17, 2014 at 11:07

Some more details:

- The microcontroller is a PX4FMU.

- No error shows up in the i2c register when placing a breakpoint at the timeout. Perhaps it is cleared before I can see it?

- This happens with and without enabling clock stretch

- This happens for I2C both speeds of 400kHz and 100kHz

- There are external resistor pull-ups on the PX4 of 1k5.

ittokor
Associate II
Posted on October 27, 2014 at 11:09

Any help would be greatly appreciated. I can provide more information as necessary.

graffiti
Associate III
Posted on October 27, 2014 at 11:49

Hi,

Sorry no answer here, but I am having EXACTLY the same problem, interfacing an STM32F437 to an i2c crystal oscillator. In my case the XO is the only slave device on the i2c bus, and I can read and write successfully between 2000 - 10000 times and then, bam, everything stops.

On the software side the failure is occurring in

I2C_WaitOnMasterAddressFlagUntilTimeout when called from I2C_MasterRequestWrite.

The slave address is written tohi2c->Instance->DR but it never appears on the bus, and theI2C_FLAG_ADDR flag is never set. Instead of the address appearing on the bus, a STOP is generated (logic probe attached).

I would also be incredibly grateful if anyone has any insight into what could be causing this.

Thanks, Kieran.

________________

Attachments :

i2c_fail.png : https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006I0eJ&d=%2Fa%2F0X0000000biv%2FqGAFmEteR8WK4bkpl7nd_Q5Ma6_1IL_2MvAoOaeJLaw&asPdf=false
Posted on October 27, 2014 at 12:27

Read out and post content of all I2C registers after the fault happened.

Read the status bytes first, as reading the data register clears some of the status bits through hardware.

Don't use a debugger to read them directly, as it may be intrusive.

JW
graffiti
Associate III
Posted on October 27, 2014 at 12:33

I have found the the reason why writes are failing. Sometimes (every 10 - 20 thousand bus transactions (every 20 seconds or so), the STOP bit in the CR1 register is not cleared.

Then when the new read or write is initiated, the START bit is set in CR1, but the STOP bit is also still set.

I can prevent these null messages on writes by clearing the STOP bit before setting the START bit. I am not using DMA and so:

static HAL_StatusTypeDef I2C_MasterRequestWrite(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint32_t Timeout)

 

{

 

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

 

{

 

//disable stop

 

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

 

}

 

  /* Generate Start */

 

  hi2c->Instance->CR1 |= I2C_CR1_START;

 

 

  /* Wait until SB flag is set */

 

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

 

  {

 

    return HAL_TIMEOUT;

 

  }

does the trick.

I am still having problems with reads though. In the case of a read, towards the end of HAL_I2C_Master_Receive, the I2C_CR1_POS bit is cleared and the function waits for the I2C_FLAG_BUSY to be cleared, which it never is. Continuing to investigate...
ittokor
Associate II
Posted on October 27, 2014 at 12:48

Nice catch!

Any clue what is causing it not to be reset? What is your pull-up resistor configuration?

Thanks for the solution, it helps a lot.

graffiti
Associate III
Posted on October 27, 2014 at 12:58

Hi Itko,

I think the 'fix' probably only hides the real problem :( I am not sure why it is happening. Furthermore, in the reference manual it states:

Note: When the STOP, START or PEC bit is set, the software must not perform any write access to I2C_CR1 before this bit is cleared by hardware. Otherwise there is a risk of setting a second STOP, START or PEC request.

So I think the 'fix' is not allowed, we must discover why it's not being cleared by hardware.

I have 1.5k pull up to 3.3v on both data and clk lines. I also tried using the MCU internal pull up (40-60k?) with no external pull up but had the same problem.

As suggested by Jan, the registers after the empty packet (when I detect the STOP bit still set) are:

SR1 = 0x0 (everything clear)

SR2 = 0x0 (everything clear)

CR1 = 0x201 (STOP and PE (peripheral enable) set)

CR2 = 0x25 (only clock freq set)

DR  = 0x55

Posted on October 27, 2014 at 13:07

> I have found the the reason why writes are failing. Sometimes (every 10 - 20 thousand bus

> transactions (every 20 seconds or so), the STOP bit in the CR1 register is not cleared.

Nice catch, but still, it's symptomatic. What is the reason that STOP is not cleared? Couldn't it be that STOP should not be written until BTF is set (i.e. until the shift register gets empty)? RM0090 rev.7 in 27.3.3 in Master transmitter-Closing the communication subchapter:

Stop condition should be programmed during EV8_2 event, when either TxE or BTF is set.

Now I understand that in English, ''either'' means ''OR'', but given the manuals are written by non-native English speakers, this can be a misunderstanding. In Fig 243, Transfer sequence diagram for master transmitter, EV8_2 is described as ''TxE=1, BTF = 1''. This again does not explicitly state ''AND'' between them, but...

Could you please do an experiment, remove the explicit STOP clearing before START, and insert a test for BTF before writing 1 into STOP?

Thanks,

Jan

graffiti
Associate III
Posted on October 27, 2014 at 13:37

Hi Jan,

I double checked and when I detect the stuck 'STOP' bit (when sending) BTF is 0.

Before setting the STOP bit (when receiving) BTF is always tested and is 1. In HAL_I2C_Master_Receive the following code always appears before setting the STOP bit:

/* Wait until BTF flag is set */

 

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

 

          {

 

            return HAL_TIMEOUT;

 

          }

 

          /* Generate Stop */

 

          hi2c->Instance->CR1 |= I2C_CR1_STOP;

However I think you may be on to something, because the reference manual states:

Note: The BTF bit is not set after a NACK reception

 

And my write failures always occur after a NACK reception. Itko is this also the case for you?