hi everyone
i’m just at the first tests with freeRTOS on a stm32f446re board, using CubeMX to configure the system and developing on AtollicTrueStudio.
i’ve noticed some weird facts:
first, is that the tick period result about 0.98ms.
doing osDelay(1000) and measuring with an oscilloscope the period of a digital pin toggling, the period is actually about 980ms.
with osDelay(100)->98ms.
i’ve configured the clock at 180MHz using the HSE, but here another problem, if from PLL source MUX i select HSE, 1 tick become 3.2ms instead of 1ms. so i suppose that the systemcoreclock in the config file is wrong (not 180MHz?).
Selecting HSI from PLL source MUX, tick period become 0.98ms.
last thing, is that chancing frequency and clock parameters in the FreeRTOSconfig.h file, don’t affect the behavior of the program (e.g. changing tick frequency to 500Hz vTaskDelay(1000) the delay is still 1 second)
Apologies if you receive a reply to this twice - I posted my first reply at exactly the same time that the forums went into read only mode.
Ref the delay accuracy. I suspect osDelay() calls vTaskDelay() - which means the delay period is relative to when the function is called. If you use vTaskDelayUntil()
then the delay period is relative to the last time the task called vTaskDelayUntil().
Ref the clocks. It sounds like ST are not using the constants in the FreeRTOSConfig.h file so you need to look at your setup to see how the tick interrupt is
being generated. If the constants in the FreeRTOSConfig.h file are being used then, at least in the code we provide, configCPU_CLOCK_HZ must be set to the frequency of the clock that is used to generate the tick interrupt.
i use the Timer1 as system clock, this should be the configuration.
as soon as i’ll try to use the systemdelayuntil method, even if with osDelay or vTaskDelay i expect to have a delay of: osDelay+Tcomputation, so a constant error not proportional as in my case. even if i don’t think that the computation time of a pin toggling could change something.
TIM_HandleTypeDef htim1;
HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
{
RCC_ClkInitTypeDef clkconfig;
uint32_t uwTimclock = 0;
uint32_t uwPrescalerValue = 0;
uint32_t pFLatency;
/*Configure the TIM1 IRQ priority */
HAL_NVIC_SetPriority(TIM1_UP_TIM10_IRQn, TickPriority ,0);
/* Enable the TIM1 global Interrupt */
HAL_NVIC_EnableIRQ(TIM1_UP_TIM10_IRQn);
/* Enable TIM1 clock */
__HAL_RCC_TIM1_CLK_ENABLE();
/* Get clock configuration */
HAL_RCC_GetClockConfig(&clkconfig, &pFLatency);
/* Compute TIM1 clock */
uwTimclock = 2*HAL_RCC_GetPCLK2Freq();
/* Compute the prescaler value to have TIM1 counter clock equal to 1MHz */
uwPrescalerValue = (uint32_t) ((uwTimclock / 1000000) - 1);
/* Initialize TIM1 */
htim1.Instance = TIM1;
/* Initialize TIMx peripheral as follow:
+ Period = [(TIM1CLK/1000) - 1]. to have a (1/1000) s time base.
+ Prescaler = (uwTimclock/1000000 - 1) to have a 1MHz counter clock.
+ ClockDivision = 0
+ Counter direction = Up
*/
htim1.Init.Period = (1000000 / 1000) - 1;
htim1.Init.Prescaler = uwPrescalerValue;
htim1.Init.ClockDivision = 0;
htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
if(HAL_TIM_Base_Init(&htim1) == HAL_OK)
{
/* Start the TIM time Base generation in interrupt mode */
return HAL_TIM_Base_Start_IT(&htim1);
}
/* Return function status */
return HAL_ERROR;
}
void HAL_SuspendTick(void)
{
/* Disable TIM1 update Interrupt */
__HAL_TIM_DISABLE_IT(&htim1, TIM_IT_UPDATE);
}
void HAL_ResumeTick(void)
{
/* Enable TIM1 Update interrupt */
__HAL_TIM_ENABLE_IT(&htim1, TIM_IT_UPDATE);
}
/ ************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
I’ve solved.
In practice the problem was the too high clock frequency, at 180MHz seem that the system tick goes faster.
The maximum frequency without this problem is about 120MHz.
One thing to look into is the results of the various calculations in the code. Sometimes you can run into issues at some clock rates that some of the numbers don’t fit into needed field widths (I don’t see an issue at first look).
One thing you could do to separate possible MCU from OS/configuration problems is monitor the DWT tick counter (or for that purpose, any Cortex Timer). Those get incremented with every MCU cycle, so after exactly one second, your counters must have a delta of exactly your configured clock frequency.
Since you’re running off the HSE, most likely the external quartz is running off. Have you measured it with your scope?
Re: Comparing against an absolut time base - sorry, I figured that if you know how to handle a scope, you could also work out one of the various ways to check the MCU signal against an external frequency - we’re talking about a 2% deviation here, that should be very easy to determine (eg 2 sec off at 100 seconds - you could even compare the processor RTC against a stop watch or something).
my oscilloscope have a bandwidth of 10MHz, so i guess that i can’t do that directly. i’m really confused about clock settings right now, because if i select HSE from PLL mux i get a system tick 3 times slower (3seconds instead 1 second), using the HSI i get that 2% deviation.
in this configuration i get 2% deviation.
but i think that HSE have no influence on the systick, could i even deactivate it?
i’m sorry but i’ve always setted up these parameters in an approximatively way, since i didn’t need high clock frequency, and now i get these strange effects
the relationship between the MCU frequency and the sys tick is determined by the freertos constants. HSE and HSI are very simply two different ways to clock the MCU. HSE means external clock (crystal), HSI internal. You normally don’t want the internal MCU clock, it’s way too imprecise to be useful. Normally it’s only used for startup and emergency fallback if the external quartz fails.
The only way for FreeRTOS to get out of sync against the MCU clock is if some ISR prevents the sys tick handler from running, so the sys tick count gets updated too infrequently. But since your sys ticks are too fast, that is pretty much a 100% guarantee that your MCU frequency already is too fast. That means that either the quartz is too imprecise or the PLL is misprogrammed. If in doubt, ask w/ ST or study several sample clock initialization routines from existing sample projects.
BTW, I just looked at the init code you provided, and I believe you are looking at the wrong place. Unless I’m mistaken, HAL_InitTick() doesn’t have anything to do with clock initialization but initializes the (completly brain dead) ST HAL timer interrupt. Look at the HAL_RCC_OscConfig() and related functions to see where the HAL initializes the MCU clock.
Added: You can call HAL_RCC_GetSysClockFreq() anywhere in your code after PLL init. It should return 180000000 for a 180 MHz configuration. If it doesn’t, your PLL is misconfigured. If it does but you’re still 2% off AND you are configured to run HSE, your crystal is too fast. Otherwise (HAL_RCC_GetSysClockFreq() ) == 180000000 but something else than the HSE is configured and you’re still 2% off) it is a misconfigured PLL.
i’ve solved finally!
was a stupid error, i was setting external clock frequency.
it is fixed at 8MHz! the possibility to enter a number misled me.
now with HSE i can set 180MHz without any errors.
with HSI ther’s still that 2% may due to the PLL