cancel
Showing results for 
Search instead for 
Did you mean: 

I2C causes STM32F051 to crash/reboot

evert2
Associate II
Posted on November 29, 2013 at 16:07

Hello,

I've an STM32F051 where i2c modules can be connected (SFP video modules)

These modules should be hot swappable, however it seems that the I2C communication is not dealing properly with these modules because sometimes a crash or reboot occurs when I plugin a i2c module.

I use next code to check if a I2C module is available, only when this check succeeded I retrieve some data from that specified module.

It looks like the crash occurs during this routine, which I borrowed from the LM75 example. Does someone have any idea what might go wrong?

Thanks in advance,

Evert Huijben

ErrorStatus SFP_GetStatus(I2C_TypeDef* I2Cx, uint8_t I2Caddr)

{

   uint32_t I2C_TimeOut = I2C_TIMEOUT;

  /* Configure slave address, nbytes, reload, end mode and start or stop generation */

  I2C_TransferHandling(I2Cx, I2Caddr, 0, I2C_AutoEnd_Mode, I2C_No_StartStop);

  /* Clear NACKF and STOPF */

  I2C_ClearFlag(I2Cx, I2C_ICR_NACKCF | I2C_ICR_STOPCF);

  /* Generate start */

  I2C_GenerateSTART(I2Cx, ENABLE);

  /* Wait until timeout elapsed */

  while ((I2C_GetFlagStatus(I2Cx, I2C_ISR_STOPF) == RESET) && (I2C_TimeOut-- != 0));

  /* Check if Temp sensor is ready for use */

  if ((I2C_GetFlagStatus(I2Cx, I2C_ISR_NACKF) != RESET) || (I2C_TimeOut == 0))

  {

    /* Clear NACKF and STOPF */

    I2C_ClearFlag(I2Cx, I2C_ICR_NACKCF | I2C_ICR_STOPCF);

    return ERROR;

  }

  else

  {

    /* Clear STOPF */

    I2C_ClearFlag(I2Cx, I2C_ICR_STOPCF);

    return SUCCESS;

  }

}

#stm32f051-i2c-crash
18 REPLIES 18
chen
Associate II
Posted on December 11, 2013 at 12:20

Hi

When measuring the Power line - put the scope channel into AC coupled mode and up the v/div on that channel. I assume the STm32 is running 3.3V

You are only looking for a high speed spike/drop

Also put a scope channel on the STM32 reset line.

Again you are looking to see if the reset line has any noise (due to the hot swap)

If you have a 4 channel scope:

Look at the I2C lines as well.

See what happens when you hot swap.

The only states that I think may cause a lock up are unhandled/fault IRQs.

Change the default IRQ (I assume that any IRQ you have not written an ISR for, the default one is used) to give you an indication on the LEDs

Does the default one go into an infinite loop?

Do any of the fault IRQs do an infinite loop?

Again - make them do something with the LEDs.

Since this is a product in the field - you are right : all you can do is to try and handle/manage the reboot/lock up.

It sounds like you can handle the reboot.

The only problem now is the lock up. I have mentioned the default and fault ISRs.

I do not know of what else could put he STM32 into a state where it has stopped or is doing something we do not know.

frankmeyer9
Associate II
Posted on December 11, 2013 at 13:23

Not sure I understood you post correctly, but if you have a watchdog enabled, and your firmware hangs (possibly in an I2C-related endless loop ?), a reset/reboot will surely follow.

And with 'I2C hotplug', you will definitely produce glitches on the SCL/SDA lines (and not on the power supply), which could cause  spurious transitions.

I suspect your firmware hangs than in some endless loops in your I2C routines, where you wait for I2C status flags to change.

evert2
Associate II
Posted on December 11, 2013 at 16:09

Dear all,

Thank you,

I'am focussing now on the hangup since I'am convinced that glitches on the i2c line are causing reboots.

Also the hangup is caused by i2c because when i cut the i2c lines no hangups and reboots occur anymore.

But also in this case the system should reboot correctly because I have added a watchdog of 1 second, see next functions.

void watchdog_service(void)

{

  IWDG_ReloadCounter();

}

/**

 * Initialises watchdog to 1 second.

*/

void watchdog_init(void)

{

  IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);

  IWDG_SetPrescaler(IWDG_Prescaler_16);

  IWDG_SetReload(2500);

  IWDG_WriteAccessCmd(IWDG_WriteAccess_Disable);

}

/**

 * Enables watchdog just before main loop

 */

void watchdog_enable(void)

{

  IWDG_Enable();

} When I don't call watchdog_service() in my main routine, the watchdog makes sure that my system reboots.

