cancel
Showing results for 
Search instead for 
Did you mean: 

TIM6 Interrupt and Compiler Optimization

MVill.6
Associate II

I have a project (for STM32L0) that use TIM6 to generate an Interrupt every 5ms and everything works perfectly both in release and debug when built wih no optimization.

Then I built the same project with -Os(optimize for Size) -ffunction-section -fdata-section and -WI, --gc-section (Discards the unused sections) and the project works no more.

The reason is that the application spends almost all the time in the Interrupt of TIM6.

(The programs enters TIM6 Interrupt, every 50us)

Here' s a scheme of the interrupt

void TIM6_DAC_IRQHandler(void)

{

 /* USER CODE BEGIN TIM6_DAC_IRQn 0 */

 /* USER CODE END TIM6_DAC_IRQn 0 */

 HAL_TIM_IRQHandler(&htim6);

 /* USER CODE BEGIN TIM6_DAC_IRQn 1 */

// dummy = dummy +1; // explained bellow

 /* USER CODE END TIM6_DAC_IRQn 1 */

}

The following is part of the HAL:

void HAL_TIM_IRQHandler(TIM_HandleTypeDef *htim)

{

...

 /* TIM Update event */

  if (__HAL_TIM_GET_FLAG(htim, TIM_FLAG_UPDATE) != RESET)

  {

    if (__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_UPDATE) != RESET)

   {

    __HAL_TIM_CLEAR_IT(htim, TIM_IT_UPDATE);

     HAL_TIM_PeriodElapsedCallback(htim);

   }

  }

}

// My callback

void  HAL_TIM_PeriodElapsedCallback()

{

.....

}

Beyong the TIM6 interrupt I have other interrupts as well but when built with optimization

I discover that HAL_TIM_IRQHandler() is called continuosly but not my callback as if

TIM_FLAG_UPDATE is always cleared ( So why the handler is get called ?)

There's no way to sort out the things: no clear pending interrupt, no memory barriers ( I saw someone who solved similar problems with that).

It's not a time issue 'cause I set a lot of NOP and nothing changes.

The only one solution I found is to put a dummy instruction like the one commented in the code above. That solved my problem but I can't explain why.

Can someone can explain why or has a better solution ?

Thanks

Marco V.

10 REPLIES 10
Pavel A.
Evangelist III

Can you locate the HAL_TIM_IRQHandler and call to HAL_TIM_IRQHandler in disassembly?

Can you set a breakpoint there and verify it goes where it should be?

Also note that this interrupt is shared with DAC.

Use bisection to limit areas with are and are not optimized.

Watch for things that need to be volatile, but aren't.

Review a disassembly, follow the code that the MCU is actually executing, relate that to you expectations and the C code.

Check the TIM's SR see what's actually flagging.

The dummy increment (rmw) forces bus transactions to complete. The code shown however is not illuminating.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

Show us all TIM6 registers content.

Any other TIM interrupt​ enabled besides TIM6 Update?

​Optimized code with 5ms tick runs OK?

JW​

MVill.6
Associate II

Thanks Everybody

I checked with the scope and the timings are OK when I put the dummy instruction

I'm going to compare the two listings: with and without the dummy write

MVill.6
Associate II

I forgot these

I compare the two listings: on the left thye one without the dummy write; on the right with the instruction: dummy = dummy+1

I agree with you that the only difference is that the dummy instruction forces a read and write operation on the bus memory. I'm more and more convinced that is not a problem of timings

But I also declared

void __attribute__((optimize("-O0"))) TIM6_DAC_IRQHandler()

and nothing changed

Marco V.

​Optimized code with 5ms tick runs OK?

I am convinced that your problem is a lengthy callback from the timer ISR, which you haven't shown us yet.

JW

MVill.6
Associate II

Maybe but you should explain to me why a long sequence of NOT has no effect and a stupid R/W operation involved the memory solve the problem.

Anyway the flow is the following:

+ TIM6_DAC_IRQHandler(void)

+ HAL_TIM_IRQHandler(TIM_HandleTypeDef *htim)

+HAL_TIM_PeriodElapsedCallback(htim);

And this is my callback:

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)

{

if (htim == &htim6)

{

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

// M.V. TIM4 was used as a timeout for SYNCRO

// now the same function is done through TIM7

if (timeout_tim4)

timeout_tim4--;

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

if (timeout_scanprg)

timeout_scanprg--;

if (!CALIBRATEMODE_FG)

{ // Avoid debounce in CALIBRATION 'cause input from down key is used to calibrate

if (DOWN_PRESSED)

{

if (!key_down_pressed)

{

key_down_pressed = true;

KeyDownCheck();

}

}

else if (!DOWN_PRESSED)

{

key_down_pressed = false;

}

}

if (ACMainsDetected)

{

if (SyncroTime > 0)

--SyncroTime;

else

{

SyncroEdge = 0;

ACMainsDetected = false;

}

}

}

}

And:

#define DOWN_PRESSED (HAL_GPIO_ReadPin(DOWN_GPIO_Port, DOWN_Pin) == GPIO_PIN_RESET)

The only function that may take some time is KeyDownCheck() but I check that the firmware never

get there so it doesn't matter.

HAL_TIM_IRQHandler(TIM_HandleTypeDef *htim) is defined in the HAL. I tried to get just the part regarding the TIM Update event but this does not solve the problem

Really the flow enter the callback and find that the condition

__HAL_TIM_GET_FLAG(htim, TIM_FLAG_UPDATE) != RESET

is never true (i.e. TIM_FLAG_UPDATE is 0) but then why does it come here?

It should come here only when the time is elapsed and the flag is SET. Right?

Marco V.

OK, I am out of ideas.

​Btw, optimized code with 5ms tick runs OK?

Oh, and are there any interrupts with higher priority?

JW