diff options
Diffstat (limited to 'examples/Scheduler_example07_WDT')
| -rw-r--r-- | examples/Scheduler_example07_WDT/Scheduler_example07_WDT.ino | 132 |
1 files changed, 132 insertions, 0 deletions
diff --git a/examples/Scheduler_example07_WDT/Scheduler_example07_WDT.ino b/examples/Scheduler_example07_WDT/Scheduler_example07_WDT.ino new file mode 100644 index 0000000..60983bd --- /dev/null +++ b/examples/Scheduler_example07_WDT/Scheduler_example07_WDT.ino @@ -0,0 +1,132 @@ +/** + * TaskScheduler Test sketch - use of task IDs and watchdog timer to identify hung tasks + * Test case: + * Watchdog timer is set to 2 seconds (interrupt + reset) + * A hearbeat task (resetting the watchdog timer) is scheduled with 500 ms interval + * A number of tasks are running every 1 second and "rolling the dice" 0..19. If 5, task is made to enter infinite loop + * Device should reset in 2 seconds after a task enters infinite loop + * A task id and a control point number are saved to EEPROM prior to device reset, and are displayed after reboot. + * In real life, device might chose to NOT activate certain tasks which failed previously (failed sensors for instance) + */ + +#define _TASK_SLEEP_ON_IDLE_RUN +#define _TASK_WDT_IDS +#include <TaskScheduler.h> + +#include <EEPROM.h> +#include <avr/wdt.h> + +Scheduler ts; + +// Callback methods prototypes +void TaskCB(); +void HB(); bool HBOn(); void HBOff(); + +// Three tasks emulating accidental infinite loop +Task tTask1(TASK_SECOND, TASK_FOREVER, &TaskCB, &ts, true); +Task tTask2(TASK_SECOND, TASK_FOREVER, &TaskCB, &ts, true); +Task tTask3(TASK_SECOND, TASK_FOREVER, &TaskCB, &ts, true); + +// Heartbeat task - resetting the watchdog timer periodically +// Initiates WDT on enable, and deactivates it on disable +Task tHB(500, TASK_FOREVER, &HB, &ts, false, &HBOn, &HBOff); + +/** + * Emulating task callback function + * Prints task id and randomly "hangs" in two places. + * Control points are stored on the task prior to section which might hang, + * making this information available to the WDT interrupt handler + */ +void TaskCB() { + Task& T = ts.currentTask(); + + Serial.print("Task #:"); + Serial.print(T.getId()); + Serial.print(" current iteration = "); + Serial.println(T.getRunCounter()); + +// Hang if random number between 0 and 19 is 5 (5% probability) + T.setControlPoint(10); + if (random(20) == 5) for(;;); + +// Hang if random number between 0 and 99 is more that 95 (5% probability) + T.setControlPoint(95); + if (random(100) > 94) for(;;); +} + +/** + * This On Enable method sets up the WDT + * for interrupt and reset after 2 seconds + */ +bool HBOn() { + + //disable interrupts + cli(); + //reset watchdog + wdt_reset(); + //set up WDT interrupt + WDTCSR = (1<<WDCE)|(1<<WDE); + //Start watchdog timer with aDelay prescaller + WDTCSR = (1<<WDIE)|(1<<WDE)|(WDTO_2S & 0x2F); +// WDTCSR = (1<<WDIE)|(WDTO_2S & 0x2F); // interrupt only without reset + //Enable global interrupts + sei(); +} + +/** + * This On Disable method disables WDT + */ +void HBOff() { + wdt_disable(); +} + +/** + * This is a periodic reset of WDT + */ +void HB() { + wdt_reset(); + +} + +/** + * Watchdog timeout ISR + * + */ +ISR(WDT_vect) +{ + Task& T = ts.currentTask(); + + digitalWrite(13, HIGH); + EEPROM.write(0, (byte)T.getId()); + EEPROM.write(1, (byte)T.getControlPoint()); + digitalWrite(13, LOW); +} + +/** + * Standard arduino setup routine + */ +void setup() { + + Serial.begin(115200); + + randomSeed(analogRead(0)+analogRead(5)); + + pinMode(13, OUTPUT); + digitalWrite(13, LOW); + + + Serial.println("WDT heartbeat test"); + Serial.print("Last task before reset="); Serial.println(EEPROM.read(0)); + Serial.print("Last control point before reset="); Serial.println(EEPROM.read(1)); + + delay(2000); + + tHB.enableDelayed(); +} + +/** + * Not much is left for the loop() + */ +void loop() { + ts.execute(); +}
\ No newline at end of file |
