Next Previous Contents

7. Real time OS

Using a real-time OS on ARM architecture has many benefits. The architecture supports stack switching without any complications and major overhead and almost every chip provides timer and other functions needed for preemptive multi-tasking.

There are many commercial RTOSes as well as many open-source. I will here describe three most important (from my point of view):

7.1 ucLinux

ucLinux is probably the best choice if your device has plenty of flash and RAM memory. Almost all ARM7TDMI microcontrollers have too low on-chip memory to suit ucLinux's needs. In order to get ucLinux working on them you have to choose micro with external memory bus and attach a huge flash and SRAM.

If you are developing a small application without need for ucLinux or any "high-level" OS, just forget it. There are many simple task switchers that will meet 99% applications needs, have less overhead and require only a few kilobytes of memory.

7.2 FreeRTOS

FreeRTOS is a real-time operating system for embedded devices, being ported to several microcontrollers, including ARM architecture. It is distributed under a modified version of the GPL. The modification permits the users proprietary code to remain closed source, while maintaining the kernel itself as open source - facilitating the use of FreeRTOS in commercial applications.

FreeRTOS can be downloaded for free, without having to fill out a form or provide any information.

For more information see FreeRTOS homepage at http://www.freeRTOS.org/.

7.3 OSEK/VDX

OSEK, an acronym for Offene Systeme und deren Schnittstellen f�r die Elektronik in Kraftfahrzeugen (eng., "Open Systems and their interfaces for the Electronics in Motor vehicles"). It is a standards body that has produced specifications for an embedded operating system, a communications stack, and a network management protocol for automotive embedded systems. It has also produced other related specifications.

OSEK have been founded in 1993 by a german automotive companies consortium (BMW, Bosch, DaimlerChrysler, Opel, Siemens, et Volkswagen Group) and the University of Karlsruhe. In 1994, the french cars manufacturers Renault and PSA Peugeot Citroen which had a similar project called VDX (Vehicle Distributed eXecutive), joined the consortium.

At the moment there is no known open-source OSEK implementation, but there are many commercial.

7.4 Your own taskswitcher

Writing your own simple task switcher is not as complicated as you might think. First of all you have to make a structure that will hold all task state information. Here is an example:


struct taskstruct
{
  unsigned int registers[16];
  unsigned int cpsr;

  void *stack;
  int stacksize;

  int eventmask;
  int events;

  int priority;
  int state;                    /* Running, Ready, Waiting, Suspended */

  /* Next and previous task in the queue */
  struct taskstruct *qnext, *qprev;
};

The following code will store and restore context when interrupt is invoked:



irq_routine_rtos:
        subs lr,lr,#4
        stmfd sp!, {lr}
        stmfd sp!,{r0}
        mrs r0,cpsr
        orr r0, r0, #(I_Bit|F_Bit)
        msr cpsr_c,r0
        ldmfd sp!,{r0}

        @@@@@@@@@@@@ Save user context ...
        ldr lr,=CurrentContext
        ldr lr,[lr]
        bne irq_savecontext
        ldmfd sp!, {r0}
        b irq_nosavecontext

irq_savecontext:
        stmia lr,{r0-r14}^
        add lr, lr,#60
        ldmfd sp!, {r0}                 // original PC
        stmia lr!,{r0}
        mrs r0,spsr
        str r0, [lr, #0]

irq_nosavecontext:
        ldr lr,=restoreirq

#define AIC_Base_Addr 0xFFFFF000
#define AIC_IVR_Off_Addr 0x100
#define AIC_EOICR_Off_Addr 0x130

        LDR r0,=(AIC_Base_Addr+AIC_IVR_Off_Addr)
        LDR r1,[r0]
        LDR r0,=irq_vectors
        ldr pc,[r0,r1]

restoreirq:
        ldr r0,=(AIC_Base_Addr+AIC_EOICR_Off_Addr)
        STR r0, [r0]

restore_task_state:
        ldr lr,=CurrentContext
        ldr lr,[lr]
        ldr r0, [lr, #64]
        msr spsr, r0

        ldmia lr,{r0-r14}^              /* restore all regs... */
        nop
        nop
        nop
        ldr lr,[lr, #60]
        subs pc, lr, #0

The next thing to do is to enable microcontroller timer to run periodically and switch the context from timer interrupt. Add few more supporting functions to handle taskswitcher data and you are (almost) done!


Next Previous Contents