ARTK

ARTK is a priority-based, pre-emptive, multitasking kernel, for the Arduino. I have released it under GPL. The most recent version is posted below.

Note that with ARTK it is a Setup() function that you define, not setup(), and you do not create a loop() function. Multitasking begins as soon as Setup() returns. Multitasking ends when all tasks have completed, or when any task calls ARTK_TerminateMultitasking(). Please note that for any Arduino IDE later than 1.0.3, you cannot use malloc (or any other dynamic allocation) outside of the ARTK Setup() function. It also means that your tasks and semaphores (and message queues, etc) should be created in Setup(). This is because assumptions made in the location of the heap relative to the stack pointer were changed after Arduino 1.0.3 in a way that is not compatible with ARTK.

It is sometimes the case that a task needs to wait on more than one event. This can be accomplished by having that task process messages from an associated message queue. An EVENTQ library is posted below along with example code for the following Buhr-Bailey task interaction diagram. The library allows both tasks and interrupt service routines to generate event messages into a queue. In the diagram, one task is shown as a rhombus, another periodic task as a rhombus with a clock, a periodic interrupt service routine as a triangle with a clock, function calls into the serial monitor library as directed lines with full arrowheads, and event messages as directed lines with half arrowheads. The periodic task is implemented using the ARTK_Sleep function, and the periodic ISR is implemented using a hardware timer. This example uses the MsTimer2 library (available at the Arduino Playground) to setup the periodic ISR. Note that the Timer1 library should not be used with ARTK because ARTK uses Timer 1 to implement ARTK_Sleep and semaphore timeouts.

Mutexes are currently implemented in ARTK as semaphores initialized to 1. Because it does not (currently) offer a more sophisticated mutex, ARTK cannot offer priority inheritance. It does, however, have a fairly small footprint, and implementing 3 tasks is quite reasonable on an Uno. You should probably use the F macro on any literal strings in order to conserve RAM.

If you are running on a Mega, or some other Arduino with an address space larger than 16-bits (65536 bytes of flash memory), you must call ARTK_SetOptions() with a 1 in the first argument from inside Setup().

The default stack space for each task is 256 bytes, but you can change that when you create the task (or you can modify the default by changing the #define in ARTK.h).

Note also that ARTK provides a Printf() function that is compatible with the F macro (which maps literal strings to flash memory, which is highly encouraged in order to conserve RAM). Format specifiers for floating point (e.g. %g and %f) work fine on the Uno but are broken on the Mega due to a problem with the compiler library. So if you're running on the Mega use f2s() along with the %s format specifier.

Interrupts run in the context of the task they interrupt, and are not required to notify the kernel upon entrance or exit. If they signal a semaphore they must be re-entrant after that point, because the signal may well cause an immediate task switch. Thus any static state in the ISR must be modified prior to signaling a semaphore. The latency of a task switch on a 16MHz Uno is roughly 70 usec.

A reference for ARTK functions and examples are posted below, and functionality for the latest version can always be found in the ARTK.h file. Although it predates the current release, you can read more about ARTK in the following article (please cite this article if you publish work that makes use of ARTK).

P. H. Schimpf, “ARTK, a Compact Real-Time Kernel for Arduino,” International Journal of Embedded Systems (IJES), Vol. 5, No. 1, pp. 106-113, 2013.