Skip to main content
MMora.7
Associate II
February 4, 2021
Solved

Interrupts and I2C Peripherals

  • February 4, 2021
  • 8 replies
  • 4566 views

Hello all! My name is Matt and I am a university student studying EE. For school, I recently designed a board with an STM32405RG MCU and BMI088 IMU. Part of the project is gathering data from the gyroscope and processing it every time step.

My original plan was to use the gyroscope in polling mode as fast as possible, and then use a timer interrupt to send out important data over serial at ~50 Hz. Before implementing this timer interrupt, the code worked perfectly fine and everything seemed ok. However, as soon as I enable the timer interrupt, my code only runs for a few milliseconds before something calls the Error_Handler().

I am unsure why this is happening. My intuition tells me that the interrupt may be interfering with stuff that HAL is doing to talk to the I2C peripheral. If I want to send out data periodically over serial, does this mean that I also must use the gyroscope in interrupt mode, instead of polling mode? Would I need to set interrupt priorities in some specific if I chose to do this?

A high level description of the code is:

while(1)

{

  1. Read gyroscope data (in polling mode)
  2. Process gyroscope data
  3. Update internal state

}

50Hz_Interrupt_Handler()

{

  1. Read internal state
  2. Send internal state over serial

}

Please forgive any amateur coding mistakes. As I said, I am a university student doing this for the first time :)

Thank you for any help!

Matt

This topic has been closed for replies.
Best answer by KnarfB

Cannot tell the root cause immediately, but some hints: BMI088_I2C_Read_Gyro probably uses a blocking HAL function. HAL relies on the SysTick interrupt which is also used by HAL_Delay. So, it is not advisable using those functions in an interrupt. You can put everything in the main loop. There is a HAL_GetTick() function providing the millisecond SysTick count which you could use to synchronize everything.

If you want to roll your own timer for that, use a volatile global variable to sync timer interrupt and main loop code.

Finally, set a breakpoint at error_Handler and find you how the code came there

hth

KnarfB

8 replies

KnarfB
Super User
February 5, 2021

Don't see an interrupt handler in your code?

MMora.7
MMora.7Author
Associate II
February 5, 2021

Hi. Thanks for the answer!

The interrupt handler is the PeriodElapsedCallback near the end of the file.

Since posting the question, I have changed my code so that there is no code in the main while loop and everything is handled by the GPIO EXTI interrupt which is connected to the sensor data_ready interrupt. I have set the GPIO interrupt to a higher priority than the serial update timer interrupt.

I have verified that the GPIO interrupt routine takes less time than the data period. However, for some reason increasing the data rate causes the Error_Handler to be called every now and then, seemingly sporadically. Now I am really confused because the problem is not consistent. What could be going on?

KnarfB
KnarfBBest answer
Super User
February 5, 2021

Cannot tell the root cause immediately, but some hints: BMI088_I2C_Read_Gyro probably uses a blocking HAL function. HAL relies on the SysTick interrupt which is also used by HAL_Delay. So, it is not advisable using those functions in an interrupt. You can put everything in the main loop. There is a HAL_GetTick() function providing the millisecond SysTick count which you could use to synchronize everything.

If you want to roll your own timer for that, use a volatile global variable to sync timer interrupt and main loop code.

Finally, set a breakpoint at error_Handler and find you how the code came there

hth

KnarfB