Dr. Dobb's is part of the Informa Tech Division of Informa PLC

This site is operated by a business or businesses owned by Informa PLC and all copyright resides with them. Informa PLC's registered office is 5 Howick Place, London SW1P 1WG. Registered in England and Wales. Number 8860726.

Channels ▼

Embedded Systems


Walter is a graduate student of mathematics at the University at Albany. He can be reached at [email protected] or found attending the monthly Connecticut Robotics Society meetings.

DOORS OS is an embedded operating system designed to run on the HC11 8-bit microcontroller. While DOORS OS requires at least 2KB of program memory and 512 bytes of storage memory (for the program's stack, variables, and so on), the more memory you have, the better off you are. I'm currently using the DOORS OS with 32KB of external RAM, which provides plenty of room for programs to expand into.

The source code, SDK, and related files for the DOORS OS are available online from Dr. Dobb's (see www.ddj.com/code/) and at www.geocities.com/waltsrobots/ doors.html. In addition to the SDK, you might also want to download the SmallC++ compiler for the HC11. The DOORS OS SDK contains several source files that let you use this compiler to create programs for the OS; for example, you can create a multitasking program using the command fork(). SmallC++ isn't required for writing DOORS OS applications, but it does make it a bit easier.

About Multitasking

A single HC11 processor is incapable of actually executing two or more programs at the same exact time. It can only run one instruction before moving on to the next. So how do you create a multitasker for this environment?

What the OS does is start running one program which, after a certain amount of time (a "timeslice"), expires. You can then start running another program. When its timeslice expires, the OS switches to the next program, then the next, until eventually the first program is again run from where it left off. The key to this is that the timeslice is so very small—approximately 4.1ms for DOORS OS—that it actually appears to be running all those programs at the same exact time, when it's really only running one and then another and so on.

So that's how this "multitasking" OS works, but how do you implement it on an HC11? The answer is in the "real-time interrupt," which triggers about every 4.1ms. When it fires, the current state of the HC11 is saved (register values, program counter, and the like) and a subroutine within the DOORS OS runs, which then switches execution to the next process in the list.

Switching Processes

The interrupt handler runs every 4.1ms, telling the OS it's time to stop running the current process and start/resume running the next. How do you know where in memory you left off? How do we know what to set the internal registers to before jumping back to the process? Luckily, most of this work is already taken care of for us by the HC11.

When the interrupt triggers, the current state of the processor is automatically pushed onto the stack. This means that the contents of every register and the program counter (telling us where we left off) now exists on the current process's stack (each process has its own stack) right before we jump to the interrupt handler (see Listing One). Following this interrupt, a simple RTI ("Return from Interrupt") command restores all the needed information and resumes running the original process. Of course, using such a command only returns you to the previously running process, while you really want to execute a different one.

 .          * Data pushed onto stack by process' normal operation
 .          * This can include return address, variables, etc.
PC       * two bytes specifying exact point in memory that we left off
REGISTER_Y  * the next three registers take up 2 bytes each
CCR         * the Condition-Code-Register takes 1 byte
       * total of 9 bytes placed on stack after interrupt is triggered
Listing One

To switch to another process, you need to first save the current stack pointer (an internal register that "points" to the current stack position in memory), then change it so that it points to the next processes' stack. This means that for every new process you run, that process must have its own unique independent stack space in storage memory which is reserved for a process when it first starts. This also means that the OS needs to keep track of all of these stack positions in an array. You can see the definition of this array in kernel.asm in the DOORS OS SDK (see stackSave) or in Listing Two, which is a C equivalent to the assembler definition.

    void* stackPointer  // a pointer to this process' stack 
                       // position (2 bytes on an HC11)
    byte  used;        // if '1' then this entry in the array contains                     
                // a valid process; if '0', then isn't currently used
    byte  processID;    // holds this process' unique ID
STACK_DATA stackSave[NUM_PROCESS]; // declare an array NUM_PROCESS elements 
                          // long to hold info on all used processes
Listing Two

In short, whenever the real-time interrupt triggers, DOORS OS first saves the current stack pointer, in this array stackSave. It then searches through this array until it finds a used process slot (an element within this array that holds information on a valid, currently used process). Once found, it loads the stack pointer with the value saved within the array. Once this completes, the OS issues an RTI command causing the HC11 to load the register and PC values from this process's stack (Listing One) and resumes execution as if nothing had interrupted.

Because each process's stack is kept isolated and the register values are saved and restored correctly, every process you run would execute just as if you weren't using the multitasking OS (the only difference being that the more processes you run, the slower they'll run).

User Interface

There's more to the DOORS OS than just multitasking. In fact, one of my original design goals for this system was that it be capable of running on its own and would manage such things as running user programs when requested and even downloading those programs into memory. However, to accomplish such tasks, you need a UI.

This UI accepts commands from the user's terminal editor via the PC's serial port. The command shell (actually a separate process) continually waits for a command to come in over the HC11's serial port; when one is received, it runs the correct action. For example, if the ASCII character r is sent to the HC11, the OS begins running the user's program. Likewise, if a d is received, the OS knows that a program is being sent over and that it should be stored in memory. Additionally, an s tells the OS to terminate all running processes and reset. Since this command shell is a separate process and is always running (even when a user program is running), you can quickly shutdown and reset your system with just a single command.

The source code for the UI is in kernel.asm under the label commandShell. You can modify this code to suit your own needs. For example, if you need to add some new commands, this is the place to do it. Or alternatively, if you want to use a different I/O device such as a keypad and LCD display, you just need to alter this small subroutine.

In addition to the DOORS UI, you need some sort of interface running on your PC that lets you communicate with the OS. Technically, the minimum interface you need is a terminal editor since most of the communication between user and OS is via the serial port. Of course, if you just use a basic terminal editor, you'll be unable to access the "download program" feature. With this in mind, I wrote a simple C# application that gives you access to all features. The complete source code for this application (see Figure 1) is included in the SDK.

Figure 1: DOORS OS in action.

Related Reading

More Insights

Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.