freertos to µc/os-iii® migration guide – arm cortex-m · └───ucos-iii ... the directory...

23
1 www.micrium.com | FreeRTOS to μC/OS-III® Migration Guide ARM Cortex-M FreeRTOS to µC/OS-III® Migration Guide – ARM Cortex-M July 21, 2017 V.1.1 Introduction Developed over the past 12 years (circa 2005), FreeRTOS is a real-time kernel that is free to use and is provided in source form. FreeRTOS was developed by Mr. Richard Barry and, has become quite popular over the years. FreeRTOS has been adopted by many semiconductor manufacturers (semis) because it avoids playing favoritism amongst RTOS suppliers and also allows them to provide examples using an RTOS kernel with their chips. However, semis provide limited support for FreeRTOS. Both FreeRTOS and Micriµm’s µC/OS-III are ‘real-time kernels’; software that manages the time of a CPU as well as resources. A full-fledge operating system typically includes other highly reusable software modules (a.k.a. Middleware) such TCP/IP stack (both IPv4 and IPv6), USB stacks (both Host and Device), a File System (either FAT compatible or transactional), CANbus, Modbus (ASCII or RTU), a Graphical User Interface (GUI) and more. Micriµm’s µC/OS-III is also provided in source form and can be expanded into a full fledge embedded Operating System (see www.micrium.com) by adding modules/components as mentioned above but, you don’t have to use all modules if your application/product doesn’t require them. For example, if you only need the TCP/IP stack and µC/OS-III then, these are the only modules you add to your product. µC/OS-III requires a licensing fee if used in commercial applications. The license also includes IP (Intellectual Property) indemnification which is often required by companies. This document provides a migration guide for those customers who want to migrate their FreeRTOS-based application to Micrium’s µC/OS-III. You will find that migrating FreeRTOS is quite straightforward and in most cases will requires just a few hours.

Upload: truongcong

Post on 04-May-2018

272 views

Category:

Documents


8 download

TRANSCRIPT

Page 1: FreeRTOS to µC/OS-III® Migration Guide – ARM Cortex-M · └───uCOS-III ... the directory structure of µC/OS-III includes some files that implement the ... -III® Migration

1 www.micrium.com |

FreeRTOS to µC/OS-III® Migration Guide – ARM Cortex-M

FreeRTOS to µC/OS-III® Migration

Guide – ARM Cortex-M

July 21, 2017 V.1.1

Introduction

Developed over the past 12 years (circa 2005), FreeRTOS is a real-time kernel that is free to use and is provided in

source form. FreeRTOS was developed by Mr. Richard Barry and, has become quite popular over the years. FreeRTOS

has been adopted by many semiconductor manufacturers (semis) because it avoids playing favoritism amongst RTOS

suppliers and also allows them to provide examples using an RTOS kernel with their chips. However, semis provide

limited support for FreeRTOS.

Both FreeRTOS and Micriµm’s µC/OS-III are ‘real-time kernels’; software that manages the time of a CPU as well as

resources. A full-fledge operating system typically includes other highly reusable software modules (a.k.a. Middleware)

such TCP/IP stack (both IPv4 and IPv6), USB stacks (both Host and Device), a File System (either FAT compatible or

transactional), CANbus, Modbus (ASCII or RTU), a Graphical User Interface (GUI) and more.

Micriµm’s µC/OS-III is also provided in source form and can be expanded into a full fledge embedded Operating System

(see www.micrium.com) by adding modules/components as mentioned above but, you don’t have to use all modules if

your application/product doesn’t require them. For example, if you only need the TCP/IP stack and µC/OS-III then,

these are the only modules you add to your product.

µC/OS-III requires a licensing fee if used in commercial applications. The license also includes IP (Intellectual Property)

indemnification which is often required by companies.

This document provides a migration guide for those customers who want to migrate their FreeRTOS-based application

to Micrium’s µC/OS-III. You will find that migrating FreeRTOS is quite straightforward and in most cases will requires

just a few hours.

Page 2: FreeRTOS to µC/OS-III® Migration Guide – ARM Cortex-M · └───uCOS-III ... the directory structure of µC/OS-III includes some files that implement the ... -III® Migration

2 www.micrium.com |

FreeRTOS to µC/OS-III® Migration Guide – ARM Cortex-M

Source Code

The folder structure for both FreeRTOS and µC/OS-III are shown in Table 1. Simply replace the FreeRTOS source

code with the files shown on the right column:

FreeRTOS µC/OS-III

└───FreeRTOS └───Source │ croutine.c │ event_groups.c │ list.c │ queue.c │ tasks.c │ timers.c │ ├───Include │ croutine.h │ event_groups.h │ FreeRTOS.h │ list.h │ mpu_prototypes.h │ mpu_wrappers.h │ portable.h │ projdefs.h │ queue.h │ semphr.h │ StackMacros.h │ task.h │ timers.h │ └───Portable └───[compiler] └───[architecture] port.c portasm.s portmacro.h

