/** * TaskScheduler Test sketch - use of task IDs and watchdog timer to identify hung tasks * THIS SKETCH RUNS ON AVR BOARDS ONLY * 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 #include #include 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<