Very simple cooperative round-robin task scheduler. See examples.
Examples/example4.h@3:95ec5c83c2fe, 2011-03-04 (annotated)
- 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?
User | Revision | Line number | New 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 |