Last edited 8 months ago

Introduction to THREADX

Applicable for STM32MP13x lines, STM32MP25x lines


1. Introduction[edit source]

ThreadX is a real-time operating system (RTOS), designed for embedded systems.
It offers two functional modes:

  • Common mode: Contains the common RTOS functionalities such as thread management and synchronization, memory pool management, messaging, and event handling.
  • Module mode: An advanced usage mode that allows loading and unloading of pre-linked ThreadX modules on-the-fly through a module manager.
ThreadX main blocks


The ThreadX core provides the common RTOS features, such as management of threads, semaphores, mutexes and SW timers. The block diagram below shows the different functional blocks in the ThreadX core.

ThreadX core functional components


The Azure RTOS ThreadX library has a FreeRTOS compatibility layer. This adaptation layer allows the user to develop a ThreadX application using FreeRTOS APIs.

Info white.png Information
All cores on which STM32s are based (Cortex M0, M0+, M4, M7, M33, A7) are supported in the Azure RTOS ThreadX stack.
Info white.png Information
For general questions, visit the general FAQ section in the introduction to middleware with STM32 article.

1.1. Unique features[edit source]

ThreadX offers a set of unique features that give higher flexibility to the user:

  • Various scheduling policies and preemption threshold [1]
  • On-the-fly properties update [2]
  • Object notifications [3]
  • Event chaining [4]
  • Runtime performance information [5]
  • Tracing mechanism [6]

1.2. Folder/file structure[edit source]

ThreadX Files and folders structure


  • common: Contains the implementation of all ThreadX APIs. It also provides some utility features such as: SW timers, performance information and tracing.
  • common_modules: Contains the implementation of the ThreadX Module feature, allowing dynamic loading of a prelinked ThreadX module. It is split into two folders:
    • module_lib: implements the txm_*.c API and should be used instead of tx_*.c when writing a ThreadX module.
    • module_manager: implements the functional block to be put on top of the ThreadX core to handle module loading, unloading, running, and so on.
  • ports/<core>/<compiler>: contains the implementation of the kernel scheduler, mostly in assembly language.
  • ports_module/<core>/<compiler>: contains the implementation of the ThreadX module related scheduler to fit with Module Manager requirements. The files in this directory are used instead of the port's files when the ThreadX Module is enabled.

Further details of the ThreadX features are available in the official documentation[7]

2. STM32 integration[edit source]

There are two possible modes: Common Mode and Module Mode.

2.1. Common mode[edit source]

To correctly run ThreadX on STM32-based MPUs, the application should provide the 3 following user-level files:

  • tx_initialize_low_level.s: Implements the tx_initialize_low_level() function called by the threadX kernel to initialize the RTOS heap base address and setup the SYSTick_Handler().

As tx_initialize_low_level.s is compiler and core dependent, a template of this file is provided for each compiler/core in the ThreadX source tree.

  • stm32XXX_hal_timebase_tim.c: Implements a timebase used by the HAL drivers, as the systick is reserved for the ThreadX kernel scheduler.
  • tx_user.h: Configures the ThreadX RTOS using some of defines. A template for this file is provided in the ThreadX source tree. It is included in the ThreadX stack by the define TX_INCLUDE_USER_DEFINE_FILE. See illustration here after taking STM32CubeMP13 as example:
ThreadX template files


Info white.png Information
It is recommended to use ThreadX Memory Pool for dynamic memory allocation in all the project, otherwise, user shall pay attention to memory allocation mechanisms (malloc/free/..): Standard heap management (IAR heap, NewLib, ..) shall not use the same region as ThreadX Memory Pool, otherwise they might overwrite each other. So linker file shall be configured in a way to separate memory zone used for heap and memory zone used for ThreadX Memory Pool.

2.2. Module mode[edit source]

In addition to the common mode files, which need to be kept on the module manager side, the application should provide the following user-level file on the module side.

  • txm_module_preamble.s: A preamble is required with each module to expose the module configuration to the Module Manager. The preamble contains particular information such as the module unique ID and attributes.
Info white.png Information
All C files in a module must define “TXM_MODULE” prior to including “txm_module.h”.
Info white.png Information
STM32CubeIDE provides specific ThreadX debugging features. Further information can be found in STM32CubeIDE user guide.

3. CMSIS-RTOS API Support[edit source]

The CMSIS-RTOS v2 (CMSIS-RTOS2) provides generic RTOS interfaces for Arm® Cortex® processor-based devices. It provides a standardized API for software components that require RTOS functionality.

The list of features supported for ThreadX is as follows:

