cancel
Showing results for 
Search instead for 
Did you mean: 

Bug: RTOS task scheduler too fast

DMeie.2
Senior

MCWB Version: 6.2.1
CubeMX Version: 6.10.0

Issue: I generate a default project for the B-G431-ESC1. Only settings I change is to enable the FreeRTOS with TIM6 as the tick timer. Firmware Package Version is V1.5.1 (Recommended).
Via CubeMX I add a GPIO output pin for debug purposes and regenerate the project. FreeRTOS settings show that TICK_RATE_HZ is set to 1000 (1ms).
I open the project with CubeIDE and add HAL code to toggle the added debug Pin inside the HAL_TIM_PeriodElapsedCallback for TIM6. My expectation is that the pin now toggles at an 1ms interval. When looking at the pin's signal, I see that this is the case, as expected.

I now create a custom task inside CubeMX. The default code adds osDelay(1) which translates to 1ms. I move the code to toggle the pin to this custom task. My expectation is that the pin should again toggle at an 1ms interval.
However, when checking the pin's signal, the pin toggles at a 500µs interval.

When double-checking the code, I noticed that the default code added by the Motor SDK that's responsible for the MediumFrequencyTask and SafetyTask tasks both add a wait time of vTaskDelay(1) which should translate to a 1ms interval (as the tick time is 1000Hz = 1ms), however there's a comment saying "/* Delay of 500us */" which means the issue with the faulty task timing is known.

 

What's the deal with this?
How can I fix this?

8 REPLIES 8
AScha.3
Chief III

What delay you get at "10" ?

Using just one tick of a interrupt generated interval always has some logical problem, read:

EFTON - STM32 gotchas - Gotcha 13

So see any delay of this kind as :  delay xx ms , +/- 0,5ms .

+

If you want a micro-second-precision delay, you have to use+set a timer for this.

If you feel a post has answered your question, please click "Accept as Solution".

osDelay of "10" gives me 5ms delay time, again half the expected value.
This also happens when I use vTaskDelay and the provided MS_TO_TICKS macro, or vTaskDelay directly.

That there's some slight delay and jitter going on with an RTOS that runs more than one task is clear, however that the specified task time is always half the expected one while the system timer itself is running correct makes no sense to me. There must be some RTOS configuration issue with the code generated by the MCWB (and thus CubeMX) that I need to fix for our application.

I mean, I could just work with this knowledge and modify the timings accordingly, or redefine the delay/wait functions, but the issue exists and I'm not sure what other things it affects, especially regarding the motor control, like regulator timings.

5ms --- is not what we expect. :)

I cannot tell you whats wrong here , i only tried Azure rtos and there i set (different from the original settings) the 1ms tick, i want . To have easy change from HAL_delay to rtos "delay" (is not just delay, is task sleep for this time).

So for your problem: i would try some delay values and if its constant 0,5ms - just calculate all your delays with

a (xx * 2) , whats easy to remove, if there is a update that suddenly giving 1ms ticks.

If you feel a post has answered your question, please click "Accept as Solution".
DMeie.2
Senior

I just found a function at the bottom of motorcontrol.c, "vPortSetupTimerInterrupt".
There's no explanation why it is there, no header, just a comment "Reconfigure the SysTick interrupt to fire every 500 us." and the code to reconfigure the SysTick.

Why increase the tick rate beyond the limit recommended by CubeMX?
And why implement it in a way that breaks the other time-related functions?

So we know now, no error here, just the "SysTick interrupt to fire every 500 us." is set.

So adjust your ms - delays (xx * 2) to get correct timing.

If you feel a post has answered your question, please click "Accept as Solution".
DMeie.2
Senior

I suppose there is a reason this has been changed to this value.
Probably has to do with the regulators.

Regardless, It would be nice to have an explanation on why, and also mention that in the documentation.

DMeie.2
Senior

Any more information on this?

We're currently implementing various other libraries that depend on proper timing (mainly communication-related), and this bug undocumented feature messes with all of them.

Of course I could try work around that in those libraries, but I'd rather like to fix the underlying issue.

Hello @DMeie.2 

Sorry for the delay,

The reason to change the SysTick frequency is to be able to execute the medium frequency task at 2 Khz. The medium frequency task is triggered by the SysTick interrupt, and in certain circonstances it could be interesting to have the speed loop regulation executed every 500us instead of every 1ms.

The modifications done are the following :

In motorcontrol.c :

__weak void MX_MotorControl_Init(void)
{
/* Reconfigure the SysTick interrupt to fire every 500 us. */
(void)HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq() / SYS_TICK_FREQUENCY);
HAL_NVIC_SetPriority(SysTick_IRQn, uwTickPrio, 0U);

/* Initialize the Motor Control Subsystem */
MCboot(pMCI);
mc_lock_pins();
}

as it is a weak function, you can rewrite it in your own sources, and your executable will be linked with your implementation.

In the SysTick_Handler, we did the following modification:

void SysTick_Handler(void)
{
#ifdef MC_HAL_IS_USED
static uint8_t SystickDividerCounter = SYSTICK_DIVIDER;
/* USER CODE BEGIN SysTick_IRQn 0 */

/* USER CODE END SysTick_IRQn 0 */
if (SystickDividerCounter == SYSTICK_DIVIDER)
{
HAL_IncTick();
HAL_SYSTICK_IRQHandler();
SystickDividerCounter = 0;
}
else
{
/* Nothing to do */
}

SystickDividerCounter ++;
#endif /* MC_HAL_IS_USED */

with the following definition:

#define SYSTICK_DIVIDER (SYS_TICK_FREQUENCY/1000U)

HAL Tick is now incremented every SYSTICK_DIVIDER. This is done to keep the HAL_Delay() function in line with its definition. (  * @brief This function provides minimum delay (in milliseconds) based on variable incremented. )

In parameters_conversion.h you will find the following define:

#define SYS_TICK_FREQUENCY (uint16_t)2000

If you want to revert the systick at 1khz, this is the only define you have to change to 1000.

Hope it helps

Cedric