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...
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:
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.
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:
Many advanced software components must depend on the implementation of the lower-level operating system. For example:
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 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.
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:
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.
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.
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.
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.
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.