cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F4 TIM6 initialization

MGall.11
Associate III

Dear all,

I'm working on a project based on STM32F479 and FreeRTOS. In this project the microcontroller is connected via I2C and SPI bus to other devices, such as switch ethernet and spi-uart converter. I run the initialization of these devices before the start of the FreeRTOS scheduler. Startup procedure requires switching some GPIOs and waiting a few milliseconds as described in the devices datasheet. I've manged the waiting part of the initialization using the HAL_Delay function. This project has been generated in 2019 with STM32F4 fw package 1.24.0 and an old version of STM32CubeMX.

Recently I've created a new project for the same hardware using fw package 1.28.0 and STM32CubeMX 6.11.1. I noticed that the initialization of TIM6 in stm32f4xx_hal_timebase_tim.c has been updated and HAL_InitTick function is changed (which you can find in the attachment). Now I'm experiencing a strange behaviour. During devices initialization the program remains stuck in the HAL_Delay function. Apparently TIM6 interrupt is not running before the start of the scheduler, so the global variable uwTick is not incremented and as a result HAL_Delay waits forever. I had to move the initialization of the devices after the start of the FreeRTOS scheduler to solve the issue.

Can anyone help me figure out what I'm missing?

Best regards.

Massimo G.

20 REPLIES 20
gbm
Principal

Sorry, I cannot see your point. Both SysTicks are non time-critical. RTOS SysTick interrupt does not trigger other interrupts (other than PendSV of the same priority as SysTick). All the other IRQs are more critical. In a properly designed system the CPU will never be saturated. With a classic, event loop approach and with RTOS-based approach, SysTicks should have the lowest priority. In some cases higher SysTick priority may be desirable in purely interrupt-driven firmware design, where the lowest priority, software-triggered interrupts logically replace the event loops for time-consuming tasks (so they may require timekeeping services).

My STM32 stuff on github - compact USB device stack and more: https://github.com/gbm-ii/gbmUSBdevice

The point is it changed. You may like it better that way, but that is beside the point.

You continue to make an argument about what it should be. That's beside the point. The point is it changed.

I hope that makes it a bit clearer.

gbm
Principal

OK. When you use FreeRTOS with CubeMX, it automatically adjusts interrupt priorities to make your life easier. So it sets both SysTicks and PendSV to the lowest priority and it sets all the other peripherals' IRQs to RTOS Syscall priority (5 by default, unless you chage it). That's actually quite good as a starting point. You may still change the priorities manually in NVIC settings.

My STM32 stuff on github - compact USB device stack and more: https://github.com/gbm-ii/gbmUSBdevice

Hi @MGall.11 

I experienced the same issue when migrated from FreeRTOS 1.0.1 to 1.5.0 (CubeMX 6.17 example STM32U5G9J-DK2-3.0.7.tpa).

CubeMX changed priority of TIM6 to 15 and my previously working Gfx demo stopped working. After i changed TIM6 prio to 0 the demo worked again.

This made me think what is TIM6 used for ? Is it 1ms time base for HAL delay ? Or tick for FreeRTOS ? I think FreeRTOS tick is coming from Cortex SysTick timer. Very confusing.

Yes it is confusing. Changing things without providing a rationale compounds the confusion, as you can see from this thread. Let me try to clear things up:

  1. All ARM devices have a SysTick (called "System tick timer" in CubeMX), in addition to any timer peripherals.
  2. CubeMX has typically defaulted to using SysTick for the HAL "timebase source". That is, SysTick fires the interrupt that increments that tick that you can read with `HAL_GetTick()`. This leaves all the timer peripherals for use by the application.
  3. FreeRTOS requires a "RTOS Tick". It also uses SysTick for this, probably because it is guaranteed to be there on Cortex-M. It is used for preemption (eg. task switching) and timing (eg. measuring delays).
  4. FreeRTOS reserves the upper few priorities (`configMAX_SYSCALL_INTERRUPT_PRIORITY` of them) for critical sections, and has long has a dedicated page to explain how to make sure your application interrupts are compatible. Usually that means using a lower priority for your own interrupts.
  5. Having the RTOS Tick work is so fundamental, that the FreeRTOS initialisation code (on Cortex-M) configures SysTick explicitly, including setting it to the lowest priority.
  6. Since FreeRTOS uses SysTick, it is somewhat common (and long "strongly recommended" in CubeMX) to move the HAL timebase source to a dedicated timer, often TIM6. This may be your situation.
  7. So far so good. But now, as is the subject of this thread, CubeMX will (whether you're using FreeRTOS or not) automatically set the SysTick, and any timer you choose as the timebase, to the lowest priority.


So in your case, TIM6 is doing whatever you configured it to do, which make take some poking around to figure out. On STM32 it's highly likely it is not providing the RTOS Tick (because SysTick does that), and given that the priority changed, it's likely it is the "timebase source" for the HAL. But there's nothing stopping you using it for other purposes too.

Hi ferro,

As explained by LiteYear, it depends on how the system is configured with STM32CubeMX. In my case, I have the TIM6 timer interrupt set to 1 ms, which increments the HAL tick, and the FreeRTOS tick interrupt is handled by the SysTick_Handler IRQ (xPortSysTickHandler) with priority set by configKERNEL_INTERRUPT_PRIORITY. The number of ticks per second is defined by configTICK_RATE_HZ. All of this is configured in xPortStartScheduler.

>> "But wanted to confirm my understanding: in the old HAL implementation the systick priority was 0 and in the new implementation the priority is set to 15 which is not working, and setting it to 0 works again?"

Exaclety. TIM6 prio has changed to 15 (was 0) and with that change, HAL_IncTick() is not called.

As soon as i set TIM6 priority to number 4 or less, the system works. So it seems it has sth to do with that number 5 that sets boundary between "RTOS aware IRQs" and the "rest". I am trying to understand what is masking the TIM6 IRQ. The RTOS initialisation is executed only after HAL modules initialisation so it is not RTOS, I think.

With TIM6 IRQ priority set to 5(or higher), my program waits at delay and HAL_GetTick() returns always 0.

hspi tim6.jpg

 

tim6 time base prio 5 hal_delay.png

 

Uf, really nice write-up, @liteyear - thank you. There’s a lot of material to go through; I’m only just starting with FreeRTOS.

I found that my application (based on STM32U5G9J-DK2-3.0.14.tpa) uses TIM6 for the STM HAL tick and the Cortex SysTick for the FreeRTOS tick.

You mentioned, “All ARM devices have a SysTick.” . Not all, but Cortex-M devices do.

ferro
Lead

@MGall.11 

In you main(), before anything else, try to call __set_BASEPRI(0)

int main(void)
{

  /* USER CODE BEGIN 1 */
  
  __set_BASEPRI(0);

  /* USER CODE END 1 */

 I am trying to understand what is masking the TIM6 IRQ. The RTOS initialisation is executed only after HAL modules initialisation so it is not RTOS, I think.

Something can call a function that internally uses a RTOS lock (for example, malloc) while the scheduler is not started yet. For FreeRTOS, in some configuration, these locks raise BASEPRI.