└───Micrium └───Software ├───uC-CPU │ │ cpu_core.c │ │ cpu_core.h │ │ cpu_def.h │ │ │ ├───Cfg │ │ cpu_cfg.h │ │ │ └───[architecture] │ └───[compiler] │ cpu.h │ ├───uC-LIB │ │ lib_ascii.c │ │ lib_ascii.h │ │ lib_def.h │ │ lib_math.c │ │ lib_mem.c │ │ lib_mem.h │ │ lib_str.c │ │ lib_str.h │ │ │ └───Cfg │ lib_cfg.h │ └───uCOS-III ├───Cfg │ os_app_hooks.c │ os_app_hooks.h │ os_cfg.h │ os_cfg_app.h │ ├───Ports │ └───[architecture] │ └───[compiler] │ os_cpu.h │ os_cpu_a.asm │ os_cpu_c.c │ ├───Source │ os.h │ os_cfg_app.c │ os_core.c │ os_dbg.c │ os_flag.c │ os_mem.c │ os_mon.c │ os_msg.c │ os_mutex.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_trace.c │ os_type.h │ os_var.c │ └───Trace └───[recorder] ├───Cfg ├───Source └───ThirdPartyLibrary

Table 1 Source Code Directory Structures

(1)

(2)

(3)

(6)

(4)

(5)

Page 3: FreeRTOS to µC/OS-III® Migration Guide – ARM Cortex-M · └───uCOS-III ... the directory structure of µC/OS-III includes some files that implement the ... -III® Migration

3 www.micrium.com |

FreeRTOS to µC/OS-III® Migration Guide – ARM Cortex-M

Like FreeRTOS, the directory structure of µC/OS-III includes some files that implement the kernel core, other files

implement specific kernel objects and services, support files that are common to the Micrium software stacks and other

files that are optional to enable kernel tracing. The table annotations below describe the different groups.

• Table 1-(1) μC/CPU consists of files that encapsulate common CPU-specific functionality such as disabling

and enabling interrupts and among others CPU and compiler-specific data types.

• Table 1-(2) μC/LIB consists of library functions meant to be highly portable and not tied to any specific

compiler. Some of the functions are occasionally used to replace stdlib functions provided by the compiler.

This facilitates third-party certification of Micriμm products. μC/OS-III does not use any μC/LIB functions,

however μC/OS-III and μC/CPU assume the presence of lib_def.h for such definitions as: DEF_YES,

DEF_NO, DEF_TRUE, DEF_FALSE, DEF_ON, DEF_OFF and more.

• Table 1-(3) µC/OS-III Configuration files are used to define μC/OS-III features (os_cfg.h) to include in the

application, specify the size of certain variables and data structures expected by μC/OS-III (os_cfg_app.h),

such as idle task stack size, tick rate and size of the message pool among others.

• Table 1-(4) This is the μC/OS-III code that is adapted to a specific CPU architecture. The file portasm.s in

FreeRTOS where the PendSVhandler and other things are defined is replaced by the port file os_cpu_a.asm

in µC/OS-III. Similarly, the file port_[toolchain].c in FreeRTOS where things such as

vPortSetupTimerInterrupt() to configure the systick timer are defined is replaced by the file os_cpu_c.c in

µC/OS-III.

• Table 1-(5) This is the μC/OS-III processor-independent code. All files in this directory should be included in

the build. Features that are not required will be compiled out based on the value of #define constants in

os_cfg.h and os_cfg_app.h.

• Table 1-(6) Kernel tracing is optional and available for recorders such as Percepio’s TraceAlyzer and

SEGGER’s SystemView. The files in this directory are required only if OS_CFG_TRACE_EN in os_cfg.h is

set to DEF_ENABLED.

For more information on the µC/OS-III directories and files refer to the µC/OS-III Documentation – Directories and Files

Page 4: FreeRTOS to µC/OS-III® Migration Guide – ARM Cortex-M · └───uCOS-III ... the directory structure of µC/OS-III includes some files that implement the ... -III® Migration

4 www.micrium.com |

FreeRTOS to µC/OS-III® Migration Guide – ARM Cortex-M

Interrupt Vector Table

Both FreeRTOS and µC/OS-III require two interrupt handlers that need to be installed in the Interrupt Vector Table

(IVT). One is called the PendSV handler and the other one is called the SysTick Handler.

The IVT 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.

Locate the startup code in your embedded project and replace the default interrupt handlers for the PendSV and

SysTick interrupts with the handlers listed in the following table:

IRQ Name FreeRTOS µC/OS-III

PendSV xPortPendSVHandler()

in portasm.s

OS_CPU_PendSVHandler()

in os_cpu_a.asm

SysTick xPortSysTickHandler()

in port_[toolchain].c

OS_CPU_SysTickHandler()

in os_cpu_c.c

Table 2 ARM Cortex-M IRQ Handlers

For the ARM Cortex architecture, some semiconductor manufacturers provide a CMSIS wrapper in assembly language,

