RTX5 Thread Creation Failure and LED Blinking Issue on STM32F103RB
The core issue revolves around the failure of an STM32F103RB microcontroller to blink an LED connected to GPIO pin A_5 when using the CMSIS-RTOS2 API with RTX5 as the underlying Real-Time Operating System (RTOS). The code compiles without errors or warnings, and the same implementation works correctly with the older CMSIS-RTOS API. The problem manifests as the LED remaining static, indicating that the application thread responsible for toggling the LED is not executing as expected.
The root cause lies in the misconfiguration of the RTX5 memory settings, specifically the OS_DYNAMIC_MEM_SIZE
parameter in the RTX_Config.h
file. This misconfiguration leads to the failure of the osThreadNew
function, which is responsible for creating the application thread. When osThreadNew
fails, it returns a NULL
pointer, and the thread is never started. Consequently, the LED control logic within the thread is never executed, resulting in the observed behavior.
Insufficient Dynamic Memory Allocation and Thread Stack Size Mismatch
The primary cause of the issue is the mismatch between the global dynamic memory size (OS_DYNAMIC_MEM_SIZE
) and the thread stack size requested during thread creation. In the provided code, the osThreadNew
function is called to create the app_main
thread, but the thread creation fails due to insufficient dynamic memory allocation. This failure occurs because the requested stack size for the thread exceeds the available dynamic memory reserved for RTX5.
The RTX_Config.h
file defines the global dynamic memory size using the OS_DYNAMIC_MEM_SIZE
macro. In the initial configuration, this value was set to 32768 bytes (32 KB). However, the STM32F103RB microcontroller has limited SRAM (20 KB), making this configuration impractical. When the osThreadNew
function attempts to allocate memory for the thread stack, it fails because the requested stack size exceeds the available memory, leading to a NULL
return value.
Additionally, the osKernelStart
function does not return to the caller, meaning the infinite loop following the osThreadNew
call is never executed. Instead, the system remains in the idle thread, which is the default behavior when no application threads are running. This further confirms that the app_main
thread is not being created or executed.
Adjusting RTX5 Memory Configuration and Validating Thread Creation
To resolve the issue, the following steps should be taken to adjust the RTX5 memory configuration and ensure successful thread creation:
Step 1: Modify RTX_Config.h
to Reduce Global Dynamic Memory Size
Open the RTX_Config.h
file and locate the OS_DYNAMIC_MEM_SIZE
macro. Reduce the value of this macro to a size that is appropriate for the available SRAM on the STM32F103RB microcontroller. For example, change the value from 32768 to 16384 (16 KB). This adjustment ensures that the dynamic memory allocation does not exceed the microcontroller’s SRAM capacity.
#define OS_DYNAMIC_MEM_SIZE 16384
Step 2: Verify Thread Stack Size and Adjust if Necessary
Ensure that the stack size requested during thread creation is compatible with the reduced global dynamic memory size. The stack size is specified as the third argument in the osThreadNew
function call. If the stack size is too large, reduce it to a value that fits within the available dynamic memory.
osThreadNew(app_main, NULL, NULL);
If necessary, explicitly define the stack size using the osThreadAttr_t
structure:
osThreadAttr_t app_main_attr = {
.stack_size = 512 // Adjust this value as needed
};
osThreadNew(app_main, NULL, &app_main_attr);
Step 3: Validate Thread Creation by Checking Return Value
Modify the code to check the return value of the osThreadNew
function. If the function returns NULL
, it indicates that thread creation has failed. This validation step helps diagnose memory allocation issues during development.
osThreadId_t app_main_id = osThreadNew(app_main, NULL, NULL);
if (app_main_id == NULL) {
// Handle thread creation failure
}
Step 4: Ensure Proper Kernel Initialization and Startup
Verify that the osKernelInitialize
and osKernelStart
functions are called correctly. The osKernelStart
function does not return, so any code following it will not execute. Ensure that all necessary initializations, such as GPIO configuration and system clock updates, are performed before starting the kernel.
int main(void) {
osKernelInitialize(); // Initialize CMSIS-RTOS
SystemCoreClockUpdate(); // Update system clock
GPIOInit(); // Initialize GPIO
osThreadNew(app_main, NULL, NULL); // Create application main thread
osKernelStart(); // Start thread execution
for (;;) {} // This loop will not execute
}
Step 5: Debugging and Monitoring
Use a debugger to monitor the system state and verify that the app_main
thread is created and running. Check the following:
- The return value of
osThreadNew
to confirm successful thread creation. - The state of the
app_main
thread in the RTOS thread list. - The execution of the LED control logic within the
app_main
thread.
Step 6: Optimize Memory Usage
If the system continues to experience memory-related issues, consider optimizing memory usage by:
- Reducing the stack sizes of all threads.
- Minimizing the use of dynamic memory allocations.
- Using memory pools or static allocations where possible.
Step 7: Test and Validate
After making the necessary adjustments, rebuild the application and test the LED blinking functionality. Verify that the LED toggles at the expected interval and that the system operates reliably.
Conclusion
The failure of the LED blinking functionality on the STM32F103RB microcontroller when using the CMSIS-RTOS2 API with RTX5 is primarily due to insufficient dynamic memory allocation and thread stack size mismatches. By adjusting the OS_DYNAMIC_MEM_SIZE
parameter in the RTX_Config.h
file, validating thread creation, and optimizing memory usage, the issue can be resolved. Proper debugging and monitoring techniques are essential to ensure the system operates as expected. This troubleshooting guide provides a comprehensive approach to diagnosing and fixing similar issues in ARM Cortex-M-based embedded systems using RTX5.