OS Abstration Layer
Introduction
TinyCTS
µC/OS-III
FreeRTOS
FreeRTOS differences
Test task statistic with blinky
New FreeRTOS statistic
Test performance with iperf / lwIP
Download
 

Introduction

In the past I have worked with different OS systems. The problem here was always that they had different APIs, or e.g. a different meaning for the priorities of a task. So there are OS systems where a low priority number means a high priority and vice versa. Since I didn't always want to change the calls in my application with another OS, there is the OSAL for this.

In addition to TinyCTS, the OSAL also supports µC/OS-III and FreeRTOS.

Using 2 examples, Blinky and lwIP, I show how to use the OSAL here. Blinky is more used here to illustrate what needs to be changed in a TinyCTS application, and lwIP to measure the difference in performance.

When I developed TinyCTS, the OSAL was already taken into account. That's why OSAL has the same API as TinyCTS. This also makes it easier when you switch an existing TinyCTS application to µC/OS-III or FreeRTOS.

The priorities of the task are set up in such a way that a smaller number has a higher task priority than a larger number.

SEGGER Embedded Studio v7.30 was used as the compiler.

TinyCTS

With an existing TinyCTS application, two changes must be made in "main.c" and in the "StartTask".

In "main.c", "tal_init" is replaced by "osal_Init":

And in "StartTask" "osal_InitPost" must be added:

In the "Preprocessor Definitions" "RTOS_TCTS" is used for TinyCTS:

And the "Process Stack Size" must be set not to 0:

Furthermore, it must be ensured that a task which can be terminated calls "OS_TaskExit" as the last function:

µC/OS-III

The changes with "osal_Init" and "osal_InitPost" are also required here as with TinyCTS. In the "Preprocessor Definitions", "RTOS_UCOS3" is now required instead of "RTOS_TCTS". And the "Process Stack Size" must be set to 0:

FreeRTOS

Same as µC/OS-III but here "RTOS_FREERTOS" is needed at the "Preprocessor Definitions".

FreeRTOS differences

Compared to TinyCTS and µC/OS-III, the default FreeRTOS has a slightly different behavior in the task statistics. With TinyCTS and µC/OS-III, the task utilization is displayed directly. This means that the display has a high value even if the load is correspondingly high. When the utilization is over again, the value is directly low again.

But if you now do an iperf test with FreeRTOS, for example, the value of the task utilization increases slowly and is still at a high value after the test. It takes a while for the value to normalize again.

The difference is that with TinyCTS and µC/OS-III the internal values for the measurement are calculated by a statistic task and will be set to 0 every 500ms. As a result, there is a direct display of the utilization. With FreeRTOS, the values are not reset again, so accumulated values are used here.

I had also tried to reset the internal values in FreeRTOS after the statistics output. But this was not working here.

Test task statistic with blinky

For testing the task statistic there exist two tasks, P10 and P50. P10 consume 10 and P50 consume 50 percent of utilization. The corresponding tasks can be stopped and started with "1" (P10) and "5" (P50):

Here P10 and P50 are running, and consume 60 percent of utilization. The task statistics are working in case of TinyCTS and µC/OS-III, but unfortunately not correct with FreeRTOS. In the case of FreeRTOS, it only works if the tasks, here P10 and P50, are running from the beginning. If the tasks are stopped and restarted a little later, incorrect values are calculated. This is due to the fact that the ratio of the runtime of the individual tasks to the complete runtime of the system is always used here.

It works for TinyCTS and µC/OS-III because a separate statistics task with a period of 500 milliseconds is used here.

New FreeRTOS statistic

In order to solve the problem with the statistics, the same procedure was implemented here as with TinyCTS and µC/OS-III. An additional statistics task was used for this, which recalculates the values every 500 milliseconds.

But there is still a small problem here. If FreeRTOS is operated in preemtive mode, the calculation of the percentage utilization is correct. But in cooperative mode the values are 17% too small.

How was this 17% determined?

The P10 and P50 task is used to control the utilization. The values here were correspondingly 17% too small.

Test performance with iperf / lwIP

For the test here I used an iMX RT1062 Developer's Kit from Embedded Artists. And for the compiler SEGGER Embedded Studio for ARM v7.30 was used.

For the later performance test, iperf v2.1.9 was used in the terminal on a Mac. The computer and the evaluation board are connected to each other via a 1GBit switch.

The application was compiled each time in "SDRAM Release" mode and then loaded into the target's SDRAM with JTAG and started.

Inside the terminal of the Mac iperf was started with: iperf -c 192.168.1.200 -P 1

The cpu load of the target can be checked in the terminal of the target by pressing "c".

With TinyCTS, µC/OS-III and FreeRTOS a bandwidth of 94.9 Mbits/sec could be achieved. But the CPU load of the target was very different:

  • 38% TinyCTS     (cooperative)
  • 59% µC/OS-III    (preemtive)
  • 67% FreeRTOS  (cooperative, 76% with 17% added)
  • 13% FreeRTOS  (preemtive, only 55.9 Mbits/sec)

At the moment I have no idea why the performance in case of preemtive mode with FreeRTOS is lower than in cooperative mode.

And it always surprises me that TinyCTS has the best performance here. I hope that this is not an error in the calculation of the statistic in TinyCTS.

Download

osal-blinky-ea1062_20230806 example for a Cortex-M7 board (9.01 MB)

osal-lwip-ea1062_20230806 example for a Cortex-M7 board (11.4 MB)