where you can specify the name of the handlers for the PendSV and SysTick interrupts instead of modifying the startup

code.

Page 5: FreeRTOS to µC/OS-III® Migration Guide – ARM Cortex-M · └───uCOS-III ... the directory structure of µC/OS-III includes some files that implement the ... -III® Migration

5 www.micrium.com |

FreeRTOS to µC/OS-III® Migration Guide – ARM Cortex-M

Critical Sections

Both kernels need to disable interrupts during critical sections. Locate all the critical sections in your project that are

currently protected by FreeRTOS:

taskENTER_CRITICAL()

taskEXIT_CRITICAL()

taskENTER_CRITICAL_FROM_ISR()

taskEXIT_CRITICAL_FROM_ISR()

and replace them with the equivalent in µC/OS-III macros (SR == Status Register):

CPU_SR_ALLOC()

CPU_CRITICAL_ENTER()

CPU_CRITICAL_EXIT()

as shown in the following example:

FreeRTOS µC/OS-III

void MyFunction (void) { // Create a critical section taskENTER_CRITICAL(); // Perform the action that is // being protected by the // critical section here. . . . // Exit the critical section taskEXIT_CRITICAL(); }

void MyFunction (void) { // Storage for SR register CPU_SR_ALLOC(); // Create a critical section CPU_CRITICAL_ENTER(); // Perform the action that is // being protected by the // critical section here. . . . // Exit the critical section CPU_CRITICAL_EXIT(); }

Table 3 Critical Sections

For more information on Critical Sections, see the full documentation of µC/CPU Critical Sections.

Page 6: FreeRTOS to µC/OS-III® Migration Guide – ARM Cortex-M · └───uCOS-III ... the directory structure of µC/OS-III includes some files that implement the ... -III® Migration

6 www.micrium.com |

FreeRTOS to µC/OS-III® Migration Guide – ARM Cortex-M

Kernel-Aware Interrupts

Interrupt Service Routines (ISRs) that need to notify a task are called Kernel Aware Interrupts (or KA). Locate all the

interrupt handlers in your project and keep in mind that during an interrupt, if you call any of the FreeRTOS queue

functionality or anything else that could trigger a task context switch, then in µC/OS-III you need to post to a semaphore,

an event flag, a message queue or other function that will notify the task that the interrupt occurred. See the µC/OS-III

API reference manual for details on these functions:

OSSemPost()

OSFlagPost()

OSQPost()

OSTaskSemPost()

OSTaskQPost()

OSTaskResume()

When using the Cortex-M, your ISR code can be simple C-functions as shown below; i.e. no need to write ISRs in

assembly language).

FreeRTOS µC/OS-III

void My_IRQ_Handler (void) { char cIn; BaseType_t xHigherPrioTaskWoken; xHigherPrioTaskWoken = pdFALSE; // Handle the interrupt xQueueSendFromISR( xRxQueue, &cIn, &xHigherPrioTaskWoken); if (xHigherPrioTaskWoken) { taskYIELD_FROM_ISR(); } }

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(); }

Table 4 Kernel Aware ISRs

Page 7: FreeRTOS to µC/OS-III® Migration Guide – ARM Cortex-M · └───uCOS-III ... the directory structure of µC/OS-III includes some files that implement the ... -III® Migration

7 www.micrium.com |

FreeRTOS to µC/OS-III® Migration Guide – ARM Cortex-M

Initializing and Starting the OS

Before calling any µC/OS-III function you need to initialize µC/OS-III by calling OSInit() and start multi-tasking by

calling OSStart() as shown in the following example:

FreeRTOS µC/OS-III

void main (void) { . . . . . // Create tasks and other // kernel objects . . . // Start the real-time scheduler vTaskStartScheduler(); // Will not get here unless there // is insufficient RAM. }

void main (void) { OS_ERR err; // Initialize µC/OS-III OSInit(&err); // Create tasks and other // kernel objects . . . // Start Multitasking OSStart(&err); // Will not get here unless there // is an error (check err). }

Table 5 Starting the Kernels

Page 8: FreeRTOS to µC/OS-III® Migration Guide – ARM Cortex-M · └───uCOS-III ... the directory structure of µC/OS-III includes some files that implement the ... -III® Migration

8 www.micrium.com |

FreeRTOS to µC/OS-III® Migration Guide – ARM Cortex-M

Task Priorities

In FreeRTOS, low priority numbers denote low priority tasks.

On the other hand, in µC/OS-III a low-priority number corresponds to a high-priority level. Priority level zero (0) is thus

the highest priority level and priority OS_CFG_PRIO_MAX-1 is the lowest priority level as shown in the following table:

Task Priority Level FreeRTOS µC/OS-III

Low 0 OS_CFG_PRIO_MAX - 1

High configMAX_PRIORITIES - 1 0

Table 6 Task Priority Levels

Both kernels have the Idle task at the lowest priority level, and both support multiple tasks at the same priority level.

For more information on task priorities see the full documentation on Assigning Task Priorities and Round-Robin

Scheduling.

Page 9: FreeRTOS to µC/OS-III® Migration Guide – ARM Cortex-M · └───uCOS-III ... the directory structure of µC/OS-III includes some files that implement the ... -III® Migration

9 www.micrium.com |

FreeRTOS to µC/OS-III® Migration Guide – ARM Cortex-M

Task Creation

In both FreeRTOS and µC/OS-III, tasks are written as an infinite loop function or, as a function that deletes the task

once completed.

Both FreeRTOS and µC/OS-III 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.

Kernel Objects such as tasks, queues, semaphores and mutexes in FreeRTOS can be created either statically or by

dynamically allocating them in FreeRTOS’s heap.

On the other hand, 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.

This means that any of the kernel objects in your project that were created on FreeRTOS heap by calling one of the

API functions that do not have the suffix Static, needs to be migrated to a similar API function in µC/OS-III that allocates

the object statically.

For example, to migrate your tasks, locate in your project all the places where a task gets created by FreeRTOS

xTaskCreate() and/or xTaskCreateStatic(). The equivalent API function in µC/OS-III is OSTaskCreate()

and the following table shows the arguments you need to change:

FreeRTOS µC/OS-III

BaseType_t xTaskCreate( TaskFunction_t pvTaskCode, const char *pcName, unsigned short usStackDepth, void *pvParameters, UBaseType_t uxPriority, TaskHandle_t *pxCreatedTask);

void OSTaskCreate( OS_TCB *p_tcb, CPU_CHAR *p_name, OS_TASK_PTR *p_task, void *p_arg, OS_PRIO prio, CPU_STK *p_stk_base, CPU_STK_SIZE stk_limit, CPU_STK_SIZE stk_size, OS_MSG_QTY q_size, OS_TICK time_quanta, void *p_ext, OS_OPT opt, OS_ERR *p_err);

Table 7 Task Creation Mapping

Page 10: FreeRTOS to µC/OS-III® Migration Guide – ARM Cortex-M · └───uCOS-III ... the directory structure of µC/OS-III includes some files that implement the ... -III® Migration

10 www.micrium.com |

FreeRTOS to µC/OS-III® Migration Guide – ARM Cortex-M

The following example shows the complete way to create a task:

FreeRTOS µC/OS-III

#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) { TaskHandle_t xHandle = NULL; xHandle = xTaskCreateStatic( MyTaskCode, "Task Name Here", MY_TASK_STACK_SIZE, (void *)1, MY_TASK_PRIORITY, MyTaskStk, &MyTaskTCB); }

#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; 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); }

Table 8 Task Creation

It is worth noting that a task in µC/OS-III must always invoke one of the services provided by µC/OS-III to wait for time

to expire, suspend the task, or wait on an object (wait on a message queue, event flag, mutex, semaphore, a signal or

a message to be sent directly to the task). This allows other tasks to gain control of the CPU.

For a more detailed description of each of the arguments in OSTaskCreate() see the full documentation on

OSTaskCreate().

Page 11: FreeRTOS to µC/OS-III® Migration Guide – ARM Cortex-M · └───uCOS-III ... the directory structure of µC/OS-III includes some files that implement the ... -III® Migration

11 www.micrium.com |

FreeRTOS to µC/OS-III® Migration Guide – ARM Cortex-M

Task Delays

Just like in FreeRTOS, you can delay a task with µC/OS-III for a certain number of ticks. In µC/OS-III 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 following example shows a task that toggles an LED

every 500ms. The 500ms delay starts from the moment the API is called (relative). For µC/OS-III, assuming the tick

rate is set at 1000 Hz (OS_CFG_TICK_RATE_HZ):

FreeRTOS µC/OS-III

void MyTaskFunction(void * pvParameters) {

// 500ms Delay. const TickType_t delay = 500 / portTICK_PERIOD_MS; for (;;) { // Toggle LED2. BSP_TOGGLE_LED(LED2); // Block task for 500ms. vTaskDelay(delay); } }

void MyTaskFunction (void *p_arg) { OS_ERR err;

// 500ms Delay. const OS_TICK delay = 500; while (DEF_ON) { // Toggle LED2. BSP_TOGGLE_LED(LED2); // Block task for 500ms. OSTimeDly(delay, OS_OPT_TIME_DLY, &err); if (err != OS_ERR_NONE) { // Handle the error } } }

Table 9 Task Delay - Relative

Page 12: FreeRTOS to µC/OS-III® Migration Guide – ARM Cortex-M · └───uCOS-III ... the directory structure of µC/OS-III includes some files that implement the ... -III® Migration

12 www.micrium.com |

FreeRTOS to µC/OS-III® Migration Guide – ARM Cortex-M

If you want to delay a task for an absolute time, then you can use the same API except that instead of passing the

second argument as OS_OPT_TIME_DLY, you pass OS_OPT_TIME_MATCH. The other option is a periodic delay

as shown in the following example:

FreeRTOS µC/OS-III

void MyTaskFunction(void * pvParameters) { TickType_t xLastWakeTime;

const TickType_t period = 100; for (;;) { // Toggle LED2. BSP_TOGGLE_LED(LED2); // Wait for the next cycle. vTaskDelayUntil(&xLastWakeTime, period); } }

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 } } }

Table 10 Task Delay - Periodic

Page 13: FreeRTOS to µC/OS-III® Migration Guide – ARM Cortex-M · └───uCOS-III ... the directory structure of µC/OS-III includes some files that implement the ... -III® Migration

13 www.micrium.com |

FreeRTOS to µC/OS-III® Migration Guide – ARM Cortex-M

Semaphores and Mutexes

Semaphores in FreeRTOS come in 4 different types including binary, counting, mutex and recursive mutex

semaphores. They all share the same API functions except for the ones to create the actual objects.

In µC/OS-III, binary and counting semaphores are implemented through a single set of API functions that start with the

prefix OSSem___(). Similarly, mutexes are implemented through a separate set of API functions that start with the

prefix OSMutex___().

Moreover, in µC/OS-III each task has its own built-in semaphore, which 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 OSTaskSem___().

The following example shows how to protect a shared resource with a mutex:

FreeRTOS µC/OS-III

SemaphoreHandle_t MyMutex = NULL; void MyInitFunction(void) { MyMutex = xSemaphoreCreateMutex(); } 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. xSemaphoreGive(MyMutex); } } }

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); } } }

