cancel
Showing results for 
Search instead for 
Did you mean: 

Global Variables and Timer Interrupt

VForm
Associate II

Greetings to all.

I'm new to this forum and new with STM32 too. So i decided to experiment (and mess) with them to learn something.

Now the first problem. I am esperimenting with timers, and after i discovered we can't use HAL_Delay() inside a timer's interrupt calling, I used a workaround. I set a global variable as a switch, so the interrupt routine only changes the switch. The rest should be made in the while(). After some days changing the code, putting breakpoints, etc.. i surrender.

Here is some code:

#include "main.h"
 
int Bounce = 0; //Bounce Counter
int swTim3 = 0; //Interrupt switch
 
/* some other code lines ...*/
 
  while (1)
  {
	  if (swTim3 > 0)
	  {
		  /* some code toggling the led*/
			swTim3=0; //reset interrupt
	  }
  }
 
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	if (htim->Instance == TIM3) 
	{
		swTim3=1;
	}
}

debugging the program, it does not enter inside the if (swTim3 > 0) {}. If I pause the debugging, it is saying me the swTim3 is equal to 1, so i suppose that the interrupt routine is executed and correctly set the variable.

If i comment the code inside the interrupt routine and set the swTim3=1 before the while(1), it enters inside the "if" block.

Sorry for my bad english and thanks a lot

Vittorio

P.s. I'm using Atollic Studio and a Nucleo F401RE board

1 ACCEPTED SOLUTION

Accepted Solutions
Bob S
Principal

Most likely the compiler is optimizing the code inside the main while loop so that it only reads swTim3 once. That is because, to the compiler, the value of swTim3 can never change (it doesn't know that HAL_TIM_PeriodElapsedCallback() can be called outside the main program flow).

Change the declaration of "swTim3" to:

volatile int swTim3 = 0; //Interrupt switch

That should fix this problem.

HAL_Delay() does not work inside interrupt functions because the timer interrupt is masking the SysTick interrupt. The solution is to set the SysTick interrupt priority to a higher priority (lower value) than the timer interrupt. BUT... you really should avoid using HAL_Delay() inside an interrupt if at all possible.

View solution in original post

5 REPLIES 5
Bob S
Principal

Most likely the compiler is optimizing the code inside the main while loop so that it only reads swTim3 once. That is because, to the compiler, the value of swTim3 can never change (it doesn't know that HAL_TIM_PeriodElapsedCallback() can be called outside the main program flow).

Change the declaration of "swTim3" to:

volatile int swTim3 = 0; //Interrupt switch

That should fix this problem.

HAL_Delay() does not work inside interrupt functions because the timer interrupt is masking the SysTick interrupt. The solution is to set the SysTick interrupt priority to a higher priority (lower value) than the timer interrupt. BUT... you really should avoid using HAL_Delay() inside an interrupt if at all possible.

S.Ma
Principal

Well, first, why not toggle the LED inside the interrupt routine?

Actually, it depends on the SW intented behaviour:

You could decide that the interrupt disable itself after setting the flag, or breakpoint in the interrupt if the flag is already set before doing so.

When stopping the SW while debugging, the HW Timer may or maynot be stopped. (user options).

What is the wished SW behaviour and how the timer is being programmed?

Fantastic! Thank you! It's working perfectly now.

VForm
Associate II

this is the config of the timer3 (84MHz)

  htim3.Instance = TIM3;
  htim3.Init.Prescaler = 41999;
  htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim3.Init.Period = 8000;
  htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;

I already put the "toggling code" inside the interrupt routine, but the execution remains stuck in Hal_Delay() function. So searching infos here and there i discovered what Bob_S said. I removed the code inside the routine, put it in the main() and used the "switch" workaround.

The program counts how many times the button1 is pressed (and bounces) before the timer3 expires, then blinks the led1 "N" times the button1 interrupt fired.

Useless in itself, but useful to practice and experiment with STM32s

VForm
Associate II

by the way, since i like to understand what i do, i searched over the internet and i found this link, hope useful to someone else

https://stackoverflow.com/questions/4437527/why-do-we-use-volatile-keyword-in-c