Channels ▼

Al Williams

Dr. Dobb's Bloggers

Shakedown Cruise

November 26, 2012

In the U.S. Navy, a plank owner is a member of a ship's original crew. Historically, the first voyage of a vessel is its shakedown cruise, where you learn what needs fixing before the ship goes into service. These initial cruises are often unremarkable, although the USS Triton won the Presidential Unit Citation for its 1960 shakedown cruise. Of course, the plank holder captain, Captain Beach, circumnavigated the globe underwater, so it was the exception that proves the rule.

The last few weeks I've been shaking down lwos, my lightweight operating system targeted for small computers. I showed a simple example running under Linux (which hardly needs lwos, but makes testing simpler). I decided it was time to really shake down lwos on some actual embedded hardware.

I have a reputation as being anti Arduino, but that's not entirely true. It is true that I find some aspects of them annoying, and I often dump the IDE and program them directly like I would a regular AVR processor (here is one good reference for that). However, they are ubiquitous and I have enjoyed the inexpensive hardware and accessories the Arduino mania has brought.

So — surprise — I decided to do a simple Arduino project with lwos. I had been wanting to figure out how to mix "normal" code with the Arduino "sketches" anyway, so I figured this would be a good chance to get it all working.

Like any shakedown cruise, I found a few rough spots to smooth out. Some of them were specific to the Arduino, but others were just things that didn't hold up under the stress of a real project.

For the hardware I used an Arduino Duemilanove board. This is a conventional Arduino based on an ATMega 328 that has a USB connection instead of a serial port. I also picked up an inexpensive LCD daughterboard (I just can't bring myself to say shield). These are fairly common and sport a 2x16 LCD with wiring for a 4-bit interface. There is also an array of switches in an up/down/left/right/select pattern. Oddly, the switches aren't directly wired to the processor. Instead, they select different resistor values in a voltage divider and the Arduino reads different values on analog channel 0 depending on which button is held down.

Despite the Triton's voyage, most shakedown cruises aren't anything too exciting. For the shakedown project I decided to make a binary clock. Actually, binary is a bit of a misnomer. I have one on my desk already — a commercial product with LEDs that shows the time in BCD format. There are four groups of LEDs: one for 10s of hours, one for hours, one for 10s of minutes, and one for minutes. This is easier to read at a glance than straight binary.

Of course, this clock has an LCD (see figure below or watch this). The operation is simple: The top line shows the BCD time as 1s and 0s (it would be easy enough to use asterisks for lit LEDs and a space or an O for a dark LED, though). The bottom line shows a moving star to indicate the clock is active. If you use the up and down buttons, the clock's backlight gets brighter or dimmer. You can press the left button and the bottom line will turn to an H. Now the up and down buttons adjust the hours (from 0 to 23). Pressing the right button allows you to adjust the minutes (and the status line shows an M). To go back to the normal mode, press select.

You might argue that you don't really need an operating system — lightweight or otherwise — to write this program. You'd be right, of course. But you can set up the program as a series of tasks and that's the purpose of a shakedown cruise.

If you recall, lwos has a task table that defines the tasks that will execute. Here's the task table for the binary clock project:

  // The task table (priority order)
  TASK_TABLE
  TASK_DEF(TASK_READY,secminutes)
  TASK_DEF(TASK_READY,hour)
  TASK_DEF(TASK_READY,timing)
  TASK_DEF(TASK_READY,disp)
  TASK_DEF(TASK_READY,ui)
  TASK_TABLE_END   

The tasks, in order, do the following functions:

  1. Update seconds and minutes
  2. Update hours
  3. Update the task_tick variable
  4. Updates the display
  5. Handles the user button inputs

The Arudino has a handy library for driving the LCD and I quickly wrote a small module for reading the switches. Armed with these, the task functions (and a few helper subroutines) were quick to write. You can find the entire program online, but here's the secminutes task, for example:

  int secminutes(Task *tcb)
  {
    ss++;
    if (ss>59) {
      mm++;
      ss=0;
    }
    task_sleep(10);
  }

The user task that handles time uses the Arduino's millis function. The timing is one place that the shakedown project uncovered a possible flaw in the original design. The original code set the wake up time as an absolute task_tick value. So if the current tick value was, say, 100 and the program did a task_sleep(10) call, the scheduler would wake it up at tick 110 or later.

The issue is that when the task_tick counter might overflow things can get confusing. It is true that a signed compare could work since overflows work out. However, that doesn't completely solve the problem. Suppose a task sleeps at tick value 0x7FF0 for 5 ticks. However, the computer is busy at tick value 0x7FF5 and instead attempts to reschedule the sleeping task much later. Since the tick counter will now be negative, it will be a very long time before the sleeping task wakes up.

There are several solutions to this problem, but I picked one that I've used before. Each task stores the number of ticks it wants to wait and each tick decreases that count. When a waiting task reaches zero, it is eligible to start again. Not only did this require a small time to the scheduler, but it also required a change in how the user task that sets the task_tick variable works. In the old scheme, the program could directly manipulate the task_tick variable. With this technique, the program has to call a function to update the count. This allows the scheduler to update each task's wait status.

That change was because using the timer feature in a real program didn't work out quite like I had planned. The other changes I had to make were to work around the peculiarities of the Arduino. I'll talk more about those changes next time.

If you want to see the code (or try it for yourself) you can download it here. I have been keeping the core code on Google code but the Arduino branch is not there yet (although it could be by the time you read this). I'll have more to say about the Arduino-specific lessons learned doing the port next time.

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.
 


Video