Table 11 Protecting a Shared Resource with a Mutex

For a more detailed description of each of the arguments in OSMutexCreate(), OSMutexPend() and

OSMutexPost() see the full documentation on Mutex Semaphores.

Page 14: FreeRTOS to µC/OS-III® Migration Guide – ARM Cortex-M · └───uCOS-III ... the directory structure of µC/OS-III includes some files that implement the ... -III® Migration

14 www.micrium.com |

FreeRTOS to µC/OS-III® Migration Guide – ARM Cortex-M

Message Queues

Both kernels support inter-task communication, which allows a task or ISR to communicate information to another task.

The main difference between the FreeRTOS and µC/OS-III 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. In other words, unlike FreeRTOS the

data sent is not copied.

FreeRTOS µC/OS-III #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 == 0) { // 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 } } }

#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 } } }

Table 12 Inter-task Communication - Tasks

Page 15: FreeRTOS to µC/OS-III® Migration Guide – ARM Cortex-M · └───uCOS-III ... the directory structure of µC/OS-III includes some files that implement the ... -III® Migration

15 www.micrium.com |

FreeRTOS to µC/OS-III® Migration Guide – ARM Cortex-M

FreeRTOS µC/OS-III

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( My_UART_Q, &rx_data, &xHigherPriorityTaskWoken); } while (UART_RX_BUFFER_COUNT); // Now we can switch context if necessary if (xHigherPriorityTaskWoken) { taskYIELD_FROM_ISR(); } }

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(); }

