23
silabs.com | Smart. Connected. Energy-friendly Rev. 0.1 Migration Guide: from FreeRTOS to Micrium OS FreeRTOS and Micrium OS Kernel 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 such as a TCP/IP stack, USB stacks, a File System and more. Micrium OS is also provided in source form and can be expanded into a full fledge em- bedded Operating System by adding modules as mentioned above but, you don’t have to use all modules if your application doesn’t require them. For example, if you only need the TCP/IP stack and the Kernel then, these are the only modules you add to your prod- uct. Micrium OS is available only to Silicon Labs customers. The Kernel is FREE for Silicon Labs chip customers. If you want to use Micrium Software for a commercial product on a different semiconductor then you need to purchase a license for either uC/OS-II or uC/OS-III. Whether you are currently running your embedded application on Silicon Labs hardware or other semiconductor, the migration path is the same; You should start from a working Micrium OS example and then move your embedded application over to the example project. Figure 1. Migration Paths Once you move your embedded application to the Micrium OS baseline example project, you need to change the code that calls the FreeRTOS API. The purpose of this document is to describe the differences between the two kernels, offer plenty of side-by-side examples and mapping tables to help you in the process of migrating your embedded application. KEY POINTS Micrium OS is available only to Silicon Labs chips and the Kernel is for free. To migrate from FreeRTOS, use a work- ing Micrium OS example as a baseline and move your application over. This document describes the differences between the kernels and presents side- by-side examples and mapping tables to help you with the migration.

Migration Guide: From FreeRTOS to Micrium OS...port_[toolchain].c in FreeRTOS where things such as vPortSetupTimerInterrupt() to configure the systick timer are defined is replaced

  • Upload
    others

  • View
    72

  • Download
    2

Embed Size (px)

Citation preview

silabs.com | Smart. Connected. Energy-friendly Rev. 0.1

Migration Guide: from FreeRTOS to Micrium OS

FreeRTOS and Micrium OS Kernel 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 such as a TCP/IP stack, USB stacks, a File System and

more.

Micrium OS is also provided in source form and can be expanded into a full fledge em-

bedded Operating System by adding modules as mentioned above but, you don’t have

to use all modules if your application doesn’t require them. For example, if you only need

the TCP/IP stack and the Kernel then, these are the only modules you add to your prod-

uct.

Micrium OS is available only to Silicon Labs customers. The Kernel is FREE for Silicon

Labs chip customers. If you want to use Micrium Software for a commercial product on a different semiconductor then you need to

purchase a license for either uC/OS-II or uC/OS-III.

Whether you are currently running your embedded application on Silicon Labs hardware or other semiconductor, the migration path is

the same; You should start from a working Micrium OS example and then move your embedded application over to the example project.

Figure 1. Migration Paths

Once you move your embedded application to the Micrium OS baseline example project, you need to change the code that calls the

FreeRTOS API.

The purpose of this document is to describe the differences between the two kernels, offer plenty of side-by-side examples and mapping

tables to help you in the process of migrating your embedded application.

KEY POINTS

• Micrium OS is available only to Silicon

Labs chips and the Kernel is for free.

• To migrate from FreeRTOS, use a work-

ing Micrium OS example as a baseline

and move your application over.

• This document describes the differences

between the kernels and presents side-

by-side examples and mapping tables to

help you with the migration.

Migration Guide: From FreeRTOS to Micrium OS

Micrium OS

silabs.com | Smart. Connected. Energy-friendly Rev. 0.1 | 1

1 Source Code

The folder structure for both FreeRTOS and Micrium OS are shown in Table 1:

FreeRTOS Micrium OS Kernel └───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_os

├───cfg

│ cpu_cfg.h

│ os_cfg.h

│ rtos_cfg.h

│ rtos_description.h

│ rtos_err_cfg.h

├───common

│ ├───include

│ │ lib_ascii.h

│ │ lib_def.h

│ │ lib_math.h

│ │ lib_mem.h

│ │ lib_str.h

│ │ lib_utils.h

