Very simple cooperative round-robin task scheduler. See examples.

Dependents:   Garage_Control

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers example4.h Source File

example4.h

00001 /*
00002     Copyright (c) 2011 Andy Kirkham
00003  
00004     Permission is hereby granted, free of charge, to any person obtaining a copy
00005     of this software and associated documentation files (the "Software"), to deal
00006     in the Software without restriction, including without limitation the rights
00007     to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00008     copies of the Software, and to permit persons to whom the Software is
00009     furnished to do so, subject to the following conditions:
00010  
00011     The above copyright notice and this permission notice shall be included in
00012     all copies or substantial portions of the Software.
00013  
00014     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00015     IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00016     FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00017     AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00018     LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00019     OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00020     THE SOFTWARE.
00021     
00022     @file          example4.h 
00023     @purpose       Simple round-robin cooperative scheduler example
00024     @date          Mar 2011
00025     @author        Andy Kirkham
00026 */
00027 
00028 /*
00029     This example uses the network stack to setup the time. Note, when I tested
00030     this I had two things in place. If you want to run this example then you too
00031     will need:-
00032     
00033         1. Your Mbed with an Ethernet jack socket. I used a Cool Components Workshop
00034            board: http://www.coolcomponents.co.uk/catalog/product_info.php?products_id=528
00035         2. You will need to import a network stack into your project. The one I used was
00036            this one: http://mbed.org/users/segundo/libraries/NetServices/ljhqix
00037            
00038     What this example shows is the usual "flash some LEDs tasks" and an example of how
00039     to setup the time on the Mbed via the attached ethernet/Internet network. I used
00040     setting the time as a network example but you could do HTTP requests, etc.
00041     
00042     The purpose of this example is to show how to use the network stack to do a NON-BLOCKING
00043     network call. SimpleScheduler is a coopertive scheduler and that means you should not
00044     wait around in task functions. You should complete your tasks as fast as possible so
00045     that other scheduled tasks are not blocked from running. However, making network calls
00046     generally take some time to complete so are considered "slow" (compared the clock freq
00047     of the LPC1768 micro that is!). So to avoid stalling out waiting for a reply our tasks
00048     must use NON-BLOCKING calls. This is what this example is for, to demostrate how to
00049     make a non-blocking network stack call.
00050 */
00051 
00052 #include "mbed.h"
00053 #include "SimpleScheduler.h"
00054 #include "EthernetNetIf.h"
00055 #include "HTTPClient.h"
00056 #include "NTPClient.h"
00057 
00058 // Setup a serial port to print the time to.
00059 Serial pc(USBTX, USBRX);
00060 
00061 // The usual suspects.
00062 DigitalOut led1(LED1);
00063 DigitalOut led2(LED2);
00064 DigitalOut led3(LED3);
00065 DigitalOut led4(LED4);
00066 
00067 // A scheduler.
00068 SimpleScheduler *scheduler;
00069 
00070 // Setup the network statck.
00071 EthernetNetIf  eth;
00072 EthernetErr ethErr;
00073 NTPClient ntp;
00074 NTPResult result;
00075 
00076 // Declare the host we are going to ask the time.
00077 Host server(IpAddr(), 123, "0.de.pool.ntp.org");
00078 
00079 // Scheduler task functions.
00080 void f2(SimpleTask *task) { led2 = !led2; }
00081 void f3(SimpleTask *task) { led3 = !led3; }
00082 void f4(SimpleTask *task) { led4 = !led4; }
00083 void netPoll(SimpleTask *task) { Net::poll(); }
00084 
00085 bool clockAccurate;
00086 
00087 // Scheduler task function.
00088 void showTime(SimpleTask *task) {
00089     time_t theTime = time(NULL);
00090     char *s = ctime(&theTime);
00091     for(char *p = s; *p != '\0'; p++) if (*p == '\n') { *p = '\0'; break; } // rtrim \n
00092     pc.printf("Time is now (UTC): %s", s);
00093     if (!clockAccurate) {
00094         pc.printf(" (maybe inaccurate)");
00095     }
00096     pc.printf("\n");
00097     if (result != NTP_OK) {
00098         pc.printf(" NTP status: ");
00099         switch(result) {
00100             case NTP_PROCESSING: pc.printf("NTP_PROCESSING.\n"); break;
00101             case NTP_PRTCL:      pc.printf("NTP_PRTCL protocol error.\n"); break;
00102             case NTP_TIMEOUT:    pc.printf("NTP_TIMEOUT.\n"); break;
00103             case NTP_DNS :       pc.printf("NTP_DNS.\n"); break;
00104         }
00105     }
00106 }
00107 
00108 // Network stack callbacks.
00109 void getTimeCallback(NTPResult i) { 
00110     result = i; 
00111     led1 = !led1;
00112     clockAccurate = i == NTP_OK ? true : false;
00113 }
00114 
00115 // Scheduler task function.
00116 void setTime(SimpleTask *task) {
00117     if (!ethErr) {
00118         result = NTP_PROCESSING;
00119         ntp.setTime(server, getTimeCallback);            
00120     }
00121 }
00122 
00123 int main() {
00124     pc.baud(115200);
00125     pc.printf("Example4 starting up.\n");
00126     
00127     clockAccurate = false;
00128     
00129     ethErr = eth.setup();
00130     if (ethErr) {
00131         pc.printf("Error %d in setup.\n", ethErr);
00132     }
00133     else {
00134         result = NTP_PROCESSING;
00135         ntp.setTime(server, getTimeCallback);        
00136     }
00137     
00138     scheduler = new SimpleScheduler;
00139     
00140     scheduler
00141         ->addTask( new SimpleTask(200, f2) )
00142         ->addTask( new SimpleTask(300, f3) )
00143         ->addTask( new SimpleTask(0.4, f4) )
00144     ;
00145     
00146     // Only add these tasks if Ethernet setup is ok.
00147     // Notice we add netPoll() with a time of zero. 
00148     // Zero means "call as often as possible". The
00149     // network stack needs to be polled on a regular 
00150     // basis. As often as possible in fact. The other
00151     // two tasks are "just print the time to serial
00152     // once every 5seconds" and the other is "update
00153     // the clock from remote host once an hour".
00154     // Remember, integers are milliseconds but real
00155     // numbers are seconds).
00156     if (!ethErr) {
00157         scheduler
00158             ->addTask( new SimpleTask(0,   netPoll) )
00159             ->addTask( new SimpleTask(5.0, showTime) )
00160             ->addTask( new SimpleTask(3600.0, setTime) )
00161         ;         
00162     }
00163     
00164     scheduler->run();    
00165 }
00166 
00167 
00168