FreeRTOS Compatibility Layer for RT-Thread Operating System

Github Address

https://github.com/RT-Thread-packages/FreeRTOS-Wrapper

Looking Forward to YourStar

This project is part of the 2022 Summer of Open Source, RT-Thread community project. It was successfully completed in September 2022 by Tang Zhaozhou (Georgia Institute of Technology, senior). The FreeRTOS compatibility layer has now been implemented in RT-Thread’s compatibility projects for ESP32-IDF (Tang Zhaozhou) and core-v-mcu (Wang Shun).

1 Overview

This is a FreeRTOS compatibility layer for the domestic RT-Thread operating system, allowing existing projects based on FreeRTOS to migrate quickly and seamlessly to the RT-Thread operating system, enabling the use of FreeRTOS APIs without awareness while also utilizing the rich components of RT-Thread. The project is based on FreeRTOS version 10.4.6.

1.1 Other RTOS Compatibility Layers of RT-Thread

  • μCOS-III compatibility layer for RT-Thread operating system: https://github.com/mysterywolf/RT-Thread-wrapper-of-uCOS-III

  • μCOS-II compatibility layer for RT-Thread operating system: https://github.com/mysterywolf/RT-Thread-wrapper-of-uCOS-II

  • RTX (i.e., CMSIS-RTOS1) compatibility layer for RT-Thread operating system: https://github.com/RT-Thread-packages/CMSIS_RTOS1

  • RTX5 (i.e., CMSIS-RTOS2) compatibility layer for RT-Thread operating system: https://github.com/RT-Thread-packages/CMSIS_RTOS2

  • Arduino ecosystem compatibility layer for RT-Thread operating system: https://github.com/RTduino/RTduino

2 FreeRTOS API Support Status and Usage Notes

For detailed API support status, please refer to the readme link below:

https://github.com/RT-Thread-packages/FreeRTOS-Wrapper

(Please copy to an external browser to open)

The compatibility layer’s support for FreeRTOS is recorded in the issues. Some supported functions may have slight differences in functionality and usage compared to FreeRTOS, so care should be taken during migration.

2.1 Threads, Message Queues, and Mutexes

2.1.1 vTaskSuspend

vTaskSuspend only supports suspending the currently running thread, and when used, the xTaskToSuspend parameter must be NULL. Otherwise, an assertion will be triggered.

2.1.2 xQueueSendToFront

xQueueSendToFront does not support setting a timeout; the xTicksToWait parameter will be ignored, and if there is no space in the message queue, it will return errQUEUE_FULL immediately.

2.1.3 xQueueCreateStatic

Static message queues need to be created with the following example, ensuring that the memory allocated for the message queue is large enough:

 1#define QUEUE_LENGTH 10
 2#define ITEM_SIZE sizeof( uint32_t )
 3
 4/* The following is the method used in the original FreeRTOS to allocate memory, as the internal implementation of the RT-Thread message queue differs from FreeRTOS, this allocation is insufficient to hold ITEM_SIZE messages */
 5//uint8_t ucQueueStorage[ QUEUE_LENGTH * ITEM_SIZE ];
 6/* Use the QUEUE_BUFFER_SIZE macro to allocate memory */
 7uint8_t ucQueueStorage[ QUEUE_BUFFER_SIZE(QUEUE_LENGTH, ITEM_SIZE)];
 8StaticQueue_t xQueueBuffer;
 9QueueHandle_t xQueue1;
10xQueue1 = xQueueCreate( QUEUE_LENGTH, ITEM_SIZE, &( ucQueueStorage[ 0 ] ), &xQueueBuffer );

2.1.4 Mutex and Recursive Mutex

FreeRTOS provides two types of mutexes, Mutex and Recursive Mutex. Recursive Mutex can be acquired repeatedly by the same thread, while Mutex cannot. The mutex provided by RT-Thread can be acquired repeatedly, so the compatibility layer does not distinguish between Mutex and Recursive Mutex.

Both mutexes created with xSemaphoreCreateMutex and xSemaphoreCreateRecursiveMutex can be acquired repeatedly.

2.2 Timers

Unlike FreeRTOS, RT-Thread does not use a message queue to pass commands to the timer thread. When using the compatibility layer, any timer function that needs to set a timeout, such as xTimerStart( xTimer, xTicksToWait ), will ignore the xTicksToWait parameter, and the function will complete the command immediately and return.