│ │ rtos_err.h

│ │ rtos_path.h

│ │ rtos_prio.h

│ │ rtos_types.h

│ │ rtos_utils.h

│ │ rtos_version.h

│ │ toolchains.h

│ └───source

│ └───lib

│ lib_ascii.c

│ lib_math.c

│ lib_mem.c

│ lib_str.c

├───cpu

│ ├───include

│ │ common.h

│ │ lib_def.h

│ └───source

│ cpu_core.c

├───kernel

│ ├───include

│ │ os.h

│ │ os_port_sel.h

│ │ os_trace.h

│ │ os_type.h

│ └───source

│ 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_priv.h

│ os_q.c

│ os_sem.c

│ os_stat.c

│ os_task.c

│ os_tick.c

│ os_time.c

│ os_tmr.c

│ os_var.c

└───ports

└───source

├───generic

│ [architecture]_cpu_int.c

└───[compiler]

[architecture]_cpu_a.S

[architecture]_os_cpu_a.S

[architecture]_os_cpu_c.c

Table 1. Source Code Directory Structures

Like FreeRTOS, the directory structure of Micrium OS Kernel includes some files that implement the kernel core, other files implement

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

enable kernel tracing. The table annotations below describe the different groups.

(1)

(2)

(3)

(4)

(5)

Migration Guide: From FreeRTOS to Micrium OS

Micrium OS

silabs.com | Smart. Connected. Energy-friendly Rev. 0.1 | 2

• Table 1-(1) Micrium OS Configuration files are used to define the kernel features (os_cfg.h) to include in the application,

specify the size of certain variables and data structures expected by the kernel, such as the heap size (common_cfg.h).

• Table 1-(2) Most of the code in /common 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. The kernel does not use any of the functions declared in common/source/lib, however, it

assumes 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) 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-(4) This is the Kernel 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.

• Table 1-(5) This is the Kernel 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.S in Micrium OS Kernel. 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 Micrium OS Kernel.

For more information on the Micrium OS Kernel directories and files refer to the Micrium OS Kernel Documentation – Directories and

Files

Migration Guide: From FreeRTOS to Micrium OS

Micrium OS

silabs.com | Smart. Connected. Energy-friendly Rev. 0.1 | 3

2 Interrupt Vector Table

Both FreeRTOS and Micrium OS Kernel 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 located at memory address 0x00000000 and its default interrupt handlers are registered directly in some startup code in

assembly language.

For example, the startup code for Silicon Labs devices is typically located in the SDK folder at: /platform/Device/Sili-

conLabs/[device]/Source/[compiler]startup_[compiler]_[device].s

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 Micrium OS Kernel

PendSV xPortPendSVHandler()

in portasm.s

PendSV_Handler()

in armv7m_os_cpu_a.S

SysTick xPortSysTickHandler()

in port_[toolchain].c

SysTick_Handler()

in armv7m_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.

Migration Guide: From FreeRTOS to Micrium OS

Micrium OS

silabs.com | Smart. Connected. Energy-friendly Rev. 0.1 | 4

3 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 Micrium OS Kernel macros (SR == Status Register):

CPU_SR_ALLOC()

CPU_CRITICAL_ENTER()

CPU_CRITICAL_EXIT()

as shown in the following example:

FreeRTOS Micrium OS Kernel

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

Migration Guide: From FreeRTOS to Micrium OS

Micrium OS

silabs.com | Smart. Connected. Energy-friendly Rev. 0.1 | 5

4 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 Micrium OS Kernel 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 Micrium OS Kernel 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 Micrium OS Kernel

void My_IRQ_Handler (void)