Table 13 Inter-task Communication - ISRs

Page 16: FreeRTOS to µC/OS-III® Migration Guide – ARM Cortex-M · └───uCOS-III ... the directory structure of µC/OS-III includes some files that implement the ... -III® Migration

16 www.micrium.com |

FreeRTOS to µC/OS-III® Migration Guide – ARM Cortex-M

Other API Functions

Locate in your project all the rest of FreeRTOS API function calls, and replace them with their equivalent µC/OS-III API

function. To help with the effort, here's a mapping of how FreeRTOS functionality maps to µC/OS-III.

Some of the most popular FreeRTOS APIs are listed in the left column, and the equivalent µC/OS-III functions are in

the right column. Some functions take different parameters or return different data; make sure you check out the full

documentation by following the link on the last column.

Kernel

Service FreeRTOS µC/OS-III Documentation

Task

Management

vTaskPrioritySet() OSTaskChangePrio() OSTaskChangePrio()

xTaskCreateStatic() OSTaskCreate() OSTaskCreate()

xTaskCreate() N.A.

vTaskDelete() OSTaskDel() OSTaskDelete()

N.A. OSTaskRegGet() OSTaskRegGet()

N.A. OSTaskRegSet() OSTaskRegSet()

vTaskResume() xTaskResumeFromISR()

OSTaskResume() OSTaskResume()

vTaskSuspend() OSTaskSuspend() OSTaskSuspend()

N.A. OSTaskStkChk() OSTaskStkChk()

N.A. OSTaskTimeQuantaSet() OSTaskTimeQuantaSet()

Time

Management

vTaskDelay() vTaskDelayUntil()

OSTimeDly() OSTimeDly()

N.A. OSTimeDlyHMSM() OSTimeDlyHMSM()

xTaskAbortDelay() OSTimeDlyResume() OSTimeDlyResume()

N.A. OSTimeGet() OSTimeGet()

Mutual

Exclusion

Semaphores

xSemaphoreCreateMutexStatic() xSemaphoreCreateRecursiveMutexStatic()