2.3 FromISR Functions

FreeRTOS provides FromISR versions for some functions that are used in interrupts; if these functions wake up a higher-priority thread, manual scheduling is required, as shown below:

1BaseType_t xHigherPrioritTaskWoken = pdFALSE;
2xQueueSendToFrontFromISR( xRxQueue, &cIn, &xHigherPriorityTaskWoken );
3if( xHigherPriorityTaskWoken )
4{
5  taskYIELD ();
6}

RT-Thread does not provide FromISR versions for functions; functions can be called in interrupts and complete scheduling internally. Therefore, after using FromISR functions in the compatibility layer, manual scheduling is not required, and xHigherPriorityTaskWoken will always be set to pdFALSE.

2.4 Memory Heap

The compatibility layer retains five memory allocation algorithms from FreeRTOS, with heap_3 being used by default. The internal calls to pvPortMalloc/vPortFree use RT_KERNEL_MALLOC/RT_KERNEL_FREE for memory allocation within RT-Thread. In this case, the size of the memory heap is determined by the RT-Thread BSP configuration and cannot be set in FreeRTOSConfig.h via configTOTAL_HEAP_SIZE. If using other algorithms, you need to modify FreeRTOS/sSConscript to select the appropriate source file.

1# You can replace heap_3.c with heap_1.c, etc.
2src += Glob(os.path.join("portable", "MemMang", "heap_3.c"))

In FreeRTOS/portable/rt-thread/FreeRTOSConfig.h, set the heap size using configTOTAL_HEAP_SIZE. Application calls to pvPortMalloc/vPortFree will allocate memory from a heap independent of RT-Thread, sized configTOTAL_HEAP_SIZE, while the internal memory heap of RT-Thread still exists, and all memory allocation within compatibility layer functions is completed in the RT-Thread memory heap.

2.5 Thread Priority

In RT-Thread, the smaller the thread priority value, the higher the priority, while in FreeRTOS, the larger the thread priority value, the higher the priority. When using FreeRTOS APIs in the compatibility layer, such as xTaskCreate, use FreeRTOS rules to specify thread priority. If RT-Thread and FreeRTOS APIs are mixed in the application, special attention should be paid when specifying thread priority. The following two macros can be used to convert between RT-Thread and FreeRTOS thread priorities:

1#define FREERTOS_PRIORITY_TO_RTTHREAD(priority)    ( configMAX_PRIORITIES - 1 - ( priority ) )
2#define RTTHREAD_PRIORITY_TO_FREERTOS(priority)    ( RT_THREAD_PRIORITY_MAX - 1 - ( priority ) )

2.6 Thread Stack Size

The unit for FreeRTOS thread stack size is sizeof(StackType_t), while for RT-Thread it is sizeof(rt_uint8_t). When creating threads using FreeRTOS API, be sure to follow FreeRTOS rules to avoid confusion.

2.7 vTaskStartScheduler

Due to differences in kernel startup processes between RT-Thread and FreeRTOS, when using the compatibility layer, the main function runs in a thread with a priority of CONFIG_RT_MAIN_THREAD_PRIORITY. (This option is configured via SCons; the smaller the value, the higher the priority.) At this point, the scheduler is already running. Typical FreeRTOS applications create threads as follows:

1xTaskCreate(pxTask1Code, ......);
2xTaskCreate(pxTask2Code, ......);
3......
4vTaskStartScheduler();

When using the compatibility layer, any thread created with xTaskCreate that has a priority higher than CONFIG_RT_MAIN_THREAD_PRIORITY will start executing immediately. vTaskStartScheduler is only provided for application compatibility and has no practical effect. When using the compatibility layer, special attention should be paid when creating threads to ensure that all resources required by the thread are initialized and can run normally before calling xTaskCreate.

3 Usage Method

Add the compatibility layer to the project using the Env tool:

1RT-Thread online packages
2    system packages --->
3        [*] FreeRTOS Wrapper --->
4            Version (latest)

Configure the RT-Thread kernel using scons --menuconfig; the following options will affect the FreeRTOS compatibility layer:

