This section shows how to configure different Real Time Operating System in STM32CubeMX to work with the code generated by the TouchGFX Generator to have a functional TouchGFX OSAL.
Generally, the TouchGFX main loop is started by calling the function
MX_TouchGFX_Process(). The call to this function should be inside the task handler where developers wish to run TouchGFX.
When TouchGFX runs without and operating system, the TouchGFX main loop runs in the infinite while-loop in
main() where the MCU is
pooling for a
VSYNC signal by calling
/* Infinite loop */
/* USER CODE BEGIN WHILE */
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
MX_TouchGFX_Process() calls forward to
touchgfx_taskEntry(), where TouchGFX starts to process the next frame when a
VSYNC has been detected.
* Main event loop will check for VSYNC signal, and then process next frame.
* Note This function returns immediately if there is no VSYNC signal.
FreeRTOS (CMSIS V1 & CMSIS V2)
The following example shows how to configure FreeRTOS (CMSIS V2) to work with TouchGFX. The same configurations apply if running CMSIS V1.
Having enabled FreeRTOS in a project navigate to the
FREERTOS menu found under Middleware in the "Categories" list on the left side of the project menu in STM32CubeMX.
TICK_RATE_HZ to 1000 to get ticks once per millisecond. Configure the
Memory Management scheme and
In this example we use heap_4 and a heap size of 70000 bytes to have a large enough heap for the touchgfx application.
The TouchGFX main loop is entered when calling the following function.
Developers can either configure their own custom task in STM32CubeMX where the TouchGFX main loop should run or use the
TouchGFX_Task() handle which is generated by TouchGFX Generator.
void touchgfx_taskEntry(void) is called by
// Calling forward to touchgfx_taskEntry in C++ domain
Developers are required to call
MX_TouchGFX_Process() in the task handler for the task they intend to run the TouchGFX main loop in.
If the developer has configured a FeeRTOS task in STM32CubeMX called
MyTask for instance, then the following example shows how
MX_TouchGFX_Process() should be called in the custom task handler to start TouchGFX.
void StartMyTask(void *argument)
/* USER CODE BEGIN 5 */
/* USER CODE END 5 */
The TouchGFX main loop can run in the TouchGFX Task. The TouchGFX Generator defines a task handler that calls
void TouchGFX_Task(void *argument)
// Calling forward to touchgfx_taskEntry in C++ domain
To have this task scheduled by the FreeRTOS scheduler, the task must be created in STM32CubeMX in the FREERTOS menu. In the Tasks and Queues tab, add a task with "TouchGFX_Task" as Entry Function and a large enough stack with Code Generation Option As external.
STM32CubeMX will create the TouchGFX Task in
main.c when generating code, which will start the TouchGFX main loop.
This section shows how to configure a TouchGFX project using ThreadX either as an X-CUBE Software Pack or Native ThreadX Middleware.
Native Middleware configuration
The following example shows how to configure ThreadX for an STM32U5 MCU, which has ThreadX available as native middleware.
Having enabled Thread native middleware in a project navigate to the
THREADX menu found under Middleware in the "Categories" list on the left side of the project menu in STM32CubeMX. Enable the
Core from the Mode list.
TX_TIMER_TICKS_PER_SECOND to 1000 to get ticks once per millisecond and set
Memory Pool Allocation to Use Static Allocation.
- If Memory Pool Allocation is set to Use Dynamic Allocation then :
- User will have to add missing code in the USER CODE BEGIN DYNAMIC_MEM_ALLOC section in the generated app_azure_rtos.c file.
- User will need also to update the linker files following the recommendation described by code comments in the generated app_azure_rtos.c file.
- Depending on the STM32CubeMX version, the Dynamic Allocation may not work properly.
STM32CubeMX is not responsible for generating the code that allocates and schedules tasks when using ThreadX. For this reason, a call to the function
MX_TouchGFX_PreOSInit(), which will initialize the TouchGFX
framework, will be generated by STM32CubeMX. After this, another call to the function
MX_ThreadX_Init(), which will initialize and start the ThreadX kernel, is generated.
/* Call PreOsInit function */
TouchGFX Generator will generate the
MX_TouchGFX_Init() function, which will create the TouchGFX thread.
UINT MX_TouchGFX_Init(VOID *memory_ptr)
UINT ret = TX_SUCCESS;
CHAR *pointer = 0;
/* Allocate the stack for TouchGFX Thread. */
if (tx_byte_allocate((TX_BYTE_POOL*)memory_ptr, (VOID **) &pointer,
TOUCHGFX_STACK_SIZE, TX_NO_WAIT) != TX_SUCCESS)
ret = TX_POOL_ERROR;
/* Create TouchGFX Thread */
else if (tx_thread_create(&TouchGFXThread, (CHAR *)"TouchGFX", TouchGFX_Task, 0,
TX_NO_TIME_SLICE, TX_AUTO_START) != TX_SUCCESS)
ret = TX_THREAD_ERROR;
TouchGFX Generator will then generate code that creates the TouchGFX task byte pool and calls
This code is inserted in the appropriate location into the function
tx_application_define() in the app_azure_rtos.c file where the TouchGFX Task byte pool is defined.
tx_application_define() function is called by the ThreadX kernel at initialization time. The TouchGFX thread will then be started later when the ThreadX kernel is started.
__ALIGN_BEGIN static UCHAR touchgfx_byte_pool_buffer[TOUCHGFX_APP_MEM_POOL_SIZE] __ALIGN_END;
static TX_BYTE_POOL touchgfx_app_byte_pool;
VOID tx_application_define(VOID *first_unused_memory)
if (tx_byte_pool_create(&touchgfx_app_byte_pool, "TouchGFX App memory pool", touchgfx_byte_pool_buffer, TOUCHGFX_APP_MEM_POOL_SIZE) != TX_SUCCESS)
/* USER CODE BEGIN TouchGFX_Byte_Pool_Error */
/* USER CODE END TouchGFX_Byte_Pool_Error */
/* USER CODE BEGIN TouchGFX_Byte_Pool_Success */
/* USER CODE END TouchGFX_Byte_Pool_Success */
memory_ptr = (VOID *)&touchgfx_app_byte_pool;
if (MX_TouchGFX_Init(memory_ptr) != TX_SUCCESS)
/* USER CODE BEGIN MX_X-CUBE-TOUCHGFX_Init_Error */
/* USER CODE END MX_X-CUBE-TOUCHGFX_Init_Error */
/* USER CODE BEGIN MX_X-CUBE-TOUCHGFX_Init_Success */
/* USER CODE END MX_X-CUBE-TOUCHGFX_Init_Success */
The following example shows have to configure ThreadX for an STM32H7 MCU, which has ThreadX available as an X-CUBE Software Pack.
Having enabled Thread as an X-CUBE Software Pack in a project navigate to the
X-CUBE-AZRTOS-XX menu found under Software Packs in the "Categories" list on the left side of the project menu in STM32CubeMX and set the
Memory Allocation setting to Use Static MemPool Allocation.
Select the ThreadX setting tab and set
TX_TIMER_TICKS_PER_SECOND to 1000 to get ticks once per millisecond.
Once configuration is done in X-CUBE-AZRTOS-XX menu, navigate to TouchGFX Generator and select
ThreadX as Real Time Operating System and define the
Memory Pool Size and
Memory Stack Size for the TouchGFX task.