OSMutexCreate() OSMutexCreate()

xSemaphoreCreateMutex() xSemaphoreCreateRecursiveMutex()

N.A.

vSemaphoreDelete() OSMutexDel() OSMutexDel()

xSemaphoreTake() xSemaphoreTakeFromISR() xSemaphoreTakeRecursive()

OSMutexPend() OSMutexPend()

N.A. OSMutexPendAbort() OSMutexPendAbort()

xSemaphoreGive() xSemaphoreGiveRecursive() xSemaphoreGiveFromISR()

OSMutexPost() OSMutexPost()

Event Flags

xEventGroupCreateStatic() OSFlagCreate() OSFlagCreate()

xEventGroupCreate() N.A.

vEventGroupDelete() OSFlagDel() OSFlagDel()

xEventGroupWaitBits() OSFlagPend() OSFlagPend()

N.A. OSFlagPendAbort() OSFlagPendAbort()

N.A. OSFlagPendGetFlagsRdy() OSFlagPendGetFlagsRdy()

xEventGroupSetBits() xEventGroupSetBitsFromISR() xEventGroupClearBits()

OSFlagPost() OSFlagPost()

Semaphores

xSemaphoreCreateBinaryStatic() xSemaphoreCreateCountingStatic()

OSSemCreate() OSSemCreate()

xSemaphoreCreateBinary() xSemaphoreCreateCounting()

N.A.

Page 17: FreeRTOS to µC/OS-III® Migration Guide – ARM Cortex-M · └───uCOS-III ... the directory structure of µC/OS-III includes some files that implement the ... -III® Migration

17 www.micrium.com |

FreeRTOS to µC/OS-III® Migration Guide – ARM Cortex-M

Table 14 API Mapping

vSemaphoreDelete() OSSemDel() OSSemDel()

xSemaphoreTake() xSemaphoreTakeFromISR()

OSSemPend() OSSemPend()

N.A. OSSemPendAbort() OSSemPendAbort()

xSemaphoreGive(), xSemaphoreGiveRecursive() xSemaphoreGiveFromISR()

OSSemPost() OSSemPost()

N.A. OSSemSet() OSSemSet()

Task

Semaphores

ulTaskNotifyTake() OSTaskSemPend() OSTaskSemPend()

N.A. OSTaskSemPendAbort() OSTaskSemPendAbort()

xTaskNotifyGive() xTaskNotifyGiveFromISR()

OSTaskSemPost() OSTaskSemPost()

N.A. OSTaskSemSet() OSTaskSemSet()

Message

Queues

xQueueCreateStatic() OSQCreate() OSQCreate()

xQueueCreate() N.A.

vQueueDelete() OSQDel() OSQDel()

xQueueReset() OSQFlush() OSQFlush()

xQueueReceive() xQueueReceiveFromISR()

OSQPend() OSQPend()

N.A. OSQPendAbort() OSQPendAbort()

xQueueSend() xQueueSendFromISR()

OSQPost() OSQPost()

Task

Message

Queues

N.A. OSTaskQFlush() OSTaskQFlush()

N.A. OSTaskQPend() OSTaskQPend()

N.A. OSTaskQPendAbort() OSTaskQPendAbort()

N.A. OSTaskQPost() OSTaskQPost()

Timers

xTimerCreateStatic() OSTmrCreate() OSTmrCreate()

xTimerCreate() N.A.

xTimerDelete() OSTmrDel() OSTmrDel()

xTimerGetExpiryTime() OSTmrRemainGet() OSTmrRemainGet()

xTimerIsTimerActive() OSTmrStateGet() OSTmrStateGet()

xTimerStart() OSTmrStart() OSTmrStart()

xTimerStop() OSTmrStop() OSTmrStop()

Memory

Partitions

N.A. OSMemCreate() OSMemCreate()

N.A. OSMemGet() OSMemGet()

N.A. OSMemPut() OSMemPut()

Page 18: FreeRTOS to µC/OS-III® Migration Guide – ARM Cortex-M · └───uCOS-III ... the directory structure of µC/OS-III includes some files that implement the ... -III® Migration

18 www.micrium.com |

FreeRTOS to µC/OS-III® Migration Guide – ARM Cortex-M

Error Handling

The errors reported back from the FreeRTOS API are different than those from µC/OS-III. In FreeRTOS you typically

declare a variable to store the return value from some of the API functions.

With µ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, as shown in the following example:

FreeRTOS µC/OS-III

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 } }

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 } }

Table 15 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:

FreeRTOS Error Codes

Error Name Error Code

pdFALSE 0

pdTRUE 1

pdPASS 1

pdFAIL 0

errQUEUE_EMPTY 0

errQUEUE_FULL 0

errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY -1

errQUEUE_BLOCKED -4

errQUEUE_YIELD -5

Table 16 FreeRTOS Error Codes