{

char cIn;

BaseType_t xHigherPriorityTaskWoken;

xHigherPriorityTaskWoken = pdFALSE;

// Handle the interrupt

.

.

.

xQueueSendFromISR(

xRxQueue,

&cIn,

&xHigherPriorityTaskWoken);

if (xHigherPriorityTaskWoken) {

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

// Post to a task

.

.

.

// Make the kernel aware that

// the interrupt has ended

OSIntExit();

}

Table 4. Kernel Aware ISRs

Migration Guide: From FreeRTOS to Micrium OS

Micrium OS

silabs.com | Smart. Connected. Energy-friendly Rev. 0.1 | 6

However, the preferred alternative in Micrium OS to make your ISR kernel aware is to register your interrupt handler by calling the function

CPU_IntSrcHandlerSetKA() as shown in the following example:

Micrium OS Kernel

// Configure the GPIO (even) interrupt handler

// Register the ISR with Micrium OS Kernel

CPU_IntSrcHandlerSetKA(GPIO_EVEN_IRQn + 16, GPIO_EVEN_IRQHandler);

// Enable the IRQ

NVIC_EnableIRQ(GPIO_EVEN_IRQn);

.

.

.

void GPIO_EVEN_IRQHandler(void)

{

uint32_t iflags;

// Get all even interrupts.

iflags = GPIO_IntGetEnabled() & 0x00005555;

// Clean only even interrupts.

GPIO_IntClear(iflags);

GPIOINT_IRQDispatcher(iflags);

}

Code Listing 1. Registering Kernel Aware ISRs in Micrium OS

In this case, you don’t need to insert the calls to OSIntEnter/Exit in your interrupt handler because by registering the interrupt handler

you ensure that a centralized interrupt handler dispatcher will take care of that for you (see CPU_IntHandlerDispatcher() declared

in [architecture]_cpu_int.c).

Migration Guide: From FreeRTOS to Micrium OS

Micrium OS

silabs.com | Smart. Connected. Energy-friendly Rev. 0.1 | 7

5 Initializing and Starting the OS

Before calling any Micrium OS Kernel function you need to initialize Micrium OS Kernel by calling OSInit() and start multi-tasking by

calling OSStart() as shown in the following example:

FreeRTOS Micrium OS Kernel

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)

{

RTOS_ERR err;

// Initialize Micrium OS Kernel

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

Migration Guide: From FreeRTOS to Micrium OS

Micrium OS

silabs.com | Smart. Connected. Energy-friendly Rev. 0.1 | 8

6 Task Priorities

In FreeRTOS, low priority numbers denote low priority tasks.

On the other hand, in Micrium OS Kernel 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 Micrium OS Kernel

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 and Round-Robin scheduling see the full documentation on Assigning Task Priorities and Round-

Robin Scheduling.

Migration Guide: From FreeRTOS to Micrium OS

Micrium OS

silabs.com | Smart. Connected. Energy-friendly Rev. 0.1 | 9

7 Task Creation

In both FreeRTOS and Micrium OS Kernel, tasks are written as an infinite loop function waiting for a kernel event or, as a function that

deletes the task once completed.

Both FreeRTOS and Micrium OS Kernel 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 Micrium OS, kernel objects are created statically only. They can be allocated dynamically but the functionality is

not built-in Micrium OS Kernel. Instead, you would need to allocate them in the Micrium Heap by using the Memory Module.

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 Micrium OS Kernel 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 Micrium OS Kernel is OSTaskCreate() and the following table shows the

arguments you need to change:

FreeRTOS Micrium OS Kernel

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,

RTOS_ERR *p_err);

Table 7. Task Creation Mapping

Migration Guide: From FreeRTOS to Micrium OS

Micrium OS

silabs.com | Smart. Connected. Energy-friendly Rev. 0.1 | 10

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

FreeRTOS Micrium OS Kernel

#define MY_TASK_PRIORITY 5

#define MY_TASK_STK_SIZE 200

StaticTask_t MyTaskTCB;

StackType_t My-

TaskStk[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)

{

RTOS_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 Micrium OS Kernel must always invoke one of the services provided by Micrium OS Kernel 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().

Migration Guide: From FreeRTOS to Micrium OS

Micrium OS

silabs.com | Smart. Connected. Energy-friendly Rev. 0.1 | 11

8 Task Delays

Just like in FreeRTOS, you can delay a task with Micrium OS Kernel for a certain number of ticks. In Micrium OS Kernel 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 Micrium OS Kernel, assuming the tick rate is set at 1000 Hz (see the variable

OSCfg_TickRate_Hz):

FreeRTOS Micrium OS Kernel

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)