Feature Supported Short description
Kernel information and control Y Provides version/system information and starts/controls the RTOS Kernel. More…
Thread management Y Defines, creates, and controls thread functions. More…
Thread flags N Synchronizes threads using flags. More…
Event flags Y Synchronizes threads using event flags. More…
Generic wait functions Y Waits for a certain period of time. More…
Timer management Y Creates and controls timer and timer callback functions. More…
Mutex management Y Synchronizes resource access using Mutual Exclusion (Mutex). More…
Semaphores Y Accesses shared resources simultaneously from different threads. More…
Memory pool N Manages thread-safe fixed-size blocks of dynamic memory. More…
Message queue Y Exchanges messages between threads in a FIFO-like operation. More…


For further information about CMSIS-RTOS v2 APIs, refer to the ARM manual: CMSIS-RTOS API v2.

For further information about the implementation of CMSIS-RTOS wrapper for ThreadX, refer to its readme file.

4. FreeRTOS API Support[edit source]

The FreeRTOS adaptation layer for ThreadX provides a set of APIs to configure, initialize and use ThreadX through FreeRTOS APIs. API support by category:

  • task creation, control and utilities
  • semaphores and mutexes
  • queues
  • queue sets
  • direct to task notifications
  • software timers
  • event groups

ThreadX flags required configuration:

Name Default value Description
configUSE_16_BIT_TICKS 0 Set to 1 to use 16-bit tick.
configSTACK_DEPTH_TYPE uint16_t Use to override the type used to specify stack depth.
configTICK_RATE_HZ - Set the kernel tick rate, used by the pdMS_TO_TICKS() macro.
configMAX_PRIORITIES - Maximum number of priorities. Must be less than or equal to the configured number of ThreadX priorities.
configMINIMAL_STACK_SIZE 512U Minimum stack size, used as the stack size of the idle task if TX_FREERTOS_IDLE_STACK is not defined.
configTOTAL_HEAP_SIZE - Amount of internal memory allocated to the adaptation layer when creating FreeRTOS objects. Can be set to 0 to disable dynamic allocation.
INCLUDE_vTaskDelete 1 Set to 0 to disable the task delete API. When disabled, the adaptation layer does not create the idle task in order to save resources.
TX_FREERTOS_IDLE_STACK 512U Define to a macro invoked on internal assertion failures from within the adaptation layer.
configASSERT - Define to a macro invoked for invalid arguments.


Info white.png Information
All other configurations not explicitly listed are ignored. In addition, a few additional definitions can be added to "FreeRTOSConfig.h" to tune the behavior of the adaptation layer.

For more information about the implementation of the FreeRTOS adaptation layer for ThreadX, refer to its readme file [8]

5. How to use[edit source]

5.1. Common mode[edit source]

1. In order to initialize and configure the Azure RTOS ThreadX kernel, the user must include the "tx_api.h" file.
2. Call tx_kernel_enter function from the main.

/* Start the ThreadX kernel */
tx_kernel_enter();

This function initializes the internal ThreadX data structure before calling the application’s definition function (tx_application_define) and starting the scheduler.

ThreadX application initialization

3. The user must also properly define the initial system resources in the tx_application_define function. Examples of system resources include threads, queues, memory pools, event flag groups, mutexes, timers and semaphores.

VOID tx_application_define(VOID *first_unused_memory)
{
  VOID *memory_ptr = first_unused_memory;
  /* USER CODE BEGIN  tx_application_define */
  /* User can add his own implementation to define the initial ThreadX system resources*/
  /* USER CODE END  tx_application_define */
}

The input parameter of tx_application_define is the first available RAM address to be used for the run-time memory allocation of thread stacks, queues and memory pools.

4. Initialize system resources using ThreadX APIs :

  • Thread creation using ThreadX API :
 /* Create ThreadOne.  */
if (tx_thread_create(&ThreadOne, "Thread One", ThreadOne_Entry, 0,  
                       pointer, THREAD_ONE_STACK_SIZE, 
                       THREAD_ONE_PRIORITY, THREAD_ONE_PREEMPTION_THRESHOLD,
                       TX_NO_TIME_SLICE, TX_AUTO_START) != TX_SUCCESS)
{
  status = TX_THREAD_ERROR;
}
  • Mutex creation using ThreadX API :
/* Create the Mutex */
if (tx_mutex_create(&MutexOne, "Mutex One", TX_NO_INHERIT) != TX_SUCCESS)
{
  ret = TX_MUTEX_ERROR;
}
Info white.png Information
It is also possible to create and delete system resources after starting the ThreadX kernel.

5. Define the entry function for each created thread :

void ThreadOne_Entry(ULONG thread_input)
{
  /* User can add their own implementation*/
}

5.2. Module mode[edit source]

5.2.1. Module manager[edit source]

  • In order to initialize and configure Azure RTOS ThreadX kernel in module mode, the user must include the “txm_module.h” file.
  • Call tx_kernel_enter function from the main.
/* Start the ThreadX kernel */
tx_kernel_enter();
  • The user must also properly define the initial system resources in the tx_application_define function. Examples of system resources include threads, queues, memory pools, event flag groups, mutexes, timers and semaphores.
