11.1.0 regression when the firmware is loaded from a bootloader
I open this issue as a follow-back of this one #65, since I see that the same issue is there with FreeRTOS 11.1.0. The last release that works properly is 10.4.6. Starting from FreeRTOS 10.5.1 I saw this issue. I summarize here what I wrote in issue #65
I have an application running on STM32H725, with peripheral configuration code generated by STM32CubeMX 6.13.0. I think that STM32CubeMX is important here (I will describe the reason later) This application can be compiled in two different ways:
- to be executed directly (out of the Cortex-M reset)
- to be started from a custom bootloader running from user flash (i.e., vector table relocation, ...)
Everything works fine with CMSIS-FreeRTOS 10.4.6, but when I upgraded the pack to 11.1.0 I see a regression:
-
when the application is executed directly, everything is ok
-
when it's started by a bootloader, this is the call chain
main() >> HAL_Init(); >> HAL_InitTick(TICK_INT_PRIORITY)where
#define TICK_INT_PRIORITY (15UL) /*!< tick interrupt priority */Then
/*Configure the TIM6 IRQ priority */ if (TickPriority < (1UL << __NVIC_PRIO_BITS)) { HAL_NVIC_SetPriority(TIM6_DAC_IRQn, TickPriority ,0); /* Enable the TIM6 global Interrupt */ HAL_NVIC_EnableIRQ(TIM6_DAC_IRQn); uwTickPrio = TickPriority; } else { return HAL_ERROR; } ``` and after that the function `void TIM6_DAC_IRQHandler(void)` is continously called and nothing else.
I suppose some issue with interrupt priorities.
Here is what I found out: STM32CubeMX 6.13.0 generates source code to use TIM6 as a time base source.
I saw that inside stm32h7xx_hal.c
__weak HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
is defined as a __weak function
and it's reimplemented by source code generated by STM32CubeMX 6.13.0 in stm32h7xx_hal_timebase_tim.c
In stm32h7xx_hal.c I see
/* Configure the SysTick IRQ priority */
if (TickPriority < (1UL << __NVIC_PRIO_BITS))
{
HAL_NVIC_SetPriority(SysTick_IRQn, TickPriority, 0U);
uwTickPrio = TickPriority;
}
else
{
return HAL_ERROR;
}
In stm32h7xx_hal_timebase_tim.c I see
/*Configure the TIM6 IRQ priority */
if (TickPriority < (1UL << __NVIC_PRIO_BITS))
{
HAL_NVIC_SetPriority(TIM6_DAC_IRQn, TickPriority ,0U);
/* Enable the TIM6 global Interrupt */
HAL_NVIC_EnableIRQ(TIM6_DAC_IRQn);
uwTickPrio = TickPriority;
}
else
{
return HAL_ERROR;
}
/* Enable TIM6 clock */
__HAL_RCC_TIM6_CLK_ENABLE();
You can see the different timer used as a base (SysTick vs TIM6), but this is not an issue by itself.
Most important, see that in stm32h7xx_hal_timebase_tim.c there is
/* Enable the TIM6 global Interrupt */
HAL_NVIC_EnableIRQ(TIM6_DAC_IRQn);
As soon as this is called, the callback void TIM6_DAC_IRQHandler(void) is called immediately, and I think this is because the clock has been already enabled by the bootloader, and/or a TIM6 interrupt is pending.
Not sure why everything work with CMSIS-FreeRTOS 10.4.6, but the code generated by STM32CubeMX doesn't convince me. I'll go on with my investigation.
Quick questions :
did the bootloader use FreeRTOS or is it BareMetal ? did it (the bootloader) disable the fautive interrupt before launching the application ?
I run in this smae sort of issue, when i restart my Apps which use TIM6 and FreeRTOS with my bare metal BootLoader.
did the bootloader use FreeRTOS or is it BareMetal ?
The bootloader uses FreeRTOS.
did it (the bootloader) disable the fautive interrupt before launching the application ?
This is the code that clears the interrupts before jumping to the application:
//Disable all enabled interrupts in NVIC
NVIC->ICER[0] = 0xFFFFFFFF;
NVIC->ICER[1] = 0xFFFFFFFF;
NVIC->ICER[2] = 0xFFFFFFFF;
NVIC->ICER[3] = 0xFFFFFFFF;
NVIC->ICER[4] = 0xFFFFFFFF;
NVIC->ICER[5] = 0xFFFFFFFF;
NVIC->ICER[6] = 0xFFFFFFFF;
NVIC->ICER[7] = 0xFFFFFFFF;
//Clear all pending interrupt requests in NVIC
NVIC->ICPR[0] = 0xFFFFFFFF;
NVIC->ICPR[1] = 0xFFFFFFFF;
NVIC->ICPR[2] = 0xFFFFFFFF;
NVIC->ICPR[3] = 0xFFFFFFFF;
NVIC->ICPR[4] = 0xFFFFFFFF;
NVIC->ICPR[5] = 0xFFFFFFFF;
NVIC->ICPR[6] = 0xFFFFFFFF;
NVIC->ICPR[7] = 0xFFFFFFFF;
//Disable SysTick module
SysTick->CTRL = 0;
//Clear its exception pending bit
SCB->ICSR |= SCB_ICSR_PENDSTCLR_Msk;
//Disable individual fault handlers
SCB->SHCSR &= ~(SCB_SHCSR_USGFAULTENA_Msk | SCB_SHCSR_BUSFAULTENA_Msk |
SCB_SHCSR_MEMFAULTENA_Msk);
last suggestions, could you verify the status of TIM6 before launching App, then if it run stop it. (and ask why ?)
This is the status of TIM6
This is (a subset of) NVIC
I haven't find the origin for this issue yet.
I see that bit0 of CR1 of TIM6 is set to 1 so Counter Enabled, you disable it. The DIER bit 0 is enabled -> Update Interrupt Enabled set this bit to 0 before jump Then status register is 1 clear it before jump (it is cleared by software)
Those 3 steps should help you
@cbusquet-expressivee thanks! As far as I can see now, your seggestion works. I'll do deeper testing in the next few weeks.
@cbusquet-expressivee based on my tests, your suggestion is the fix for the issue. Thanks again