To investigate the use of software synthesis technology, the authors set out to use the SynthOS software synthesis tool to generate an embedded real-time operating system (RTOS).
Implementing the system
It is perhaps a testimony to the value of SynthOS that the student doing the actual development, Matt Hill, was able to successfully complete the project and then make performance measurements on the completed embedded system. Generally speaking, porting an OS to a new platform would not be the first project that you give to a newly-minted engineering graduate.
Matt was relatively new to the embedded system world and so he had to fit a semester course in embedded systems into a few weeks. With little-to-no knowledge of embedded systems, many basic things had to be learned before work on the project could begin. For example, the project had several aspects that required the use of a timer including displaying information on the LED display and taking measurements from an A/D converter. Timers must be initialized correctly and consideration has to be given in the code for the possibility that multiple timers will trigger simultaneously.
Different processors handle interrupt service routines (ISRs) in different ways. Something we didn't initially realize is that the ColdFire processor requires that during an ISR, the interrupt must be acknowledged and other interrupts must be masked. Not properly handling interrupts in the ISRs caused errors which manifested themselves during the integration and synthesis phase of the project. This caused confusion when testing and debugging because this problem manifests itself in different ways that seem random or appear to be a hardware problem.
Once Matt mastered enough of the arcane arts that the grizzled embedded veterans know only too well, he had to turn his attention to actually using SynthOS and integrating it with the ColdFire platform to create an embedded OS. Matt discovered that an annoying shortcoming of the product is the set of vague error messages when SynthOS failed. For example, one particularly frequent error message was, 'java.lang.RuntimeException: Assertion failed.' A more meaningful error message could have said, 'Loop tasks must have a return value of void.' Matt recorded these usability issues and sent them to Bob for correcting in future revisions of the product. As an aside, this is a particularly good example of industrial/academic cooperation where both sides come out with a win.
Another issue that we believe needs to be addressed in SynthOS is that during synthesis, all comments are stripped from the generated code. Obviously, this makes debugging more difficult, making the final synthesized code harder to read.
What happened?
The specifications for this project outlined that the different types of tasks that were to be executed by the RTOS created by SynthOS had to be written, tested, and debugged individually before integration and synthesis. Once all tasks worked individually, they were to be integrated as much as possible before synthesis and without an RTOS. After as much integration testing as possible, SynthOS 'primitives' (see Table 1) must be added and all the code was to be synthesized and tested as a whole. This process of creation, testing, integration, testing, synthesis, and more testing is to find and eliminate errors as soon as they are introduced. If tasks are integrated before they are tested individually, it can be very hard to locate an error. It is also very important to test before synthesis because synthesis can introduce new errors and compound existing errors.

Table 1. SynthOS Primitives.
Once tasks were created and tested, we only had to insert these simple primitives and then create a very simple configuration file. We did not need to focus on the details of the RTOS such as the scheduling algorithms and semaphores/mutexes. The tasks we created were functions written in C (some were written in assembly language with C wrappers), designed for the operating system to call them. They generally performed a single task and then exited the function. Tasks can be anything from functions with low-level code that interact with hardware to complex functions with higher-level code. Tasks can also interact with other tasks and the operating system using the SynthOS primitives. There are several types of tasks: Initialization tasks, Loop tasks, and Call tasks. Fig 2 provides a simplified illustration as to how each type of task fits into the system.

2. Tasks in SynthOS.
Init tasks are called by the RTOS once at startup to initialize the hardware and software components of the system. Once initialization has finished, the task scheduler assumes control and continuously executes Loop tasks based on the scheduling algorithm selected in the SynthOS Project Configuration (SOP) File. Loop tasks can do many things including using SynthOS primitives to call Call tasks.
As their name might suggest, Call tasks are only executed when they are called by another task using a SynthOS primitive. Call tasks can do many things, often interacting with the hardware of the system. ISRs will generally use a non-blocking primitive to call a Call task to do the work of the ISR to minimize the time that interrupts are masked. A non-blocking call means that the Call task will be executed whenever the scheduler decides; if the Call task is given a sufficiently high priority, the task can potentially be executed right away. Inside tasks, SynthOS primitives can be used to interact with the RTOS and other tasks. When the code is synthesized, SynthOS primitives are replaced with a fair amount of code, usually related to the scheduler or TCB (task control block). Table 1 summarizes the various SynthOS primitives.
There are some limitations regarding the use of the primitives including where they can be placed and how they should be used. Blocking primitives can only be placed in the highest level of a task and cannot be placed in a function or subroutine that is called from a task. One of the repercussions of this is that recursion is not allowed. Another limitation regarding primitives is that the scheduler is not preemptive. A developer can potentially write tasks that monopolize CPU time. In order to have a responsive system, it is sometimes necessary to put in SynthOS_sleep() calls throughout long blocks of code so other tasks can be scheduled.
Once SynthOS primitives are inserted into tasks, all that is left to do is create the SOP (SynthOS Project configuration) file. The SOP file is a simple text file with a .SOP extension used to allow the developer to customize the RTOS that will be synthesized. In this file, every source code file is listed, every task is listed, and some important options are included. Table 2 lists some of the options that can be specified in the SOP file.

Table 2. SOP file options.