中文 | English
This is a FreeRTOS application compatibility layer (ACL) for RT-Thread operating system. It allows developers to quickly and seamlessly migrate their existing FreeRTOS applications to RT-Thread. Developers can use the same FreeRTOS API on their new RT-Thread applications, and take advantage of the feature-rich software components and packages offered by RT-Thread. The ACL is based on FreeRTOS V10.4.6. As of now it has supported migrations of multiple FreeRTOS-based SDK to RT-Thread.
- μCOS-III ACL for RT-Thread:https://github.com/mysterywolf/RT-Thread-wrapper-of-uCOS-III
- μCOS-II ACL for RT-Thread:https://github.com/mysterywolf/RT-Thread-wrapper-of-uCOS-II
- RTX(CMSIS-RTOS1) ACL for RT-Thread:https://github.com/RT-Thread-packages/CMSIS_RTOS1
- RTX5(CMSIS-RTOS2) ACL for RT-Thread:https://github.com/RT-Thread-packages/CMSIS_RTOS2
- Arduino Ecosystem Compatibility Layer for RT-Thread:https://github.com/RTduino/RTduino
Below is the current status of FreeRTOS API support offered by the FreeRTOS wrapper:
- xTaskCreate
- xTaskCreateStatic
- xTaskCreateRestrictedStatic
- vTaskDelete
- vTaskDelay
- vTaskDelayUntil
- xTaskDelayUntil
- uxTaskPriorityGet
- vTaskPrioritySet
- vTaskSuspend (Only support suspending the currently running task)
- vTaskResume
- xTaskResumeFromISR
- xTaskAbortDelay
- uxTaskGetSystemState
- vTaskGetInfo
- vTaskList
- vTaskGetRunTimeStats
- vTaskStartTrace
- ulTaskEndTrace
- SetThreadLocalStoragePointer
- GetThreadLocalStoragePointer
- xTaskGetApplicationTaskTag
- xTaskGetCurrentTaskHandle
- xTaskGetIdleTaskHandle
- uxTaskGetStackHighWaterMark
- eTaskGetState
- pcTaskGetName
- xTaskGetTickCount
- xTaskGetTickCountFromISR
- xTaskGetSchedulerState
- uxTaskGetNumberOfTasks
- vTaskSetApplicationTaskTag
- xTaskCallApplicationTaskTag
- vTaskSetTimeoutState
- xTaskGetCheckForTimeout
- taskYIELD
- taskENTER_CRITICAL
- taskEXIT_CRITICAL
- taskENTER_CRITICAL_FROM_ISR
- taskEXIT_CRITICAL_FROM_ISR
- taskDISABLE_INTERRUPTS
- taskENABLE_INTERRUPTS
- vTaskStartScheduler
- vTaskEndScheduler
- vTaskSuspendAll
- xTaskResumeAll
- vTaskStepTick
- xTaskCatchUpTicks
- xTaskNotifyGive
- vTaskNotifyGiveFromISR
- ulTaskNotifyTake
- xTaskNotify
- xTaskNotifyAndQuery
- xTaskNotifyAndQueryFromISR
- xTaskNotifyFromISR
- xTaskNotifyWait
- xTaskNotifyStateClear
- ulTaskNotifyValueClear
- xQueueCreate
- xQueueCreateStatic
- vQueueDelete
- xQueueSend
- xQueueSendFromISR
- xQueueSendToBack
- xQueueSendToBackFromISR
- xQueueSendToFront (Time out not supported)
- xQueueSendToFrontFromISR
- xQueueReceive
- xQueueReceiveFromISR
- uxQueueMessagesWaiting
- uxQueueMessagesWaitingFromISR
- uxQueueSpacesAvailable
- xQueueReset
- xQueueOverwrite
- xQueueOverwriteFromISR
- xQueuePeek
- xQueuePeekFromISR
- xQueueIsQueueFullFromISR
- xQueueIsQueueEmptyFromISR
- vQueueAddToRegistry
- vQueueUnregisterQueue
- pcQueueGetName
- xSemaphoreCreateBinary
- xSemaphoreCreateBinaryStatic
- vSemaphoreCreateBinary
- xSemaphoreCreateCounting
- xSemaphoreCreateCountingStatic
- xSemaphoreCreateMutex
- xSemaphoreCreateMutexStatic
- xSem'CreateRecursiveMutex
- xSem'CreateRecursiveMutexStatic
- vSemaphoreDelete
- xSemaphoreGetMutexHolder
- uxSemaphoreGetCount
- xSemaphoreTake
- xSemaphoreTakeFromISR
- xSemaphoreTakeRecursive
- xSemaphoreGive
- xSemaphoreGiveRecursive
- xSemaphoreGiveFromISR
- xTimerCreate
- xTimerCreateStatic
- xTimerIsTimerActive
- xTimerStart
- xTimerStop
- xTimerChangePeriod
- xTimerDelete
- xTimerReset
- xTimerStartFromISR
- xTimerStopFromISR
- xTimerChangePeriodFromISR
- xTimerResetFromISR
- pvTimerGetTimerID
- vTimerSetReloadMode
- vTimerSetTimerID
- xTimerGetTimerDaemonTaskHandle
- xTimerPendFunctionCall
- xTimerPendFunctionCallFromISR
- pcTimerGetName
- xTimerGetPeriod
- xTimerGetExpiryTime
- uxTimerGetReloadMode
- xEventGroupCreate
- xEventGroupCreateStatic
- vEventGroupDelete
- xEventGroupWaitBits
- xEventGroupSetBits
- xEventGroupSetBitsFromISR
- xEventGroupClearBits
- xEventGroupClearBitsFromISR
- xEventGroupGetBits
- xEventGroupGetBitsFromISR
- xEventGroupSync
Similar to FreeRTOS, RT-Thread is a real-time operating system supporting multiple architectures, including ARM, RISC-V, etc. RT-Thread offers the typical task control APIs, software timer, and various task synchronization mechanisms including semaphores, mutexes, message queues and event groups. However, there are some subtle differences between implementations of similar features in FreeRTOS and RT-Thread. These differences are detailed below and care needs to be taken when using the following APIs.
vTaskSuspend
only supports suspending the currently-running task. When using xTaskToSuspend
, the xTaskToSuspend
must be NULL
. Otherwise an assertion will be triggered.
xQueueSendToFront
does not support specifying a time out. When calling the API the xTicksToWait
parameter is ignored. If the queue is full errQUEUE_FULL
will be returned immediately.
Please follow the example below to create a static queue. This will ensure enough memory is allocated to store the specified number of queue items.
#define QUEUE_LENGTH 10
#define ITEM_SIZE sizeof( uint32_t )
/* This is how the memory of a static queue is allocated in a FreeRTOS application. Because of differences between implementation details of queues in RT-Thread and FreeRTOS, memory allocated using this approach is not sufficient to store QUEUE_LENGTH number of elements. */
//uint8_t ucQueueStorage[ QUEUE_LENGTH * ITEM_SIZE ];
/* Need to use the QUEUE_BUFFER_SIZE macro to allocate memory */
uint8_t ucQueueStorage[ QUEUE_BUFFER_SIZE(QUEUE_LENGTH, ITEM_SIZE)];
StaticQueue_t xQueueBuffer;
QueueHandle_t xQueue1;
xQueue1 = xQueueCreate( QUEUE_LENGTH, ITEM_SIZE, &( ucQueueStorage[ 0 ] ), &xQueueBuffer );
FreeRTOS offers two types of Mutexes: Mutex and Recursive Mutex. Recursive Mutexes can be taken repeatedly by the same task, while Mutexes cannot. All Mutexes in RT-Thread can be taken repeatedly. Therefore, the FreeRTOS wrapper does not distinguish between Mutexes and Recursive Mutexes. Mutexes created using either xSemaphoreCreateMutex
or xSemaphoreCreateRecursiveMutex
can be taken repeatedly.
Unlike FreeRTOS, RT-Thread does not send timer commands to the timer task using a message queue. When using any timer APIs that requires setting a time out in the FreeRTOS wrapper, such as xTimerStart( xTimer, xTicksToWait )
, the xTicksToWait
parameter is ignored and all such functions return immediately.
FreeRTOS distinguish those APIs that can be used from ISR and those that cannot. Those can be used from ISR has the word FromISR
in their names. Is using these APIs from ISR wakes up a higher priority task, a FreeRTOS application normally needs to invoke the scheuler manually, as shown in the following example:
BaseType_t xHigherPrioritTaskWoken = pdFALSE;
xQueueSendToFrontFromISR( xRxQueue, &cIn, &xHigherPriorityTaskWoken );
if( xHigherPriorityTaskWoken )
{
taskYIELD ();
}
RT-Thread does not provide a FromISR
version for its APIs. RT-Thread APIs can be used from ISR and they invoke the scheduler automatically. Therefore when using the FreeRTOS wrapper, you do not need to manually invoke the scheduler after using FromISR APIs. xHigherPriorityTaskWoken
is always set to pdFALSE
.
The FreeRTOS wrapper preserves the five heap allocation algorithms of FreeRTOS. By default heap_3
is used, and pvPortMalloc/vPortFree
invokes RT_KERNEL_MALLOC/RT_KERNEL_FREE
to allocate memory from the system heap maintained by RT-Thread. When using heap_3
the heap size is controlled by RT-Thread BSP configurations and you cannot change it by setting configTOTAL_HEAP_SIZE
in FreeRTOSConfig.h
.
If you want to use other heap allocation algorithms you need to modify FreeRTOS/sSConscript
and choose the source file accordingly
#You can replace heap_3 with heap_1, etc
src += Glob(os.path.join("portable", "MemMang", "heap_3.c"))
When using algorithms other than heap_3
you can set the heap size using configTOTAL_HEAP_SIZE
in FreeRTOS/portable/rt-thread/FreeRTOSConfig.h
. When using pvPortMalloc/vPortFree
, memory is allocated from a heap maintained by the FreeRTOS wrapper, separate from the RT-Thread system heap, with a size of configTOTAL_HEAP_SIZE
. Other memory allocations without invoking pvPortMalloc/vPortFree
, including the allocations made by the FreeRTOS wrapper APIs internally, are satisfied using the RT-Thread system heap.
In RT-Thread a smaller numerical value indicates a higher task priority. On the contrary, in FreeRTOS a larger numerical value indicates a higher priority. When using the FreeRTOS wrapper APIs such as xTaskCreate
, task priority is specified using FreeRTOS rules.Care needs to be taken when both RT-Thread and FreeRTOS task APIs are used in the same application. You can use the following two macros to convert between RT-Thread and FreeRTOS task priority:
#define FREERTOS_PRIORITY_TO_RTTHREAD(priority) ( configMAX_PRIORITIES - 1 - ( priority ) )
#define RTTHREAD_PRIORITY_TO_FREERTOS(priority) ( RT_THREAD_PRIORITY_MAX - 1 - ( priority ) )
The unit of FreeRTOS task stack size is sizeof(StackType_t)
, while it is sizeof(rt_uint8_t)
for RT-Thread. Do not confuse between the two and stick to FreeRTOS rules when creating tasks using FreeRTOS APIs.
The startup procedure of RT-Thread is different from FreeRTOS. When using the FreeRTOS wrapper, the main
function is run in the context of a task, whose priority is CONFIG_RT_MAIN_THREAD_PRIORITY
. (This is specified using RT-Thread SCons configuration. A smaller numerical value indicates a higher priority.) At this time the scheduler is already started. The code for creating a task and starting the scheduler normally looks like the following in a FreeRTOS application:
xTaskCreate(pxTask1Code, ......);
xTaskCreate(pxTask2Code, ......);
......
vTaskStartScheduler();
When using the application compatibility layer, if you use xTaskCreate
to create any task that has a priority higher than CONFIG_RT_MAIN_THREAD_PRIORITY
, it will execute immediately. vTaskStartScheduler
is only a dummy function. Care needs to be taken when creating tasks using the FreeRTOS wrapper. You need to make sure all resources needed for the task are initialized and the task can execute normally when creating tasks using xTaskCreate
.
First use Env tool or RT-Thread Studio to add the FreeRTOS wrapper to your project:
RT-Thread online packages
system packages --->
[*] FreeRTOS Wrapper --->
Version (latest)
These configuration operations will impact the FreeRTOS wrapper
RT_USING_TIMER_SOFT /* Must enable when using FreeRTOS timers */
RT_TIMER_THREAD_PRIO /* Timer task priority. Smaller numerical value indicates higher priority. */
RT_TIMER_THREAD_STACK_SIZE /* Timer thread stack size. Unit is sizeof(rt_uint8_t). */
RT_USING_MUTEX /* Must enable when using FreeRTOS mutexes */
RT_USING_SEMAPHORE /* Must enable when using FreeRTOS semaphores */
RT_USING_HEAP /* Must enable when using FreeRTOS heap or dynamic allocation */
RT_TICK_PER_SECOND /* equivalent to FreeRTOS configTICK_RATE_HZ */
RT_THREAD_PRIORITY_MAX /* equivalent to FreeRTOS configMAX_PRIORITIES */
RT_NAME_MAX /* equivalent to FreeRTOS configMAX_TASK_NAME_LEN */
You can find a FreeRTOSConfig.h
template in FreeRTOS/portable/rt-thread
. Most configuration options are read-only or depend on RT-Thread configurations. Those can be modified are detailed below:
/* You can choose not to use recursive mutex */
#ifdef RT_USING_MUTEX
#define configUSE_RECURSIVE_MUTEXES 1
#define configUSE_MUTEXES 1
#endif
/* You can choose not to use counting semaphore */
#ifdef RT_USING_SEMAPHORE
#define configUSE_COUNTING_SEMAPHORES 1
#endif
/* If not using heap_3, you can configure heap size using configTOTAL_HEAP_SIZE */
#define configSUPPORT_STATIC_ALLOCATION 1
#ifdef RT_USING_HEAP
#define configSUPPORT_DYNAMIC_ALLOCATION 1
#define configTOTAL_HEAP_SIZE 10240
#define configAPPLICATION_ALLOCATED_HEAP 0
#endif
#define configMINIMAL_STACK_SIZE 128
/* Optional functions or features */
#define INCLUDE_vTaskPrioritySet 1
#define INCLUDE_uxTaskPriorityGet 1
#define INCLUDE_vTaskDelete 1
#define INCLUDE_vTaskSuspend 1
#define INCLUDE_xTaskDelayUntil 1
#define INCLUDE_vTaskDelay 1
#define INCLUDE_xTaskGetIdleTaskHandle 1
#define INCLUDE_xTaskAbortDelay 1
#define INCLUDE_xSemaphoreGetMutexHolder 1
#define INCLUDE_xTaskGetHandle 1
#define INCLUDE_uxTaskGetStackHighWaterMark 1
#define INCLUDE_uxTaskGetStackHighWaterMark2 1
#define INCLUDE_eTaskGetState 1
#define INCLUDE_xTaskResumeFromISR 1
#define INCLUDE_xTaskGetSchedulerState 1
#define INCLUDE_xTaskGetCurrentTaskHandle 1
#define configUSE_APPLICATION_TASK_TAG 1
#define configUSE_TASK_NOTIFICATIONS 1
#define configTASK_NOTIFICATION_ARRAY_ENTRIES 3
Some examples are provided under the test
directory. You can copy them to the application
folder under the BSP directory. After building with SCons and downloading the application, you can enter relevant msh commands from the serial monitor and observe the behavior of these examples:
msh />queue_dynamic
Task 1 receive data 0 from queue
Task 1 receive data 1 from queue
Task 1 receive data 2 from queue
Task 1 receive data 3 from queue
Task 1 receive data 4 from queue
Task 1 receive data 5 from queue
Task 1 receive data 6 from queue
Task 1 receive data 7 from queue
Task 1 receive data 8 from queue
Task 1 receive data 9 from queue
Task 1 receive data 10 from queue
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
Homepage:https://github.com/RT-Thread-packages/FreeRTOS-Wrapper
Maintainer:Zhaozhou Tang