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

Dependencies:   mbed

Revision:
0:a61d29450691
--- /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);
+}