But I'am pretty sure that the the system tries to reboot because I enable some outputs (LEDS) at the startup of my application, and when the hangup occurs they are switched off.

I have also added a hardfault handler, but also this handler is not activated.

If endless loops should be the issue I expected that the LED's were not turned of and the watchdog should be activated.

Or should I use a WWDG watchdog?

And is there a way to check for other interrupts?

Thanks in advance,

Evert Huijben

chen
Associate II
Posted on December 11, 2013 at 16:30

Hi

I agree - concentrate on the hang ups.

Do a search through all the code for any loops which do not have a time out exit.

The code you showed at the beginning has a while loop with a timeout exit.

Change any loop that does not have a timeout exit to have one.

Look at the ISR table - probably in the start up assembly file.

This will list all the ISRs in the system and what to run for each.

As I said, for any you have not defined, a default one is called.

Look at the default one - does it contain an infinite loop?

Change the default one so that it shows something on your LEDs.

Do you have a debugger connected?

What does it show when there is a lockup?

(you may have to deal with assembler but that is OK, the address and the map file will give you an indication of where the code is running.)

frankmeyer9
Associate II
Posted on December 11, 2013 at 16:32

I haven't used the watchdog on STM32 MCUs yet, but the WWDG is just a more 'restrictive' version of a WDG. One needs to do the WDG access in a specific time frame (i.e. the 'window'), instead of before expiration. I don't see any specific advantage in your case.

If endless loops should be the issue I expected that the LED's were not turned of and the watchdog should be activated.

 

That is my expectation, too.

A quick option to check for endless flag busy-pollings would be to replace

while (wait_for_flag);

 

with something like:

do

 

  toggle_gpio;

 

while (wait_for_flag);

 

This should make such busy-waits observable with a scope.

But, as mentioned: you are not able to guarantee that a ''hot plug event'' does not happen while an I2C transmission is ongoing, were any glitch has rather bad effects. So I would not allow hot plugging at all.

evert2
Associate II
Posted on December 12, 2013 at 12:01

Hi,

I have checked all my while loops and they seem to be ok.

I have not connected a debugger yet.

But the issue also appears when I do not call any i2c function.

When physically disconnecting the lines it seems to be ok.

However I discovered that pulling the NRST pin to ground is also not resetting the device in case of an hangup. In normal circumstances this pin works fine.

This may explain why a software reset by the watchdog is also not working.

Only a hard reset by power on and off is resetting the device.

Maybe someone has have similar issues in the past?

Regards,

Evert Huijben

frankmeyer9
Associate II
Posted on December 12, 2013 at 13:41

That sounds rather strange.

Could your code possibly cause a core lockup, e.g. is your hardfault handler causing a hardfault ? Is your vector table located in RAM ?

evert2
Associate II
Posted on December 13, 2013 at 09:18

Hi,

My hardfault handler is never reached, so it lookslike a hardfault within a hardfault is not possible.

About the vector table, it's indeed located in SRAM, because I have implemented a bootloader and when I enter my application I move the vector table to SRAM because the STM32f0 only allows one instance of the vector table.

I used the IAP example from the ST library, see next

Can this implementation lead to the mentioned problems?

Regards,

Evert Huijben

/*************************************************************************/

/* The Cortex M0 does not support multiple instances of the vector table */

/* So move the vector table to RAM, See ST documentation IAP             */

  __IO uint32_t VectorTable[48] __attribute__((section(''.RAMVectorTable'')));

At the start of my main() loop:

   /*********************************************************************************/

   /* Relocate by software the vector table to the internal SRAM at 0x20000000 ***/

   /* Copy the vector table from the Flash (mapped at the base of the application

      load address 0x08008000) to the base address of the SRAM at 0x20000000.

      Needed because the Cortex M0 only supports one instance of the vector table*/

  uint32_t i = 0;

  for(i = 0; i < 48; i++)

  {

     VectorTable[i] = *(__IO uint32_t*)(APPLICATION_ADDRESS + (i<<2));

  }

   /* Enable the SYSCFG peripheral clock*/

  RCC_APB2PeriphResetCmd(RCC_APB2Periph_SYSCFG, ENABLE);

  /* Remap SRAM at 0x00000000 */

  SYSCFG_MemoryRemapConfig(SYSCFG_MemoryRemap_SRAM);

  /**********************************************************************************/

frankmeyer9
Associate II
Posted on December 13, 2013 at 10:16

My hardfault handler is never reached, so it lookslike a hardfault within a hardfault is not possible.

 

You will find more detailed info on the ARM infocenter webpage, just use your favourite search engine. But one example of lockup cause is given there - invalid handler addresses. Remember, all handler addresses bear the mode bit, i.e. the LSB must be 1 to indicate Thumb mode.