1RT_USING_TIMER_SOFT /* Must be enabled when using FreeRTOS timer */
2RT_TIMER_THREAD_PRIO  /* Timer thread priority. Opposite to FreeRTOS, the smaller the value, the higher the priority */
3RT_TIMER_THREAD_STACK_SIZE  /* Timer thread stack size, unit is sizeof(rt_uint8_t) */
4RT_USING_MUTEX  /* Must be enabled when using FreeRTOS mutex */
5RT_USING_SEMAPHORE  /* Must be enabled when using FreeRTOS semaphore */
6RT_USING_HEAP /* Must be enabled when using FreeRTOS dynamic memory allocation */
7RT_TICK_PER_SECOND  /* Equivalent to FreeRTOS configTICK_RATE_HZ */
8RT_THREAD_PRIORITY_MAX /* Equivalent to FreeRTOS configMAX_PRIORITIES */
9RT_NAME_MAX /* Equivalent to FreeRTOS configMAX_TASK_NAME_LEN */

The FreeRTOSConfig.h template is provided in FreeRTOS/portable/rt-thread. Most of the content cannot be modified or depends on RT-Thread kernel configuration; the following content can be manually modified:

 1/* You can choose not to use recursive mutex */
 2#ifdef RT_USING_MUTEX
 3    #define configUSE_RECURSIVE_MUTEXES         1
 4    #define configUSE_MUTEXES                   1
 5#endif
 6
 7/* You can choose not to use counting semaphore */
 8#ifdef RT_USING_SEMAPHORE
 9    #define configUSE_COUNTING_SEMAPHORES       1
10#endif
11
12/* If not using heap_3, you can configure the heap size via configTOTAL_HEAP_SIZE */
13#define configSUPPORT_STATIC_ALLOCATION         1
14#ifdef RT_USING_HEAP
15    #define configSUPPORT_DYNAMIC_ALLOCATION    1
16    #define configTOTAL_HEAP_SIZE               10240
17    #define configAPPLICATION_ALLOCATED_HEAP    0
18#endif
19
20#define configMINIMAL_STACK_SIZE                128
21
22/* Selectable functions and features */
23#define INCLUDE_vTaskPrioritySet                1
24#define INCLUDE_uxTaskPriorityGet               1
25#define INCLUDE_vTaskDelete                     1
26#define INCLUDE_vTaskSuspend                    1
27#define INCLUDE_xTaskDelayUntil                 1
28#define INCLUDE_vTaskDelay                      1
29#define INCLUDE_xTaskGetIdleTaskHandle          1
30#define INCLUDE_xTaskAbortDelay                 1
31#define INCLUDE_xSemaphoreGetMutexHolder        1
32#define INCLUDE_xTaskGetHandle                  1
33#define INCLUDE_uxTaskGetStackHighWaterMark     1
34#define INCLUDE_uxTaskGetStackHighWaterMark2    1
35#define INCLUDE_eTaskGetState                   1
36#define INCLUDE_xTaskResumeFromISR              1
37#define INCLUDE_xTaskGetSchedulerState          1
38#define INCLUDE_xTaskGetCurrentTaskHandle       1
39#define configUSE_APPLICATION_TASK_TAG          1
40#define configUSE_TASK_NOTIFICATIONS            1
41#define configTASK_NOTIFICATION_ARRAY_ENTRIES   3

Some examples are provided in the test directory, which can be added to the applications folder under the BSP directory. After compiling and burning with SCons, you can connect to the serial port, input the corresponding msh commands, and observe the execution results of the examples:

 1msh />queue_dynamic
 2Task 1 receive data 0 from queue
 3Task 1 receive data 1 from queue
 4Task 1 receive data 2 from queue
 5Task 1 receive data 3 from queue
 6Task 1 receive data 4 from queue
 7Task 1 receive data 5 from queue
 8Task 1 receive data 6 from queue
 9Task 1 receive data 7 from queue
10Task 1 receive data 8 from queue
11Task 1 receive data 9 from queue
12Task 1 receive data 10 from queue

4 References

RT-Thread Documentation

https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/README

FreeRTOS Documentation

https://www.freertos.org/a00106.html

Github Address

https://github.com/RT-Thread-packages/FreeRTOS-Wrapper

Looking Forward to YourStar

———————End———————

You can add WeChat:rtthread2020 as a friend, and note:Company + Name, to join the official RT-Thread WeChat group!

FreeRTOS Compatibility Layer for RT-Thread Operating System

If you love me, please give me a thumbs upFreeRTOS Compatibility Layer for RT-Thread Operating System

👇ClickRead Original

Leave a Comment

×