Page 19: FreeRTOS to µC/OS-III® Migration Guide – ARM Cortex-M · └───uCOS-III ... the directory structure of µC/OS-III includes some files that implement the ... -III® Migration

19 www.micrium.com |

FreeRTOS to µC/OS-III® Migration Guide – ARM Cortex-M

For a more thorough error handling, in µC/OS-III, you can use the table below that lists all the possible error codes.

µC/OS-III Error Codes

Group Error Name Error Code

OS_ERR_NONE 0

A OS_ERR_ACCEPT_ISR 10001

C OS_ERR_CREATE_ISR 12001

D OS_ERR_DEL_ISR 13001

F

OS_ERR_FATAL_RETURN 15001

OS_ERR_FLAG_GRP_DEPLETED 15101

OS_ERR_FLAG_NOT_RDY 15102

OS_ERR_FLAG_PEND_OPT 15103

OS_ERR_FLUSH_ISR 15104

I

OS_ERR_ILLEGAL_CREATE_RUN_TIME 18001

OS_ERR_INT_Q 18002

OS_ERR_INT_Q_FULL 18003

OS_ERR_INT_Q_SIZE 18004

OS_ERR_INT_Q_STK_INVALID 18005

OS_ERR_INT_Q_STK_SIZE_INVALID 18006

OS_ERR_ILLEGAL_DEL_RUN_TIME 18007

L OS_ERR_LOCK_NESTING_OVF 21001

M

OS_ERR_MEM_CREATE_ISR 22201

OS_ERR_MEM_FULL 22202

OS_ERR_MEM_INVALID_P_ADDR 22203

OS_ERR_MEM_INVALID_BLKS 22204

OS_ERR_MEM_INVALID_PART 22205

OS_ERR_MEM_INVALID_P_BLK 22206

OS_ERR_MEM_INVALID_P_MEM 22207

OS_ERR_MEM_INVALID_P_DATA 22208

OS_ERR_MEM_INVALID_SIZE 22209

OS_ERR_MEM_NO_FREE_BLKS 22210

OS_ERR_MSG_POOL_EMPTY 22301

OS_ERR_MSG_POOL_NULL_PTR 22302

OS_ERR_MUTEX_NOT_OWNER 22401

Page 20: FreeRTOS to µC/OS-III® Migration Guide – ARM Cortex-M · └───uCOS-III ... the directory structure of µC/OS-III includes some files that implement the ... -III® Migration

20 www.micrium.com |

FreeRTOS to µC/OS-III® Migration Guide – ARM Cortex-M

OS_ERR_MUTEX_OWNER 22402

OS_ERR_MUTEX_NESTING 22403

OS_ERR_MUTEX_OVF 22404

N

OS_ERR_NAME 23001

OS_ERR_NO_MORE_ID_AVAIL 23002

O

OS_ERR_OBJ_CREATED 24001

OS_ERR_OBJ_DEL 24002

OS_ERR_OBJ_PTR_NULL 24003

OS_ERR_OBJ_TYPE 24004

OS_ERR_OPT_INVALID 24101

OS_ERR_OS_NOT_RUNNING 24201

OS_ERR_OS_RUNNING 24202

OS_ERR_OS_NOT_INIT 24203

OS_ERR_OS_NO_APP_TASK 24204

P

OS_ERR_PEND_ABORT 25001

OS_ERR_PEND_ABORT_ISR 25002

OS_ERR_PEND_ABORT_NONE 25003

OS_ERR_PEND_ABORT_SELF 25004

OS_ERR_PEND_DEL 25005

OS_ERR_PEND_ISR 25006

OS_ERR_PEND_LOCKED 25007

OS_ERR_PEND_WOULD_BLOCK 25008

OS_ERR_POST_NULL_PTR 25101

OS_ERR_POST_ISR 25102

OS_ERR_PRIO_EXIST 25201

OS_ERR_PRIO 25202

OS_ERR_PRIO_INVALID 25203

OS_ERR_PTR_INVALID 25301

Q

OS_ERR_Q_FULL 26001

OS_ERR_Q_EMPTY 26002

OS_ERR_Q_MAX 26003

OS_ERR_Q_SIZE 26004

R OS_ERR_REG_ID_INVALID 27001

Page 21: FreeRTOS to µC/OS-III® Migration Guide – ARM Cortex-M · └───uCOS-III ... the directory structure of µC/OS-III includes some files that implement the ... -III® Migration

21 www.micrium.com |

FreeRTOS to µC/OS-III® Migration Guide – ARM Cortex-M

OS_ERR_ROUND_ROBIN_1 27002

OS_ERR_ROUND_ROBIN_DISABLED 27003

S

OS_ERR_SCHED_INVALID_TIME_SLICE 28001

OS_ERR_SCHED_LOCK_ISR 28002

OS_ERR_SCHED_LOCKED 28003

OS_ERR_SCHED_NOT_LOCKED 28004

OS_ERR_SCHED_UNLOCK_ISR 28005

OS_ERR_SEM_OVF 28101

OS_ERR_SET_ISR 28102