{

RTOS_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 (RTOS_ERR_CODE_GET(err) !=

RTOS_ERR_NONE) {

// Handle the error

}

}

}

Table 9. Task Delay – Relative

Migration Guide: From FreeRTOS to Micrium OS

Micrium OS

silabs.com | Smart. Connected. Energy-friendly Rev. 0.1 | 12

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 Micrium OS Kernel

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)

{

RTOS_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 (RTOS_ERR_CODE_GET(err) !=

RTOS_ERR_NONE) {

// Handle the error

}

}

}

Table 10. Task Delay Periodic

Migration Guide: From FreeRTOS to Micrium OS

Micrium OS

silabs.com | Smart. Connected. Energy-friendly Rev. 0.1 | 13

9 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 Micrium OS Kernel, 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 Micrium OS Kernel 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 Micrium OS Kernel

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)

{

RTOS_ERR err;

OSMutexCreate(&MyMutex,

"Mutex Name Here",

&err);

}

void MyTaskCode (void *p_arg)

{

RTOS_ERR err;

CPU_TS ts;

while (DEF_ON) {

// Acquire the mutex

OSMutexPend(&MyMutex,

0,

OS_OPT_PEND_BLOCKING,

&ts,

&err);

if (RTOS_ERR_CODE_GET(err) == RTOS_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 s 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.

Migration Guide: From FreeRTOS to Micrium OS

Micrium OS

silabs.com | Smart. Connected. Energy-friendly Rev. 0.1 | 14

10 Message Queues

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

ence between the FreeRTOS and Micrium OS Kernel message queue functionality is that in Micrium OS Kernel 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 Micrium OS Kernel

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

{

RTOS_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 (RTOS_ERR_CODE_GET(err) != RTOS_ERR_NONE) {

// Handle the error

}

// Create a Q of 128 pointers

OSQCreate(&My_UART_Q,

"Queue name here",

BUFFER_SIZE,

&err);

if (RTOS_ERR_CODE_GET(err) != RTOS_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 (RTOS_ERR_CODE_GET(err) == RTOS_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

Migration Guide: From FreeRTOS to Micrium OS

Micrium OS

silabs.com | Smart. Connected. Energy-friendly Rev. 0.1 | 15

FreeRTOS Micrium OS Kernel

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)

{

RTOS_ERR err;

char rx_data;

// 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,

(RTOS_ERR *)&err);

// Don't point to sent buffer

My_UART_RxDataPtr = NULL;

} while (UART_RX_BUFFER_COUNT);

}

Table 13. Inter-task Communication - ISRs

For more information on Message Queues in Micrium OS see the section Using Message Queues from our Kernel Programming Guide.

Migration Guide: From FreeRTOS to Micrium OS

Micrium OS

silabs.com | Smart. Connected. Energy-friendly Rev. 0.1 | 16

11 Other API Functions

Locate in your project all the rest of FreeRTOS API function calls, and replace them with their equivalent Micrium OS Kernel API function.

To help with the effort, here's a mapping of how FreeRTOS functionality maps to Micrium OS Kernel.

Some of the most popular FreeRTOS APIs are listed in the left column, and the equivalent Micrium OS Kernel 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 Micrium OS Kernel 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.

vSemaphoreDelete() OSSemDel() OSSemDel()

Migration Guide: From FreeRTOS to Micrium OS

Micrium OS

silabs.com | Smart. Connected. Energy-friendly Rev. 0.1 | 17

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

Table 14. API Mapping

Migration Guide: From FreeRTOS to Micrium OS

Micrium OS

silabs.com | Smart. Connected. Energy-friendly Rev. 0.1 | 18

12 Error Handling

The errors reported back from the FreeRTOS API are different than those from Micrium OS Kernel. In FreeRTOS you typically declare

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

With Micrium OS Kernel, each API function returns an error code concerning the outcome of the function call via a pointer to a variable

of type RTOS_ERR that is always the last argument of the API function, as shown in the following example:

FreeRTOS Micrium OS Kernel

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)

{

RTOS_ERR err;

OSMutexCreate(&MyMutex,

"Mutex Name Here",

&err);

if (RTOS_ERR_CODE_GET(err) ==

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

Migration Guide: From FreeRTOS to Micrium OS

Micrium OS

silabs.com | Smart. Connected. Energy-friendly Rev. 0.1 | 19

For a more thorough error handling, in Micrium OS Kernel, you can use the table below that lists all the possible error codes.

Micrium OS Error Codes

Error Code Description

RTOS_ERR_NONE No error.

RTOS_ERR_FAIL Generic failure for operation.

RTOS_ERR_NOT_READY Module is not ready for requested operation.

RTOS_ERR_ASSERT_DBG_FAIL Debug assertion failed.

RTOS_ERR_ASSERT_CRITICAL_FAIL Critical assertion failed.

RTOS_ERR_ASSERT_ERR_PTR_NULL Pointer to error variable to return error code is null.

RTOS_ERR_NOT_AVAIL Feature not avail (due to cfg val(s).

RTOS_ERR_NOT_SUPPORTED Feature not supported.

RTOS_ERR_INVALID_ARG Invalid argument or consequence of invalid argument.

RTOS_ERR_INVALID_CFG Invalid configuration provided.

RTOS_ERR_NULL_PTR Invalid null pointer received as argument.

RTOS_ERR_INVALID_HANDLE Invalid handle passed to function.

RTOS_ERR_INVALID_TYPE Invalid type for operation.

RTOS_ERR_INVALID_CREDENTIALS Credentials used are invalid.

RTOS_ERR_NOT_FOUND Requested item could not be found.

RTOS_ERR_ALLOC Generic allocation error.

RTOS_ERR_NO_MORE_RSRC Resource not available to perform the operation.

RTOS_ERR_INIT Initialization failed.

RTOS_ERR_NOT_INIT Module has not been initialized.

RTOS_ERR_ALREADY_INIT Module has already been initialized.

RTOS_ERR_ALREADY_EXISTS Item already exists.

RTOS_ERR_SEG_OVF Mem seg would overflow.

RTOS_ERR_POOL_FULL Mem pool full; i.e. all mem blks avail in mem pool.

RTOS_ERR_POOL_EMPTY Mem pool empty; i.e. NO mem blks avail in mem pool.

RTOS_ERR_POOL_UNLIMITED Mem pool is unlimited, cannot obtain rem nbr of blks.

RTOS_ERR_BLK_ALLOC_CALLBACK Block alloc callback failed.

RTOS_ERR_OWNERSHIP Ownership error.

RTOS_ERR_PERMISSION Operation not allowed.

RTOS_ERR_WOULD_BLOCK Non-blocking operation would block.

RTOS_ERR_WOULD_OVF Item would overflow.

RTOS_ERR_INVALID_STATE Cannot execute requested operation while in current state.

RTOS_ERR_ISR Illegal call from ISR.

RTOS_ERR_ABORT Operation aborted.

RTOS_ERR_TIMEOUT Operation timed out.

RTOS_ERR_IS_OWNER Already/still owning resource.

RTOS_ERR_NONE_WAITING No task waiting/pending for that action/event.

RTOS_ERR_IO Generic I/O err.

Migration Guide: From FreeRTOS to Micrium OS

Micrium OS

silabs.com | Smart. Connected. Energy-friendly Rev. 0.1 | 20

RTOS_ERR_IO_FATAL Generic I/O fatal err.

RTOS_ERR_TX Generic Tx err.

RTOS_ERR_RX Generic Rx err.

RTOS_ERR_RX_OVERRUN Overrun error, in Rx.

RTOS_ERR_OS_SCHED_LOCKED Operation cannot be done when the scheduler is locked.

RTOS_ERR_OS_TASK_WAITING Operation not allowed when tasks are waiting/pending on OS object.

RTOS_ERR_OS_TASK_SUSPENDED Task is still suspended.

RTOS_ERR_OS_ILLEGAL_RUN_TIME Operation not allowed after call to OSStart.

RTOS_ERR_OS_OBJ_DEL Object has been deleted during pend.

RTOS_ERR_OS Generic OS err.

RTOS_ERR_SHELL_CMD_EXEC Error when shell executed command.

RTOS_ERR_CMD_EMPTY Shell command is empty.

RTOS_ERR_TIME_INVALID Time is invalid.

RTOS_ERR_SIZE_INVALID Size is invalid.

RTOS_ERR_NAME_INVALID Name contains illegal characters.

RTOS_ERR_ECC_CORR Correctable ECC error.

RTOS_ERR_ECC_CRITICAL_CORR Critical correctable ECC error.

RTOS_ERR_ECC_UNCORR Uncorrectable ECC error.

RTOS_ERR_ENTRY_PARENT_NOT_DIR Entry parent must be a directory.

RTOS_ERR_ENTRY_ROOT_DIR Operation not allowed on root directory.

RTOS_ERR_ENTRY_MAX_DEPTH_EXCEEDED Maximum directory tree depth exceeded.

RTOS_ERR_ENTRY_OPENED Operation not allowed on opened entry.

RTOS_ERR_ENTRY_CLOSED Operation not allowed on closed entry.

RTOS_ERR_FILE_ACCESS_MODE_INVALID File access mode is invalid.

RTOS_ERR_FILE_ERR_STATE Operation cannot be performed on a file in error state.

RTOS_ERR_DIR_FULL Directory is full.

RTOS_ERR_DIR_NOT_EMPTY Directory containes files or sub-directories.

RTOS_ERR_WRK_DIR_CLOSED Working directory is closed.

RTOS_ERR_VOL_FMT_INVALID Volume format is invalid.

RTOS_ERR_VOL_CORRUPTED Volume metadata is corrupted.

RTOS_ERR_VOL_OPENED Operation not allowed on opened volume.

RTOS_ERR_VOL_CLOSED Operation not allowed on closed volume.

RTOS_ERR_VOL_FULL Volume is full.

RTOS_ERR_PARTITION_INVALID Partition is invalid.

RTOS_ERR_PARTITION_MAX_EXCEEDED Maximum partition count exceeded.

RTOS_ERR_BLK_DEV_FMT_INCOMPATIBLE Block device low-level format is incompatible with user configuration.

RTOS_ERR_BLK_DEV_FMT_INVALID Block device low-level format is invalid.

RTOS_ERR_BLK_DEV_CORRUPTED Block device metadata is corrupted.

RTOS_ERR_BLK_DEV_OPENED Block device is opened.

RTOS_ERR_BLK_DEV_CLOSED Block device is closed.

RTOS_ERR_DEV_ALLOC Device allocation failed.

Migration Guide: From FreeRTOS to Micrium OS

Micrium OS

silabs.com | Smart. Connected. Energy-friendly Rev. 0.1 | 21

RTOS_ERR_CONFIG_ALLOC Configuration allocation failed.

RTOS_ERR_IF_ALLOC Interface allocation failed.

RTOS_ERR_IF_ALT_ALLOC Interface allocation failed.

RTOS_ERR_IF_GRP_ALLOC Interface group allocation failed.

RTOS_ERR_FNCT_ALLOC No more class function in this config.

RTOS_ERR_EP_ALLOC USB core unable to allocate endpoint.

RTOS_ERR_EP_NONE_AVAIL Physical endpoint/pipe NOT available.

RTOS_ERR_URB_ALLOC USB core unable to allocate URB.

RTOS_ERR_DRV_EP_ALLOC USB driver/controller unable to allocate endpoint.

RTOS_ERR_DRV_URB_ALLOC USB driver/controller unable to allocate URB.

RTOS_ERR_CLASS_INSTANCE_ALLOC Unable to allocate class instance.

RTOS_ERR_SUBCLASS_INSTANCE_ALLOC Unable to allocate subclass instance.

RTOS_ERR_AOAP_FNCT_ALLOC Unable to allocate AOAP class function instance.

RTOS_ERR_CDC_FNCT_ALLOC Unable to allocate CDC class function instance.

RTOS_ERR_CDC_ACM_FNCT_ALLOC Unable to allocate CDC-ACM subclass function instance.

RTOS_ERR_USB2SER_FNCT_ALLOC Unable to allocate USB2Ser class function instance.

RTOS_ERR_HID_FNCT_ALLOC Unable to allocate HID class function instance.

RTOS_ERR_MSC_FNCT_ALLOC Unable to allocate MSC class function instance.

RTOS_ERR_INVALID_DEV_STATE Invalid device state.

RTOS_ERR_INVALID_CLASS_STATE Invalid class state.

RTOS_ERR_INVALID_EP_STATE Invalid endpoint state.

RTOS_ERR_DEV_HANDLE_HAS_CHANGED Handle has changed since providing it to caller.

RTOS_ERR_INVALID_DESC Desciptor content is invalid.

RTOS_ERR_OVERFLOW_DESC Desciptor's size is bigger than buffer size.

RTOS_ERR_INVALID_DEV_SPD Invalid device speed.

RTOS_ERR_DEV_CONN_DECLINED Connection for device was declined by app.

RTOS_ERR_DEV_SUSPEND Operation failed because device is suspended.

RTOS_ERR_EP_INVALID Invalid endpoint (address, type or direction).

RTOS_ERR_EP_BW_NOT_AVAIL Not enough bandwidth available to open endpoint.

RTOS_ERR_EP_QUEUING Unable to queue transfer on endpoint.

RTOS_ERR_EP_STALL Endpoint was/is stalled.

RTOS_ERR_CLASS_DRV_NOT_FOUND No class driver found.

RTOS_ERR_SUBCLASS_DRV_NOT_FOUND No subclass driver found.

RTOS_ERR_USB2SER_FLOW_CTRL_EN Operation not allowed when flow control enabled.

RTOS_ERR_NET_INVALID_ADDR_SRC Address source not found to send data.

RTOS_ERR_NET_IF_LINK_DOWN The interface link is down.

RTOS_ERR_NET_RETRY_MAX The maximum number of retry was reached.

RTOS_ERR_NET_ADDR_UNRESOLVED The stack was unable to resolved the IP address.

RTOS_ERR_NET_ICMP_ECHO_REPLY_DATA_CMP Data received in echo reply is not the same as the data sent.

RTOS_ERR_NET_NEXT_HOP The stack was unable to found a valid next hop to send the packet to.

RTOS_ERR_NET_INVALID_CONN The socket connection is invalid.

Migration Guide: From FreeRTOS to Micrium OS

Micrium OS

silabs.com | Smart. Connected. Energy-friendly Rev. 0.1 | 22

RTOS_ERR_NET_CONN_CLOSE_RX The stack received a connection closed from other half.

RTOS_ERR_NET_CONN_CLOSED_FAULT The connection was closed abruptly by other half.

RTOS_ERR_NET_OP_IN_PROGRESS The current operation is still in progress.

RTOS_ERR_NET_SOCK_CLOSED The operation cannot be done because the socket is closed.

RTOS_ERR_NET_STR_ADDR_INVALID The string address is in an invalid format.

RTOS_ERR_NET_PHY_TIMEOUT_AUTO_NEG The PHY auto-negotiation timed out.

RTOS_ERR_MQTT_MSG_FAIL Message failed to complete correctly.

RTOS_ERR_MQTTc_QoS_LEVEL_NOT_GRANTED Broker failed to grant QoS level requested.

Table 17. Micrium OS Error Codes

For more information on Error Handling in Micrium OS see our RTOS_ERR Programming Guide.