This is an old revision of the document!
This page describes how to migrate the µC/OS-III to FreeRTOS for those customers who want to migrate their µC/OS-III-based application to FreeRTOS. You will find that migrating µC/OS-III Applications into FreeRTOS is quite straightforward and in most cases will requires just a few hours.
Applicable Version
Name | Version | Description | |
---|---|---|---|
µC/OS-III | v2.9.0 | ADI-uCOS-III-Rel2.9.0 | |
FreeRTOS | v1.0.0 | ADI-FreeRTOS-Addin-1.0.0 ( Based Official FreeRTOSv10.0.0 ) | |
Supported Boards
Analog Devices ADPS-SC5xx | ADSP-215xx | ADSP-BF7xx series boards.
The guide covers the following topics:
The folder structure for both µC/OS-III and FreeRTOS are shown below in Table 1. Simple replace the µC/OS-III source code with the files shown on the right column.
uCOS-III
uCOS-III ├── common │ ├── Templates │ │ ├── app_cfg.h │ │ ├── app_ucos3_cfg.h │ │ ├── os_app_hooks.c │ │ ├── os_app_hooks.h │ │ ├── os_cfg_app.h │ │ ├── os_cfg.h │ │ └── rom │ └── uCOS-III │ ├── os.h │ ├── Source │ │ ├── os_cfg_app.c │ │ ├── os_core.c │ │ ├── os_dbg.c │ │ ├── os_flag.c │ │ ├── os.h │ │ ├── os_int.c │ │ ├── os_mem.c │ │ ├── os_msg.c │ │ ├── os_mutex.c │ │ ├── os_pend_multi.c │ │ ├── os_prio.c │ │ ├── os_q.c │ │ ├── os_sem.c │ │ ├── os_stat.c │ │ ├── os_task.c │ │ ├── os_tick.c │ │ ├── os_time.c │ │ ├── os_tmr.c │ │ ├── os_type.h │ │ └── os_var.c │ └── TLS │ └── CCES │ └── os_tls.c ├── ARM-Cortex-A5 │ └── uCOS-III │ └── Ports │ ├── os_adi_xx.x │ └── os_cpu_xx.x ├── Blackfin │ └── uCOS-III │ └── Ports │ ├── os_adi_xx.x │ └── os_cpu_xx.x └── SHARC └── uCOS-III └── Ports ├── os_adi_xx.x └── os_cpu_xx.x
FreeRTOS
FreeRTOS └── Source ├── croutine.c ├── event_groups.c ├── list.c ├── queue.c ├── stream_buffer.c (1-1) ├── tasks.c ├── timers.c ├── include │ ├── deprecated_definitions.h │ ├── message_buffer.h │ ├── stack_macros.h │ ├── stdint.readme │ ├── stream_buffer.h │ ├── croutine.h │ ├── event_groups.h │ ├── FreeRTOS.h (1-2) │ ├── list.h │ ├── mpu_prototypes.h │ ├── mpu_wrappers.h │ ├── portable.h │ ├── projdefs.h │ ├── queue.h │ ├── semphr.h │ ├── StackMacros.h │ ├── task.h │ └── timers.h └── portable ├── GCC │ └── ARM_CA9 │ ├── portASM.S (2-1) │ ├── port.c │ └── portmacro.h └── CCES ├── ARM_CA5 │ ├── dispatcher.c │ ├── freertos.specs │ ├── io_startup.c (2-2) │ ├── timer.c │ └── vectors.S ├── Blackfin_BF70x │ ├── portASM.asm │ ├── portASM.h (2-3) │ ├── port.c │ └── portmacro.h └── SHARC_215xx ├── portASM.asm ├── portASM.h (2-4) ├── port.c └── portmacro.h
Table 1 Source Code Directory Structures
Like the µC/OS-III, the directory structure of FreeRTOS includes some files that implement the kernel core, other files implement specific kernel objects and services.The table annotations below describe the different groups
Section | Name | note |
---|---|---|
Section (1-1) | FreeRTOS Source Code processor-independent | Common and official source code providing the FreeRTOS general functionalities and features implementation about the Tasks Co-routines Queues/Mutexes/Semaphores Task Notifications Event Groups(or “Flags”) Stream & Message Buffers and Software Timers . All files in this directory should be included in the build. And features that are not required will be compiled out based on the value of #define constants in the configuration file FreeRTOSConfig.h |
Section (1-2) | FreeRTOS Header File processor-independent | Header Files of the FreeRTOS common & official functionalities and features |
Section (2-1) | FreeRTOS Portable Code proccessor-dependent, ARM | Portable folder allows the vendors to add the implementation codes to the functions of interrupt vector tables interrupt handlers critical section handling and context switch , etc. based on the processor information |
Section (2-2) | FreeRTOS Portable Code proccessor-dependent, Cortex A5 | provide the portable code for ADSP-SC5xx Cortex-A5 Core |
Section (2-3) | FreeRTOS Portable Code proccessor-dependent, Blackfin | provide the portable codes for ADSP-BF7xx BLACKFIN Core |
Section (2-4) | FreeRTOS Portable Code proccessor-dependent, SHARC | provide the portable code for ADSP-215XX SHCAC Core |
Both µC/OS-III and FreeRTOS require two interrupt handlers that need to be installed in the Interrupt Vector Table(IVT).
PendSV Handler
: Suspend system interrupt VectorSysTick Handler
: System tick timer interrupt Vector.
The Interrupt Vector Table
is typically located at some known memory address (e.g. 0x00000000) and its default interrupt handlers are registered directly in some startup code in assembly language by the compiler.
This startup code is compiler-dependent and varies widely depending on the architecture and semiconductor manufacturer.
ADI provides the respective Interrupt Handler Vector Table
for Processor BLACKFIN
, CORTEX-A5
and SHARC
on µC/OS-III and FreeRTOS listed in the following Table 2.
IRQ Handler Name | Processor Name | µC/OS-III | FreeRTOS |
---|---|---|---|
PendSV | CORTEX-A5 | OS_CPU_PendSVHandler() | FreeRTOS_IRQ_Handler() [ in portASM.s ] |
BACKFIN | _xPortIVG14Handler() [ in portASM.asm ] | ||
SHARC | xPortSFT31Handler() [ in portASM.asm ] | ||
SysTick | ALL Processors | OS_CPU_SysTickHandler() | xPortSysTickHandler() [ located in port.c ] |
Table 2 Cortex-A5/Blackfin/SHARC IRQ Handlers
Both in the µC/OS-III and FreeRTOS, kernel needs to disable interrupts during the critical section, and below will show the functions used in µC/OS-III and FreeRTOS.
µC/OS-III
All of the critical sections function macros that are currently protected by µC/OS-III :
CPU_SR_ALLOC() CPU_CRITICAL_ENTER() CPU_CRITICAL_EXIT()
FreeRTOS
These macros can be replaced with the equivalent in FreeRTOS macros as below:
taskENTER_CRITICAL() taskEXIT_CRITICAL() taskENTER_CRITICAL_FROM_ISR() taskEXIT_CRITICAL_FROM_ISR()
FreeRTOS provides two sets of kernel control APIs for critical sections:
name | type | note | |
---|---|---|---|
taskENTER_CRITICAL() | Calling None-IRQ | In a Critical Sections are entered by calling taskENTER_CRITICAL() , and subsequently exited by calling taskEXIT_CRITICAL() | |
taskEXIT_CRITICAL() | |||
taskENTER_CRITICAL_FROM_ISR() | Calling with IRQ | In an ISR Critical Sections are entered by calling taskENTER_CRITICAL_FROM_ISR() , and subsequently exited by calling taskEXIT_CRITICAL_FROM_ISR() | |
taskEXIT_CRITICAL_FROM_ISR() | |||
Note That the configMAX_SYSCALL_INTERRUPT_PRIORITY
in the FreeRTOS configuration file when you use the above APIs, more detail can be found at RTOS Kernel Control.
Example Usage
µC/OS-III
void MyFunction (void) { // Storage for SR register CPU_SR_ALLOC(); // Create a critical section CPU_CRITICAL_ENTER(); : : : // Code protected by critical sections ... : : : // ... from interrupts or concurrent access. : : // Exit the critical section CPU_CRITICAL_EXIT(); }
FreeRTOS
void MyFunction_1 (void) /** Called without ISR **/ { /** Create a critical section **/ taskENTER_CRITICAL(); : /** Code protected by critical sections ...**/ /** Exit the critical section **/ taskEXIT_CRITICAL(); } void MyFunction_2_FromISR (void) /** Called from ISR **/ { UBaseType_t uxSavedIrqStatus; /** Create a critical section **/ uxSavedIrqStatus = taskENTER_CRITICAL_FROM_ISR(); : /**... from interrupts or concurrent access.**/ /** Exit the critical section **/ taskEXIT_CRITICAL_FROM_ISR( uxSavedIrqStatus ); }
Table 3 Critical Sections
For more information on Critical Sections, see the full documentation of RTOS Kernel Control in FreeRTOS API Reference.
Interrupt Service Routines (ISRs) that need to notify a task are called Kernel Aware Interrupts (or KAI) and trigger the task context switching. When writing an interrupt handler function in your project, keep in mind that during an interrupt, if a semaphore
, event flag
, message queue
, or other functions that could trigger a task context switch
was previously used in µC/OS-III, now you can call the corresponding API called xxx_FromIS
in FreeRTOS (and please note that the corresponding API without “FromISR” is not allowed on ISR.).
If the following APIs are called in the interrupt handler function in µC/OS-III, please replace it with thexxx_FromISR
API in FreeRTOS.
µC/OS-III
OSSemPost() OSFlagPost() OSQPost() OSTaskSemPost() OSTaskResume()
FreeRTOS
xSemaphoreGiveFromISR() xEventGroupSetBitsFromISR() xQueueSendFromISR() vTaskNotifyGiveFromISR() xTaskResumeFromISR()
Example Usage
Here is an example in using the Queue Send from an interrupt in µC/OS-III(left)
and FreeRTOS(right)
.
µC/OS-III
void My_IRQ_Handler (void) { // Save the CPU registers CPU_SR_ALLOC(); // Protect a critical section CPU_CRITICAL_ENTER(); // Make the kernel aware that // the interrupt has started OSIntEnter(); CPU_CRITICAL_EXIT(); // Handle the interrupt . . . OS___Post(); // Make the kernel aware that // the interrupt has ended OSIntExit(); }
FreeRTOS
void My_IRQ_Handler (void) { char cIn; BaseType_t xHigherPrioTaskWoken; xHigherPrioTaskWoken = pdFALSE; /* Handle the interrupt */ xQueueSendFromISR( xRxQueue, &cIn, &xHigherPrioTaskWoken); if (xHigherPrioTaskWoken) { taskYIELD_FROM_ISR(); } }
Table 4 Kernel Aware ISRs
Deferred Interrupt Handling
Generally, both for µC/OS-III and FreeRTOS, it is considered best practice to keep ISRs as short as possible. If there is a long-term response/pending in the IRS, The same as we called The tick task (OS_TickTask(), os_tick.c) and The ISR handler task (OS_IntQTask(), os_int.c) in the µC/OS-III, FreeRTOS also provides the ISR Handler mechanism called Deferred Interrupt Handling. Typically, it's to deliver the processing necessitated by the interrupt to be performed at a high priority unblocked task( High priority deferred interrupter handler task ), rather than within the ISR.
Diagram
Figure 1 Deferred Interrupt Processing
The above diagram showing how the deferred interrupt process, which to trigger a high-priority task and complete interrupt processing in this high-priority task.
Time | Name | Note |
---|---|---|
t1 | task 1 running | A low priority task Task 1 is running |
t2 | Interrupt occurring | The low priority task Task 1 is pre-empted by an interrupt, an the ISR executes, handles the interrupting peripheral, clears the interrupt, then unblocks Task 2 |
t3 | task 2 running | The ISR returns directly to a deferred processing task task 2 that was unblocked from within the ISR. The majority of interrupt processing is performed within this unblocked task |
t4 | task 1 continue | The deferred processing task task 2 that was unblocked by the ISR returns to the Blocked state to wait for the next interrupt, allowing the lower priority application task task 1 to continue its execution |
Here provides two categories of methods for users in using the Deferred Interrupt Handling:
For example, the function pvPortMalloc() is forbidden to be called at any Standard ISR Processing in FreeRTOS, but we can call it at the Deferred Interrupt Handling. For more information on Critical Sections, see the full documentation of Deferred Interrupt Handling.
For both of the µC/OS-III and FreeRTOS, we need to use the corresponding function to start the Operating System (OS). The difference is that before calling any µC/OS-III function we need to initialize µC/OS-III by calling OSInit() and start multi-tasking by calling OSStart(), but at FreeRTOS, just call vTaskStartScheduler() to start the real-time scheduler after creating tasks and kernel objects.
µC/OS-III
APIs for initializing and starting the OS at µC/OS-III
OSInit() OSStart()
FreeRTOS
API to start the OS at FreeRTOS:
vTaskStartScheduler()
Typically, before the scheduler has been started, main() (or a function called by main()) will be executing. After the scheduler has been started, only tasks and interrupts will ever execute. Starting the scheduler causes the highest priority task that was created while the scheduler was in the Initialization state to enter the Running state.
Example Usage
µC/OS-III
void main (void) { OS_ERR err; // Initialize µC/OS-III OSInit(&err); // Create tasks and other // kernel objects CreateTasksFun(); . . . // Start Multitasking OSStart(&err); // Will not get here unless there is an error (check err) }
FreeRTOS
void main (void) { /* Create tasks and other */ /* kernel objects */ CreateTasksFun(); . . . /* Start the scheduler */ vTaskStartScheduler(); /* This code will only be reached if the idle task could not be created inside vTaskStartScheduler(). An infinite loop is used to assist debugging by ensuring this scenario does not result in main() exiting. */ for( ;; ); }
Table 5 Starting the Kernels
For more information, please see the full documentation of RTOS Kernel Control to Start Scheduler in FreeRTOS API Reference.
In µC/OS-III, low priority numbers denote high priority tasks. On the other hand, a low-priority number corresponds to a low-priority level in FreeRTOS. Priority level zero (0) is thus the lowest priority level and priority configMAX_PRIORITIES - 1 is the highest priority level as shown in the following table.
Task Priority Leve
Both kernels have the Idle task at the lowest priority level. As same as the µC/OS-III changing the task's priority via the API OSTaskChangePrio()
, FreeRTOS also provides to queries or changes the priority of a task by calling the corresponding API Functions uxTaskPriorityGet()
or vTaskPrioritySet()
when the system is running.
Level | µC/OS-III | FreeRTOS |
---|---|---|
LOW | OS_CFG_PRIO_MAX - 1 | 0 |
HIGH | 0 | configMAX_PRIORITIES - 1 |
Table 6 Task Priority Levels
µC/OS-III
OSTaskChangePrio()
FreeRTOS
uxTaskPriorityGet() vTaskPrioritySet()
Please find the examples in using these APIs at the full documentations uxTaskPriorityGet() and vTaskPrioritySet() of Task Control.
Both of µC/OS-III and FreeRTOS support multiple tasks at the same priority level. For more information on task priorities in FreeRTOS see the full documentation on Task Priorities of the FreeRTOS Feature/Tasks.
In both µC/OS-III and FreeRTOS , tasks are written as an infinite loop function or, as a function that deletes the task once completed.
common
Both µC/OS-III and FreeRTOS tasks support passing an argument to the task when it’s created and this argument is declared as a void *. In other words, you do not need to change the function prototype of your task functions.
difference
In µC/OS-III
: Kernel Objects are created statically only. They can be allocated dynamically but the functionality is not built-in µC/OS-III. Instead, you would need to allocate them in the Micrium Heap by using the Memory Module in µC/LIB.
In FreeRTOS
: Kernel Objects such as tasks, queues, semaphores and mutexes can be created either statically or by dynamically allocating them in FreeRTOS’s heap.
Supported feature | µC/OS-III | FreeRTOS |
---|---|---|
Passing an argument to the task | ✔ | ✔ |
Static RTOS memory Allocation | ✔ | ✔ |
Dynamic RTOS memory Allocation | ✘ | ✔ |
This means that any of the kernel objects in your µC/OS-III project were created statically, when migrating them to FreeRTOS with the similar API functions, two methods of allocating them from the Heap statically
or dynamically
can be used in FreeRTOS.
And more detail about the FreeRTOS memory allocation can be found in Memory Management.
For example, to migrate your tasks, locate in your project all the places where a task gets created by µC/OS-III OSTaskCreate()
, The equivalent API functions in FreeRTOS are/is xTaskCreate()
and/or xTaskCreateStatic()
.
µC/OS-III
OSTaskCreate() OSTaskDel()
FreeRTOS
xTaskCreate() xTaskCreateStatic() vTaskDelete()
name | note |
---|---|
xTaskCreate() | Create a new task and add it to the list of tasks that are ready to run. configSUPPORT_DYNAMIC_ALLOCATION must be set to 1 in FreeRTOSConfig.h, or left undefined (in which case it will default to 1), for this RTOS API function to be available. |
xTaskCreateStatic() | Create a new task and add it to the list of tasks that are ready to run. configSUPPORT_STATIC_ALLOCATION must be set to 1 in FreeRTOSConfig.h for this RTOS API function to be available. If a task is created using xTaskCreateStatic() then the RAM is provided by the application writer, which results in a greater number of parameters, but allows the RAM to be statically allocated at compile time. |
vTaskDelete() | INCLUDE_vTaskDelete must be defined as 1 for this function to be available. calling this function will remove a task from the RTOS kernels management. The task being deleted will be removed from all ready , blocked , suspended and event lists. |
Example Usage
µC/OS-III
#define MY_TASK_PRIORITY 5 #define MY_TASK_STK_SIZE 200 OS_TCB MyTaskTCB; CPU_STK MyTaskStk[MY_TASK_STK_SIZE]; void MyTaskCode (void *p_arg) { while (DEF_ON) { // Wait for an event (i.e. Pend) // Task code goes here } } void MyInitFunction (void) { OS_ERR err; // Create a user application task OSTaskCreate ( &MyTaskTCB, "Task Name Here", MyTaskCode, (void *)0, MY_TASK_PRIORITY, &MyTaskStk[0], MY_TASK_STK_SIZE / 10, MY_TASK_STK_SIZE, 0, 0, (void *)0, OS_OPT_TASK_STK_CHK + OS_OPT_TASK_STK_CLR, &err); // Check “err” : : : : : }
FreeRTOS
#define MY_TASK_PRIORITY 5 #define MY_TASK_STK_SIZE 200 StaticTask_t MyTaskTCB; StackType_t MyTaskStk[MY_TASK_STK_SIZE]; void MyTaskCode (void *pvParameters) { for (;;) { /* Wait for an event */ /* Task code goes here */ } } void MyInitFunction(void) { BaseType_t xReturned; TaskHandle_t xHandle = NULL; /** Method 1 to Create the task static **/ xHandle = xTaskCreateStatic( MyTaskCode, "Task Name Here", MY_TASK_STACK_SIZE, ( void * ) 1, MY_TASK_PRIORITY, MyTaskStk, &MyTaskTCB); /** Method 2 to Create the task **/ xReturned = xTaskCreate( MyTaskCode, "Task Name Here", MY_TASK_STACK_SIZE, ( void * ) 1, MY_TASK_PRIORITY, &xHandle ); if( xReturned == pdPASS ) { vTaskDelete( xHandle ); } }
Table 7 Task Creation
For more information on the task creation, see the full documentation of Task Creation in FreeRTOS API Reference.
Just like in µC/OS-III, you can delay a task with FreeRTOS for a certain number of ticks. In both of µC/OS-III and FreeRTOS the delay can either be relative
(delay from current time), periodic
(delay occurs at fixed intervals) or absolute
(delay until we reach some time). The actual delay time depends on the tick rate. The API functions usage and introduction in the two OS are as follows.
µC/OS-III
OSTimeDly() OSTimeDlyHMSM() OSTimeDlyResume()
Typically, in µC/OS-III, the Task delay modes (Relative, periodic or absolute) can be selected by inputting the parameter opt of OSTimeDly()
or OSTimeDlyHMSM()
.
FreeRTOS
vTaskDelay() vTaskDelayUntil() xTaskAbortDelay()
name | note |
---|---|
vTaskDelay() | define INCLUDE_vTaskDelay as 1 to enable this function. It delays a task for a given number of ticks and the task's actual blocked time depends on the tick rate. Also vTaskDelay() specifies a time at which the task wishes to unblock relative to the time at which vTaskDelay() is called. |
vTaskDelayUntil() | define INCLUDE_vTaskDelayUntil as 1 to enable this function. It delays a task until a specified time and can be used by periodic tasks to ensure a constant execution frequency. unlike the vTaskDelay , vTaskDelayUntil() specifies an absolute time at which the task wishes to unblock. |
xTaskAbortDelay | define INCLUDE_xTaskAbortDelay as 1 to enable this function. Forces a task to leave the Blocked state, and enter the Ready state, even if the event the task was in the Blocked state to wait for has not occurred, and any specified timeout has not expired. |
Example Usage
The following example shows a task that toggles a LED every 500ms. The 500ms delay starts from the moment the API is called (relative
).
µC/OS-III
void MyTaskFunction (void *p_arg) { OS_ERR err; const OS_TICK delay = 500; // 500ms Delay. while (DEF_ON) { BSP_TOGGLE_LED(LED2); // Toggle LED2. OSTimeDly(delay, // Block task for 500ms. OS_OPT_TIME_DLY, &err); if (err != OS_ERR_NONE) { // Handle the error } } }
FreeRTOS
void MyTaskFunction(void * pvParameters) { /* Block for 500ms. */ const TickType_t xDelay = 500 / portTICK_PERIOD_MS; for (;;) { /* Simply toggle the LED every 500ms, * blocking between each toggle. */ BSP_TOGGLE_LED(LED2); /* Block task for 500ms. */ vTaskDelay( delay ); } }
Table 8 Task Delay - Relative
If you want to delay a task for an absolute time, then you can use the API vTaskDelayUntil() to replace vTaskDelay(), The other option is a periodic delay as shown in the following example(periodic
).
µC/OS-III
void MyTaskFunction (void *p_arg) { OS_ERR err; const OS_TICK period = 100; while (DEF_ON) { // Toggle LED2. BSP_TOGGLE_LED(LED2); // Wait for the next cycle. OSTimeDly(period, OS_OPT_TIME_PERIODIC, &err); if (err != OS_ERR_NONE) { // Handle the error } } }
FreeRTOS
void MyTaskFunction( void * pvParameters ) { TickType_t xLastWakeTime; /* Perform an action every 100 ticks. */ const TickType_t xFrequency = 100; /* Initialise "xLastWakeTime" with current time. */ xLastWakeTime = xTaskGetTickCount(); for( ;; ) { /* Toggle LED2.*/ BSP_TOGGLE_LED(LED2); /* Wait for the next cycle.*/ vTaskDelayUntil( &xLastWakeTime, xFrequency ); /* Perform action here.*/ } }
Table 9 Task Delay - Periodic
More about the Task Delay in FreeRTOS can be found at the Section of Task Control of API Reference.
Both of the µC/OS-III and FreeRTOS provide to Suspend and Resume the tasks by calling the relevant function interface. The suspended task is invisible for the scheduler, so it will never available until it is Resumed.
µC/OS-III
OSTaskSuspend() OSTaskResume()
FreeRTOS
In FreeRTOS, the corresponding APIs called with/without ISR for controlling tasks suspend/resume are provided as below:
vTaskSuspend() vTaskResume() xTaskResumeFromISR()
name | note |
---|---|
vTaskSuspend() | define INCLUDE_vTaskSuspend as 1 to enable this function. Suspend any task and when suspended a task will never get any microcontroller processing time, no matter what its priority. |
vTaskResume() | define INCLUDE_vTaskSuspend as 1 to enable this function. Resumes a suspended task that has been suspended by one or more calls to vTaskSuspend() . |
xTaskResumeFromISR() | define INCLUDE_vTaskSuspend and INCLUDE_xTaskResumeFromISR as 1 to enable this function. Function to resume a suspended task that can be called from within an ISR. |
Example Usage
µC/OS-III
OS_TCB Task_1_TCB; void main( void ) { // Create a user application task OSTaskCreate ( &Task_1_TCB, "Task_1", Task_1, ... &err); } void Task_1 (void *p_arg) { OS_ERR err; (void)&p_arg; while (DEF_ON) { // ... /* Suspend current task Task_1*/ OSTaskSuspend((OS_TCB *)0, &err); /* Check “err” */ // ... } } void Task_2 (void *p_arg) { OS_ERR err; (void)&p_arg; while (DEF_ON) { // ... /* Resume suspended task Task_1 */ OSTaskResume(&Task_1_TCB, &err); /* Check “err” */ // ... // ... } }
FreeRTOS
TaskHandle_t xHandleTask_1; void main( void ) { // Create a task, storing the handle. xTaskCreate( vTask_1, "Task_1", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandleTask_1 ); } void vTask_1( void * pvParameters ) { ( void ) pvParameters; for( ; ; ) { // ... // Suspend current task vTask_1 /* The created task will not run during * this period, unless another task calls * vTaskResume( xHandleTask_1 ). */ vTaskSuspend( NULL ); } } void vTask_2( void * pvParameters ) { ( void ) pvParameters; for( ; ; ) { // ... // Resume the suspended task vTask_1. vTaskResume( xHandleTask_1 ); /* The created task will once again get * microcontroller processing time in accordance * with its priority within the system. */ // ... } }
Table 10 Task Suspend
For more information about the FreeRTOS task suspend and resume, please see the full documentation of Task Control in FreeRTOS API Reference.
Both µC/OS-III and FreeRTOS allow a task to retain control of the CPU and suspend the remaining tasks (or lock the scheduler so that context switches will not occur until the scheduler is unlocked) even though other higher-priority tasks are ready-to-run. However but interrupts are still recognized and serviced (assuming interrupts are enabled).
µC/OS-III
OSSchedLock() OSSchedUnlock()
FreeRTOS
vTaskSuspendAll() xTaskResumeAll()
name | note |
---|---|
vTaskSuspendAll() | Suspends the scheduler without disabling interrupts. RTOS ticks that occur while the scheduler is suspended will be held pending until the scheduler has been unsuspended using a call to xTaskResumeAll() . |
xTaskResumeAll() | Resumes the scheduler after it was suspended using a call to vTaskSuspendAll() . |
API functions that have the potential to cause a context switch (for example, Task delay, Queue/message blocking send, etc.) must not be called while the scheduler is locked/suspended.
xTaskResumeAll() only resumes the scheduler. It does not unsuspend tasks that were previously suspended by a call to vTaskSuspend().
Example Usage
µC/OS-III
void MyTaskFunction(void *p_arg) { OS_ERR err; (void)&p_arg; while (DEF_ON) { /* Task code goes here. */ : /* Prevent other tasks to run */ OSSchedLock(&err); /* Check “err” */ /* Code protected from context switch */ : : : /* Enable other tasks to run */ OSSchedUnlock(&err); /* Check “err” */ : : } }
FreeRTOS
void vMyTaskFunction( void * pvParameters ) { for( ;; ) { // Task code goes here. // ... // Prevent the RTOS kernel swapping out the task. vTaskSuspendAll(); /* Code protected from context switch * During this time interrupts will still * operate and the RTOS kernel tick count * will be maintained. */ // ... // Operation is complete. Restart the RTOS kernel. xTaskResumeAll(); } }
Table 11 Scheduler Suspend
At some point the task wants to perform a long operation during which it does not want to get swapped out. It cannot use taskENTER_CRITICAL() or taskEXIT_CRITICAL() as the length of the operation may cause interrupts to be missed - including the ticks, so you can use the scheduler suspend/lock API vTaskSuspendAll() and xTaskResumeAll() in this moment.
For more information about the FreeRTOS vTaskSuspendAll()
and xTaskResumeAll()
, please see the full documentation of RTOS Kernel Control in FreeRTOS API Reference.
Both of the µC/OS-III and FreeRTOS, the Semaphores and Mutexes APIs are shared and visible to all tasks, they can be divided into 3 types of semaphores including Binary Semaphore
, Counting Semaphore
and Mutex
, FreeRTOS also provides the APIs of Recursive Mutex
.
type | name | µC/OS-III | FreeRTOS | |
---|---|---|---|---|
Semaphores | Binary Semaphore | Binary and Counting semaphores are implemented through a single set of API functions that start with the prefix OSSem_XXX() , and via the argument OS_SEM_CTR cnt to distinguish this is called a binary or counting semaphore | FreeRTOS uses the APIs with xSemaphoreCreateBinary_XXX() to create the Binary Semaphores. | |
Counting Semaphore | FreeRTOS uses the APIs with the xSemaphoreCreateCounting_XXX() to create the Counting Semaphores. | |||
Mutexes | Mutex | mutexes are implemented through a separate set of API functions that start with the prefix OSMutex_xxx() | FreeRTOS uses the APIs with xSemaphoreCreateMutex_XXX() to create the Mutexes. | |
Recursive Mutex | ✘ | FreeRTOS use the APIs with xSemaphoreCreateRecursiveMutex_XXX() to create the Recursive Mutexes | ||
µC/OS-III
Kernel Semaphore/Mutex APIs in µC/OS-III
/*Kernel Semaphore API*/ OSSemCreate() OSSemDel() OSSemPend() OSSemPendAbort() OSSemPost() OSSemSet() /*Kernel Mutex API*/ OSMutexCreate() OSMutexDel() OSMutexPend() OSMutexPendAbort() OSMutexPost()
FreeRTOS
Kernel Semaphore/Mutex APIs in FreeRTOS
/*Binary Semaphore Create.*/ xSemaphoreCreateBinary(); xSemaphoreCreateBinaryStatic(); /*Counting Semaphore Create.*/ xSemaphoreCreateCounting() xSemaphoreCreateCountingStatic() /*Mutex Create*/ xSemaphoreCreateMutex() xSemaphoreCreateMutexStatic() /*Recursive Mutex Create.*/ xSemaphoreCreateRecursiveMutex() xSemaphoreCreateRecursiveMutexStatic() /*All Semaphores/Mutexes share the same delete function.*/ vSemaphoreDelete() /*Semaphores/Mutexes Take/Give.*/ xSemaphoreTake() xSemaphoreGive() /*Semaphores/Mutexes Take/Give from ISR.*/ xSemaphoreTakeFromISR() xSemaphoreGiveFromISR() /*Mutexes Take/Give Recursive.*/ xSemaphoreTakeRecursive() xSemaphoreGiveRecursive() /*Others.*/ xSemaphoreGetMutexHolder() uxSemaphoreGetCount()
In FreeRTOS, Binary Semaphore
, Counting Semaphore
, Mutex
and Recursive Mutex
all share the same API functions except for the ones to create the actual objects. More about the Semaphore/Mutexes in FreeRTOS can be found at the Section of Semaphore/Mutexes of API Reference.
Example Usage
The following example shows how to protect a shared resource with a mutex.
µC/OS-III
OS_MUTEX MyMutex; void MyInitFunction( void ) { OS_ERR err; OSMutexCreate(&MyMutex, "Mutex Name Here", &err); } void MyTaskCode( void *p_arg ) { OS_ERR err; CPU_TS ts; while (DEF_ON) { // Acquire the mutex OSMutexPend(&MyMutex, 0, OS_OPT_PEND_BLOCKING, &ts, &err); if (err == OS_ERR_NONE) { // We now have the mutex and can // access the shared resource. . . . // We have finished accessing // the shared resource. // Now we can free the mutex. OSMutexPost(&MyMutex, OS_OPT_POST_NONE, &err); } } }
FreeRTOS
SemaphoreHandle_t MyMutex = NULL; void MyInitFunction( void ) { MyMutex = xSemaphoreCreateMutex(); if(MyMutex == NULL) { /* Create the Semaphore Error.*/ } } void MyTaskCode( void *pvParameters ) { for ( ;; ) { /* Acquire the mutex */ if (xSemaphoreTake( MyMutex, (TickType_t)0) ) { /* We now have the mutex and can */ /* access the shared resource.*/ . . . /* We have finished accessing the*/ /* shared resource.*/ /* Now we can free the mutex.*/ if( xSemaphoreGive(MyMutex) != pdPASS ) { /* Give semaphore Error. */ } else { /* Give semaphore Correct.*/ } } } }
Table 12 Protecting a Shared Resource with a Mutex
More examples in using the FreeRTOS Kernel Semaphores and Mutexes can be found in the FreeRTOS Add-In Example Projects .
µC/OS-III
In µC/OS-III, for the Task Semaphore APIs, each task has its own built-in semaphore, that in those cases where your code knows which task to signal, makes for a simpler and more efficient code than using a separate semaphore object. The API functions for Task Semaphores start with the prefix OSTaskSemXXX().
/*OS Task Semaphore API.*/ OSTaskSemPend() OSTaskSemPendAbort() OSTaskSemPost() OSTaskSemSet()
FreeRTOS
Corresponding to the µC/OS-III Task Semaphore APIs is the Task Notifications Feature. Each FreeRTOS task has a 32-bit notification value which is initialized to zero when the RTOS task is created. An RTOS task notification is an event sent directly to a task that can unblock the receiving task, and optionally update the receiving task’s notification value.
xTaskNotifyGive() vTaskNotifyGiveFromISR() ulTaskNotifyTake() xTaskNotify() xTaskNotifyStateClear()
More about the Task Notifications in FreeRTOS can be found at the Section of Direct To Task Notifications of API Reference.
Both kernels support inter-task communication, which allows a task or ISR to communicate information to another task.
The difference between the µC/OS-III and FreeRTOS message queue functionality is that in µC/OS-III the data sent must remain in scope, because it is sent by reference instead of by value, but in FreeRTOS, the data sent no need to be remain in scope. In other words, unlike the µC/OS-III, FreeRTOS enables the data sent to be copied via the buffer or a pointer.
type | µC/OS-III | FreeRTOS |
---|---|---|
Send/Recv Data from a Task | ✔ | ✔ |
Send/Recv Data from an ISR | ✔ | ✔ |
No-need-remain (in scope) Data sending | ✘ | ✔ |
µC/OS-III
OSQCreate() OSQDel() OSQFlush() OSQPend() OSQPendAbort() OSQPost()
FreeRTOS
Mainly queue APIs in FreeRTOS.
xQueueCreate() xQueueCreateStatic() vQueueDelete() xQueueSend() xQueueSendToBack() xQueueSendToFront() xQueueReceive() uxQueueMessagesWaiting() uxQueueSpacesAvailable() xQueueReset() xQueueOverwrite() xQueuePeek() vQueueAddToRegistry() vQueueUnregisterQueue() pcQueueGetName() /*APIs with ISR*/ xQueueSendFromISR() xQueueSendToBackFromISR() xQueueSendToFrontFromISR() xQueueReceiveFromISR() uxQueueMessagesWaitingFromISR() xQueueOverwriteFromISR() xQueuePeekFromISR() xQueueIsQueueFullFromISR() xQueueIsQueueEmptyFromISR()
name | note |
---|---|
xQueueCreate() | Creates a new queue and returns a handle by which the queue can be referenced. |
vQueueDelete() | Delete a queue – freeing all the memory allocated for storing of items placed on the queue. |
xQueueSend() | Post an item on a queue. |
xQueueSendToBack() | Post an item to the back of a queue |
xQueueSendToFront() | Post an item to the front of a queue. |
xQueueReceive() | Receive an item from a queue. |
uxQueueMessagesWaiting() | Return the number of messages stored in a queue. |
uxQueueSpacesAvailable() | Return the number of free spaces in a queue. |
name | note |
---|---|
xQueueReset() | Resets a queue to its original empty state. |
xQueueOverwrite() | Will write to the queue even if the queue is full, overwriting data that is already held in the queue. |
xQueuePeek() | Receive an item from a queue without removing the item from the queue. |
vQueueAddToRegistry() | Assigns a name to a queue and adds the queue to the registry. |
vQueueUnregisterQueue() | Removes a queue from the queue registry. |
pcQueueGetName () | Look up a queue name from the queue’s handle. |
For a more detailed description of each of the arguments/usage for the above FreeRTOS Queue APIs, please see the full documentation on the Queues and Queue Management section of FreeRTOS API Reference.
Example Usage
µC/OS-III
#define BUFFER_SIZE 128 OS_Q My_UART_Q; OS_MEM My_UART_MemPartition; char My_UART_Buffer[BUFFER_SIZE]; void My_UART_RxTaskCode (void *p_arg) { OS_ERR err; void *p_msg; OS_MSG_SIZE msg_size; CPU_TS ts; // Create a memory pool of 128 bytes OSMemCreate(&My_UART_MemPartition, "UART Memory Pool", (void *)&My_UART_Buffer[0], BUFFER_SIZE, 1, &err); if (err != OS_ERR_NONE) { // Handle the error } // Create a Q of 128 pointers OSQCreate(&My_UART_Q, "Queue name here", BUFFER_SIZE, &err); if (err != OS_ERR_NONE) { // Handle the error } else { // Enable UART interrupts } while (1) { // Receive a message from the queue. // Block for 10-ticks if queue is empty. p_msg = (char *)OSQPend(&My_UART_Q, 10, OS_OPT_PEND_BLOCKING, &msg_size, &ts, &err); if (err == OS_ERR_NONE) { // Process the received byte p_msg // Put p_msg back to the memory pool OSMemPut(&My_UART_MemPartition, p_msg, &err); } else { // Handle the error } } }
FreeRTOS
#define BUFFER_SIZE 128 QueueHandle_t My_UART_Q; void My_UART_RxTaskCode (void *pvParameters) { char *pxRxedMessage; /* Create a Q capable of containing 128 bytes */ My_UART_Q = xQueueCreate( BUFFER_SIZE, 1 ); if (My_UART_Q == pdFAIL) { /* Failed to create the queue. */ } else { /* Enable UART interrupts */ . . . } for ( ;; ) { /* Receive a message from the queue.*/ /* Block for 10-ticks if queue is empty.*/ if( xQueueReceive( My_UART_Q, &(pxRxedMessage), (TickType_t)10) ) { /* Process the received byte. */ . . . . } else { /* Handle the error */ } } }
Table 13-1 Inter-task Communication - Tasks
µC/OS-III
char *My_UART_RxDataPtr; void My_UART_IRQ_Handler(void) { OS_ERR err; char rx_data; // Storage for the SR register CPU_SR_ALLOC(); // Protect a critical section CPU_CRITICAL_ENTER(); // Make the kernel aware that // the interrupt has started OSIntEnter(); CPU_CRITICAL_EXIT(); // Loop until the buffer is empty do { // Obtain a byte from the UART rx_data = UART_RX_REGISTER; My_UART_RxDataPtr = (char *)OSMemGet(&My_UART_MemPartition, &err); *My_UART_RxDataPtr++ = rx_data; // Post byte to task for processing OSQPost((OS_Q *)&My_UART_Q, (void *)My_UART_RxDataPtr, (OS_MSG_SIZE)1, (OS_OPT )OS_OPT_POST_FIFO, (OS_ERR *)&err); // Don't point to sent buffer My_UART_RxDataPtr = NULL; } while (UART_RX_BUFFER_COUNT); // Make the kernel aware that // the interrupt has ended OSIntExit(); }
FreeRTOS
QueueHandle_t xQueue; void My_UART_IRQ_Handler(void) { char rx_data; BaseType_t xHigherPriorityTaskWoken; xHigherPriorityTaskWoken = pdFALSE; // Loop until the buffer is empty. do { // Obtain a byte from the UART. rx_data = UART_RX_REGISTER; // Post byte to task for processing. xQueueSendToBackFromISR(xQueue, &rx_data, &xHigherPriorityTaskWoken); //A character was received and output it now. vOutputCharacter( rx_data ); : : : /* If removing the character from the queue woke the task that was posting onto the queue xHigher- PriorityTaskWoken will have been set to pdTRUE. No matter how many times this loop iterates only one task will be woken.*/ } while (UART_RX_BUFFER_COUNT); /* Now we can switch context if necessary */ if ( xHigherPriorityTaskWoken != pdFALSE ) { /* We should switch context so the ISR returns to a different task. NOTE: How this is done depends on the port you are using. Check the documentation and examples for your port. */ taskYIELD_FROM_ISR(); } }
Table 13-2 Inter-task Communication - ISRs
Queue Sets
FreeRTOS also provides a feature Queue sets that enables an RTOS task to block (pend) when receiving from multiple queues and/or semaphores at the same time. Queues and semaphores are grouped into sets, then, instead of blocking on an individual queue or semaphore, a task instead blocks on the set.
xQueueCreateSet() xQueueAddToSet() xQueueRemoveFromSet() xQueueSelectFromSet() xQueueSelectFromSetFromISR()
Define configUSE_QUEUE_SETS to 1
to enable the above API functions of queue sets.
Example usage can be found at the section of Queue Sets and see the Blocking on Multiple Objects page for more information.
Both kernels provide a single to single communication mechanisms that allows a task to send/receive messages directly to/from an ISR or another task, without going through an intermediate message queue. In µC/OS-III, you can use the Task Message Queue APIs OSTaskQPost()
/OSTaskQPend()
, and in FreeRTOS, Stream Buffers and Message Buffers can be used.
Task Message Queue
Stream Buffer
Message Buffer
µC/OS-III
Task Message Queue APIs
OSTaskQPost() OSTaskQPend() OSTaskQPendAbort() OSTaskQFlush()
FreeRTOS
Stream/Message buffers are an RTOS task to RTOS task, and interrupt to task communication primitives. Unlike most other FreeRTOS communications primitives, they are optimised for single reader single writer scenarios, such as passing data from an interrupt service routine to a task, or from one microcontroller core to another on dual core CPUs. Data is passed by copy – the data is copied into the buffer by the sender and out of the buffer by the read.
name | note |
---|---|
Stream Buffer | Stream buffers pass a continuous stream of bytes. |
Message Buffer | Message buffers pass variable sized but discrete messages. |
Stream Buffer
xStreamBufferCreate() xStreamBufferCreateStatic() xStreamBufferSend() xStreamBufferSendFromISR() xStreamBufferReceive() xStreamBufferReceiveFromISR() vStreamBufferDelete() xStreamBufferBytesAvailable() xStreamBufferSpacesAvailable() xStreamBufferSetTriggerLevel() xStreamBufferReset() xStreamBufferIsEmpty() xStreamBufferIsFull()
Message Buffers
xMessageBufferCreate() xMessageBufferCreateStatic() xMessageBufferSend() xMessageBufferSendFromISR() xMessageBufferReceive() xMessageBufferReceiveFromISR() vMessageBufferDelete() xMessageBufferSpacesAvailable() xMessageBufferReset() xMessageBufferIsEmpty() xMessageBufferIsFull()
For a more detailed description of each of the arguments/usage for the above FreeRTOS Stream& Message Buffer APIs, please see the full documentation on the Stream & Message Buffers and the API Reference sections of Stream buffers and Message Buffers.
Event flags are used when a task needs to synchronize with the occurrence of multiple events. Both µC/OS-III and FreeRTOS provide the Event Flags ( or 'Group') Feature for user to conveniently using it.
µC/OS-III
OSFlagCreate() OSFlagDel() OSFlagPend() OSFlagPendAbort() OSFlagPendGetFlagsRdy() OSFlagPost()
FreeRTOS
xEventGroupCreate() xEventGroupCreateStatic() vEventGroupDelete() xEventGroupWaitBits() xEventGroupSetBits() xEventGroupGetBits() xEventGroupClearBits() xEventGroupSetBitsFromISR() xEventGroupGetBitsFromISR() xEventGroupClearBitsFromISR() xEventGroupSync()
For this RTOS API function to be available:
1
in FreeRTOSConfig.h, or left undefined (in which case it will default to 1
).name | note |
---|---|
xEventGroupCreate() | Creates a new RTOS event group, and returns a handle by which the newly created event group can be referenced. configSUPPORT_STATIC_ALLOCATION must be set to 1 in FreeRTOSConfig.h to use the API xEventGroupCreateStatic() . |
xEventGroupCreateStatic() |
|
vEventGroupDelete | Delete an event group that was previously created using a call to xEventGroupCreate() . |
xEventGroupWaitBits() | Read bits within an RTOS event group, optionally entering the Blocked state (with a timeout) to wait for a bit or group of bits to become set. |
xEventGroupSetBits() | Set bits (flags) within an RTOS event group. |
xEventGroupClearBits() | Clear bits (flags) within an RTOS event group. |
xEventGroupSync() | This functionality is typically used to synchronize multiple tasks (often called a task rendezvous), where each task has to wait for the other tasks to reach a synchronization point before proceeding. |
For a more detailed description of each of the arguments/usage for the above FreeRTOS Event Flags APIs, please see the full documentation on the Event Groups (or 'flags') Section of FreeRTOS API Reference.
Example Usage
The following example demonstrates how to use the Event Flags in the both µC/OS-III and FreeRTOS.
µC/OS-III
#define TEMP_LOW (OS_FLAGS)0x0001 #define BATT_LOW (OS_FLAGS)0x0002 OS_FLAG_GRP MyEventFlagGrp; void main (void) { OS_ERR err; OSInit(&err); : OSFlagCreate(&MyEventFlagGrp, ”My Event Flag Group”, (OS_FLAGS)0, &err); /* Check ’err” */ : OSStart(&err); } void MyTask (void *p_arg) { OS_ERR err; CPU_TS ts; const OS_TICK delay = 100; while (DEF_ON) { OSFlagPend(&MyEventFlagGrp, TEMP_LOW + BATT_LOW, (OS_TICK )delay, (OS_OPT)OS_OPT_PEND_FLAG_SET_ANY, &ts, &err); /* Check ’err” */ : : /* Handle the event */ : : : : : : : : : } } void MyISR (void) { OS_ERR err; : OSFlagPost(&MyEventFlagGrp, BATT_LOW, (OS_OPT)OS_OPT_POST_FLAG_SET, &err); /* Check ’err” */ : }
FreeRTOS
#define BIT_0 ( 1 << 0 ) #define BIT_4 ( 1 << 4 ) EventGroupHandle_t xEventGroup = NULL; void main (void) { /* Create an event group. */ xEventGroup = xEventGroupCreate(); if( xEventGroup == NULL) { /* Event group create Error. */ } /* Create task and start the scheduler */ : : vTaskStartScheduler(); } void MyTask( void *pvParameters ) { EventBits_t uxBits; const TickType_t xTicksToWait = 100 / portTICK_PERIOD_MS; /* Were the event flags have been set? */ uxBits = xEventGroupWaitBits( xEventGroup, BIT_0 | BIT_4, pdFALSE, pdFALSE, xTicksToWait ); if( (uxBits & (BIT_0 | BIT_4)) == (BIT_0 | BIT_4) ) { /*returned because both bits were set. */ } else if( ( uxBits & BIT_0 ) != 0 ) { /*returned because just BIT_0 was set. */ } else if( ( uxBits & BIT_4 ) != 0 ) { /*returned because just BIT_4 was set. */ } else { /*returned because xTicksToWait ticks passed * without either BIT_0 or BIT_4 becoming set. */ } } void MyISR (void) { : if( (BIT_4 & xEventGroupSetBitsFromISR(xEventGroup, BIT_4)) != BIT_4 ) { /* Set event Error.*/ : } /* Set event Correctly.*/ : }
Table 14 Event Flags/Group
Both kernels allows users to create a software timer that enable a function to be executed at a set time in the future, The timer can be configured to run continuously or only once (one-short).
µC/OS-III
OSTmrCreate() OSTmrDel() OSTmrRemainGet() OSTmrSet() OSTmrStart() OSTmrStateGet() OSTmrStop()
FreeRTOS
Mainly Software Timer APIs in FreeRTOS.
xTimerCreate() xTimerDelete() xTimerStart() xTimerStop() xTimerReset() pvTimerGetTimerID() pcTimerGetName() xTimerGetPeriod() xTimerGetExpiryTime()
name | note |
---|---|
xTimerCreate() | Creates a new software timer instance and returns a handle by which the timer can be referenced. |
xTimerDelete() | Deletes a timer that was previously created using the xTimerCreate() API function. |
xTimerStart() | Starts a timer that was previously created using the xTimerCreate() API function. |
xTimerStop() | Stopping a timer ensures the timer is not in the active state. |
xTimerReset() | Re-starts a timer that was previously created using the xTimerCreate() API function. |
For a more detailed description of each of the arguments/usage for the above FreeRTOS Software Timers APIs, please see the full documentation on the Software Timers Section and FreeRTOS Software Timer API Functions.
Example Usage
µC/OS-III
OS_TMR CloseDoorTmr; void Task (void *p_arg) { OS_ERR err; CPU_BOOLEAN status; (void)&p_arg; while (DEF_ON) { OSTmrCreate(&CloseDoorTmr, // p_tmr “Door close” // p_name 10, // dly 100, // period OS_OPT_TMR_PERIODIC, // opt DoorCloseFnct, // p_callback 0, // p_callback_arg &err); // p_err /* Check “err” */ : : status = OSTmrStart(&CloseDoorTmr, &err); /* Check “err” */ : : } } void DoorCloseFnct (OS_TMR *p_tmr, void *p_arg) { /* Close the door! */ }
FreeRTOS
TimerHandle_t xTimers; void Task (void *pvParameters) { ( void ) pvParameters; while (DEF_ON) { xTimers = xTimerCreate( "Door close", // pcTimerName 100, // period pdTRUE, // uxAutoReload ( void * ) 0, // pvTimerID DoorCloseFnct );// Callback Func if( xTimers == NULL ) { /* The timer was not created. */ } else { // delay 10 (in ticks) if( xTimerStart( xTimers, 10 ) != pdPASS ) { /* The timer could not be set into the Active state. */ } } } } void DoorCloseFnct( TimerHandle_t xTimer ) { /* Close the door! */ }
Table 15 Software Timers
Locate in your project all the rest of µC/OS-III API function calls, and replace them with their equivalent FreeRTOS API function.
Features | µC/OS-III | FreeRTOS | Description |
---|---|---|---|
Task Management | OSTaskCreate() | xTaskCreate() | xTaskCreate() |
xTaskCreateStatic() | xTaskCreateStatic() | ||
OSTaskDel() | OSTaskDel() | vTaskDelete | |
OSTaskChangePrio() | vTaskPrioritySet() | vTaskPrioritySet() | |
N.A. | uxTaskPriorityGet() | uxTaskPriorityGet() | |
OSTaskSuspend() | vTaskSuspend() | vTaskSuspend() | |
OSTaskResume() | vTaskResume() | vTaskResume() | |
xTaskResumeFromISR() | xTaskResumeFromISR() | ||
OSTaskRegGet() | N.A. | ||
OSTaskRegSet() | N.A. | ||
OSTaskStkChk() | N.A. | ||
OSTaskTimeQuantaSet() | N.A. | ||
Time Management | OSTimeDly() | vTaskDelay() | vTaskDelay() |
vTaskDelayUntil() | vTaskDelayUntil() | ||
N.A. | xTaskAbortDelay() | xTaskAbortDelay() | |
OSTimeDlyHMSM() | N.A. | ||
OSTimeDlyResume() | N.A. | ||
OSTimeDynTick() | N.A. | ||
OSTimeGet() | xTaskGetTickCount() | xTaskGetTickCount() | |
xTaskGetTickCountFromISR() | xTaskGetTickCountFromISR() | ||
OSTimeSet() | N.A. | ||
OSTimeTick() | N.A. | ||
Mutual Exclusion Semaphores | OSMutexCreate() | xSemaphoreCreateMutex() | xSemaphoreCreateMutex() |
xSemaphoreCreateMutexStatic() | xSemaphoreCreateMutexStatic() | ||
xSemaphoreCreateRecursiveMutex() | xSemaphoreCreateRecursiveMutex() | ||
xSemaphoreCreateRecursiveMutexStatic() | xSemaphoreCreateRecursiveMutexStatic() | ||
OSMutexDel() | vSemaphoreDelete() | vSemaphoreDelete() | |
OSMutexPend() | xSemaphoreTake() | xSemaphoreTake() | |
xSemaphoreTakeFromISR() | xSemaphoreTakeFromISR() | ||
xSemaphoreTakeRecursive() | xSemaphoreTakeRecursive() | ||
OSMutexPendAbort() | N.A. | ||
OSMutexPost() | xSemaphoreGive() | xSemaphoreGive() | |
xSemaphoreGiveFromISR() | xSemaphoreGiveFromISR() | ||
xSemaphoreGiveRecursive() | xSemaphoreGiveRecursive() | ||
N.A. | xSemaphoreGetMutexHolder() | xSemaphoreGetMutexHolder() | |
Semaphores | OSSemCreate() | xSemaphoreCreateBinary() | xSemaphoreCreateBinary() |
xSemaphoreCreateBinaryStatic() | xSemaphoreCreateBinaryStatic() | ||
xSemaphoreCreateCounting() | xSemaphoreCreateCounting() | ||
xSemaphoreCreateCountingStatic() | xSemaphoreCreateCountingStatic() | ||
OSSemDel() | vSemaphoreDelete() | vSemaphoreDelete() | |
OSSemPend() | xSemaphoreTake() | ||
xSemaphoreTakeFromISR() | xSemaphoreTakeFromISR() | ||
OSSemPendAbort() | N.A. | ||
OSSemPost() | xSemaphoreGive() | xSemaphoreGive() | |
xSemaphoreGiveFromISR() | xSemaphoreGiveFromISR() | ||
OSSemSet() | N.A. | ||
N.A. | uxSemaphoreGetCount() | uxSemaphoreGetCount() | |
Task Semaphores (Task Notifications) | OSTaskSemPend() | ulTaskNotifyTake() | ulTaskNotifyTake() |
OSTaskSemPendAbort() | N.A. | ||
OSTaskSemPost() | xTaskNotifyGive() | xTaskNotifyGive() | |
vTaskNotifyGiveFromISR() | vTaskNotifyGiveFromISR() | ||
OSTaskSemSet() | N.A. | ||
N.A. | xTaskNotify() | Notify a task form a Task or an ISR xTaskNotify() xTaskNotifyFromISR() | |
xTaskNotifyFromISR() | |||
N.A. | xTaskNotifyWait() | Waiting for the Notifies from a Task xTaskNotifyWait() | |
N.A. | xTaskNotifyAndQuery() | Quarry and Notify from a Task or an ISR xTaskNotifyAndQuery() xTaskNotifyAndQueryFromISR() | |
xTaskNotifyAndQueryFromISR() | |||
N.A. | xTaskNotifyStateClear() | Clear (Pending to Not Pending) a pending notification.xTaskNotifyStateClear() | |
Message Queues | OSQCreate() | xQueueCreate() | xQueueCreate() |
xQueueCreateStatic() | xQueueCreateStatic() | ||
OSQDel() | vQueueDelete() | vQueueDelete | |
OSQFlush() | xQueueReset() | xQueueReset() | |
OSQPend() | xQueueReceive() | xQueueReceive() | |
xQueueReceiveFromISR() | xQueueReceiveFromISR() | ||
OSQPendAbort() | N.A. | ||
OSQPost() | xQueueSend() | xQueueSend() | |
xQueueSendFromISR() | xQueueSendFromISR() | ||
xQueueSendToBack() | xQueueSendToBack() | ||
xQueueSendToBackFromISR() | xQueueSendToBackFromISR() | ||
xQueueSendToFront() | xQueueSendToFront() | ||
xQueueSendToFrontFromISR() | xQueueSendToFrontFromISR() | ||
N.A. | uxQueueMessagesWaiting() | uxQueueMessagesWaiting() | |
uxQueueMessagesWaitingFromISR() | uxQueueMessagesWaitingFromISR() | ||
N.A. | uxQueueSpacesAvailable() | uxQueueSpacesAvailable() | |
N.A. | xQueueOverwrite() | xQueueOverwrite() | |
xQueueOverwriteFromISR() | xQueueOverwriteFromISR() | ||
N.A. | xQueuePeek() | xQueuePeek() | |
N.A. | xQueuePeekFromISR() | xQueuePeekFromISR() | |
N.A. | pcQueueGetName() | pcQueueGetName() | |
N.A. | xQueueIsQueueFullFromISR() | xQueueIsQueueFullFromISR() | |
N.A. | xQueueIsQueueEmptyFromISR() | xQueueIsQueueEmptyFromISR() | |
N.A. | vQueueAddToRegistry() | vQueueAddToRegistry() | |
Task Message Queues (Stream&Message Buffer) | N.A. | xStreamBufferCreate() | xStreamBufferCreateStatic() |
xStreamBufferCreateStatic() | xStreamBufferCreateStatic() | ||
xMessageBufferCreate() | xMessageBufferCreate() | ||
xMessageBufferCreateStatic() | xMessageBufferCreateStatic() | ||
N.A. | vStreamBufferDelete() | vStreamBufferDelete() | |
vMessageBufferDelete() | vMessageBufferDelete() | ||
OSTaskQFlush() | xStreamBufferReset() | xStreamBufferReset() | |
xMessageBufferReset() | xMessageBufferReset() | ||
OSTaskQPend() | xStreamBufferReceive() | xStreamBufferReceive() | |
xStreamBufferReceiveFromISR() | xStreamBufferReceiveFromISR() | ||
xMessageBufferReceive() | xMessageBufferReceive() | ||
xMessageBufferReceiveFromISR() | xMessageBufferReceiveFromISR() | ||
OSTaskQPendAbort() | N.A. | ||
OSTaskQPost() | xStreamBufferSend() | xStreamBufferSend() | |
xStreamBufferSendFromISR() | xStreamBufferSendFromISR() | ||
xMessageBufferSend() | xMessageBufferSend() | ||
xMessageBufferSendFromISR() | xMessageBufferSendFromISR() | ||
Event Flags | OSFlagCreate() | xEventGroupCreate() | xEventGroupCreate() |
xEventGroupCreateStatic() | xEventGroupCreateStatic() | ||
OSFlagDel() | vEventGroupDelete() | vEventGroupDelete() | |
OSFlagPend() | xEventGroupWaitBits() | xEventGroupWaitBits() | |
OSFlagPendAbort() | N.A. | ||
OSFlagPendGetFlagsRdy() | xEventGroupGetBits() | xEventGroupGetBits() | |
xEventGroupGetBitsFromISR() | xEventGroupGetBitsFromISR() | ||
OSFlagPost() | xEventGroupSetBits() | xEventGroupSetBits() | |
xEventGroupSetBitsFromISR() | xEventGroupSetBitsFromISR() | ||
xEventGroupClearBits() | xEventGroupClearBits() | ||
xEventGroupClearBitsFromISR() | xEventGroupClearBitsFromISR() | ||
N.A. | xEventGroupSync() | xEventGroupSync() | |
Software Timers | OSTmrCreate() | xTimerCreate() | xTimerCreate() |
xTimerCreateStatic() | xTimerCreateStatic() | ||
OSTmrDel() | xTimerDelete() | xTimerDelete() | |
OSTmrStart() | xTimerStart() | xTimerStart() | |
xTimerStartFromISR() | xTimerStartFromISR() | ||
OSTmrStop() | xTimerStop() | xTimerStop() | |
xTimerStopFromISR() | xTimerStopFromISR() | ||
N.A. | xTimerReset() | xTimerReset() | |
xTimerResetFromISR() | xTimerResetFromISR() | ||
OSTmrRemainGet() | xTimerGetExpiryTime() | xTimerGetExpiryTime() | |
OSTmrSet() | vTimerSetReloadMode() | vTimerSetReloadMode() | |
vTimerSetTimerID() | vTimerSetTimerID() | ||
xTimerChangePeriod() | xTimerChangePeriod() | ||
xTimerChangePeriodFromISR() | xTimerChangePeriodFromISR() | ||
xTimerPendFunctionCall() | xTimerPendFunctionCall() | ||
xTimerPendFunctionCallFromISR() | xTimerPendFunctionCallFromISR() | ||
OSTmrStateGet() | OSTmrStateGet() | ||
N.A. | pcTimerGetName() | pcTimerGetName() | |
pvTimerGetTimerID() | pvTimerGetTimerID() | ||
xTimerGetPeriod() | xTimerGetPeriod() | ||
xTimerGetTimerDaemonTaskHandle() | xTimerGetTimerDaemonTaskHandle() | ||
Fixed-Size Memory Partitions (Memory Management) | OSMemCreate() | N.A. | |
OSMemGet() | pvPortMalloc() | pvPortMalloc() | |
OSMemPut() | vPortFree() | vPortFree() | |
Thread Local Storage | OS_TLS_GetID() | N.A. | |
OS_TLS_GetValue() | pvTaskGetThreadLocalStoragePointer() | pvTaskGetThreadLocalStoragePointer() | |
OS_TLS_SetDestruct() | N.A. | ||
OS_TLS_SetValue() | vTaskSetThreadLocalStoragePointer() | vTaskSetThreadLocalStoragePointer() |
Table 16 API Mapping
The errors reported back from the FreeRTOS API are different from µC/OS-III. In µC/OS-III, each API function returns an error code concerning the outcome of the function call via a pointer to a variable of type OS_ERR that is always the last argument of the API function, but in FreeRTOS, Typically you just declare a variable to store the return value from some of the API functions.
µC/OS-III
OS_MUTEX MyMutex; void MyFunction (void) { OS_ERR err; OSMutexCreate( &MyMutex, "Mutex Name Here", &err ); if (err == OS_ERR_NONE) { // The mutex was created // and can be used } else { // Handle the error } }
FreeRTOS
SemaphoreHandle_t MyMutex; StaticSemaphore_t MyMutexBuffer; void MyFunction(void) { MyMutex = xSemaphoreCreateMutexStatic( &MyMutexBuffer ); if( MyMutex != pdFALSE ) { // The mutex was created // and can be used } else { // Handle the error } }
Table 17 - 1 Error Handling
As a basic error handling, you can simply check that the returned error code is OS_ERR_NONE, which is equivalent to the way you are currently doing it with FreeRTOS, where the returned error code can basically be either 0 or 1 as shown in the following table:
Group | Macro Name | Values | Note |
---|---|---|---|
a | pdFALSE | ( ( BaseType_t ) 0 ) | FreeRTOS general error code check values |
pdTRUE | ( ( BaseType_t ) 1 ) |
||
b | pdPASS | ( ( BaseType_t ) 1 ) | FreeRTOS general error code check values |
pdFAIL | ( ( BaseType_t ) 0 ) |
||
c | errQUEUE_EMPTY | ( ( BaseType_t ) 0 ) | Queue functions error check values |
errQUEUE_FULL | ( ( BaseType_t ) 0 ) |
||
d | errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY | ( -1 ) | Memory and other error check values |
errQUEUE_BLOCKED | ( -4 ) |
||
errQUEUE_YIELD | ( -5 ) |
Table 17 - 2 FreeRTOS Error Check Codes
To learn more about FreeRTOS including the API reference and the Features, Please refer to ADI FreeRTOS-Addin and FreeRTOS official web.
ADI FreeRTOS-Addin:
FreeRTOS Official Link:
If you are doing a commercial product, using the µC/OS-III and looking at migrating to FreeRTOS, don’t hesitate to contact us at: