Skip to main content
MauFanGilaMedical
Associate III
November 27, 2025
Solved

TouchGFX + Free RTOS TImer and Thread

  • November 27, 2025
  • 5 replies
  • 612 views

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.

Best answer by M_Schmidt

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:

M_Schmidt_0-1764239987974.png

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.

5 replies

M_Schmidt
Associate II
November 27, 2025


@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.

MauFanGilaMedical
Associate III
November 27, 2025

I use Software timer (Freertos), PREEMPTION is Enabled.

I don't know the Timer priority: is there a parameter to set it ?

M_Schmidt
M_SchmidtBest answer
Associate II
November 27, 2025

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:

M_Schmidt_0-1764239987974.png

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.

gbm
Principal
November 27, 2025

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.

My STM32 stuff on github - compact USB device stack and more: https://github.com/gbm-ii/gbmUSBdevice
M_Schmidt
Associate II
November 27, 2025

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.

MauFanGilaMedical
Associate III
November 27, 2025

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);
 }
}

 

 

M_Schmidt
Associate II
November 27, 2025

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.

gbm
Principal
November 27, 2025

If your UART task is the only highest priority task, then other tasks will not run at all. If it has the same or lower priority as any other task, UART data will not be received correctly. A really bad alternative. 

Basically all HAL_UART_Receive functions are close-to useless. What you need in a real world is always-enabled reception using UART interrupt and "byte received" callback (or an equivalent processing block written inside UART ISR). The simplest to write but not the most efficient way of doing this under RTOS is to put data into a queue (but that's not exactly what the queues are for - overkill) or raise a semaphore when a byte is received (may lead to losing data).

My STM32 stuff on github - compact USB device stack and more: https://github.com/gbm-ii/gbmUSBdevice
M_Schmidt
Associate II
November 27, 2025

@gbm 
https://controllerstech.com/stm32-uart-5-receive-data-using-idle-line/
Have you looked at this example? It is the perfect implementation assuming the bar-code scanner is not continuously sending data and there are always pauses between data transmissions. No need for RTOS queues/semaphore. Just a simple flag and a large enough buffer will be sufficient for the given requirements. 

gbm
Principal
November 27, 2025

Yes, it could be done that way (with some problem which could be easily avoided with "byte received" callback from ISR). And semaphore is a much better idea in this case than a flag tested in a polling loop - something in direct conflict with the concept of RTOS.

With RTOS, there should be no polling loops other than the ones using OS blocking calls as their "condition".

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

That has no chance to work correctly when you add some other tasks.

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