2023-11-17 01:16 PM - edited 2023-11-18 03:45 AM
I have set up ThreadX on my STM32U5A9 board using CubeMX. In such configuration it is recommended to use SysTick for ThreadX and select some other timer as a Timebase Source so I selected TIM7.
Now HAL_Delay() and HAL_GetTick() functions are very unreliable. If the system is a bit busy, 1s delay can easily take 10s and HAL_GetTick() counts much slower than it should. The problem is TIM7 IRQ priority. CubeMX generates code setting it to the lowest available priority 15, instead to the highest allowable - probably 1 would be a good choice so it is a bit lower than SysTick priority 0. Where/how do I modify current HAL_GetTick() timer priority in CubeMX?
The problem is that many HAL functions rely on HAL_Delay() and HAL_GetTick() functions while using LL_mDelay() is not recommended and SysTick is handled in ThreadX assembler code.
I begin to contemplate using DWT counter. It could be used in HAL_Delay() function, but not in HAL_GetTick() since at 160MHz DWT.CYCCNT resets every ~28s. Maybe high resolution 32b TIM2 timer incrementing every 1ms would be a better choice.
ST, why do not you implement a simple 64b DTW hardware clock cycle counter? I think it would perfectly fit HAL_Delay() and HAL_GetTick() needs without using ISR just to increment software counter.
Probably this problem can be seen as a CubeMX bug.
2023-11-17 04:56 PM - edited 2023-11-17 05:01 PM
> probably 1 would be a good choice so it is a bit lower than SysTick priority 0
> I begin to contemplate using DWT counter.
Using a free-running timer to implement HAL_Delay, HAL_GetTick is ok if your code does not require tick interrupts. There are other 32-bit timers. Get longer time between overflows with resolution lower than 1 ms.
> Where/how do I modify current HAL_GetTick() timer priority in CubeMX?
You do this in stm...hal_conf.h, exactly as on your picture. If the Cube gets in your way when it re-generates the code, fight back and revert undesired changes.
> ST, why do not you implement a simple 64b DTW hardware clock cycle counter?
DWT design comes from ARM, so direct this plea to them :)
2023-11-18 12:08 AM - edited 2023-11-18 03:41 AM
@PawelP All I need is HAL_Delay(), HAL_GetTick() functions working properly.
Needless to say, fighting with CubeMX and reverting TICK_INT_PRIORITY every time code is generated is error/problem prone and it is precisely what I try to avoid, hence it think lack of way to configure and retain this setting in CubeMX is a bug or at least a substantial shortcoming.
There is no need for HAL_Delay and HAL_GetTick functions to use a timer with ISR just to increment software counter. I believe some hardware counter, e.g. free-running timer, would be much better.
2023-11-18 04:40 AM - edited 2023-11-18 08:08 AM
well, here we are on RTOS system now (maybe, not because we like or need it, just forced by STM - no other choice.)
so we have some basic new rules now : 1. any real "delay" is a no-go. forbidden. it renders "Rtos" pointless/useless.
so if we want "wait" , for user response or whatever, we have to use the matching function of the rtos, here:
tx_thread_sleep(xx); ( = delay for xx *timetick ; standard is 10ms in Azure; then delay for (xx * 10ms). )
the non-rtos call HAL_Delay() shouldnt be used any more.
the big difference is: the _sleep lets wait the program here, but switches immediate to other thread(s), running the multitasking. So every delay has to call _sleep.
Just for calling the HAL-lib, maybe there are still a few HAL_Delay() calls, replace them, if possible. Otherwise they still should work (more or less exactly, this depends on other settings/actions in the rtos and can be tuned - if needed.)
to replace the hal_delay, i just put in main.c :
void HAL_Delay(uint32_t Delay)
{
tx_thread_sleep((TX_TIMER_TICKS_PER_SECOND*Delay)/1000);
}
or better in ms - resolution, same as HAL ->
#include <ux_api.h>
/* USER CODE END Includes */
....
....
void HAL_Delay(uint32_t Delay)
{
ux_utility_delay_ms(Delay);
}
/* DESCRIPTION */
/* */
/* This function causes the calling thread to sleep for the */
/* specified number of milliseconds */
/* */
2023-11-18 07:56 AM - edited 2023-11-18 08:00 AM
@AScha.3 You seem to be missing my point. tx_thread_sleep(), as the function name suggests, is used to sleep a thread while HAL_Delay() can work in/from ISR, that is, outside of the ThreadX realm.
tx_thread_sleep() description clearly states:
"This service can be called only from an application thread."
> Just for calling the HAL-lib, maybe there are still a few HAL_Delay() calls, replace them, if possible
Have you actually checked and tried that?
Are you suggesting I should start maintaining my own custom version of HAL?
2023-11-18 08:57 AM - edited 2023-11-18 08:58 AM
ok ok, i would never have come up with the idea, to use a HAL_Delay() in ISR . :)
i just use: (re-defines HAL_Delay)
#include <ux_api.h> /* USER CODE END Includes */ .... .... void HAL_Delay(uint32_t Delay) { ux_utility_delay_ms(Delay); }
..se my older post.
2023-11-18 11:45 AM - edited 2023-11-18 03:49 PM
@AScha.3 I still do not quite understand. ux_utility_delay_ms() is USBX, not ThreadX function, which inside uses
uint32_t HAL_GetTick() {
return tx_time_get() * 10; // x10 since by default ThreadX timer ticks every 10ms
}