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.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *