Very simple cooperative round-robin task scheduler. See examples.
Diff: Examples/example4.h
- Revision:
- 1:f043501c4bed
- Child:
- 3:95ec5c83c2fe
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Examples/example4.h Fri Mar 04 12:15:38 2011 +0000 @@ -0,0 +1,168 @@ +/* + Copyright (c) 2011 Andy Kirkham + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + + @file example4.h + @purpose Simple round-robin cooperative scheduler example + @date Mar 2011 + @author Andy Kirkham +*/ + +/* + This example uses the network stack to setup the time. Note, when I tested + this I had two things in place. If you want to run this example then you too + will need:- + + 1. Your Mbed with an Ethernet jack socket. I used a Cool Components Workshop + board: http://www.coolcomponents.co.uk/catalog/product_info.php?products_id=528 + 2. You will need to import a network stack into your project. The one I used was + this one: http://mbed.org/users/segundo/libraries/NetServices/ljhqix + + What this example shows is the usual "flash some LEDs tasks" and an example of how + to setup the time on the Mbed via the attached ethernet/Internet network. I used + setting the time as a network example but you could do HTTP requests, etc. + + The purpose of this example is to show how to use the network stack to do a NON-BLOCKING + network call. SimpleScheduler is a coopertive scheduler and that means you should not + wait around in task functions. You should complete your tasks as fast as possible so + that other scheduled tasks are not blocked from running. However, making network calls + generally take some time to complete so are considered "slow" (compared the clock freq + of the LPC1768 micro that is!). So to avoid stalling out waiting for a reply our tasks + must use NON-BLOCKING calls. This is what this example is for, to demostrate how to + make a non-blocking network stack call. +*/ + +#include "mbed.h" +#include "SimpleScheduler.h" +#include "EthernetNetIf.h" +#include "HTTPClient.h" +#include "NTPClient.h" + +// Setup a serial port to print the time to. +Serial pc(USBTX, USBRX); + +// The usual suspects. +DigitalOut led1(LED1); +DigitalOut led2(LED2); +DigitalOut led3(LED3); +DigitalOut led4(LED4); + +// A scheduler. +SimpleScheduler *scheduler; + +// Setup the network statck. +EthernetNetIf eth; +EthernetErr ethErr; +NTPClient ntp; +NTPResult result; + +// Declare the host we are going to ask the time. +Host server(IpAddr(), 123, "0.de.pool.ntp.org"); + +// Scheduler task functions. +void f2(SimpleTask *task) { led2 = !led2; } +void f3(SimpleTask *task) { led3 = !led3; } +void f4(SimpleTask *task) { led4 = !led4; } +void netPoll(SimpleTask *task) { Net::poll(); } + +bool clockAccurate; + +// Scheduler task function. +void showTime(SimpleTask *task) { + time_t theTime = time(NULL); + char *s = ctime(&theTime); + for(char *p = s; *p != '\0'; p++) if (*p == '\n') { *p = '\0'; break; } // rtrim \n + pc.printf("Time is now (UTC): %s", s); + if (!clockAccurate) { + pc.printf(" (maybe inaccurate)"); + } + pc.printf("\n"); + if (result != NTP_OK) { + pc.printf(" NTP status: "); + switch(result) { + case NTP_PROCESSING: pc.printf("NTP_PROCESSING.\n"); break; + case NTP_PRTCL: pc.printf("NTP_PRTCL protocol error.\n"); break; + case NTP_TIMEOUT: pc.printf("NTP_TIMEOUT.\n"); break; + case NTP_DNS : pc.printf("NTP_DNS.\n"); break; + } + } +} + +// Network stack callbacks. +void getTimeCallback(NTPResult i) { + result = i; + led1 = !led1; + clockAccurate = i == NTP_OK ? true : false; +} + +// Scheduler task function. +void setTime(SimpleTask *task) { + if (!ethErr) { + result = NTP_PROCESSING; + ntp.setTime(server, getTimeCallback); + } +} + +int main() { + pc.baud(115200); + pc.printf("Example3 starting up.\n"); + + clockAccurate = false; + + ethErr = eth.setup(); + if (ethErr) { + pc.printf("Error %d in setup.\n", ethErr); + } + else { + result = NTP_PROCESSING; + ntp.setTime(server, getTimeCallback); + } + + scheduler = new SimpleScheduler; + + scheduler + ->addTask( new SimpleTask(200, f2) ) + ->addTask( new SimpleTask(300, f3) ) + ->addTask( new SimpleTask(0.4, f4) ) + ; + + // Only add these tasks if Ethernet setup is ok. + // Notice we add netPoll() with a time of zero. + // Zero means "call as often as possible". The + // network stack needs to be polled on a regular + // basis. As often as possible in fact. The other + // two tasks are "just print the time to serial + // once every 5seconds" and the other is "update + // the clock from remote host once an hour". + // Remember, integers are milliseconds but real + // numbers are seconds). + if (!ethErr) { + scheduler + ->addTask( new SimpleTask(0, netPoll) ) + ->addTask( new SimpleTask(5.0, showTime) ) + ->addTask( new SimpleTask(3600.0, setTime) ) + ; + } + + scheduler->run(); +} + + +