VOID tx_application_define(VOID *first_unused_memory)
{
  VOID *memory_ptr = first_unused_memory;
  /* USER CODE BEGIN  tx_application_define */
  /* User can add his own implementation to define the initial ThreadX system resources*/
  /* USER CODE END  tx_application_define */
}

The input parameter of tx_application_define is the first available RAM address to be used for the run-time memory allocation of thread stacks, queues and memory pools.

  • The user must create a module manager thread to:
    • Initialize the module manager.
      status = txm_module_manager_initialize((VOID *) module_data_area, MODULE_DATA_SIZE);
      
    • Create a pool for module objects
      status = txm_module_manager_object_pool_create(object_memory, OBJECT_MEM_SIZE);
      
    • Register the module manager memory fault notification
      status = txm_module_manager_memory_fault_notify(module_fault_handler);
      
    • Load the module from his specific address.
      status = txm_module_manager_in_place_load(&ModuleOne, "Module One", (VOID *) MODULE_FLASH_ADDRESS);
      
    • Configure the memory management (example: enable the shared memory for the module).
      status = txm_module_manager_external_memory_enable(&ModuleOne, (void*)READONLY_REGION, SHARED_MEM_SIZE, TXM_MODULE_ATTRIBUTE_READ_ONLY);
      
    • Start the module.
      status = txm_module_manager_start(&ModuleOne);
      
    • Stop the module.
      status = txm_module_manager_stop(&ModuleOne);
      
    • Unload the module.
      status = txm_module_manager_unload(&ModuleOne);
      
Info white.png Information
Multiple modules can be loaded, started, stopped, and unloaded on-the-fly.

5.2.2. Module[edit source]

In order to initialize and configure the module, the user must:

  • Define “TXM_MODULE” and include the “txm_module.h” file.
  • Define the default module entry function “default_module_start”.
VOID default_module_start(ULONG id)
{
  /* Users can add their own implementation to define the initial ThreadX module system resources*/
}
  • Initialize system resource using ThreadX APIs:
    • Allocate object from the created memory pool for module objects.
txm_module_object_allocate((void*)&MainThread, sizeof(TX_THREAD));
    • Create system resource using ThreadX common API. Example:
/* Create ThreadOne.  */
if (tx_thread_create(&ThreadOne, "Thread One", ThreadOne_Entry, 0,  
                       pointer, THREAD_ONE_STACK_SIZE, 
                       THREAD_ONE_PRIORITY, THREAD_ONE_PREEMPTION_THRESHOLD, TX_NO_TIME_SLICE, TX_AUTO_START) != TX_SUCCESS)
{
  status = TX_THREAD_ERROR;
}
  • Request access to the module manager object:
status = txm_module_object_pointer_get(TXM_QUEUE_OBJECT, "Resident Queue", (VOID **)&ResidentQueue);

6. Migration from FreeRTOS to ThreadX[edit source]

ThreadX supports the same standard groups of APIs as most RTOS's such as FreeRTOS. It is possible to use either the CMSIS-RTOS wrapping layer or the ThreadX FreeRTOS wrapping layer in order to migrate from an RTOS to ThreadX. The table below lists the API equivalence between FreeRTOS and ThreadX.

Feature ThreadX FreeRTOS Example of ThreadX APIs Example of FreeRTOS APIs
Thread management Supported Supported tx_thread_create
tx_thread_sleep
tx_thread_suspend
xTaskCreate
vTaskDelay
vTaskSuspend
Message queue Supported Supported tx_queue_create
tx_queue_send
tx_queue_receive
xQueueCreate
xQueueSend
xQueueReceive
Event flags Supported Supported tx_event_flags_create
tx_event_flags_get
tx_event_flags_set
xEventGroupCreate
xEventGroupGetBits
xEventGroupSetBits
Mutex Supported Supported tx_mutex_create
tx_mutex_put, tx_mutex_get
xSemaphoreCreateMutex
Semaphore Supported Supported tx_semaphore_create
tx_semaphore_put
tx_semaphore_get
xSemaphoreCreateCounting
xSemaphoreGive
xSemaphoreTake
Software Timer Supported Supported tx_timer_create
tx_timer_delete
xTimerCreate
xTimerDelete
Memory Mangement Advanced
(using Byte Pools
and Block Pools)
Simple
Low Power Supported Supported
TrustZone Supported Supported
BasePri Supported Supported
MPU In Module
Mode
Managed in
FreeRTOS Kernel


Warning white.png Warning
  • Unlike FreeRTOS, ThreadX does not have an idle task to clean the deleted tasks
  • FreeRTOS does not support simply returning from a task
  • Yielding and PreemptionFromISR are not supported in ThreadX
  • Unlike ThreadX, FreeRTOS fixes the total heap size in FreeRTOSConfig.h file (configTOTAL_HEAP_SIZE)
  • The default value of ticks number per second is fixed to 1000 for FreeRTOS and 100 for ThreadX


7. References[edit source]