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

Committer:
AjK
Date:
Fri Mar 04 13:10:39 2011 +0000
Revision:
3:95ec5c83c2fe
Parent:
1:f043501c4bed
1.2 See ChangeLog.h

Who changed what in which revision?

UserRevisionLine numberNew contents of line
AjK 1:f043501c4bed 1 /*
AjK 1:f043501c4bed 2 Copyright (c) 2011 Andy Kirkham
AjK 1:f043501c4bed 3
AjK 1:f043501c4bed 4 Permission is hereby granted, free of charge, to any person obtaining a copy
AjK 1:f043501c4bed 5 of this software and associated documentation files (the "Software"), to deal
AjK 1:f043501c4bed 6 in the Software without restriction, including without limitation the rights
AjK 1:f043501c4bed 7 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
AjK 1:f043501c4bed 8 copies of the Software, and to permit persons to whom the Software is
AjK 1:f043501c4bed 9 furnished to do so, subject to the following conditions:
AjK 1:f043501c4bed 10
AjK 1:f043501c4bed 11 The above copyright notice and this permission notice shall be included in
AjK 1:f043501c4bed 12 all copies or substantial portions of the Software.
AjK 1:f043501c4bed 13
AjK 1:f043501c4bed 14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
AjK 1:f043501c4bed 15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
AjK 1:f043501c4bed 16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AjK 1:f043501c4bed 17 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
AjK 1:f043501c4bed 18 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
AjK 1:f043501c4bed 19 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
AjK 1:f043501c4bed 20 THE SOFTWARE.
AjK 1:f043501c4bed 21
AjK 1:f043501c4bed 22 @file example4.h
AjK 1:f043501c4bed 23 @purpose Simple round-robin cooperative scheduler example
AjK 1:f043501c4bed 24 @date Mar 2011
AjK 1:f043501c4bed 25 @author Andy Kirkham
AjK 1:f043501c4bed 26 */
AjK 1:f043501c4bed 27
AjK 1:f043501c4bed 28 /*
AjK 1:f043501c4bed 29 This example uses the network stack to setup the time. Note, when I tested
AjK 1:f043501c4bed 30 this I had two things in place. If you want to run this example then you too
AjK 1:f043501c4bed 31 will need:-
AjK 1:f043501c4bed 32
AjK 1:f043501c4bed 33 1. Your Mbed with an Ethernet jack socket. I used a Cool Components Workshop
AjK 1:f043501c4bed 34 board: http://www.coolcomponents.co.uk/catalog/product_info.php?products_id=528
AjK 1:f043501c4bed 35 2. You will need to import a network stack into your project. The one I used was
AjK 1:f043501c4bed 36 this one: http://mbed.org/users/segundo/libraries/NetServices/ljhqix
AjK 1:f043501c4bed 37
AjK 1:f043501c4bed 38 What this example shows is the usual "flash some LEDs tasks" and an example of how
AjK 1:f043501c4bed 39 to setup the time on the Mbed via the attached ethernet/Internet network. I used
AjK 1:f043501c4bed 40 setting the time as a network example but you could do HTTP requests, etc.
AjK 1:f043501c4bed 41
AjK 1:f043501c4bed 42 The purpose of this example is to show how to use the network stack to do a NON-BLOCKING
AjK 1:f043501c4bed 43 network call. SimpleScheduler is a coopertive scheduler and that means you should not
AjK 1:f043501c4bed 44 wait around in task functions. You should complete your tasks as fast as possible so
AjK 1:f043501c4bed 45 that other scheduled tasks are not blocked from running. However, making network calls
AjK 1:f043501c4bed 46 generally take some time to complete so are considered "slow" (compared the clock freq
AjK 1:f043501c4bed 47 of the LPC1768 micro that is!). So to avoid stalling out waiting for a reply our tasks
AjK 1:f043501c4bed 48 must use NON-BLOCKING calls. This is what this example is for, to demostrate how to
AjK 1:f043501c4bed 49 make a non-blocking network stack call.
AjK 1:f043501c4bed 50 */
AjK 1:f043501c4bed 51
AjK 1:f043501c4bed 52 #include "mbed.h"
AjK 1:f043501c4bed 53 #include "SimpleScheduler.h"
AjK 1:f043501c4bed 54 #include "EthernetNetIf.h"
AjK 1:f043501c4bed 55 #include "HTTPClient.h"
AjK 1:f043501c4bed 56 #include "NTPClient.h"
AjK 1:f043501c4bed 57
AjK 1:f043501c4bed 58 // Setup a serial port to print the time to.
AjK 1:f043501c4bed 59 Serial pc(USBTX, USBRX);
AjK 1:f043501c4bed 60
AjK 1:f043501c4bed 61 // The usual suspects.
AjK 1:f043501c4bed 62 DigitalOut led1(LED1);
AjK 1:f043501c4bed 63 DigitalOut led2(LED2);
AjK 1:f043501c4bed 64 DigitalOut led3(LED3);
AjK 1:f043501c4bed 65 DigitalOut led4(LED4);
AjK 1:f043501c4bed 66
AjK 1:f043501c4bed 67 // A scheduler.
AjK 1:f043501c4bed 68 SimpleScheduler *scheduler;
AjK 1:f043501c4bed 69
AjK 1:f043501c4bed 70 // Setup the network statck.
AjK 1:f043501c4bed 71 EthernetNetIf eth;
AjK 1:f043501c4bed 72 EthernetErr ethErr;
AjK 1:f043501c4bed 73 NTPClient ntp;
AjK 1:f043501c4bed 74 NTPResult result;
AjK 1:f043501c4bed 75
AjK 1:f043501c4bed 76 // Declare the host we are going to ask the time.
AjK 1:f043501c4bed 77 Host server(IpAddr(), 123, "0.de.pool.ntp.org");
AjK 1:f043501c4bed 78
AjK 1:f043501c4bed 79 // Scheduler task functions.
AjK 1:f043501c4bed 80 void f2(SimpleTask *task) { led2 = !led2; }
AjK 1:f043501c4bed 81 void f3(SimpleTask *task) { led3 = !led3; }
AjK 1:f043501c4bed 82 void f4(SimpleTask *task) { led4 = !led4; }
AjK 1:f043501c4bed 83 void netPoll(SimpleTask *task) { Net::poll(); }
AjK 1:f043501c4bed 84
AjK 1:f043501c4bed 85 bool clockAccurate;
AjK 1:f043501c4bed 86
AjK 1:f043501c4bed 87 // Scheduler task function.
AjK 1:f043501c4bed 88 void showTime(SimpleTask *task) {
AjK 1:f043501c4bed 89 time_t theTime = time(NULL);
AjK 1:f043501c4bed 90 char *s = ctime(&theTime);
AjK 1:f043501c4bed 91 for(char *p = s; *p != '\0'; p++) if (*p == '\n') { *p = '\0'; break; } // rtrim \n
AjK 1:f043501c4bed 92 pc.printf("Time is now (UTC): %s", s);
AjK 1:f043501c4bed 93 if (!clockAccurate) {
AjK 1:f043501c4bed 94 pc.printf(" (maybe inaccurate)");
AjK 1:f043501c4bed 95 }
AjK 1:f043501c4bed 96 pc.printf("\n");
AjK 1:f043501c4bed 97 if (result != NTP_OK) {
AjK 1:f043501c4bed 98 pc.printf(" NTP status: ");
AjK 1:f043501c4bed 99 switch(result) {
AjK 1:f043501c4bed 100 case NTP_PROCESSING: pc.printf("NTP_PROCESSING.\n"); break;
AjK 1:f043501c4bed 101 case NTP_PRTCL: pc.printf("NTP_PRTCL protocol error.\n"); break;
AjK 1:f043501c4bed 102 case NTP_TIMEOUT: pc.printf("NTP_TIMEOUT.\n"); break;
AjK 1:f043501c4bed 103 case NTP_DNS : pc.printf("NTP_DNS.\n"); break;
AjK 1:f043501c4bed 104 }
AjK 1:f043501c4bed 105 }
AjK 1:f043501c4bed 106 }
AjK 1:f043501c4bed 107
AjK 1:f043501c4bed 108 // Network stack callbacks.
AjK 1:f043501c4bed 109 void getTimeCallback(NTPResult i) {
AjK 1:f043501c4bed 110 result = i;
AjK 1:f043501c4bed 111 led1 = !led1;
AjK 1:f043501c4bed 112 clockAccurate = i == NTP_OK ? true : false;
AjK 1:f043501c4bed 113 }
AjK 1:f043501c4bed 114
AjK 1:f043501c4bed 115 // Scheduler task function.
AjK 1:f043501c4bed 116 void setTime(SimpleTask *task) {
AjK 1:f043501c4bed 117 if (!ethErr) {
AjK 1:f043501c4bed 118 result = NTP_PROCESSING;
AjK 1:f043501c4bed 119 ntp.setTime(server, getTimeCallback);
AjK 1:f043501c4bed 120 }
AjK 1:f043501c4bed 121 }
AjK 1:f043501c4bed 122
AjK 1:f043501c4bed 123 int main() {
AjK 1:f043501c4bed 124 pc.baud(115200);
AjK 3:95ec5c83c2fe 125 pc.printf("Example4 starting up.\n");
AjK 1:f043501c4bed 126
AjK 1:f043501c4bed 127 clockAccurate = false;
AjK 1:f043501c4bed 128
AjK 1:f043501c4bed 129 ethErr = eth.setup();
AjK 1:f043501c4bed 130 if (ethErr) {
AjK 1:f043501c4bed 131 pc.printf("Error %d in setup.\n", ethErr);
AjK 1:f043501c4bed 132 }
AjK 1:f043501c4bed 133 else {
AjK 1:f043501c4bed 134 result = NTP_PROCESSING;
AjK 1:f043501c4bed 135 ntp.setTime(server, getTimeCallback);
AjK 1:f043501c4bed 136 }
AjK 1:f043501c4bed 137
AjK 1:f043501c4bed 138 scheduler = new SimpleScheduler;
AjK 1:f043501c4bed 139
AjK 1:f043501c4bed 140 scheduler
AjK 1:f043501c4bed 141 ->addTask( new SimpleTask(200, f2) )
AjK 1:f043501c4bed 142 ->addTask( new SimpleTask(300, f3) )
AjK 1:f043501c4bed 143 ->addTask( new SimpleTask(0.4, f4) )
AjK 1:f043501c4bed 144 ;
AjK 1:f043501c4bed 145
AjK 1:f043501c4bed 146 // Only add these tasks if Ethernet setup is ok.
AjK 1:f043501c4bed 147 // Notice we add netPoll() with a time of zero.
AjK 1:f043501c4bed 148 // Zero means "call as often as possible". The
AjK 1:f043501c4bed 149 // network stack needs to be polled on a regular
AjK 1:f043501c4bed 150 // basis. As often as possible in fact. The other
AjK 1:f043501c4bed 151 // two tasks are "just print the time to serial
AjK 1:f043501c4bed 152 // once every 5seconds" and the other is "update
AjK 1:f043501c4bed 153 // the clock from remote host once an hour".
AjK 1:f043501c4bed 154 // Remember, integers are milliseconds but real
AjK 1:f043501c4bed 155 // numbers are seconds).
AjK 1:f043501c4bed 156 if (!ethErr) {
AjK 1:f043501c4bed 157 scheduler
AjK 1:f043501c4bed 158 ->addTask( new SimpleTask(0, netPoll) )
AjK 1:f043501c4bed 159 ->addTask( new SimpleTask(5.0, showTime) )
AjK 1:f043501c4bed 160 ->addTask( new SimpleTask(3600.0, setTime) )
AjK 1:f043501c4bed 161 ;
AjK 1:f043501c4bed 162 }
AjK 1:f043501c4bed 163
AjK 1:f043501c4bed 164 scheduler->run();
AjK 1:f043501c4bed 165 }
AjK 1:f043501c4bed 166
AjK 1:f043501c4bed 167
AjK 1:f043501c4bed 168