diff options
| author | Anatoli Arkhipenko <arkhipenko@hotmail.com> | 2015-12-17 16:19:01 -0500 |
|---|---|---|
| committer | Anatoli Arkhipenko <arkhipenko@hotmail.com> | 2015-12-17 16:27:13 -0500 |
| commit | ff9be9377117960d03f44e493afb2e280f9b86ab (patch) | |
| tree | 5a3a1684d70411e45e2710ff5a5ac5b291ae5d2e | |
| parent | ea4d2f858cf8da39258976f3c15c982c8127c3f5 (diff) | |
v1.9.1 bug fixes, automatic millis rollover, update to time critical
* _TASK_ROLLOVER_FIX is deprecated (not necessary)
* bug fixes: automatic millis rollover support for delay methods
* new method for _TASK_TIMECRITICAL option: getStartDelay()
| -rw-r--r-- | README | 24 | ||||
| -rw-r--r-- | examples/Scheduler_example1/Scheduler_example1.ino (renamed from examples/Scheduler_example/Scheduler_example.ino) | 0 | ||||
| -rw-r--r-- | examples/Scheduler_example10_Benchmark/Scheduler_example10_Benchmark.ino | 93 | ||||
| -rw-r--r-- | examples/Scheduler_example9_TimeCritical/Scheduler_example9_TimeCritical.ino | 57 | ||||
| -rw-r--r-- | extras/TaskScheduler.doc | bin | 205312 -> 206848 bytes | |||
| -rw-r--r-- | extras/TaskScheduler.html | 48 | ||||
| -rw-r--r-- | keywords.txt | 1 | ||||
| -rw-r--r-- | src/TaskScheduler.h | 1 |
8 files changed, 202 insertions, 22 deletions
@@ -1,20 +1,24 @@ Task Scheduler – cooperative multitasking for Arduino microcontrollers -Version 1.9.1: 2015-11-28 +Version 1.9.1: 2015-12-17 OVERVIEW: -A lightweight implementation of cooperative multitasking (task scheduling) supporting: -1. Periodic task execution (with dynamic execution period in milliseconds) -2. Number of iterations (n times) -3. Execution of tasks in predefined sequence -4. Dynamic change of task execution parameters (frequency, number of iterations, callback function) -5. Power saving via entering IDLE sleep mode between tasks are scheduled to run -6. Support for task invocation via Status Request object -7. Support for task IDs and Control Points for error handling and watchdog timer -8. Support for Local Task Storage pointer (allowing use of same callback code for multiple tasks) + A lightweight implementation of cooperative multitasking (task scheduling) supporting: + 1. Periodic task execution (with dynamic execution period in milliseconds) + 2. Number of iterations (n times) + 3. Execution of tasks in predefined sequence + 4. Dynamic change of task execution parameters (frequency, number of iterations, callback function) + 5. Power saving via entering IDLE sleep mode between tasks are scheduled to run + 6. Support for task invocation via Status Request object + 7. Support for task IDs and Control Points for error handling and watchdog timer + 8. Support for Local Task Storage pointer (allowing use of same callback code for multiple tasks) + +Scheduling overhead: between 15 and 18 microseconds per scheduling pass (check the banchmark example). Changelog: v1.9.1: 2015-11-28 - _TASK_ROLLOVER_FIX is deprecated (not necessary) + 2015-12-16 - bug fixes: automatic millis rollover support for delay methods + 2015-12-17 - new method for _TASK_TIMECRITICAL option: getStartDelay() v1.9.0: 2015-11-24 - packed three byte-long status variables into one byte-long bit array structure data type - saving 2 bytes per each task instance diff --git a/examples/Scheduler_example/Scheduler_example.ino b/examples/Scheduler_example1/Scheduler_example1.ino index 2175e57..2175e57 100644 --- a/examples/Scheduler_example/Scheduler_example.ino +++ b/examples/Scheduler_example1/Scheduler_example1.ino diff --git a/examples/Scheduler_example10_Benchmark/Scheduler_example10_Benchmark.ino b/examples/Scheduler_example10_Benchmark/Scheduler_example10_Benchmark.ino new file mode 100644 index 0000000..221b676 --- /dev/null +++ b/examples/Scheduler_example10_Benchmark/Scheduler_example10_Benchmark.ino @@ -0,0 +1,93 @@ +
+/**
+ * This is a test to benchmark TaskScheduler execution.
+ *
+ * This test executes 1,000,000 cycles of a task with empty callback method
+ * Compiled with different options, you can assess the impact of each on the size of the Task object
+ * and the execution overhead of the main execution pass route.
+ *
+ * Sample execution times (in milliseconds per 1M iterations) are provided below.
+ * The test board is Arduino UNO 16MHz processor.
+ *
+
+
+TaskScheduler 1.9.0:
+No modifiers
+Duration=15656
+
+with SLEEP
+Duration=16285
+
+with status request:
+Duration=16600
+
+with rollover fix:
+Duration=18109
+
+
+TaskScheduler 1.8.5:
+Duration=15719
+
+with SLEEP
+Duration=16348
+
+with status request:
+Duration=18360
+
+with rollover fix:
+Duration=18423
+
+ */
+
+
+//#define _TASK_TIMECRITICAL // Enable monitoring scheduling overruns
+#define _TASK_STATUS_REQUEST // Compile with support for StatusRequest functionality - triggering tasks on status change events in addition to time only
+//#define _TASK_WDT_IDS // Compile with support for wdt control points and task ids
+//#define _TASK_LTS_POINTER // Compile with support for local task storage pointer
+#define _TASK_ROLLOVER_FIX // Compensate for millis() rollover once every 47 days
+#define _TASK_SLEEP_ON_IDLE_RUN
+#include <TaskScheduler.h>
+
+Scheduler ts;
+
+// Callback methods prototypes
+bool tOn(); void tOff();
+void callback();
+
+// Tasks
+Task t(TASK_IMMEDIATE, 1000000, &callback, &ts, false, &tOn, &tOff);
+
+unsigned long c1, c2;
+
+bool tOn() {
+ c1 = millis();
+ c2 = 0;
+
+ return true;
+}
+
+void tOff() {
+ c2 = millis();
+ Serial.println("done.");
+ Serial.print("Tstart =");Serial.println(c1);
+ Serial.print("Tfinish=");Serial.println(c2);
+ Serial.print("Duration=");Serial.println(c2-c1);
+}
+
+void setup() {
+ // put your setup code here, to run once:
+ Serial.begin(115200);
+ Serial.print("Start...");
+
+ t.enable();
+}
+
+void callback() {
+
+}
+
+
+void loop() {
+ // put your main code here, to run repeatedly:
+ ts.execute();
+}
diff --git a/examples/Scheduler_example9_TimeCritical/Scheduler_example9_TimeCritical.ino b/examples/Scheduler_example9_TimeCritical/Scheduler_example9_TimeCritical.ino new file mode 100644 index 0000000..b330d6f --- /dev/null +++ b/examples/Scheduler_example9_TimeCritical/Scheduler_example9_TimeCritical.ino @@ -0,0 +1,57 @@ +/** + * TaskScheduler Test + * Illustration of use of Time Critical Information + * + * Task1 runs every 1 second indefinitely + * On each run it reports how delayed the invokation of the callback method was, + * and what was the scheduling overun. + * Each run task 1 is dealyed randomly for up to 2 seconds, thus simulating scheduling overrun + */ + + #define _TASK_TIMECRITICAL + #define _TASK_SLEEP_ON_IDLE_RUN +#include <TaskScheduler.h> + +// Callback methods prototypes +void t1Callback(); + + +//Tasks +Task t1(1000, -1, &t1Callback); + +Scheduler runner; + + +void t1Callback() { + Serial.print(millis()); + Serial.print(": overrun = "); + Serial.print(t1.getOverrun()); + Serial.print(", start delayed by "); + Serial.println(t1.getStartDelay()); + + int i = random(2000); + Serial.print("Delaying for "); Serial.println(i); + delay(i); +} + +void setup () { + Serial.begin(115200); + Serial.println("Scheduler TimeCritical TEST"); + + runner.init(); + Serial.println("Initialized scheduler"); + + runner.addTask(t1); + Serial.println("added t1. Waiting for 5 seconds."); + + delay(5000); + + t1.enable(); + + Serial.println("Enabled t1"); +} + + +void loop () { + runner.execute(); +} diff --git a/extras/TaskScheduler.doc b/extras/TaskScheduler.doc Binary files differindex a6e1933..5c1ed8d 100644 --- a/extras/TaskScheduler.doc +++ b/extras/TaskScheduler.doc diff --git a/extras/TaskScheduler.html b/extras/TaskScheduler.html index 1631975..d78f5f2 100644 --- a/extras/TaskScheduler.html +++ b/extras/TaskScheduler.html @@ -15,7 +15,7 @@ <!-- @page { margin: 0.79in } P { margin-bottom: 0.08in; direction: ltr; color: #000000; widows: 0; orphans: 0 } - P.western { font-family: "Liberation Serif", "MS PMincho", serif; font-size: 12pt; so-language: en-US } + P.western { font-family: "Liberation Serif", "Times New Roman", serif; font-size: 12pt; so-language: en-US } P.cjk { font-family: "WenQuanYi Micro Hei", "MS Mincho"; font-size: 12pt; so-language: zh-CN } P.ctl { font-family: "Lohit Hindi", "MS Mincho"; font-size: 12pt; so-language: hi-IN } A:link { color: #0000ff } @@ -28,7 +28,7 @@ Scheduler</B></FONT></P> <P CLASS="western" STYLE="margin-bottom: 0in"><B>cooperative multitasking for Arduino microcontrollers</B></P> <P CLASS="western" STYLE="margin-bottom: 0in; border-top: none; border-bottom: 1px solid #000000; border-left: none; border-right: none; padding-top: 0in; padding-bottom: 0.01in; padding-left: 0in; padding-right: 0in"> -<FONT SIZE=2 STYLE="font-size: 11pt"><B>Version 1.9.1: 2015-11-28</B></FONT></P> +<FONT SIZE=2 STYLE="font-size: 11pt"><B>Version 1.9.1: 2015-12-17</B></FONT></P> <P CLASS="western" STYLE="margin-bottom: 0in"><BR> </P> <P CLASS="western" STYLE="margin-bottom: 0in"><B>OVERVIEW</B>:</P> @@ -58,6 +58,10 @@ supporting:</P> </OL> <P CLASS="western" STYLE="margin-bottom: 0in"><BR> </P> +<P CLASS="western" STYLE="margin-bottom: 0in">Scheduling overhead: +between 15 and 18 microseconds per scheduling pass.</P> +<P CLASS="western" STYLE="margin-bottom: 0in"><BR> +</P> <P CLASS="western" STYLE="margin-bottom: 0in"><B>TASK</B>:</P> <P CLASS="western" STYLE="margin-bottom: 0in">“Task” is a container concept that links together:</P> @@ -200,10 +204,19 @@ defined before the library header file in the body of arduino sketch.</P> <P CLASS="western" STYLE="margin-bottom: 0in">...will compile the library with time critical tracking option enabled.</P> <P CLASS="western" STYLE="margin-bottom: 0in">Time critical option -keeps track where next execution time of the task falls, and makes it -available via API through <B>Task::getOverrun()</B> method. If -<B>getOverrun </B>returns a negative value, this Task’s next -execution time point is <I>already</I> in the past, and task is +keeps track when current execution took place relative to when it was +scheduled, and where next execution time of the task falls. Two +methods provide this information. +</P> +<P CLASS="western" STYLE="margin-bottom: 0in"><B>Task::getStartDelay() +</B><SPAN STYLE="font-weight: normal">method: return number of +milliseconds between current system time (millis) and point in time +when the task was scheduled to start. A value of 0 (zero) indicates +that task started right on time per schedule. </SPAN> +</P> +<P CLASS="western" STYLE="margin-bottom: 0in"><B>Task::getOverrun()</B> +method: If <B>getOverrun </B>returns a negative value, this Task’s +next execution time point is <I>already</I> in the past, and task is behind schedule. This most probably means that either task’s callback method's runtime is too long, or the execution interval is too short (and therefore schedule is too aggressive).</P> @@ -780,8 +793,8 @@ do last part of the stuff</FONT></FONT></P> </P> <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">This will execute all parts of the callback function in three successive -steps, sheduled immediately, but allowing other tasks in the cahin to -run. Notince that task is scheduled to run immediately, and 1 second +steps, sheduled immediately, but allowing other tasks in the chain to +run. Notice that task is scheduled to run immediately, and 1 second period is achieved by delaying the task for 1000 millis at the last step. </P> @@ -1022,6 +1035,16 @@ getIterations() </B> <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR> </P> <P CLASS="western" STYLE="margin-bottom: 0in"><B>long getOverrun()</B></P> +<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in; font-weight: normal"> +If library is compiled with <FONT FACE="Courier New, monospace">_TASK_TIMECRITICAL</FONT> +enabled, you can assess how much later the callback method was +invoked against when it was scheduled to be invoked. The return value +of <B>getOverrun() </B>method provides this information in +milliseconds. +</P> +<P CLASS="western" STYLE="margin-bottom: 0in"><BR> +</P> +<P CLASS="western" STYLE="margin-bottom: 0in"><B>long getOverrun()</B></P> <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">If library is compiled with <FONT FACE="Courier New, monospace">_TASK_TIMECRITICAL</FONT> enabled, tasks are monitored for “long running” scenario. A “long @@ -1031,8 +1054,9 @@ other tasks where they don't run on a scheduled interval, but rather “catch up” and are behind. When task scheduler sets the next execution target time, it adds Task's execution interval to the previously scheduled execution time:</P> -<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"> <B>next -execution time = previous execution time + task execution interval</B></P> +<P CLASS="western" ALIGN=CENTER STYLE="margin-left: 0.49in; margin-bottom: 0in"> +<B>next execution time = current execution scheduled time + task +execution interval</B></P> <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR> </P> <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">If @@ -2794,7 +2818,7 @@ time examples of TaskScheduler are available here:</FONT></FONT></P> <P CLASS="western" STYLE="margin-bottom: 0in"><BR> </P> <DIV TYPE=FOOTER> - <P STYLE="margin-top: 0.35in; margin-bottom: 0in"> <SDFIELD TYPE=PAGE SUBTYPE=RANDOM FORMAT=ARABIC>4</SDFIELD></P> + <P STYLE="margin-top: 0.35in; margin-bottom: 0in"> <SDFIELD TYPE=PAGE SUBTYPE=RANDOM FORMAT=ARABIC>31</SDFIELD></P> </DIV> </BODY> -</HTML> +</HTML>
\ No newline at end of file diff --git a/keywords.txt b/keywords.txt index 5332e33..df63872 100644 --- a/keywords.txt +++ b/keywords.txt @@ -43,6 +43,7 @@ setOnEnable KEYWORD2 setOnDisable KEYWORD2 disableOnLastIteration KEYWORD2 getOverrun KEYWORD2 +getStartDelay KEYWORD2 isFirstIteration KEYWORD2 isLastIteration KEYWORD2 setWaiting KEYWORD2 diff --git a/src/TaskScheduler.h b/src/TaskScheduler.h index aa0a05a..ab5ac11 100644 --- a/src/TaskScheduler.h +++ b/src/TaskScheduler.h @@ -71,6 +71,7 @@ // // v1.9.1: // 2015-11-28 - _TASK_ROLLOVER_FIX is deprecated (not necessary) +// 2015-12-16 - bug fixes: automatic millis rollover support for delay methods // 2015-12-17 - new method for _TASK_TIMECRITICAL option: getStartDelay() |
