|Last modified on Sat Sep 30 20:31:20 2017 UTC.||Improve this page|
My interest in system programming dates from the first moments when I started to play with computers. After learning FORTRAN in my first college year, I wondered how does the big computer compile my programs and how is it able to run multiple jobs at the same time. However, my first hands-on experience with multitasking code was in the late 80s, when I ported the Version 7 Unix system to the Motorola MC68000 microprocessor. Soon after this I designed and implemented a simple scheduler running on Zilog Z80, that was successfully used in a commercial product. Another significant step towards the embedded world was in the late 90s, when I ported eCos to run on Intel i960.
There were many embedded operating systems available by the time this project was initiated. However, the context I planned to use this embedded OS was slightly more specific, i.e. aviation instruments. I started to experiment with aviation instruments some years before, and one determining factor on the decision was an article stating that for the design of an aviation instrument, a framework is acceptable if it allows to complete the design within one day. Although this seems rather extreme, the idea is quite valid, and has important consequences.
The first consequence is that it promotes modular design, i.e. instead of do-it-all box (a kind of a Swiss army knife like design), it is better to split the design into multiple independent modules, each performing a specific job.
The second consequence is that the framework should be very well structured, easily configurable and as light as possible, in order to run with limited resources on simple processors. By well structured I mean modular, object oriented design, favouring a high degree of code reuse, both between related projects, and between different hardware platforms.
After a long and detailed search, there were many partial solutions identified, but none was able to address all the requirements; so, based on my previous experience with multitasking systems, the decision to develop an in-house solution came naturally.
The decision for C++ was a tough one, and I’m convinced it raises a lot of questions and critics. However, I’m also convinced it was a good decision, and those who take the time to seriously consider it will probably reach the same conclusion.
First of all, by C++ I do not mean the full C++ implementation, but a limited subset: no exceptions, no real time typing, possibly no multiple inheritance; more or less a kind of Embedded C++, i.e. a more structured way of writing C. Writing object oriented code is perfectly possible in C too, but the syntax is significantly more complex. One common argument against C++ is the assumed performance penalty, but most of those who claim this have no compiler expertise, since for the subset of C++ that is needed for embedded applications the performance gain for C vs C++ is null for regular classes, and almost null for classes that require polymorphism.
Finally, the contributing factor on making the decision to use C++ came after reading Michael Barr’s book, Programming Embedded Systems in C and C++, that came with some good code samples written in C++.
The original µOS++ implementation was done in 2007, and although initially it was intended to run on Atmel AVR8 processors, the design was modular and portable from the very beginning.
Central to the µOS++ design was the scheduler and the low-level synchronisation primitives. Based on my previous Unix experience, the main synchronisation primitives were inspired by the original Unix
wakeup() primitives. However, the names, and slightly the functionality, were also influenced by the Java Threads implementation of
notify(), and so the current names of
eventNotify() were born.
In 2009 the µOS++ was easily ported to ARM Cortex M3, during an evaluation phase for the next generation of the aviation instruments.
A more difficult and complex port of µOS++ was the Atmel AVR32 port, done in 2011. The difficulty was inherent to the hardware design of the AVR32 architecture, way less software-friendly than the ARM Cortex M3 (my personal feeling is that the ARM Cortex M3 design team was leaded by a software guy, with good knowledge of operating system intricacies, while the AVR32 architecture seems to be designed by a team where access for software guys was strictly forbidden).
But not everything was bad with the AVR32 experience: since this architecture uses 4 nested interrupts levels, now the µOS++ is able to properly handle nested interrupts.
Another significant addition to µOS++ was a mechanism to handle very fast interrupts, required for some Real Time applications.
The need for second edition of µOS++ become obvious while using it for several commercial projects, but active work started in early 2013, after the XCDL (eXtended Components Definition Language) project become functional.
Starting from scratch, the first version of a unit testing infrastructure was implemented on the OS X synthetic platform.
The µOS++ SE (second edition) project wiki was created, initially hosted in the SourceForge project web space, then moved to the livius.net domain due to major SourceForge shortcomings.
In April 2013 the general framework with functional initialisation code for STM32F1 and STM32F4 was implemented and tested on several development boards.
The project grew steadily, with the scheduler running on STM32Fx cores (in pre-emptive mode), and on synthetic POSIX platforms (OS X and GNU/Linux, in cooperative mode). The sources compiled without warnings on GCC 4.7, GCC 4.8 and LLVM clang 3.2/3.3, in 32/64-bit variants, and a multitude of tests were running on OS X and Ubuntu.
The repository increased steadily, and in October 2013 it numbered more than 700 files, with more than 150K lines.
Acknowledging the need for a better Eclipse integration, in Oct. 2013 the development was temporarily interrupted, with focus changed to GNU ARM Eclipse plug-ins.
The need for the third edition of µOS++ become evident after the experience with GNU ARM Eclipse plug-ins and the obvious need to integrate µOS++ with Eclipse.
After experimenting with several implementations of the GpioPort & Pin, it was concluded that best readability for accessing the hardware registers is offered by using the CMSIS large device header; the second choice was offered by using RegisterAccess policies, with the advantage of compile time checks for read/write violations, but with loss of readability.
In mid 2014 the documentation for the ARM CMSIS packages was studied and some tests were performed with the Keil tools and an experimental package manager was implemented as an Eclipse plug-in; something derived from the CMSIS packages might become the preferred distribution mechanism.
A more C-friendly approach was adopted.
Further research concluded that CMSIS Packs alone are not enough, and a more elaborate solution is necessary; inspired from yotta, in late 2015 the xPacks format was tested and adopted.
In December 2015 the project was migrated to GitHub and restructured as xPacks, stored as separate sub-projects.
In Jan 2016, the CMSIS++ repository was created, with a double intent: to act as a proposal for the next generation CMSIS, due in June 2016, and to serve as a portable API for the third edition of µOS++.
Unfortunately experience with CMSIS RTOS, Drivers and other components was disappointing, and further support for it was no longer considered appropriate.
In mid 2017 support for RISC-V was added and, for more portability, the use of the CMSIS name, associated with ARM, was discontinued.
In June 20, 2016 the reference implementation was complete, with two functional ports, one for Cortex-M and one for a synthetic POSIX platform.
The µOS++ RTOS API was tagged as v0.2.1.