A simple Round Robin Task scheduler (a sub minimalistic Operating System) with no inter Task communication implemented (semaphores, mailboxes etc) nor task local varibales can be used. They have to be global (static). But, it's the first step up to an OS.

Dependencies:   mbed

Files at this revision

API Documentation at this revision

Comitter:
Stanislaus
Date:
Fri Jun 11 20:52:03 2010 +0000
Commit message:

Changed in this revision

main.c 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
scheduler.cpp Show annotated file Show diff for this revision Revisions of this file
scheduler.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.c	Fri Jun 11 20:52:03 2010 +0000
@@ -0,0 +1,170 @@
+#include "mbed.h"
+#include "scheduler.h"
+
+#define ON  1
+#define OFF 0
+
+DigitalOut myLED(LED1);         // LED for task A and B
+DigitalOut myLEDTaskC(LED2);    // LED for Task C
+DigitalOut myLEDTaskD(LED3);    // LED for Task D
+DigitalOut myLEDTaskE(LED4);    // LED for Task E
+
+Timer t;
+Ticker keepAlive;
+
+// *******************************************************************************
+// * @brief       "taskA" task code
+// * @param[in]   None
+// * @param[out]  None
+// * @retval      bool
+// * @par Description
+// * @details    This task use to print message "taskA running". Indicate "taskA"
+// *             had been executed.
+// *******************************************************************************
+bool taskA(void* pData) 
+{
+    static unsigned int cnt_numA = 0;
+
+    myLED = ON;
+    cnt_numA++;
+
+    return true;
+}
+
+// *******************************************************************************
+// * @brief       "taskB" task code
+// * @param[in]   None
+// * @param[out]  None
+// * @retval      bool
+// * @par Description
+// * @details    This task use to print message "taskB running". Indicate "taskB"
+// *             had been executed.
+// *******************************************************************************
+bool taskB(void* pData) 
+{
+    static unsigned int cnt_numB = 0;
+
+    myLED = OFF;
+    cnt_numB++;
+
+    return true;
+}
+
+// *******************************************************************************
+// * @brief       "taskC" task code
+// * @param[in]   None
+// * @param[out]  None
+// * @retval      bool
+// * @par Description
+// * @details    This task use to print message "tasC running". Indicate "taskC"
+// *             had been executed.
+// *******************************************************************************
+bool taskC(void* pData) 
+{
+    static unsigned int cnt_numC = 0;
+
+    myLEDTaskC = !myLEDTaskC.read();
+    cnt_numC++;
+
+    return true;
+}
+
+// *******************************************************************************
+// * @brief       "taskD" task code
+// * @param[in]   None
+// * @param[out]  None
+// * @retval      bool
+// * @par Description
+// * @details    This task use to print message "taskB running". Indicate "taskD"
+// *             had been executed.
+// *******************************************************************************
+bool taskD(void* pData) 
+{
+    static unsigned int cnt_numD = 0;
+
+    myLEDTaskD = !myLEDTaskD.read();
+    cnt_numD++;
+
+    return true;
+}
+
+// *******************************************************************************
+// * @brief       "taskE" task code
+// * @param[in]   None
+// * @param[out]  None
+// * @retval      bool
+// * @par Description
+// * @details    This task use to print message "taskE running". Indicate "taskE"
+// *             had been executed.
+// *******************************************************************************
+bool taskE(void* pData) 
+{
+    static unsigned int cnt_numE = 0;
+
+    myLEDTaskE = !myLEDTaskE.read();
+    cnt_numE++;
+
+    return true;
+}
+
+// *******************************************************************************
+// * @brief       "taskF" task code
+// * @param[in]   None
+// * @param[out]  None
+// * @retval      bool
+// * @par Description
+// * @details    This task use to print message "taskF running". Indicate "taskF"
+// *             had been executed.
+// *******************************************************************************
+bool taskF(void* pData) 
+{
+    static unsigned int cnt_numF = 0;
+
+    cnt_numF++;     // task is only running for 30 seconds -> cnt_numF has the value 5 than
+
+    return true;
+}
+
+// *******************************************************************************
+// * @brief       "runningTasks" a Ticker routine 
+// * @param[in]   None
+// * @param[out]  None
+// * @retval      None
+// * @par Description
+// * @details    This method is used to keep the scheduler alife
+// *             
+// *******************************************************************************
+void runningTasks() 
+{
+    // you can do this here in running Tasks or in the main routine while loop -> see below
+    schedulerRun(t.read_ms());  
+}
+
+int main() 
+{
+    schedulerInit();        // init and start scheduler
+
+    t.start();              // start task timer
+
+    int handleTaskA = schedulerAddTask(t.read_ms(), 0, 500,  (taskfuncptr) taskA);  // Task A is switching LED1 on
+    int handleTaskB = schedulerAddTask(t.read_ms(), 0, 1000, (taskfuncptr) taskB);  // Task B is switching LED1 off
+    int handleTaskC = schedulerAddTask(t.read_ms(), 0, 200,  (taskfuncptr) taskC);  // Task C is switching LED2 on and off - every 200 ms -> five times per sec.
+    int handleTaskD = schedulerAddTask(t.read_ms(), 0, 100,  (taskfuncptr) taskD);  // Task D is switching LED3 on anf off - every 100 ms -> ten times per sec.
+    int handleTaskE = schedulerAddTask(t.read_ms(), 0, 500,  (taskfuncptr) taskE);  // Task E is switching LED4 on and off - vice versa to LED1 -> starting with on
+    int handleTaskF = schedulerAddTask(t.read_ms(), 6, 5000, (taskfuncptr) taskF);  // Task F finished after 30 seconds 
+    
+
+    // the address of the function to be attached (runTasks) and the interval (,5 micro seconds)
+    keepAlive.attach_us(&runningTasks, 500); 
+    
+    while (1) 
+    {
+        //// we can feed the scheduler here, too 
+        ////schedulerRun(t.read_ms());
+        ////wait(0.001);                        //wait one ms
+        // with a short delay we can power down the controller here...
+        // or poll very fast variables that are set in interrupt service routines (ISR's) etc.
+    }
+    // The code don't reach here -> if so, a great mess occured
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Fri Jun 11 20:52:03 2010 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/029aa53d7323
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scheduler.cpp	Fri Jun 11 20:52:03 2010 +0000
@@ -0,0 +1,126 @@
+/*! \file scheduler.c \brief Simple Task Scheduler. */
+//*****************************************************************************
+//
+// File Name    : 'scheduler.c'
+// Title        : Simple Task Scheduler
+// Author       : Pascal Stang - Copyright (C) 2006
+// Created      : 2006.05.24
+// Revised      : 2006.05.26
+// Version      : 0.1
+// Target MCU   : Atmel AVR Series
+// Editor Tabs  : 4
+//
+// NOTE: This code is currently below version 1.0, and therefore is considered
+// to be lacking in some functionality or documentation, or may not be fully
+// tested.  Nonetheless, you can expect most functions to work.
+//
+// This code is distributed under the GNU Public License
+//      which can be found at http://www.gnu.org/licenses/gpl.txt
+//
+//*****************************************************************************
+ 
+#include "scheduler.h"
+
+// the task list
+struct task TaskList[TASKLIST_SIZE];
+ 
+// functions
+void schedulerInit(void)
+{
+     int i;
+     
+     // reset task list
+     for(i=0; i<TASKLIST_SIZE; i++)
+     {
+         // initialize task list
+         TaskList[i].runtime = 0;
+         TaskList[i].funcptr = 0;
+     }
+ }
+ 
+void schedulerRun(int systime)
+{
+     int i;
+     
+     // locate active task slots
+     for(i=0; i<TASKLIST_SIZE; i++)
+     {
+         if(TaskList[i].funcptr)
+         {
+             // check systime against runtime
+             if(systime >= TaskList[i].runtime)
+             {
+                 // run task, then update it
+                 TaskList[i].funcptr(i,systime);
+                 
+                 if(TaskList[i].nrepeat)
+                 {
+                     TaskList[i].runtime += TaskList[i].interval;
+                     TaskList[i].nrepeat--;
+                     // task has expired, remove it now
+                     if(!TaskList[i].nrepeat)
+                         schedulerRemoveTask(i);
+                 }
+                 else
+                 {
+                     // nrepeat==0 means run forever
+                     TaskList[i].runtime += TaskList[i].interval;
+                 }
+                 
+             }
+         }
+     }
+ 
+     // increment scheduler timer
+     //SchedulerTimer++;
+}
+ 
+int schedulerAddTask(int runtime, int nrepeat, int interval, taskfuncptr taskfunc)
+{
+    int i;
+    
+    // locate empty scheduler slot
+    for(i=0; i<TASKLIST_SIZE; i++)
+    {
+        //CRITICAL_SECTION_BEGIN;
+        if(!TaskList[i].funcptr)
+        {
+            // setup entry
+            TaskList[i].funcptr = taskfunc;
+            TaskList[i].runtime = runtime;
+            TaskList[i].nrepeat = nrepeat;
+            TaskList[i].interval = interval;
+            
+            // return task handle
+            return i;
+        }
+        //CRITICAL_SECTION_END;
+    }
+    // error - no task slots left
+    return -1;
+}
+
+int schedulerRemoveTask(int taskhandle)
+{
+    // clear the task entry
+    TaskList[taskhandle].runtime = 0;
+    TaskList[taskhandle].interval = 0;
+    TaskList[taskhandle].nrepeat = 0;
+    TaskList[taskhandle].funcptr = 0;
+    
+    return taskhandle;
+}
+ 
+int schedulerRemoveTaskFunc(taskfuncptr funcptr)
+{
+    int i;
+    int taskhandle = -1;
+    
+    // locate the task
+    for(i=0; i<TASKLIST_SIZE; i++)
+    {
+        // on match, disable the task
+        if(TaskList[i].funcptr == funcptr) taskhandle = schedulerRemoveTask(i);
+    }
+    return taskhandle;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scheduler.h	Fri Jun 11 20:52:03 2010 +0000
@@ -0,0 +1,62 @@
+/*! \file scheduler.h \brief Simple Task Scheduler. */
+//*****************************************************************************
+//
+// File Name    : 'scheduler.h'
+// Title        : Simple Task Scheduler
+// Author       : Pascal Stang - Copyright (C) 2006
+// Created      : 2006.05.24
+// Revised      : 2006.05.26
+// Version      : 0.2
+// Target MCU   : NXP Cortex M3 LPC17xx and LPC13xx 
+// Editor Tabs  : 4
+//
+// NOTE: This code is currently below version 1.0, and therefore is considered
+// to be lacking in some functionality or documentation, or may not be fully
+// tested.  Nonetheless, you can expect most functions to work.
+//
+// This code is distributed under the GNU Public License
+//      which can be found at http://www.gnu.org/licenses/gpl.txt
+//
+//*****************************************************************************
+ 
+#ifndef SCHEDULER_H
+#define SCHEDULER_H
+ 
+// structures and typedefs
+typedef void (*taskfuncptr)(int htask, int systime);
+typedef void (*voidFuncPtr)(void);
+ 
+struct task
+{
+    int runtime;
+    int nrepeat;
+    int interval;
+    taskfuncptr funcptr;
+};
+ 
+#ifndef TASKLIST_SIZE
+#define TASKLIST_SIZE   10
+#endif
+ 
+// functions
+ 
+// initialize scheduler
+void schedulerInit(void);
+ 
+// run scheduler
+//  this function should be called at the system clock tick rate
+//  the system time must be passed in systime
+void schedulerRun(int systime);
+ 
+// schedule a task
+//  returns a handle to the task (or -1 for failure)
+int schedulerAddTask(int runtime, int nrepeat, int interval, taskfuncptr taskfunc);
+ 
+// remove a scheduled task by handle
+int schedulerRemoveTask(int taskhandle);
+ 
+// remove a scheduled task(s) by function reference
+//  NOTE: this will remove ALL tasks referencing the specified function
+int schedulerRemoveTaskFunc(taskfuncptr funcptr);
+ 
+#endif