How does the ThreadX Mutex work on STM32?
A mutex is basically a binary semaphore, which means that only one thread can own a mutex at a time. In addition, the same thread may perform a successful mutex get operation on an owned mutex multiple times. There are two main operations on the mutex object: tx_mutex_get and tx_mutex_put.
The get operation obtains a mutex not owned by another thread, while the put operation releases a previously obtained mutex. For a thread to release a mutex, the number of put operations must equal the number of prior get operations. ThreadX mutexes are used solely for mutual exclusion, this means it pertains to controlling the access of threads to certain application areas (also called critical sections or application resources).
1. Goal:
The purpose of this article is to provide a brief explanation with a working example on how the mutex works. Although the example is using the NUCLEO-H723ZG, you can use the same steps for other STM32H7 based boards. The main differences are usually pinout and clock configuration. This article will start a project from scratch, add the AzureRTOS Middleware using the Software Packs available in the STM32CubeIDE and add a few code lines. 2 Threads with the same priorities will be used to showcase the mutex, controlling the printf (acting as the resource). In this demo, both Threads will get and put the mutex. This is the demo representation:Getting to know the functions:
UINT tx_mutex_get(
TX_MUTEX *mutex_ptr,
ULONG wait_option);
Parameters:
- mutex_ptr: Pointer to a previously created mutex.
- wait_option: Defines how the service behaves if the mutex is already owned by another thread. The wait options are defined as follows:
- *TX_NO_WAIT: (0x00000000) - Selecting TX_NO_WAIT results in an immediate return from this service regardless of whether or not it was successful.
- TX_WAIT_FOREVER timeout value (0xFFFFFFFF)
- timeout value (0x00000001 through 0xFFFFFFFE) - Selecting a numeric value (1-0xFFFFFFFE) specifies the maximum number of timer-ticks to stay suspended while waiting for the mutex.
UINT tx_mutex_create(
TX_MUTEX *mutex_ptr,
CHAR *name_ptr,
UINT priority_inherit);
Parameters:
- mutex_ptr: Pointer to a mutex control block.
- name_ptr: Pointer to the name of the mutex.
- priority_inherit: Specifies whether or not this mutex supports priority inheritance. If this value is TX_INHERIT, then priority inheritance is supported. However, if TX_NO_INHERIT is specified, priority inheritance is not supported by this mutex.
2. STM32CubeIDE – step by step demo:
Launch STM32CubeIDE (version used 1.7.0), select your preferred workspace, click on Launch. Once open, locate the Information Center, select to Start New STM32 Project – alternatively, click on File->New->STM32 Project. For this demo, we’ll use the NUCLEO-H723ZG as the starting point
Give your project a name, just remember to avoid space and special characters – the name given by this article is “Mutex”. A pop up asking if we should initialize the peripherals in the default mode, click yes. Then second popup to ask to open device configuration perspective, click yes againTime to add the software pack:
Browse and locate the AzureRTOS pack in the component selection window and open the RTOS ThreadX and check the Core box and click OK
This will add the Software Pack in the lower part of the Categories:
Now, by clicking on it, you can add the RTOS ThreadX box, this will show the configuration options for the AzureRTOS application
As this demo is just meant to create small printfs to indicate which thread it is and use the mutex, the default settings are alright, but we do need to do one other modification. By default, the HAL driver will use the Systick as its primary time base, but this timer should be left to the AzureRTOS only. We can simply select a different time base for the HAL by clicking in the System Core/SYS and selecting the time base Source as TIM6:
As the USB and Ethernet are not used in this demo, we can remove it by unchecking the boxes at the Project Manager tab/ advanced settings:
All set, we can press Alt+K to generate the code and Ctrl+S to save it. The project now has a new set of folders, this is the detail of its structure:
On the second part of the article, we'll see the code needed for the demo and how to debug it.
3. Useful links and Resources:
4. Conclusion:
Adding mutex to a ThreadX application consists of:
-
- Adding the ThreadX component in STM32CubeMX/STM32CubeIDE
- Adapt ThreadX configuration in STM32CubeMX/ STM32CubeIDE
- Generate the code from STM32CubeMX/ STM32CubeIDE
- This will update the project structure with all needed files
- Use ThreadX API to create ThreadX components thread and mutex
- Have fun :)