2025-11-26 11:12 PM - last edited on 2025-11-27 4:57 AM by mƎALLEm
Hello.
I'm using STM32H747XI with touchgfx designer 4.24.2 and Free RTOS 10.3.1.
In this RTOS I setup some threads(with osPriorityNormal 24) and a Periodic Timer at 400ms.
I notice that when I start this thread
void threadEntryPoint() {
// Pulisco la FIFO del'RX USART
__HAL_UART_FLUSH_DRREGISTER(BARCODE_UART);
char msg[BARCODE_LENGTH+1];
while (;;) {
memset(msg, 0, sizeof(msg));
// Appena vedo il primo carattere ...
if ( HAL_UART_Receive ( BARCODE_UART, (uint8_t*)&msg[0], 1, 50 ) == HAL_OK ) {
// ... ricevo gli altri
HAL_UART_Receive ( BARCODE_UART, (uint8_t*)&msg[1], BARCODE_LENGTH - 1, 50 );
if (strchr(msg, BARCODE_SUFFIX)) {
queue.put(msg);
}
}
}
}
Timer will not trigger.
Is the reason that I have no osDelay ? Or a priority question ?
Thankyou in advance.
2025-11-27 12:35 AM - edited 2025-11-27 12:41 AM
@MauFanGilaMedical wrote:Is the reason that I have no osDelay ? Or a priority question ?
Have you tried using a osDelay() in your task?
@MauFanGilaMedical wrote:Timer will not trigger.
Can you describe what type of timer you are using: Software timer (Freertos)/or Hardware timer (Tim1, ...)
Is preemption enabled in your FreeRTOS config (USE_PREEMPTION)?
The problem with not having a osDelay in your task is that the operating system is never allowed to run any task/functionality (like timers), if they have a lower priority than the running task or if preemption is disabled.
2025-11-27 2:22 AM
I use Software timer (Freertos), PREEMPTION is Enabled.
I don't know the Timer priority: is there a parameter to set it ?
2025-11-27 2:44 AM - edited 2025-11-27 2:52 AM
https://freertos.org/Documentation/02-Kernel/02-Kernel-features/05-Software-timers/03-Timer-daemon-configuration
See documentation of FreeRTOS software timers. The parameter in the ioc.-File is shown in the screenshot:
Increasing this parameter to a higher value than osPriorityNormal should work.
Give it a try and get back to me if it works.
Afterwards i would suggest rewriting your
void threadEntryPoint() {function. The problem is that this function blocks for up to 50 milliseconds each time HAL_UART_Receive is called. Instead use a lower timeout and instead check once per millisecond if something arrived, maybe something like the following (used autotranslate for comments):
void BarcodeTask(void *argument)
{
char msg[BARCODE_LENGTH + 1];
uint8_t c;
// Pulisco la FIFO del'RX USART
__HAL_UART_FLUSH_DRREGISTER(BARCODE_UART);
for (;;)
{
memset(msg, 0, sizeof(msg));
size_t idx = 0;
// Appena vedo il primo carattere ...
int attempts = 0;
while (attempts < 50)
{
/* timeout molto corto per evitare HAL_Delay() */
if (HAL_UART_Receive(BARCODE_UART, &c, 1, 0) == HAL_OK)
{
msg[idx++] = c;
break;
}
/* se non arriva nulla, cedo la CPU */
osDelay(1);
attempts++;
}
/* se non ho ricevuto nulla nelle 50 iterazioni → riparto */
if (idx == 0)
continue;
// ... ricevo gli altri
HAL_UART_Receive ( BARCODE_UART, (uint8_t*)&msg[1], BARCODE_LENGTH - 1, 50 );
if (strchr(msg, BARCODE_SUFFIX))
{
queue.put(msg);
}
}
}Edit: Changed suggested code example.
Will work if the Data is not permanently received, otherwise might lead to same issue. Could rewrite the second HAL_UART_Receive to also be non-blocking.
2025-11-27 3:54 AM - edited 2025-11-27 3:54 AM
I hope you realize that for this code to work, the thread you present above must be the only one wit the highest priority. Otherwise UART data may not be received.
It is generally a very bad idea to use any non-interrupt, non-DMA functions under RTOS, especially for UART.
2025-11-27 4:10 AM
Well, to work reliable, yes.
As the user at the moment is able to receive data on the UART with his given example, and Preemption is on, there does not seem to be higher priority task that is interrupting the UART data transmission.
It might be a coincidence at the moment/adding more tasks might lead to a problem in the future. But for now it should be a working fix.
I agree that the user should use DMA based UART and not polling. But the suggested example will fix the issue of the timer not working. With the osDelay the lower priority timer task will be allowed to execute.
2025-11-27 4:29 AM - edited 2025-11-27 4:35 AM
Interesting!
But I understand that I have poor knoweldge of STM drivers and RTOS:
correct me if I wrong:
HAL_UART_Receive(UART,&c,1, 50)
blocks CPU for 50ms because it uses internally HAL_Delay() (if no char was detetected) and no osDelay
so, to "convert" a blocking delay in a not blocking delay I have to change code in the way you suggest me in the previous post.
But if I understand, I can rewrite your suggest in this way
void BarcodeTask(void *argument)
{
char msg[BARCODE_LENGTH + 1];
uint8_t c;
// Pulisco la FIFO del'RX USART
__HAL_UART_FLUSH_DRREGISTER(BARCODE_UART);
for (;;)
{
/* timeout molto corto per evitare HAL_Delay() */
if (HAL_UART_Receive(BARCODE_UART, &msg[0], 1, 0) == HAL_OK)
{
memset(&msg[1], 0, sizeof(msg)-1);
// ... ricevo gli altri
HAL_UART_Receive ( BARCODE_UART, (uint8_t*)&msg[1], BARCODE_LENGTH - 1, 50);
if (strchr(msg, BARCODE_SUFFIX))
{
queue.put(msg);
}
}
/* se non arriva nulla, cedo la CPU */
osDelay(1);
}
}
2025-11-27 5:09 AM
Should work i.m.o., yes.
If you have gotten it to work, I agree with @gbm , you should try to set it up with DMA/Interrupt instead.
Checkout following guide
community.st.com/t5/stm32-mcus/implementing-uart-receive-and-transmit-functions-on-an-stm32
which goes step by step using polling, using interupt and using DMA for UART communication:
"From this article, you can see that there are a few different ways to approach UART when creating your application. The interrupt/DMA methods are ideal since they allow other processing to occur while waiting for UART data. In this article, we also used the STM32CubeIDE embedded terminal. I hope you enjoyed this article and that it has helped you in understanding these essential functions."
Interrupt/DMA are ideal for your application, as your FreeRTOS is allowed to to other things during the time waiting for the UART receive data.
There should be other examples on the internet using UART with DMA in FreeRTOS envirnoment as well.
2025-11-27 5:11 AM
The slave that send me data is a BarCode Reader.
I don't know the size of bar code scanned, so I have to develop a driver that can receive an asyncronous packet of unknow length.
I see INT,DMA mode but it requires size
2025-11-27 5:21 AM - edited 2025-11-27 5:26 AM