TIM6 Interrupt and Compiler Optimization
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2022-07-08 6:49 AM
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.
- Labels:
-
STM32L0 Series
-
TIM
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2022-07-08 3:47 PM
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2022-07-08 4:41 PM
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.
Up vote any posts that you find helpful, it shows what's working..
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2022-07-09 12:57 AM
Show us all TIM6 registers content.
​
Any other TIM interrupt​ enabled besides TIM6 Update?
​
​Optimized code with 5ms tick runs OK?
​
JW​
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2022-07-11 12:00 AM
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2022-07-11 12:02 AM
I forgot these
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2022-07-11 12:41 AM
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2022-07-11 2:49 AM
​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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2022-07-11 3:25 AM
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2022-07-11 7:35 AM
OK, I am out of ideas.
​Btw, optimized code with 5ms tick runs OK?
Oh, and are there any interrupts with higher priority?
JW
