Arduino Real Time

January 14, 2014

I was interested in NilRTOS since it is quite small and the installation was simple.

Many tasks that you handle with a small microcontroller don’t require an operating system. However, as the definition of “small” keeps getting bigger, it is getting more tempting to do projects where you can benefit from some help with things like multitasking and concurrency management. Besides, as small gets bigger, you also get more processing power that you can afford a little overhead to make life easier.

Look at the Arduino, just as an example. The old ATmega 8 chip had 8K words of flash and 1K of RAM. The newer versions of Arduino often use an ATmega328, which has 32K of flash and 2K of RAM. However, last time I checked, the price of an ATmega328 was actually less than an ATmega8. So if I wanted an ATmega8, I could save money by buying the larger chip and I could use 1K of RAM and 24K of flash for my operating system before I would impact what I wanted to use anyway.

I looked at this once before when I was writing LWOS, which could target several different small processors. However, there are several other Arduino-friendly RTOS choices.

A project on Google Code covers several choices including NilRTOS, ChibiOS/RT, and a FreeRTOS port. There is also the duinos port of FreeRTOS. I also found RTuinOS and I’m sure there are plenty more out there.

All of these take some setup. For example, RTuinOS uses make and has some restrictions on where you can install it. I was interested in NilRTOS since it is quite small and the installation was as simple as copying three library directories over to your Arduino libraries.

Once I did the copy, it was easy to open a few examples, including the obligatory LED blinker with two threads (one turns the LED on and the other turns it off). The download includes an HTML file with documentation. Since it is such a simple system, there isn’t much to learn.

Here’s a semaphore define:


// Declare a semaphore with an inital counter value of zero.
SEMAPHORE_DECL(sem, 0);

Here’s the code to set a semaphore:

   nilSemSignal(&sem);

And, of course, to test a semaphore:

  nilSemWait(&sem);

You do need to set up an initial stack for each thread:

NIL_WORKING_AREA(waThread1, 128);

The thread functions are declared via a macro and there is a static thread table (very similar to lwos). The examples cover using serial I/O, I2C, analog, and more. For a low overhead system, it seems pretty robust.

Are you using an operating system for small projects or just programming to the metal? If you aren’t, how long do you think you can hold out?