Testing [Andrew L] mbos RTOS for mbed Simply by copying code for main.cpp from mbos.h-comments

Dependencies:   mbed

Files at this revision

API Documentation at this revision

Comitter:
chalikias
Date:
Thu May 05 07:34:12 2011 +0000
Commit message:

Changed in this revision

main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
mbos.cpp Show annotated file Show diff for this revision Revisions of this file
mbos.h Show annotated file Show diff for this revision Revisions of this file
mbos_asm.s Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r a61d29450691 main.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Thu May 05 07:34:12 2011 +0000
@@ -0,0 +1,86 @@
+ // 2011.05.05 NX
+ // This a test of [Andrew L] mbos
+ // main.c copied from  mbos.h comments
+ // ** A 3d task added **
+ 
+ 
+ //* A typical simple example with two tasks, and one timer, might look like this:
+ //* @code
+ // mbos Blinky demonstration.
+ // Task 1 toggles LED1 every second, under control of a timer. It then posts an event to
+ // task 2 which flashed LED2 briefly.
+  #include "mbed.h"                    
+  #include "mbos.h"
+ 
+  #define TASK1_ID                1       // Id for task 1 (idle task is 0)
+  #define TASK1_PRIO              50      // priority for task 1
+  #define TASK1_STACK_SZ          32      // stack size for task 1 in words 
+  
+  #define TASK2_ID                2       // Id for task 2 
+  #define TASK2_PRIO              60      // priority for task 2
+  #define TASK2_STACK_SZ          32      // stack size for task 2 in words 
+  
+  #define TASK3_ID                3       // Id for task 3 
+  #define TASK3_PRIO              70      // priority for task 3
+  #define TASK3_STACK_SZ          32      // stack size for task 2 in words 
+  
+  #define TIMER0_ID               0       // Id for timer 0
+  #define TIMER0_PERIOD           1000    // Time period in milliseconds
+  #define TIMER0_EVENT            1       // Event flag (1 << 0)
+  
+  #define T1_TO_T2_EVENT          2       // Event flag (1 << 1)
+  #define T2_TO_T3_EVENT          2       // Event flag (1 << 1)
+ 
+  void task1(void);                       // task function prototypes
+  void task2(void);
+  void task3(void);
+
+  DigitalOut led1(LED1);
+  DigitalOut led2(LED2);
+  DigitalOut led3(LED3);
+  mbos os(3, 1);                          // Instantiate mbos with 3 tasks & 1 timer    
+ 
+  int main(void)
+  {
+      // Configure tasks and timers
+      os.CreateTask(TASK1_ID, TASK1_PRIO, TASK1_STACK_SZ, task1);
+      os.CreateTask(TASK2_ID, TASK2_PRIO, TASK2_STACK_SZ, task2);
+      
+      os.CreateTask(TASK3_ID, TASK3_PRIO, TASK3_STACK_SZ, task3);
+      
+      os.CreateTimer(TIMER0_ID, TIMER0_EVENT, TASK1_ID);
+      // Start mbos
+      os.Start();
+      // never  return!
+  }
+ 
+  void task1(void)
+  {
+      os.SetTimer(TIMER0_ID, TIMER0_PERIOD, TIMER0_PERIOD);
+      while(1){
+          os.WaitEvent(TIMER0_EVENT);
+          led1 = !led1;
+          os.SetEvent(T1_TO_T2_EVENT, TASK2_ID);
+      }
+  }
+ 
+  void task2(void)
+  {
+      while(1){
+          os.WaitEvent(T1_TO_T2_EVENT);
+          led2 = 1;
+          wait_ms(100);
+          led2 = 0;
+          os.SetEvent(T2_TO_T3_EVENT, TASK3_ID);
+      }
+  }
+
+  void task3(void)
+  {
+      while(1){
+          os.WaitEvent(T2_TO_T3_EVENT);
+          led3 = 1;
+          wait_ms(100);
+          led3 = 0;
+      }
+  }
diff -r 000000000000 -r a61d29450691 mbed.bld
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Thu May 05 07:34:12 2011 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/e2ac27c8e93e
diff -r 000000000000 -r a61d29450691 mbos.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbos.cpp	Thu May 05 07:34:12 2011 +0000
@@ -0,0 +1,347 @@
+/***********************************************************************************
+ *  m b o s   R T O S   F O R    m b e d  (ARM CORTEX M3) 
+ *
+ * Copyright (c) 2010 - 2011 Andrew Levido
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED 
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "mbos.h" 
+#include "mbed.h"
+
+#define MAX_PRIO                    99                  // maximum priority
+#define READY                       MAX_PRIO + 1        // always > MAX_PRIO
+#define WAITING                     0                   // aways 0
+#define DEFAULT_IDLE_STACK_SZ       32                  // in words
+#define MAX_TASKS                   99                  // tasks 0.. 99 including idle
+#define MAX_TIMERS                  99                  // timers 0..99
+#define MAX_RESOURCES               99                  // resources 0..99
+#define MIN_STACKSZ                 32                  // enough to run an empty function
+#define TICKS_PER_SECOND            1000                // 1ms Ticks
+
+typedef struct _tcb{                                    // task control block  
+    uint id;                               
+    uint *stack;
+    uint priostate;
+    uint eventlist;
+    uint eventmask;
+    uint *stacklimit;
+}_tcb_t;
+
+typedef struct _timer{                                  // timer cotrol block
+    uint timer;
+    uint reload;
+    uint event;
+    uint task;
+}_timer_t;    
+
+typedef struct _rcb{                                    // resource control block
+    uint lock;
+    uint priority;
+    uint taskprio;
+}_resource_t;    
+
+extern "C" void _startos(void);                         // Assembly routine to start the scheduler
+extern "C" void _swap(void);                            // Assembly routine to set PendSV exception
+extern "C" void SysTick_Handler(void);                  // Override weak declaration in startup file
+extern "C" void _stackerror(uint task);                 // Stack error function called by assembler
+
+extern void __attribute__((__weak__)) mbosIdleTask(void); // Allow user to write their own idle task
+
+// Static Variables
+uint _hardstacklimit;                                   // stack limit
+_tcb_t **_tasklist;                                     // pointer to task list
+_tcb_t *_tasks;                                         // pointer to task control block 0        
+_timer_t *_timers;                                      // pointer to timer control block 0
+_resource_t *_resources;                                // pointer to resource control block 0
+uint _numtasks;                                         // number of tasks (including idle)
+uint _numtimers;                                        // number of timers
+uint _numresources;                                     // number of resources
+uint _tasklistsize;                                     // task list length in bytes
+
+// Default Idle Task -------------------------------------------------------------------
+void _idletask(void) { while(1); }                      // Default idle task
+
+// Constructor  -------------------------------------------------------------------------
+mbos::mbos(uint ntasks, uint ntimers, uint nresources)
+{
+    uint i;
+    
+    ntasks += 1;
+    // Create the tcblist, zero initialised
+    if(ntasks > MAX_TASKS || ntasks < 1) error("mbos::mbos - %i is an invalid number of tasks\n", ntasks);
+    _tasklist = (_tcb_t**)calloc(sizeof(_tcb_t*), ntasks);
+    if(_tasklist == 0) error("mbos::mbos - Insufficient memory to create Tasklist\n");
+    
+    // Create the tcbs
+    _tasklist[0] = (_tcb_t*)calloc(sizeof(_tcb_t), ntasks);
+    if(_tasklist[0] == 0) error("mbos::mbos - Insufficient memory to create TCBs\n");
+    for(i = 1; i < ntasks; i++){
+        _tasklist[i] = _tasklist[i - 1]    + 1;
+    }
+    // Create the timers and clear them      
+    if(ntimers > MAX_TIMERS + 1) error("mbos::mbos - %i is an invalid number of Timers\n", ntimers);    
+    _timers = (_timer_t*)calloc(sizeof(_timer_t), ntimers);
+    if(_timers == 0) error("mbos::mbos - Insufficient memory to create Timers");
+
+    // create the resources & clear them
+    if(nresources > MAX_RESOURCES + 1) error("mbos::mbos - %i is an invalid number of Resources\n", nresources); 
+    _resources = (_resource_t*)calloc(sizeof(_resource_t), nresources);
+    if(_resources  == 0) error("mbos::mbos - Insufficient memory to create Resources");
+    _hardstacklimit = (uint)malloc(1);
+    if(_hardstacklimit == 0) error("mbos::mbos - Insufficient memory to create HardStackLimit");
+    _numtasks = ntasks;
+    _numtimers = ntimers;
+    _numresources = nresources;
+    _tasks =  _tasklist[0];
+}
+// Create Tasks Function  --------------------------------------------------------------
+void mbos::CreateTask(uint id, uint priority, uint stacksz, void (*fun)(void))
+{
+    uint* stackbase;
+
+    // check bounds 
+    if(id >= _numtasks || id < 1) error("mbos::CreateTask - %i is an invalid task id\n", id); 
+    if(priority > MAX_PRIO) error("mbos::CreateTask - %i is an invalid priority for Task %i\n", priority, id);
+    if(stacksz < MIN_STACKSZ) stacksz = MIN_STACKSZ;
+        
+    // fill tcb 
+    if(_tasks[id].id == 0) _tasks[id].id = id;
+    else error("mbos::CreateTask - Task %i already created\n", id); 
+    _tasks[id].priostate = READY + priority;
+    _tasks[id].eventlist = 0;
+    _tasks[id].eventmask = 0;
+    stackbase = (uint*)malloc(stacksz * 4);
+    if(stackbase == 0) error("mbos::CreateTask - Insufficient memory to create Task %i\n", id);
+    _tasks[id].stacklimit = stackbase;
+    _tasks[id].stack = _initstack(stackbase + stacksz, fun);
+}
+// Start OS function  -------------------------------------------------------------------
+void mbos::Start(uint stacksize)
+{
+    uint * stackbase;
+
+    // Fill idle tcb and initialise idle stack 
+    _tasks[0].priostate = READY;
+    _tasks[0].id = 0;
+    _tasks[0].eventlist = 0;
+    _tasks[0].eventmask = 0;
+    if(mbosIdleTask){
+        if(stacksize < MIN_STACKSZ) stacksize = MIN_STACKSZ;
+        stackbase = (uint*)malloc(stacksize * 4);
+        if(stackbase == 0) error("mbos::Start - Insufficient memory to create idle task\n");    
+        _tasks[0].stacklimit = stackbase;
+        _tasks[0].stack = _initstack(stackbase + stacksize, mbosIdleTask);
+    }
+    else {
+        stackbase = (uint*)malloc(DEFAULT_IDLE_STACK_SZ * 4);
+        if(stackbase == 0) error("mbos::Start - Insufficient memory to create idle task\n");
+        _tasks[0].stacklimit = stackbase;
+        _tasks[0].stack = _initstack(stackbase + DEFAULT_IDLE_STACK_SZ, _idletask);
+    }        
+    _tasklistsize = 4 * (_numtasks - 1);
+    SysTick_Config(SystemCoreClock / TICKS_PER_SECOND);
+    NVIC_SetPriority(SysTick_IRQn, 0);
+    _startos();
+    
+    while(1);                            
+}
+// OS Tick Function   -------------------------------------------------------------------
+void SysTick_Handler(void)
+{
+    uint i;
+    
+    __disable_irq();
+    
+    for(i = 0; i < _numtimers; i++){
+        if(_timers[i].timer){
+            _timers[i].timer--;    
+            if(_timers[i].timer == 0){
+                _timers[i].timer = _timers[i].reload;    
+                if(_tasks[_timers[i].task].eventmask & _timers[i].event){
+                    _tasks[_timers[i].task].eventlist |= _timers[i].event;
+                    _tasks[_timers[i].task].priostate += READY;
+                }     
+            }
+        }
+    } 
+    if((__return_address() & 0x08) == 0) {            // called from Handler, so swap later
+    __enable_irq();
+    return;
+    }
+    _swap();
+    __enable_irq();
+}
+// Get Task id Function -----------------------------------------------------------------
+uint mbos::GetTask(void)
+{ 
+    return _tasklist[0]->id; 
+}
+// Set Priority Function ----------------------------------------------------------------
+void mbos::SetPriority(uint priority) 
+{  
+    if(_tasklist[0]->id == 0) return;
+    if(priority > MAX_PRIO) error("mbos::SetPriority - %i is an invalid priority\n", priority);
+    _tasklist[0]->priostate = priority + READY;
+}
+// Get Priority Function ----------------------------------------------------------------
+uint mbos::GetPriority(void) 
+{ 
+    return _tasklist[0]->priostate - READY; 
+}
+// Wait Event Function  ------------------------------------------------------------------
+void mbos::WaitEvent(uint event)
+{   
+    if(_tasklist[0]->id == 0) return;
+    if(event == 0) return;
+    __disable_irq();
+    _tasklist[0]->eventlist = 0;
+    _tasklist[0]->eventmask = event;
+    _tasklist[0]->priostate -= READY;
+    _swap();
+    __enable_irq();
+}
+// Set Event Function --------------------------------------------------------------------
+void mbos::SetEvent(uint event, uint task)
+{    
+    // check bounds
+    if(task >= _numtasks || (task < 1)) return; 
+
+    __disable_irq();
+    if(_tasks[task].eventmask & event){            
+        _tasks[task].eventlist |= event;
+        _tasks[task].priostate += READY;
+    }
+    else{
+        __enable_irq();
+        return;
+    } 
+    _swap();
+    __enable_irq();
+}         
+// Get event Function   -----------------------------------------------------------------
+uint mbos::GetEvent(void)
+{
+    return _tasklist[0]->eventlist;
+}
+// Create Timer Function  --------------------------------------------------------------
+void mbos::CreateTimer(uint id, uint task, uint event)
+{
+    // check bounds 
+    if(id >= _numtimers) error("mbos::CreateTimer - %i is an invalid timer id\n", id); 
+    if(task < 1|| task >= _numtasks) error("mbos::CreateTimer - %i is an invalid task id for Timer %i\n", task, id); 
+    if(event == 0) error("mbos::CreateTimer - Can't use null event for Timer %i\n", id); 
+  
+    // fill tcb 
+    _timers[id].timer = 0;
+    _timers[id].reload = 0;
+    _timers[id].task = task;
+    _timers[id].event = event;
+}
+// Set Timer Function  -------------------------------------------------------------------
+void mbos::SetTimer(uint id, uint time, uint reload)
+{
+    // check bounds
+    if(id >= _numtimers) error("mbos::SetTimer - %i is an invalid timer id\n", id); 
+   
+    __disable_irq();
+    _timers[id].timer = time;
+    _timers[id].reload = reload;
+    __enable_irq();
+} 
+// Redirect Timer Function -----------------------------------------------------------------
+void mbos::RedirectTimer(uint id, uint task, uint event)
+{
+    // check bounds 
+    if(id >= _numtimers) error("mbos::RedirectTimer - %i is an invalid timer id\n", id); 
+    if(task < 1|| task >= _numtasks) error("mbos::RedirectTimer - %i is an invalid task id for Timer %i\n", task, id); 
+    if(event == 0) error("mbos::RedirectTimer - Can't use null event for Timer %i\n", id); 
+    
+    __disable_irq();
+    if( _timers[id].timer == 0){
+        _timers[id].task = task;
+        _timers[id].event = event;
+    }
+    __enable_irq();
+}
+// Clear Timer Function  -------------------------------------------------------------------
+void mbos::ClearTimer(uint id)
+{
+    // check bounds
+    if(id >= _numtimers) error("mbos::ClearTimer - %i is an invalid timer id\n", id); 
+    
+    __disable_irq();
+    _timers[id].timer = 0;
+    _timers[id].reload = 0;
+    __enable_irq();
+}    
+// Create resources Function  --------------------------------------------------------------
+void mbos::CreateResource(uint id, uint priority)
+{
+    // check bounds 
+    if(id >= _numresources) error("mbos::CreateResource - %i is an invalid resource id\n", id);  
+    if(priority > MAX_PRIO) error("mbos::CreateResource - %i is an invalid priority for Resource %i\n", priority, id);
+  
+    // fill rcb 
+       _resources[id].priority = priority;
+       _resources[id].lock = 0;
+}
+// Lock Resource Function  --------------------------------------------------------------
+uint mbos::LockResource(uint id)
+{
+    // check bounds
+    if(id >= _numresources) error("mbos::LockResource - %i is an invalid resource id\n", id);
+    if(_tasklist[0]->id == 0 ||_resources[id].lock != 0) return _resources[id].lock;
+    
+    __disable_irq();
+    _resources[id].lock = _tasklist[0]->id;
+    _resources[id].taskprio = _tasklist[0]->priostate;
+    _tasklist[0]->priostate = _resources[id].priority + READY;
+    __enable_irq();
+    return 0;
+}
+// Test Resource Function  --------------------------------------------------------------
+uint mbos::TestResource(uint id)
+{
+    // check bounds
+    if(id >= _numresources) error("mbos::TestResource - %i is an invalid resource id\n", id);
+    return(_resources[id].lock);
+}
+// Free Resource Function  --------------------------------------------------------------
+uint mbos::FreeResource(uint id)
+{
+    // check bounds
+    if(id >= _numresources) error("mbos::FreeResource - %i is an invalid resource id\n", id);
+    if(_tasklist[0]->id == 0 || _tasklist[0]->id != _resources[id].lock) return _resources[id].lock;
+    
+    __disable_irq();
+    _resources[id].lock = 0;
+    _tasklist[0]->priostate = _resources[id].taskprio;
+    __enable_irq();
+    return 0;
+}
+// Initialise stack function  -----------------------------------------------------------
+uint* mbos::_initstack(uint *stack, void (*fun)())
+{
+    stack -= 3;                                // leave a spare word
+    *stack = 0x01000000;                        // Initial xPSR    (reset value)
+    stack--;
+    *stack = (uint)fun - 1;                    // Start address of the task corrected
+    stack--;
+    *stack = 0;                                // LR
+    stack -= 5;                                // R12, R3, R2, R1, R0 
+    stack -= 8;                                // R11, R10, R9, R8, R7, R6, R5, R4
+    return stack;    
+} 
+// Stack Error function  ----------------------------------------------------------------
+void _stackerror(uint task)
+{
+    error("Stack Overflow on Task %i\n", task);
+}
diff -r 000000000000 -r a61d29450691 mbos.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbos.h	Thu May 05 07:34:12 2011 +0000
@@ -0,0 +1,251 @@
+/***********************************************************************************
+ *  m b o s   R T O S   F O R    m b e d  (ARM CORTEX M3)
+ *
+ * Copyright (c) 2010 - 2011 Andrew Levido
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef MBOS_H
+#define MBOS_H
+
+typedef unsigned int uint;
+
+/**A pre-emptive, mutlitasking real-time operating system for mbed applications.
+ *
+ * Allows the user to write their application in the form of independant tasks.
+ * The operating system manages a completely separate processor context for each
+ * task (processor registers and stack) and swaps between the tasks according to a
+ * simple scheduling algorithm.
+ *
+ * Tasks are allocated a priority, and the scheduler ensures that the task
+ * that with the highest priority that is not waiting for an event, has control of
+ * the processor. If more than one task shares the highest priority, they will be
+ * run sequentially in round-robin fashion.
+ *
+ * Each task may wait for one or more of up to 32 different events, each represented by
+ * one bit in the event flags word. Events may be posted by another task, by a mbos
+ * timer, or in response to some asynchronous event such as an peripheral interrupt.
+ *
+ * mbos implements the SysTick timer to generate a System Tick every millisecond.
+ * Scheduling occurs once every Tick, or whenever a task blocks or an event is posted.
+ * The user may create one-shot or continuous timers to post events to tasks.
+ *
+ * mbos implements a simple ceiling protocol resource locking mechanism To manage access
+ * to system resources. Tasks may take exclusive ownership of resources for a period.
+ *
+ * A typical simple example with two tasks, and one timer, might look like this:
+ * @code
+ * // mbos Blinky demonstration.
+ * // Task 1 toggles LED1 every second, under control of a timer. It then posts an event to
+ * // task 2 which flashed LED2 briefly.
+ * #include "mbed.h"                    
+ * #include "mbos.h"
+ *
+ * #define TASK1_ID                1       // Id for task 1 (idle task is 0)
+ * #define TASK1_PRIO              50      // priority for task 1
+ * #define TASK1_STACK_SZ          32      // stack size for task 1 in words 
+ * #define TASK2_ID                2       // Id for task 2 
+ * #define TASK2_PRIO              60      // priority for task 2
+ * #define TASK2_STACK_SZ          32      // stack size for task 2 in words 
+ * #define TIMER0_ID               0       // Id for timer 0
+ * #define TIMER0_PERIOD           1000    // Time period in milliseconds
+ * #define TIMER0_EVENT            1       // Event flag (1 << 0)
+ * #define T1_TO_T2_EVENT          2       // Event flag (1 << 1)
+ *
+ * void task1(void);                       // task function prototypes
+ * void task2(void);
+ *
+ * DigitalOut led1(LED1);
+ * DigitalOut led2(LED2);
+ * mbos os(2, 1);                          // Instantiate mbos with 2 tasks & 1 timer    
+ *
+ * int main(void)
+ * {
+ *     // Configure tasks and timers
+ *     os.CreateTask(TASK1_ID, TASK1_PRIO, TASK1_STACK_SZ, task1);
+ *     os.CreateTask(TASK2_ID, TASK2_PRIO, TASK2_STACK_SZ, task2);
+ *     os.CreateTimer(TIMER0_ID, TIMER0_EVENT, TASK1_ID);
+ *     // Start mbos
+ *     os.Start();
+ *     // never  return!
+ * }
+ *
+ * void task1(void)
+ * {
+ *     os.SetTimer(TIMER0_ID, TIMER0_PERIOD, TIMER0_PERIOD);
+ *     while(1){
+ *         os.WaitEvent(TIMER0_EVENT);
+ *         led1 = !led1;
+ *         os.SetEvent(T1_TO_T2_EVENT, TASK2_ID);
+ *     }
+ * }
+ *
+ * void task2(void)
+ * {
+ *     while(1){
+ *         os.WaitEvent(T1_TO_T2_EVENT);
+ *         led2 = 1;
+ *         wait_ms(100);
+ *         led2 = 0;
+ *     }
+ * }
+ * @endcode
+ */
+
+class mbos {
+public:
+    /** Create an mbos object. Instantiate mbos and define the number of tasks, timers 
+     * and resources. 
+     *
+     * @param ntasks The number of user tasks (1 .. 99). 
+     * @param ntimers Optional number of timers (0 ..  100).
+     * @param nresources Optional number of resources (0 .. 100).
+     */
+    mbos(uint ntasks, uint ntimers = 0, uint nresources = 0);
+
+    /** Start mbos. Optionally specify the size of the stack for a user-written idle task. 
+     * All tasks, timers and resources must be created before calling Start. 
+     *
+     * @param idlestacksize Size in words (>= 32) of the user-written idle task if present. 
+     * @returns Never returns
+     */
+    void Start(uint idlestacksize = 32);
+
+    /** Create an mbos task. Allocates and initialises data structures for the task.
+     *
+     * @param taskid Unique ID for the task. (1 .. ntasks).
+     * @param priority Priority (0 .. 99) of the task. Tasks may share the same priority.
+     * @param stacksize Size in words (>= 32) of the task's stack.
+     * @param fun Pointer to the task function. Function must be of type static void, 
+     * and must return nothing.
+     */
+    void CreateTask(uint taskid, uint priority, uint stacksz, void (*fun)(void));
+
+    /** Get the ID of the current task.
+     *
+     * @returns The ID (0 .. 99) of the calling task.
+     */
+    uint GetTask(void);
+
+    /** Set the priority of the current task.  Does nothing if called from the idle task.
+     *
+     * @param priority Priority (0 .. 99) to apply to the calling task.
+     */
+    void SetPriority(uint priority);
+
+    /** Get the priority of the current task.
+     *
+     * @returns The priority (0 .. 99) of the calling task.
+     */
+    uint GetPriority(void);
+
+    /** Wait for an event or events. Causes the current task to block, waiting for the 
+     * specified event. Does nothing if called from the idle task, or if the event is NULL.
+     *
+     * @param event Event flag(s) to wait for.
+     */
+    void WaitEvent(uint event);
+
+    /** Post an event or events to a task.
+     * Posts the nominated event(s) to the specified task. Forces a context switch if the events
+     * are posted successfully. Does nothing if the task is not waiting, or is not waiting for 
+     * the posted event.
+     *
+     * @param event Event flag(s) to post. 
+     * @param task The ID of the task to which to post the event(s). May not be idle task.
+     */
+    void SetEvent(uint event, uint task);
+
+    /** Returns the event flag(s) which last caused the task to unblock.
+     *
+     * @returns The event flags.
+     */
+    uint GetEvent(void);
+
+    /** Create a mbos timer. Allocates and initialises the data structures for the timer.
+     *
+     * @param timerid Unique ID for the timer (0 .. ntimers - 1). 
+     * @param taskid The ID of the task to which the timer will post events. May not be 
+     * the idle task.
+     * @param event The event flag(s) that the timer should post on timeout. May not be NULL.
+     */
+    void CreateTimer(uint timerid, uint taskid, uint event);
+
+    /** Starts an mbos timer. If the reload time is zero or omitted, the timer will be reset 
+     * once it has posted a single event, after time milliseconds. If the reload time is
+     * non-zero, this value will be loaded into the timer on time-out, and the timer will 
+     * continue indefinitely. In this case the interval to the first event will be time, 
+     * and the interval between subsequent events will be reloadtime.
+     *
+     * @param timerid The ID of the timer. 
+     * @param time The period in milliseconds before the timer times out.
+     * @param reload The optional time to reload into the timer when it times out.
+     */
+    void SetTimer(uint timerid, uint time, uint reload = 0);
+    
+    /** Redirects an mbos timer. Changes the task and event associated with a timer. If the timer
+     * is running, the fun ction has no effect.
+     *
+     * @param timerid The ID of the timer.
+     * @param taskid The ID of the task to which the timer will post events. May not be 
+     * the idle task.
+     * @param event The event flag(s) that the timer should post on timeout. May not be NULL.
+     */
+     void RedirectTimer(uint timerid, uint taskid, uint event); 
+
+    /** Stops and clears an mbos timer.
+     *
+     * @param timerid The ID of the timer to clear. 
+     */
+    void ClearTimer(uint timerid);
+
+    /** Creates an mbos resource. Allocates and initialises the data structures for the Resource.
+     *
+     * @param resourceid Unique ID for the resource (0 .. nresource).
+     * @param priority Priority of the resource (normally > than that of any task using the 
+     * resource).
+     */
+    void CreateResource(uint resourceid, uint priority);
+
+    /** Locks an mbos resource and temporarily allocates the resource's priority to the calling 
+     * task. 
+     * Does nothing if the resource is already locked, or if called from the idle task.
+     *
+     * @param resourceid The ID of the resource to lock. 
+     * @returns Zero if the resource was locked successfully, or the ID of the task that is
+     * currently locking the resource, if not.
+     */
+    uint LockResource(uint resourceid);
+
+    /** Tests whether a resource is locked or free, without changing its state.
+     *
+     * @param resourceid The ID of the resouce to test.
+     * @returns Zero if the resource is free, or the ID of the task that is currently
+     * locking the resouce , if not.
+
+     */
+    uint TestResource(uint resourceid);
+
+    /** Frees a resource
+     * Frees an mbos resource and restores the calling task's original priority. Does nothing 
+     * if the resource is already free, if called from the idle task, or the resource was 
+     * locked by a different task.
+     *
+     * @param resourceid The ID of the resource t free. 
+     * @returns Zero if the resource was freed successfully, or the ID of the task that is
+     * locking the resource, if not.
+     */
+    uint FreeResource(uint resource);
+
+private:
+    uint* _initstack(uint *stack, void (*fun)());
+};
+#endif
diff -r 000000000000 -r a61d29450691 mbos_asm.s
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbos_asm.s	Thu May 05 07:34:12 2011 +0000
@@ -0,0 +1,121 @@
+;***********************************************************************************
+;   m b o s   R T O S   F O R    m b e d  (ARM CORTEX M3) 
+; 
+;  Copyright (c) 2010 - 2011 Andrew Levido
+; 
+;  THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED 
+;  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
+;  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
+;  SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
+;  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
+;  OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+;  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
+;  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+;  OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+    EXPORT  _startos    
+    EXPORT  SVC_Handler
+    EXPORT  PendSV_Handler
+    EXPORT  _swap
+
+    EXTERN  _tasklist
+    EXTERN  _tasklistsize
+    EXTERN  _stackerror
+    EXTERN  _hardstacklimit
+
+ID_OFFSET           equ     0               ; 0 word (0byte) offset
+STACK_OFFSET        equ     4               ; 1 word (4byte) offset
+PRIO_OFFSET         equ     8               ; 2 word (8byte) offset
+LIMIT_OFFSET        equ     20              ; 5 word (20byte) offset
+
+    AREA    |.text|, CODE, READONLY, ALIGN=3
+    PRESERVE8
+
+; Function to invoke an SVC exception to start 1st task ----------------------------------
+_startos
+    svc             0                       ; Initiate a system call to start the first task
+    bx              lr                      ; Return (should never happen!)
+    ALIGN
+
+; Function to initiate a SetPend Exception to swap tasks ---------------------------------
+_swap
+    mov             r0, #0xe000e000         ; Base address of ICSR
+    ldr             r1, [r0, #0x0d04]       ; Read ICSR    
+    orr             r1, #0x10000000         ; Set setPend bit
+    str             r1, [r0, #0xd04]        ; write back to ICSR
+    bx              lr
+    ALIGN
+
+; Main task switching and scheduling functions -------------------------------------------
+PendSV_Handler                              ; entered here as handler for context switch
+     cpsid          i                       ; disable interrupts
+    ; save context of running task (that not saved by exception entry)
+    mrs             r0, msp
+    stmdb           r0!, {r4-r11}
+; store the sp in the tcb 
+    ldr             r1, =_tasklist
+    ldr             r1, [r1]
+    ldr             r1, [r1]
+    str             r0, [r1, #STACK_OFFSET]
+; check for stack overflow against task limit
+    ldr             r2, [r1, #LIMIT_OFFSET]
+    cmp             r0, r2
+    bls             stackerror
+; check for stack overflow against hard limit
+    ldr                r2, =_hardstacklimit
+    ldr                r2, [r2]
+    cmp             r0, r2
+    bls                stackerror
+SVC_Handler                                 ; entered here as handler for 1st task start
+    cpsid           i                       ; Disable interrupts
+; sort the task list 
+    ldr             r5, =_tasklist          ; r5 = _tasklist[i] where i = 0
+    ldr             r5, [r5]
+    ldr             r9, =_tasklistsize      ; byte offset of last item in tasklist
+    ldr             r9, [r9]
+    add             r9, r5                  ; outer loop limit
+    sub             r10, r9, #4             ; inner loop limit
+outerloop
+    ldr             r1, [r5]                ; r8 = _tasklist[i]->priostate
+    ldr             r8, [r1, #PRIO_OFFSET]
+    mov             r7, r5                  ; k = i
+    add             r6, r5, #4              ; j = i + 1
+innerloop
+    ldr             r0, [r6]                ; r0 = _tasklist[j]->priostate
+    ldr             r0, [r0, #PRIO_OFFSET]
+    cmp             r0, r8                  ; r0 - r8
+    bcc             innerlooptest           ; branch if r8 higher 
+; found bigger or same!
+    mov             r7, r6                  ; k = j
+    mov             r8, r0                  ; r8 =     _tasklist[j]->priostate
+innerlooptest
+    add             r6, #4                  ; j++
+    cmp             r6, r9                  ; r6 - r9  (j - inner limit)
+    bls             innerloop               ; branch if r9 lower or same
+; swap
+    ldr             r0, [r5]
+    ldr             r1, [r7]
+    str             r1, [r5]
+    str             r0, [r7]
+outerlooptest
+    add             r5, #4                  ; i++
+    cmp             r5, r10                 ; r5 - r10 (i - outer limit)
+    bls             outerloop               ; branch if r10 is lower or same
+    ; restore the context (that not restored by the exception exit) ---------------------
+    ldr             r0, =_tasklist          ; get the sp from the TCB
+    ldr             r0, [r0]
+    ldr             r0, [r0]
+    ldr             r0, [r0, #STACK_OFFSET]
+    ldmia           r0!,{r4-r11}            ; pop the stack
+    msr             msp, r0                 ; and put the sp away
+    cpsie           i                       ; re-enable interrupts
+; Force a return from exception and the restoration of the rest of the regs     
+    bx              lr    
+; A stack error has occurred
+stackerror
+    ldr             r0, [r1, #ID_OFFSET]    ; get id of task into r0
+    bl.w            _stackerror             ; call the C function
+_donothing
+    bl              _donothing
+    ALIGN
+    END
\ No newline at end of file