cancel
Showing results for 
Search instead for 
Did you mean: 

I2C Receive getting extra invalid byte using HAL

Ross Yeager
Associate III

Posted on May 31, 2017 at 19:33

I am using an stm32f030x8. I am using the HAL. Normal operation I can use I2C reads/writes with no problems; however, I can occasionally have errors in the receive data when more activity is taking place on the MCU. I scoped the lines and the bytes on the line are correct/as expected. While step debugging, I can see that the data seemingly gets shifted by a byte when this occurs (i.e. byte 0 in the receive array is some garbage value that was not actually on the bus (verified from scoping the lines), byte 1, 2 etc are the expected data. 

Things to note: using synchronous reads here, interrupts are not in play. this system uses single priority interrupts (no nesting)

Things I have verified:

  • The actual data on the physical line is correct (scope + logic analyzer verifies this)
  • I verified that the pointer address for the buffer being passed in does not get changed (rules out memory corruption of that pointer)
  • Verified that the bad data byte is being read out of the rx hw register. The following line shows that RXDR is holding the 'garbage' byte during step debug: (*hi2c->pBuffPtr++) = hi2c->Instance->RXDR;
  • Verified that worse case memory does not corrupt stack/heap (this was my initial thought since we are pretty close to utilizing the full RAM capabilities of this device). We have ~800 bytes to spare between heap/stack region in worse case scenario.♯

1 ACCEPTED SOLUTION

Accepted Solutions
Ross Yeager
Associate III
Posted on June 20, 2017 at 09:25

Turns out the solution here was to flush the stale byte out of the data register.  Seems like it may be a HAL or HW bug that that byte was not cleared during previous reads, but reading the data register before making the call to the HAL_I2C_Master_Read() call gets it to work as expected.

View solution in original post

19 REPLIES 19
Ross Yeager
Associate III
Posted on June 20, 2017 at 09:25

Turns out the solution here was to flush the stale byte out of the data register.  Seems like it may be a HAL or HW bug that that byte was not cleared during previous reads, but reading the data register before making the call to the HAL_I2C_Master_Read() call gets it to work as expected.

ingwmeier
Senior
Posted on June 20, 2017 at 15:27

had the same problem with an STM32F051 chip reading 18bytes of a hall angle detector chip. For about 5min everything runs fine, after that, the extra byte seems always to be there. Since I knew the result bit pattern, and the ghost byte always being zero I could detect and fix the reading. Doing a dummy read like x=hi2c1.Instance->RXDR; right before HAL_I2C_Master_Read() seems to fix it. Thank you Ross. It feels better like that. I would appreciate a statement from ST, and especially if it is a HW bug, find it's way into the official 'device limitations' document

Posted on August 07, 2017 at 03:19

Thanks for the suggestion to do the dummy read!

I was having the same issue with an STM32F303.  If an interrupt hit while an I2C read sequence was in process, and the IRQ took long enough, I would get an extra byte in the I2C data.

I have sense added the dummy read at the top of the 

HAL_I2C_Master_Read() function itself, and I don't seem to get the extra byte anymore.

On a side note, I ported my code over to an F4 nucleo board, and wasn't able to replicate the bug.  

Matthias Schranz
Associate II
Posted on November 14, 2017 at 07:28

i had the same problem on my stm32l082czw. fun thing is, the problem only occured when the usb driver was enablet and transmitting data besides the i2c. but the dummy read on top of the HAL i2c read function cleared out the problem! thank you so much! is this bug reported yet?

David Henretty
Associate II

Posted on November 14, 2017 at 19:19

I also have been experiencing this issue with an STM32F769 connected to an STMPE811 Touchscreen Controller over I2C3. It has been driving me crazy as the I2C bus transactions all look OK (as seen by a Logic Analyzer) .

When the HAL gets into this state, even reading registers from the STMPE811 results in garbage. e.g. The CHIP_ID register (which should return 0x0811) returns 0x??08 (where ?? is some random value). Reading the ID_VER register (next register address) in the next HAL_I2C_Mem_Read() transaction then returns the remaining 0x11 from the CHIP_ID register instead of the 0x03 that is expected. You can imagine what this does for the rest of the touchscreen interface !

To date, my solution has been to periodically read the CHIP_ID register and, if 'corrupt', perform both an I2C3 re-initialisation AND an STMPE811 re-initialisation. None of this should be necessary in a properly tested HAL. I will look into your suggestion Ross, but would like to echo Werner's call for ST to provide some sort of an update. This appears to be the same issue as

https://community.st.com/s/question/0D50X00009XkepL/stm32f7-hal-i2c-reading-bytes-out-of-sync

which has been outstanding for 18 months.

Is it just me or do ST make a general habit of going silent when a problem is raised ? There is still an outstanding issue awaiting comment (after almost seven months) on

https://community.st.com/s/question/0D50X00009XkgKx/stm32-cyptolib-with-iar-811

. Even acknowledging the issues would be a significant step forward.

ferrario
Associate III
Posted on January 22, 2018 at 21:24

I had a similar behaviuor :

- In Master Polling mode I had to read back 4 Bytes from HiH6130.

It worrked pretty much ok for some minutes.

After that I realized that the STM32 was always sending the right number of clock edges to the slave that sent B0, B1, B2, B3 back.

Received Byte0 was indeed stored one byte ahead in the memory. Say mi buffer was located @ 0x200083d0, the first received byte was stored @ 0x200083d1. This was not the case a few seconds before.

Location 0x200083d0  was indeed filled with Byte 3 from the previous read!!

Say STM32 started reading  and stored first the last byte B3' of the previous transmission  @ location 0x200083d0, than the first 'real byte' B0 came in and was stored  @0x200083d1. Of course the first byte on the bus was B0. 

The last byte being stored was B2 @0x200083d3.

Proper operation, B are the bytes on the bus seen with my protocol analyzer

0x200083d0    B0

0x200083d1    B1

0x200083d2    B2

0x200083d3    B3

Real operation, after few minutes

0x200083d0    B3'

0x200083d1    B0

0x200083d2    B1

0x200083d3    B2

where B3' is the last byte from the previous transfer.

The 4th byte B3 was not stored this time but would be used the next one as B0.

After reading I reset the peripheral and get rid of this issue.

Fabio

Nix Wayne
Associate III

Hi guys,

I can easily join you in this conversation as I have similar problem with my STM32F072 and polling MPU6050. However I haven't implemented the solution yet.

It happens similar to me... I am reading 14 bytes and works fine but then after some time something happens and data seems to be shifted by one byte. So first read byte is always wrong and next bytes are fine.

I used logic analyzer to inspect communication and it looks ok on wires.

So data on wire looks as follows:

  1. packet: 0xcc, 0xdd, 0xee, 0xff
  2. packet: 0x11, 0x22, 0x33, 0x44
  3. pacekt: 0x55, 0x66, 0x77, 0x88....

But the reading out of that second packet looks that in the code:

data[] = 0xff, 0x11, 0x22, 0x33,

the next packet reading will be:

data[] = 0x44, 0x55, 0x66, 0x77 .... (logic analyzer will show 0x55, 0x66, 0x77, 0x88)

As you can see it's shifted by one byte...

what exactly you did to solve that problem? ¸I am reading that you made dummy read. But how do you detect that first byte get's corrupted to perform dummy read?

Thanks for your help.

I seem to be having exactly the same problem...except for me a failure takes many hours (usually over night) and if I'm running 4 separate targets with the same code not all the boards will fail at the same time. I have also noticed that if I'm running a debugger attached and running the problem doesn't seem to occur at all. I see the last post here was 2 years ago...has this problem been solved by or even acknowledged by ST yet? what is the exact code I need to add to fix this issue?

Nix Wayne
Associate III

I found some workarounds instead of solutions. It seems there's problem with I2C on F1 series and workaround is explained in ERRATA. I spoke with some of my friends who are also working with I2C and they complained about similar issues. Workaround is first to detect that I2C stopped working (eg. timer watchdog checking line activities) then you manually reconfigure lines and toggle levels to clockout data line, then you reconfigure it back to I2C and it (usually) will work again. This can be done quite fast so the data will be corrupted only for short time. I had similar experience with STM32L101, STM32F07 and STM32F403 I2C peripherals. Solution for us was not to use I2C sensors anymore. We rathere use sensors with SPI which work much better in my experience.