OS_ERR_STAT_RESET_ISR 28201

OS_ERR_STAT_PRIO_INVALID 28202

OS_ERR_STAT_STK_INVALID 28203

OS_ERR_STAT_STK_SIZE_INVALID 28204

OS_ERR_STATE_INVALID 28205

OS_ERR_STATUS_INVALID 28206

OS_ERR_STK_INVALID 28207

OS_ERR_STK_SIZE_INVALID 28208

OS_ERR_STK_LIMIT_INVALID 28209

T

OS_ERR_TASK_CHANGE_PRIO_ISR 29001

OS_ERR_TASK_CREATE_ISR 29002

OS_ERR_TASK_DEL 29003

OS_ERR_TASK_DEL_IDLE 29004

OS_ERR_TASK_DEL_INVALID 29005

OS_ERR_TASK_DEL_ISR 29006

OS_ERR_TASK_INVALID 29007

OS_ERR_TASK_NO_MORE_TCB 29008

OS_ERR_TASK_NOT_DLY 29009

OS_ERR_TASK_NOT_EXIST 29010

OS_ERR_TASK_NOT_SUSPENDED 29011

OS_ERR_TASK_OPT 29012

OS_ERR_TASK_RESUME_ISR 29013

OS_ERR_TASK_RESUME_PRIO 29014

OS_ERR_TASK_RESUME_SELF 29015

Page 22: FreeRTOS to µC/OS-III® Migration Guide – ARM Cortex-M · └───uCOS-III ... the directory structure of µC/OS-III includes some files that implement the ... -III® Migration

22 www.micrium.com |

FreeRTOS to µC/OS-III® Migration Guide – ARM Cortex-M

OS_ERR_TASK_RUNNING 29016

OS_ERR_TASK_STK_CHK_ISR 29017

OS_ERR_TASK_SUSPENDED 29018

OS_ERR_TASK_SUSPEND_IDLE 29019

OS_ERR_TASK_SUSPEND_INT_HANDLER 29020

OS_ERR_TASK_SUSPEND_ISR 29021

OS_ERR_TASK_SUSPEND_PRIO 29022

OS_ERR_TASK_WAITING 29023

OS_ERR_TASK_SUSPEND_CTR_OVF 29024

OS_ERR_TCB_INVALID 29101

OS_ERR_TLS_ID_INVALID 29120

OS_ERR_TLS_ISR 29121

OS_ERR_TLS_NO_MORE_AVAIL 29122

OS_ERR_TLS_NOT_EN 29123

OS_ERR_TLS_DESTRUCT_ASSIGNED 29124

OS_ERR_TICK_PRIO_INVALID 29201

OS_ERR_TICK_STK_INVALID 29202

OS_ERR_TICK_STK_SIZE_INVALID 29203

OS_ERR_TICK_WHEEL_SIZE 29204

OS_ERR_TIME_DLY_ISR 29301

OS_ERR_TIME_DLY_RESUME_ISR 29302

OS_ERR_TIME_GET_ISR 29303

OS_ERR_TIME_INVALID_HOURS 29304

OS_ERR_TIME_INVALID_MINUTES 29305

OS_ERR_TIME_INVALID_SECONDS 29306

OS_ERR_TIME_INVALID_MILLISECONDS 29307

OS_ERR_TIME_NOT_DLY 29308

OS_ERR_TIME_SET_ISR 29309

OS_ERR_TIME_ZERO_DLY 29310

OS_ERR_TIMEOUT 29401

OS_ERR_TMR_INACTIVE 29501

OS_ERR_TMR_INVALID_DEST 29502

OS_ERR_TMR_INVALID_DLY 29503

Page 23: FreeRTOS to µC/OS-III® Migration Guide – ARM Cortex-M · └───uCOS-III ... the directory structure of µC/OS-III includes some files that implement the ... -III® Migration

23 www.micrium.com |

FreeRTOS to µC/OS-III® Migration Guide – ARM Cortex-M

OS_ERR_TMR_INVALID_PERIOD 29504

OS_ERR_TMR_INVALID_STATE 29505

OS_ERR_TMR_INVALID 29506

OS_ERR_TMR_ISR 29507

OS_ERR_TMR_NO_CALLBACK 29508

OS_ERR_TMR_NON_AVAIL 29509

OS_ERR_TMR_PRIO_INVALID 29510

OS_ERR_TMR_STK_INVALID 29511

OS_ERR_TMR_STK_SIZE_INVALID 29512

OS_ERR_TMR_STOPPED 29513

OS_ERR_TMR_INVALID_CALLBACK 29514

Y OS_ERR_YIELD_ISR 34001

Table 17 µC/OS-III Error Codes

Further Reading

To learn more about µC/OS-III including not only how the kernel works but also an API reference in detail, read the full

µC/OS-III Documentation.

Getting Help

If you are doing a commercial product, using FreeRTOS and looking at migrating to µC/OS-III, don’t hesitate to contact

us at Micrium: www.micrium.com.