Why and How to Migrate from Bare Metal to Zephyr RTOS?

Introduction:

At BayLibre we are often asked by our customers to help them select the right software for their embedded mission. For a long time, “bare metal” (direct programming on hardware) has been the norm, mainly due to particularly limited hardware resources. However, with the increasing complexity of projects and the need to rationalize software developments, real-time operating systems (RTOS) like Zephyr are becoming essential. This is a similar situation to when people moved away from assembly to C programming.

In this article, we will explore the reasons for this migration and the steps to follow.

Why Migrate from Bare Metal to Zephyr RTOS?

Complexity Management: Modern embedded projects often involve multiple simultaneous tasks, network protocols, user interfaces, etc. An RTOS simplifies the management of these complexities through task scheduling, synchronization, and inter-process communication.

Code Reusability: Zephyr offers a Hardware Abstraction Layer (HAL) that facilitates code porting between different platforms. This significantly reduces development time and effort when changing hardware. It would be safer for product development companies to consider multi-hardware suppliers, and Zephyr could be the solution as a cross-platform OS. Today most of the well known hardware vendors provide a decent Zephyr SDK, such as STM, Nordic, NXP, … 

Community and Support: Zephyr benefits from an active community and solid support, with many examples, libraries, and tools available. This accelerates development and problem-solving. If features are missing, the Zephyr contributors are very active and will be helping with completing the features’ implementation.

Security: Zephyr integrates security features such as memory protection, task isolation, and secure updates. These features are essential for critical applications.

Compliance : Zephyr provides tools for generating a SBOM of the firmware, which is going to be legally required at some point. There is an effort to provide an IEC 61508 subset of features for functional safety requirements

Modularity: Zephyr is highly configurable and modular, allowing you to include only the necessary components. This optimizes memory footprint and power consumption. Being extremely modular, it’s even possible to use it without multi-thread support. Here is an example showing how to reduce Zephyr size down to 2-3KB (https://docs.zephyrproject.org/latest/samples/basic/minimal/README.html) of ROM.

Long Term Support: Zephyr Long Term Support (LTS) releases are published every 2 years and are branched and maintained independently of the main tree for at least 2.5 years after it was released. That is crucial for markets like IoT and industrial, which requires up to 10 years of SW support. 

Steps to migrate from Bare Metal to Zephyr RTOS:

First of all, be careful about the selection of the relevant target hardware. Check if your target hardware platform provider has already provided an upstreamed Zephyr basic support, which will significantly ease your Zephyr migration. For example, today in Zephyr community, Nordic is one of the most active actors. Many of their software releases very closely follow Zephyr’s upstreamed code and release cadence.

Then, you need to do your current project evaluation. Analyze your existing bare metal code, identify the main tasks, interrupts, shared resources, and hardware dependencies. While Zephyr is perfectly suited for MCU-based devices with connectivity (BT, WIFI…), it is “heavier” than bare metal, so it’s important to check your constraints in terms of Real-Time performance and ensure that Zephyr will be able to meet the needs.

It is important to consider a quick Zephyr training. If your R&D team is discovering Zephyr, it is strongly recommended to take a Zephyr training beforehand, to understand the philosophy of Zephyr and to be able to carry out the implementation with good practices. The link of training partners of Zephyr project is here.

Further, you could start Zephyr environment configuration. Install the Zephyr tools (SDK, Ninja, etc.) and configure your development environment.

After this, it is time for Zephyr project creation. Initialize a new Zephyr project for your target platform. Use the examples and templates provided to get started quickly.

Regarding Code Porting, it is important to perform the following steps:

  • Hardware Abstraction: Replace direct access to hardware registers with Zephyr’s HAL APIs.
  • Task Management: Transform your main loops into Zephyr tasks. Use the scheduling and synchronization APIs (mutex, semaphore, etc.).
  • Interrupt Management: Adapt your interrupt handlers to use Zephyr’s interrupt APIs.

It’s essential to structure your code using the Zephyr framework as much as possible. This will allow you to leverage the full power of the Zephyr architecture, and mainly lower drastically the maintenance of your application, making it really easy to port to newer versions of Zephyr. The pitfall to avoid would be to reinvent the software stack without respecting the Zephyr’s framework designed for. For instance, if you need to write custom drivers, we highly recommend sticking to the Zephyr driver model. This may seem an useless burden at the beginning if you plan to call your driver functions directly from your application code, like you would do for a bare-metal application. However, this becomes very handy when you need to add the power management support to your whole application, allowing Zephyr to call your custom driver power management callbacks at the correct moment and interfacing with all the power management subsystems flawlessly.

When it comes to Testing and Debugging, please use Zephyr’s debugging tools to test your application. Check task behavior, synchronization, and performance.

Once your porting is almost done, you can adjust the Zephyr configuration to optimize memory footprint, power consumption, and performance according to your needs.

Last but not least, please think about upstreaming any changes you had to do to get your platform to run, whether it was simple fixes or new mpu/peripheral/device/platform support.

Conclusion:

Migrating from bare metal to Zephyr RTOS may seem daunting at first, but the advantages in terms of complexity management, code reusability, and security are worth it. By following these steps, you can successfully make your transition and take advantage of the many features offered by Zephyr RTOS.

Keywords: 

Zephyr RTOS, bare metal, embedded, migration, embedded development, real-time operating system, IoT.