Why a bare-metal developer moved to operating systems

Article By : Zhu Tianlong

I can still remember the excitement when my first cycling lamp program ran successfully. However, the more bare-metal programs I wrote, the more issues I met...

Looking back at the ‘Bare-Metal Age’

The first time I knew about the embedded software was about 2008, I was a sophomore and started to learn about programming on a 51 chip. Since I majored in computer science, most of my programs were executed on PC. That was a completely different experience to see programs running on a bare-metal board, and I can still remember the excitement when my first cycling lamp program ran successfully. However, the more bare-metal programs I wrote, the more issues I met. I summarize them as follows:

Concurrency

For bare-metal programs, there is inevitably a huge ‘while (1)’ loop, which contains almost all the transaction logic of the whole project. Each transaction invokes one or more delay functions and they are executed serially when the CPU is running a delay function, the rest of the transactions have to wait. In this way, much of the CPU time is wasted on empty loops, which causes a pretty low concurrency.

Modularity

From the perspective of the software project, the principle of high cohesion and low coupling is always emphasized during the development process. However, modules in a bare-metal software usually depend on each other heavily, it is not convenient to design software with low coupling, which makes it difficult to develop large projects on bare-metal boards. For example:

  • As mentioned above, most functions are collected in a huge ‘while (1)’ loop and hard to divide into modules.
  • As another example, developers must be careful to use delay functions when the watchdog timer is involved. If the delay time is too long, the main function doesn’t have the opportunity to reset the watchdog, then the watchdog will be triggered during execution. So, for bare-metal development, there are too many things to consider even when invoking a delay function. The more complex the project is, the more care needs to be taken.

Ecosystem

Many advanced software components must depend on the implementation of the lower-level operating system. For example:

  • I have developed an open-source project based on ‘FreeModbus’ that I had planned to transplant to various platforms, even the bare-metal boards were considered. But compared to the convenience of adapting it to different operating systems, some functions are too complex to implement on all bare-metal boards. On the other hand, many implementations must be designed from scratch on different hardware platforms because of the lack of commonality, which is a boring and time-consuming task. For now, my implementation of Modbus stack is still not able to run on bare-metal boards.
  • Many WiFi software development kits (SDKs) provided by big companies such as Realteck, TI, and MediaTek can only be run on the operating system. They don’t publish the source code of firmware for the user to modify, so you cannot use them within the bare-metal environment.

Real-time

Real-time capability is necessary for some application fields. In this situation, some critical steps of the software must be triggered at a specific time. For industry control, the mechanical devices must complete actions in a pre-determined order and timing. If the real-time capability cannot be assured, it will cause malfunctions, which may endanger the lives of workers. On bare-metal platforms, when all the functions are jammed into one big ‘while (1)’ loop, it is impossible to maintain the real-time capabilities.

Reusability

Reusability depends on the modularity directly. I believe no one would like to do the same job again and again, especially when writing code. But on various hardware platforms with different chips, the same function has to be adapted to different hardware, whose implementations depend heavily on the low-level hardware. It’s inevitable to rebuild wheels.

The advantage of operating systems

It was about 2010 when I first used the operating system. The series of STM32 MCUs were starting to be popular. With powerful features, many people ran operating systems on them. I was then using the RT-Thread operating system for which there are many available, ready-to-use components. Compared to other operating systems, I feel more comfortable and have been developing on it for 10 years.

Based on my understanding, I’d like to discuss the advantages of operating systems:

Modularity

With the operating system, the entire software could be split into several tasks (known as threads), each thread has its own independent execution space. They are independent of each other, which improves the modularity.

Concurrency

When a thread invokes the delay function, it will automatically yield the CPU to other threads in need, which improves the utilization of the entire CPU and ultimately the concurrency.

Real-time

An RTOS is designed with real-time capabilities. Each thread is assigned a specified priority. More important threads are set to a higher priority, less important threads are set to lower ones. In this way, the real-time performance of the entire software is guaranteed.

Development Efficiency

The operating system provides a unified layer of abstract interfaces, which facilitates the accumulation of reusable components and improves development efficiency.

The operating system is a product of the wisdom of a group of software geeks. Many common software functions, such as semaphore, event notification, mailbox, ring buffer, one-way chain list / two-way list, and so on, are encapsulated and abstracted to make these functions ready to use.

Operating systems such as Linux and RT-Thread implement a standard set of hardware interfaces for fragmented hardware, known as the device-driver framework. Therefore, software engineers only need to focus on development and no longer need to concern themselves about the underlying hardware, or to rebuild wheels.

Software Ecosystem

The richness of the ecosystem brings the process of quantitative changes to qualitative ones.

The improvement of modularity and reusability with operating systems allow us to encapsulate operating system-based, embedded-friendly reusable components, which not only can be used in our projects but also can be shared with more embedded developers in need—maximizing the value of the software.

I am an open-source geek and I’ve open-sourced some embedded software on GitHub. Before creating open-source software, I rarely talked with others about my projects because I considered that because people are using different chips or hardware platforms, my code could hardly run on their hardware. With operating systems, software reusability is greatly improved, many experts can communicate with each other about the same project. They are even from different countries. This is encouraging more and more people to share and to talk about their projects.

— Zhu Tianlong has over 10 years of RTOS programming experience and is committed to researching and developing cutting-edge technology.

Leave a comment