Thought Leadership

The one line RTOS

I like simple things. Excessive complexity tends to annoy me. When I first started working with computers, I thought that mainframes were overly complicated, so I was pleased to discover minicomputers, where I could really understand exactly what was going on. Embedded software was a natural progression, as, again, I could grasp the entire functionality of the software. But that began to change, as commercial real time operating systems and other software IP became more common. Everything became more complex and invisible.

I am not saying that this situation is necessarily a problem or that all complexity is intrinsically bad. It is just that sometimes I yearn for the simple life. It might be suggested that perhaps the world of software is not the best place for me, but I will ignore those murmurings and consider where simplicity might still be appropriate …

This may sound a little naive, but I have always found multi-tasking software fascinating. Whilst I am quite clear that a single CPU cannot really run two or more programs simultaneously, software that makes it look like it can is rather appealing. Way back in the early 1980s, I wrote a kernel for a project and found it very rewarding to have cracked context saving and switching and task scheduling so that it behaved in a predictable way. That code was small and simple – just a couple of K of assembly language.

Nowadays, I would mostly council against writing your own kernel, unless your needs are extremely simple and I will come on to that. If you need a preemptive multi-threading operating system for a hard real time application, it makes most sense to look at a commercial RTOS like Nucleus. If real time and limited memory footprint are not priorities and you want a lot of middleware available off the shelf, perhaps Linux or Android might fit the bill.

Maybe your needs are very simple: just a few tasks; not hard real time; each task has a modest amount of work to do every so often. You could use a commercial RTOS, but perhaps that would be overkill. All you need is a Run to Completion [RTC] scheduler. Here is the code:

#define NTASKS 3
void (*tasklist[NTASKS])() = {alpha, beta, gamma};
int taskcount;
while (1)
{
   for (taskcount=0; taskcount<NTASKS; taskcount++)
      (*tasklist[taskcount])();
}

This is very simple. The array tasklist contains pointers to three functions, alpha(), beta() and gamma(), each of which is a “task”. These are executed in turn and are obliged to complete their work and return in a timely fashion. When all three tasks have been run, the sequence is repeated.

OK, to be strict, this was not one line of code and it is not an RTOS, but it is a simple way to get basic multi-threading.

Colin Walls

I have over thirty years experience in the electronics industry, largely dedicated to embedded software. A frequent presenter at conferences and seminars and author of numerous technical articles and two books on embedded software, I am a member of the marketing team of the Mentor Graphics Embedded Systems Division, and am based in the UK. Away from work, I have a wide range of interests including photography and trying to point my two daughters in the right direction in life. Learn more about Colin, including his go-to karaoke song and the best parts of being British: http://go.mentor.com/3_acv

More from this author

Comments

0 thoughts about “The one line RTOS
  • Colin,

    Absolutely, complexity kills. And the approach above is so much more maintainable than a huge “superloop” sprinkled with flag-checking (and watchdog kicks) throughout.

    For basic multi-tasking needs, the approach you described is perfectly adequate.

    About 4 years ago, there was an article @ embedded.com by Miro Samek & Robert Ward describing their “Super Simple Tasker” (SST), which they describe as “a prioritized, fully preemptive, deterministic real-time kernel, which we call Super Simple Tasker (SST), with only a few dozen lines of portable C code”.

    The article is located at: http://www.eetimes.com/design/other/4025691/Build-a-Super-Simple-Tasker

    I believe the SST is at the heart of Miro Samek’s Quantum Kernel (QK) which is part of the Quantum Platform framework.

    The SST is a little more intricate than the loop above (due to the support of preemption), but not by much. Still significantly less complicated than the scheduler at the heart of an RTOS.

    With the Run to Completion (RTC) “constraint”, which is natural for state machines, things become much simpler & intuitive. Fewer context switch triggers, single stack, etc.

    There is also an interesting discussion (via user comments) at the end of the article. As with this blog, the comments are always interesting to read.

  • So I don’t need Nucleus after all? What mad marketing ploy is this!? 😉

    Would it be over complicating things to make the task list a structure with a “period” member, so that each task function could optionally be invoked *periodically* rather than *every time*? Marginal added complexity in the loop I suggest, while potentially relieving tasks from performing their own internal timing (with the resulting duplication of code and maintenance overhead).

  • This is similar to a scheduler in Michael Pont’s “patterns for time triggered systems”

    typedef struct
    {
    void (* pTask)();
    unsigned int Delay;
    unsigned int Period;
    unsigned char RunMe;
    } sTask;

    The ISR iterates through the array of task blocks and runs the task when the time period expires. I’ve used this on Rabbit, AVR and even ported it to an Apple Mac. I had to use “setitimer” to generate the interrupt in Unix.

  • While I fully endorse the principle of less complexity (KISS = Keep It Simple but Smart), Einstein also said that things should be as simple as possible but never too simple!
    I am rather amazed/shocked that after all these years we still have articles and comments at this level. Progress has clearly been very poor compared with 20-30 years ago. I have nothing against the use of such simple statemachines but don’t calls this an RTOS because it is not. Next, you can only use such simple code for simple, not safety critical applications. If for whatever reason the code gets stuck or executes too long in one of these pseudo tasks, the whole system hangs.
    At Altreonic we have also shown using formal techniques that an RTOS doesn’t need to be complex and can be small, even when distributed, so it fits in 5 Kbytes (32bit target). Still it has all the support one expects from an RTOS plus time-out support, priority inheritance etc. Is that complex? No, because the semantics are clean and the behaviour is predictable, it actually simplifies the development of more complex applications. Without a good RTOS, developing such applications might even be close to impossible.

    • I agree with your comments entirely Eric. I even said at the end that it was not an RTOS.

      There is one thing that embedded systems all have in common: they are all different. So, such a simple approach would be fine for a simple application, but inappropriate for something else.

  • Ok, with over 35+ years of professional software experience I can see what you are getting at, but let’s not confuse a simple task list process loop with an RTOS. The one does not come anywhere near the other. There is little new in RTOSes except newer languages that versions of the older RTOSes can be rewritten into. RTOS complexity varies with the complexity of the functions you want the RTOS to perform. One of the very neat things about the mini computer RTOSes of the past, DEC’s PDP 11 RSX-11M is an example, is that you could tailor the RTOS to do exactly the functions you wanted it to do by the way you did your system build. I long for the days when we could control 1500+ channels with a Kernel around 24k words in size instead of the monsters things have devolved into now a days!!

  • I think this is just another version of the one-line replacement for a switch statement, as published in Michael Barr’s Programming Embedded Systems: With C and GNU Development Tools, 2nd Edition.

    • Mike B:
      In this trivial case, I agree your code would be better because it is easier to read/understand. The generated code would probably be identical or nearly so. However, any increase in sophistication is likely to be easier to apply using the array of pointers. For example, there may be a parallel array which contains task status – running or suspended.

  • Hi Mr. Walls,
    I d like to know if your book will be avaible soon. I am trying to study RTOS and your book seems to be a good start. unfortunatly your book is not available anywhere.

    • I am sorry David, but that book never got finished. It may get done one day, but, for the moment, the project is on hold. Please email me if you would like recommendations on possible reading matter or if you have any specific queries.

Leave a Reply

This article first appeared on the Siemens Digital Industries Software blog at https://blogs.stage.sw.siemens.com/embedded-software/2010/09/06/the-one-line-rtos/