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.♯

19 REPLIES 19

Think I mentioned this way above, but if you always flush the data register before performing a read transaction, that should do the trick.

No problem!

So I got in touch with ST and they said there was a problem that was fixed in v.1.7.1 of the HAL Libraries where if an interrupt occured during an I2C read it would cause the I2C receive register to get out of sync by 1 byte. I was using v.1.7.0 and they are currently on v. 1.7.3. I tried doing a "dummy read" as others in this thread have suggested and that did not work 100% (though it seemed to help for a while). ST recommended that I update my HAL Library files to v.1.7.3 and reprogram my targets. Here is a detailed explanation of the problem I received in e-mail.

The issue was relevant to how the RXNE and STOP flag were managed inside the static function I2C_WaitOnRXNEFlagUntilTimeout, which is used in polling mode.

Basically the bug could happen if the function would be interrupted in a specific point by an interrupt, like the systick. In the following the details:

 

static HAL_StatusTypeDef I2C_WaitOnRXNEFlagUntilTimeout

(I2C_HandleTypeDef *hi2c, uint32_t Timeout, uint32_t Tickstart)

 while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_RXNE) == RESET)

 {

   /* Check if a NACK is detected */

   if (I2C_IsAcknowledgeFailed(hi2c, Timeout, Tickstart) != HAL_OK)

   {

     return HAL_ERROR;

   }

   // At this moment the last byte is being received but not

completely received (let's say few bits received)

   // Systick gets fired and loads the CPU for few microseconds

   // I2C hardware receives the last byte in RXDR and generates the

NAK and STOP condition as it was set to auto end in I2C_TransferConfig

()

   // Systick finishes the processing

   // CPU gets back to I2C_WaitOnRXNEFlagUntilTimeout() and the first

thing to check the STOP flag which is already set

    // The HAL driver returns a timeout and the last byte is not

copied in the user buffer but the RXDR register does have that data

   /* Check if a STOPF is detected */

   if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_STOPF) == SET)

   {

     /* Clear STOP Flag */

     __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF);

 

     /* Clear Configuration Register 2 */

     I2C_RESET_CR2(hi2c);

 

     hi2c->ErrorCode = HAL_I2C_ERROR_NONE;

     hi2c->State = HAL_I2C_STATE_READY;

     hi2c->Mode = HAL_I2C_MODE_NONE;

 

     /* Process Unlocked */

     __HAL_UNLOCK(hi2c);

 

     return HAL_ERROR;

   }

Nix Wayne
Associate III

Thanks for sharing your findings with ST. That's great to know. I will have a look again at my old code.... I am quite sure my HAL drivers I had used in that project are dated to the version you're mentioning and I think this might help solving my issues. Thanks again.

glad I could help. I am currently testing the fix, but it could take me a few days to see any failures if there are any. I'll re-post if I see any issues.

ingwmeier
Senior

Hi Nicholas,

thanks for sharing ST's answer!

I am also still not sure if I can skip the dummy read which I left in all my projects, since I had no more issues.

static void EEprom_ReadI2C_Page(void)
{
  uint32_t x;
  
  aCommand[0]=0;
  Eeprom.Init=HAL_I2C_Master_Transmit(&hi2c1, EEPROM_ADDRESS, (uint8_t *)aCommand, 1, 2);
  x=hi2c1.Instance->RXDR; // dummy read -> bugfix // todo ???
  Eeprom.Response=HAL_I2C_Master_Receive(&hi2c1, EEPROM_ADDRESS, (uint8_t *)EEpromData, 256, 100);
}

Maybe it was never necessary in L4xx family.

My current hardware is a STM32L431. Halversion is defined:

#define STM32L4XX_HAL_VERSION_MAIN  (0x01U) /*!< [31:24] main version */

#define STM32L4XX_HAL_VERSION_SUB1  (0x0BU) /*!< [23:16] sub1 version */

#define STM32L4XX_HAL_VERSION_SUB2  (0x01U) /*!< [15:8] sub2 version */

does this expand to v1.11.1 ? (STM32F0xx has v1.7.3)

a few days ago with CubeMX 6 it got updated to

#define STM32L4XX_HAL_VERSION_MAIN  (0x01U) /*!< [31:24] main version */

#define STM32L4XX_HAL_VERSION_SUB1  (0x0CU) /*!< [23:16] sub1 version */

#define STM32L4XX_HAL_VERSION_SUB2  (0x00U) /*!< [15:8] sub2 version */

but I feel a bit reluctant to update right now to this latest version,

Werner

​I removed the dummy reads from my code and ran it over night with the updated HAL libraries and so far no failures.  Encouraging results.

Nix Wayne
Associate III

That's very encouraging, indeed. It was my main concern should I change my old working code on live projects or not. I will probably leave is as it is and do a rework for newer versions and other projects. Anyway I am really glad that there is some light at the end of that tunel. 🙂 Take care guys!

​Been testing for almost a week non-stop now and the I2C has not failed.  We are calling it fixed by the newest release of HAL libraries.

Great to hear that! Thanks for letting us know! Take care!