Migration from FreeRTOS to embOS
This wiki article describes the migration from FreeRTOS to embOS. We will extend this Wiki article if necessary. Please don't hesitate to let us know if you think any helpful information is missing here.
Contents
Introduction
The following information help to migrate an existing application from FreeRTOS to embOS.
The actual work can be split into two parts:
- Replacing of the FreeRTOS sources with the embOS library (or sources).
- Replacing of the FreeRTOS API with the according embOS API.
Replacing FreeRTOS with embOS
Assuming you have a working project with FreeRTOS please remove all FreeRTOS related files. These FreeRTOS source files are named:
- croutine.c
- event_groups.c
- list.c
- queue.c
- stream_buffer.c
- tasks.c
- timers.c
- port.c
- portmacro.h
- atomic.h
- croutine.h
- deprecated_definitions.h
- event_groups.h
- FreeRTOS.h
- list.h
- message_buffer.h
- mpu_prototypes.h
- mpu_wrappers.h
- portable.h
- projdefs.h
- queue.h
- semphr.h
- stack_macros.h
- StackMacros.h
- stream_buffer.h
- task.h
- timers.h
Depending on the actual FreeRTOS port and version there might be additional files or files with a similar name.
embOS comes as object or as source code variant. The object code variant includes embOS as library whereas the source code variant additionally includes the embOS source code. It is your choice if you prefer to use the embOS library or the embOS source code in your project. If you like to use the embOS library we suggest to start with the debug + profiling library. The library name includes the characters "dp", e.g. libos_v7m_t_vfpv4_le_dp.a.
If you like to use the embOS sources instead please add the following files from GenOSSrc/ folder to your project:
- OS_Alloc.c
- OS_Com.c
- OS_EventObject.c
- OS_Global.c
- OS_Info.c
- OS_Kern.c
- OS_LowPower.c
- OS_Mailbox.c
- OS_MemPool.c
- OS_MPU.c (only in case of embOS-MPU)
- OS_Mutex.c
- OS_Queue.c
- OS_RWLock.c
- OS_Semaphore.c
- OS_SoftwareTimer.c
- OS_Spinlock.c
- OS_SysTick.c
- OS_Task.c
- OS_TaskEvent.c
- OS_Timing.c
- OS_Trace.c
There are additional port specific source files in the CPU/ and CPU/OSSrcCPU/ folder. Please add them to your project as well. Set includes paths to RTOS.h in Start/Inc/ and in case of embOS source code also to CPU/ and GenOSSrc/ folder. The define OS_LIBMODE_DP must be set in the preprocessor settings.
For more information on how to set up a project with embOS sources, please refer to Source code project.
Additional embOS board support package files need to be added to your project. You can find these files in the Setup/ and SEGGER/ folder of the according board support package. The board support packages are located in Start/BoardSupport. These files are e.g.:
- OS_Error.c
- RTOSInit.c
- SEGGER_RTT.c (in case RTT should be used)
- SEGGER_SYSVIEW.c (in case SystemView should be used)
SEGGER RTT and SystemView are not viable for embOS but are helpful tools.
Replacing FreeRTOS API with embOS API
Most FreeRTOS API has an appropriate embOS API. Since the parameter meaning could be different the FreeRTOS API can't be replaced just with search & replace.
xTaskCreate | OS_TASK_Create, OS_TASK_CreateEx |
xTaskCreateStatic | OS_TASK_Create, OS_TASK_CreateEx |
vTaskDelete | OS_TASK_Terminate |
vTaskDelay | OS_TASK_Delay |
vTaskDelayUntil | OS_TASK_DelayUntil |
uxTaskPriorityGet | OS_TASK_GetPriority |
vTaskPrioritySet | OS_TASK_SetPriority |
vTaskSuspend | OS_TASK_Suspend |
vTaskResume | OS_TASK_Resume |
xTaskResumeFromISR | OS_TASK_Resume |
xTaskAbortDelay | OS_TASK_Wake |
uxTaskGetSystemState | See vTaskGetInfo |
vTaskGetInfo | OS_TASK_GetName OS_TASK_GetPriority OS_TASK_GetID OS_STACK_GetTaskStackBase |
xTaskGetCurrentTaskHandle | OS_TASK_GetID |
xTaskGetIdleTaskHandle | |
uxTaskGetStackHighWaterMark | OS_STACK_GetTaskStackSpace |
eTaskGetState | |
pcTaskGetName | OS_TASK_GetName |
xTaskGetHandle | |
xTaskGetTickCount | OS_TIME_GetTicks |
xTaskGetTickCountFromISR | OS_TIME_GetTicks |
xTaskGetSchedulerState | OS_IsRunning |
uxTaskGetNumberOfTasks | OS_TASK_GetNumTasks |
vTaskList | |
vTaskStartTrace | See SystemView |
ulTaskEndTrace | See SystemView |
vTaskGetRunTimeStats | See embOSView or SystemView |
vTaskGetIdleRunTimeCounter | |
vTaskSetApplicationTaskTag | |
xTaskGetApplicationTaskTag | |
xTaskCallApplicationTaskHook | |
pvTaskGetThreadLocalStoragePointer | |
vTaskSetThreadLocalStoragePointer | |
vTaskSetTimeOutState | |
xTaskCheckForTimeOut | |
taskYIELD | OS_TASK_Yield |
taskENTER_CRITICAL | OS_INT_IncDI (embOS provides critical regions that prevent preemptive task switches and don't disable interrupts like taskENTER_CRITICAL and taskEXIT_CRITICAL. See OS_TASK_EnterRegion and OS_TASK_LeaveRegion.) |
taskEXIT_CRITICAL | OS_INT_DecRI (embOS provides critical regions that prevent preemptive task switches and don't disable interrupts like taskENTER_CRITICAL and taskEXIT_CRITICAL. See OS_TASK_EnterRegion and OS_TASK_LeaveRegion.) |
taskENTER_CRITICAL_FROM_ISR | OS_INT_IncDI |
taskEXIT_CRITICAL_FROM_ISR | OS_INT_DecRI |
taskDISABLE_INTERRUPTS | OS_INT_Disable |
taskENABLE_INTERRUPTS | OS_INT_Enable |
vTaskStartScheduler | OS_Start |
vTaskEndScheduler | OS_Stop |
vTaskSuspendAll | OS_TASK_SuspendAll |
xTaskResumeAll | OS_TASK_ResumeAll |
vTaskStepTick | OS_TICKLESS_AdjustTime |
xTaskCatchUpTicks | OS_TICKLESS_AdjustTime |
xTaskNotifyGive() / xTaskNotifyGiveIndexed() | OS_TASKEVENT_Set (if xTaskNotifyGive used with ulTaskNotifyWait) OS_SEMAPHORE_Give (if xTaskNotifyGive used with ulTaskNotifyTake) |
vTaskNotifyGiveFromISR() / vTaskNotifyGiveIndexedFromISR() | OS_TASKEVENT_Set (if xTaskNotifyGive used with ulTaskNotifyWait) OS_SEMAPHORE_Give (if xTaskNotifyGive used with ulTaskNotifyTake) |
ulTaskNotifyTake() / ulTaskNotifyTakeIndexed() | OS_SEMAPHORE_Take, OS_SEMAPHORE_TakeTimed, OS_SEMAPHORE_TakeBlocked |
xTaskNotify() / xTaskNotifyIndexed() | OS_TASKEVENT_Set (if eNoAction or eSetBits was used) OS_MAILBOX_Put, OS_MAILBOX_Put1 (if eSetValueWithoutOverwrite was used) OS_SEMAPHORE_Give (if eIncrement was used) |
xTaskNotifyAndQuery() / xTaskNotifyAndQueryIndexed() | |
xTaskNotifyAndQueryFromISR / xTaskNotifyAndQueryFromISRIndexed()/ | |
xTaskNotifyFromISR() / xTaskNotifyFromISRIndexed() | OS_TASKEVENT_Set (if eNoAction or eSetBits was used) OS_MAILBOX_Put (if eSetValueWithoutOverwrite was used) OS_SEMAPHORE_Give (if eIncrement was used) |
xTaskNotifyWait() / xTaskNotifyWaitIndexed() | OS_TASKEVENT_Get, OS_TASKEVENT_GetTimed, OS_TASKEVENT_GetBlocked |
xTaskNotifyStateClear() / xTaskNotifyStateClearIndexed() | OS_TASKEVENT_Clear |
ulTasknotifyValueClear() / ulTasknotifyValueClearIndexed() | |
xQueueCreate | OS_QUEUE_Create |
xQueueCreateStatic | OS_QUEUE_Create |
vQueueDelete | OS_QUEUE_Delete |
xQueueSend | OS_MAILBOX_Put, OS_MAILBOX_Put1 |
xQueueSendFromISR | OS_MAILBOX_Put |
xQueueSendToBack | OS_MAILBOX_Put, OS_MAILBOX_Put1 |
xQueueSendToBackFromISR | OS_MAILBOX_Put |
xQueueSendToFront | OS_MAILBOX_PutFront, OS_MAILBOX_PutFront1 |
xQueueSendToFrontFromISR | OS_MAILBOX_PutFront |
xQueueReceive | OS_MAILBOX_Get, OS_MAILBOX_GetTimed, OS_MAILBOX_GetBlocked |
xQueueReceiveFromISR | OS_MAILBOX_Get |
uxQueueMessagesWaiting | OS_MAILBOX_GetMessageCnt |
uxQueueMessagesWaitingFromISR | OS_MAILBOX_GetMessageCnt |
uxQueueSpacesAvailable | |
xQueueReset | OS_MAILBOX_Clear |
xQueuePeek | OS_MAILBOX_Peek |
xQueuePeekFromISR | OS_MAILBOX_Peek |
vQueueAddToRegistry | OS_DEBUG_SetObjName |
pcQueueGetName | OS_DEBUG_GetObjName |
vQueueUnregisterQueue | OS_DEBUG_RemoveObjName |
xQueueIsQueueEmptyFromISR | OS_QUEUE_GetMessageCnt |
xQueueIsQueueFullFromISR | Use OS_QUEUE_GetMessageCnt to check if returned value equals max message count. Alternatively, OS_QUEUE_Put returns a value unequal to zero if a message couldn't be put into the queue, because the queue is full. |
xQueueOverwrite | |
xQueueOverwriteFromISR | |
xSemaphoreCreateBinary | OS_SEMAPHORE_Create (used together with OS_SEMAPHORE_GiveMax and 1 as argument the semaphore will behave like a binary semaphore) |
xSemaphoreCreateBinaryStatic | OS_SEMAPHORE_Create (used together with OS_SEMAPHORE_GiveMax and 1 as argument the semaphore will behave like a binary semaphore) |
vSemaphoreCreateBinary | OS_SEMAPHORE_Create (used together with OS_SEMAPHORE_GiveMax and 1 as argument the semaphore will behave like a binary semaphore) |
xSemaphoreCreateCounting | OS_SEMAPHORE_Create |
xSemaphoreCreateCountingStatic | OS_SEMAPHORE_Create |
xSemaphoreCreateMutex | OS_MUTEX_Create |
xSemaphoreCreateMutexStatic | OS_MUTEX_Create |
xSemaphoreCreateRecursiveMutex | OS_MUTEX_Create |
xSemaphoreCreateRecursiveMutexStatic | OS_MUTEX_Create |
vSemaphoreDelete | OS_SEMAPHORE_Delete, OS_MUTEX_Delete |
xSemaphoreGetMutexHolder | OS_MUTEX_GetOwner |
xSemaphoreTake | OS_SEMAPHORE_Take, OS_SEMAPHORE_TakeTimed, OS_SEMAPHORE_TakeBlocked, OS_MUTEX_Lock, OS_MUTEX_LockTimed, OS_MUTEX_LockBlocked |
xSemaphoreTakeFromISR | OS_SEMAPHORE_Take |
xSemaphoreTakeRecursive | OS_SEMAPHORE_Take, OS_SEMAPHORE_TakeTimed, OS_SEMAPHORE_TakeBlocked, OS_MUTEX_Lock, OS_MUTEX_LockTimed, OS_MUTEX_LockBlocked |
xSemaphoreGive | OS_SEMAPHORE_Give, OS_MUTEX_Unlock |
xSemaphoreGiveRecursive | OS_SEMAPHORE_Give, OS_MUTEX_Unlock |
xSemaphoreGiveFromISR | OS_SEMAPHORE_Give |
uxSemaphoreGetCount | OS_SEMAPHORE_GetValue, OS_MUTEX_GetValue |
xTimerCreate | OS_TIMER_Create, OS_TIMER_CreateEx |
xTimerCreateStatic | OS_TIMER_Create, OS_TIMER_CreateEx |
xTimerIsTimerActive | OS_TIMER_GetStatus, OS_TIMER_GetStatusEx |
pvTimerGetTimerID | OS_TIMER_GetCurrent, OS_TIMER_GetCurrentEx (Can be used from within a timer callback to get the timer ID) |
pcTimerGetName | OS_DEBUG_GetObjName |
vTimerSetReloadMode | The timer automatically restarts when the timer callback calls OS_TIMER_Restart/OS_TIMER_RestartEx |
xTimerStart | OS_TIMER_Start, OS_TIMER_StartEx |
xTimerStop | OS_TIMER_Stop, OS_TIMER_StopEx |
xTimerChangePeriod | OS_TIMER_SetPeriod, OS_TIMER_SetPeriodEx |
xTimerDelete | OS_TIMER_Delete, OS_TIMER_DeleteEx |
xTimerReset | OS_TIMER_Restart, OS_TIMER_RestartEx |
xTimerStartFromISR | OS_TIMER_Start, OS_TIMER_StartEx |
xTimerStopFromISR | OS_TIMER_Stop, OS_TIMER_StopEx |
xTimerChangePeriodFromISR | OS_TIMER_SetPeriod, OS_TIMER_SetPeriodEx |
xTimerResetFromISR | OS_TIMER_Restart, OS_TIMER_RestartEx |
vTimerSetTimerID | |
xTimerGetTimerDaemonTaskHandle | |
xTimerPendFunctionCall | |
xTimerPendFunctionCallFromISR | |
pcTimerGetName | OS_DEBUG_GetObjName |
xTimerGetPeriod | OS_TIMER_GetPeriod |
xTimerGetExpiryTime | OS_TIME_GetTicks + OS_TIMER_GetRemainingPeriod/OS_TIMER_GetRemainingPeriodEx |
xEventGroupCreate | OS_EVENT_Create, OS_EVENT_CreateEx |
xEventGroupCreateStatic | OS_EVENT_Create, OS_EVENT_CreateEx |
xEventGroupWaitBits | OS_EVENT_GetMask, OS_EVENT_GetMaskTimed, OS_EVENT_GetMaskBlocked |
xEventGroupSetBits | OS_EVENT_SetMask |
xEventGroupSetBitsFromISR | OS_EVENT_SetMask |
xEventGroupClearBits | OS_EVENT_ResetMask |
xEventGroupClearBitsFromISR | OS_EVENT_ResetMask |
xEventGroupGetBits | OS_EVENT_GetMask (Returns and consumes the passed bit mask) |
xEventGroupGetBitsFromISR | |
xEventGroupSync | |
vEventGroupDelete | OS_EVENT_Delete |
Configuration
FreeRTOS is configured in FreeRTOSConfig.h. Although there exists a similar file OS_Config.h with embOS it is not necessary to configure anything there. If the embOS library mode is set in the preprocessor settings OS_Config.h is not used at all. Especially if you are working with the embOS source code OS_Config.h can be helpful to define optional settings.
Include files
With FreeRTOS different include files must be included in the application source file depending on the used FreeRTOS API.
#include "FreeRTOS.h"
#include "task.h"
With embOS just the RTOS.h needs to be included:
#include "RTOS.h"
Memory allocation
FreeRTOS offers different memory allocation methods. These are implemented in the files heap_1.c - heap_5.c. With FreeRTOS the RAM can be automatically dynamically allocated from the RTOS heap within the RTOS API object creation functions, or it can be provided by the application writer.
embOS API object creation functions expect a pointer to allocated memory. This memory is usually statically allocated by the application but can also be allocated from the heap.
Example for static allocation
#include "RTOS.h"
static OS_MUTEX Mutex;
int main(void) {
...
OS_MUTEX_Create(&Mutex);
...
return 0;
}
Example for dynmaic allocation
#include "RTOS.h"
#include "stdlib.h"
static OS_MUTEX* pMutex;
int main(void) {
...
pMutex = malloc(sizeof(OS_MUTEX));
OS_MUTEX_Create(pMutex);
...
return 0;
}
Sample application
FreeRTOS
STM32H743ZI_Nucleo_OS_Migration_FreeRTOS.zip
#include "FreeRTOS.h"
#include "task.h"
static void HPTask(void *pvParameters) {
(void)pvParameters;
while (1) {
vTaskDelay(50);
}
}
static void LPTask(void *pvParameters) {
(void)pvParameters;
while (1) {
vTaskDelay(200);
}
}
int main(void) {
xTaskCreate( HPTask, "HP Task", configMINIMAL_STACK_SIZE, NULL, 1, NULL );
xTaskCreate( LPTask, "LP Task", configMINIMAL_STACK_SIZE, NULL, 1, NULL );
vTaskStartScheduler();
return 0;
}
embOS
STM32H743ZI_Nucleo_OS_Migration_embOS.zip
#include "RTOS.h"
static OS_STACKPTR int StackHP[128], StackLP[128]; // Task stacks
static OS_TASK TCBHP, TCBLP; // Task control blocks
static void HPTask(void) {
while (1) {
OS_TASK_Delay(50);
}
}
static void LPTask(void) {
while (1) {
OS_TASK_Delay(200);
}
}
int main(void) {
OS_Init(); // Initialize embOS
OS_InitHW(); // Initialize required hardware
OS_TASK_CREATE(&TCBHP, "HP Task", 100, HPTask, StackHP);
OS_TASK_CREATE(&TCBLP, "LP Task", 50, LPTask, StackLP);
OS_Start(); // Start embOS
return 0;
}