Scheduler_example07_WDT.ino 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. /**
  2. * TaskScheduler Test sketch - use of task IDs and watchdog timer to identify hung tasks
  3. * THIS SKETCH RUNS ON AVR BOARDS ONLY
  4. * Test case:
  5. * Watchdog timer is set to 2 seconds (interrupt + reset)
  6. * A hearbeat task (resetting the watchdog timer) is scheduled with 500 ms interval
  7. * A number of tasks are running every 1 second and "rolling the dice" 0..19. If 5, task is made to enter infinite loop
  8. * Device should reset in 2 seconds after a task enters infinite loop
  9. * A task id and a control point number are saved to EEPROM prior to device reset, and are displayed after reboot.
  10. * In real life, device might chose to NOT activate certain tasks which failed previously (failed sensors for instance)
  11. */
  12. #define _TASK_SLEEP_ON_IDLE_RUN
  13. #define _TASK_WDT_IDS
  14. #include <TaskScheduler.h>
  15. #include <EEPROM.h>
  16. #include <avr/wdt.h>
  17. Scheduler ts;
  18. // Callback methods prototypes
  19. void TaskCB();
  20. void HB(); bool HBOn(); void HBOff();
  21. // Three tasks emulating accidental infinite loop
  22. Task tTask1(TASK_SECOND, TASK_FOREVER, &TaskCB, &ts, true);
  23. Task tTask2(TASK_SECOND, TASK_FOREVER, &TaskCB, &ts, true);
  24. Task tTask3(TASK_SECOND, TASK_FOREVER, &TaskCB, &ts, true);
  25. // Heartbeat task - resetting the watchdog timer periodically
  26. // Initiates WDT on enable, and deactivates it on disable
  27. Task tHB(500, TASK_FOREVER, &HB, &ts, false, &HBOn, &HBOff);
  28. /**
  29. * Emulating task callback function
  30. * Prints task id and randomly "hangs" in two places.
  31. * Control points are stored on the task prior to section which might hang,
  32. * making this information available to the WDT interrupt handler
  33. */
  34. void TaskCB() {
  35. Task& T = ts.currentTask();
  36. Serial.print("Task #:");
  37. Serial.print(T.getId());
  38. Serial.print(" current iteration = ");
  39. Serial.println(T.getRunCounter());
  40. // Hang if random number between 0 and 19 is 5 (5% probability)
  41. T.setControlPoint(10);
  42. if (random(20) == 5) for(;;);
  43. // Hang if random number between 0 and 99 is more that 95 (5% probability)
  44. T.setControlPoint(95);
  45. if (random(100) > 94) for(;;);
  46. }
  47. /**
  48. * This On Enable method sets up the WDT
  49. * for interrupt and reset after 2 seconds
  50. */
  51. bool HBOn() {
  52. //disable interrupts
  53. cli();
  54. //reset watchdog
  55. wdt_reset();
  56. //set up WDT interrupt
  57. WDTCSR = (1<<WDCE)|(1<<WDE);
  58. //Start watchdog timer with aDelay prescaller
  59. WDTCSR = (1<<WDIE)|(1<<WDE)|(WDTO_2S & 0x2F);
  60. // WDTCSR = (1<<WDIE)|(WDTO_2S & 0x2F); // interrupt only without reset
  61. //Enable global interrupts
  62. sei();
  63. }
  64. /**
  65. * This On Disable method disables WDT
  66. */
  67. void HBOff() {
  68. wdt_disable();
  69. }
  70. /**
  71. * This is a periodic reset of WDT
  72. */
  73. void HB() {
  74. wdt_reset();
  75. }
  76. /**
  77. * Watchdog timeout ISR
  78. *
  79. */
  80. ISR(WDT_vect)
  81. {
  82. Task& T = ts.currentTask();
  83. digitalWrite(13, HIGH);
  84. EEPROM.write(0, (byte)T.getId());
  85. EEPROM.write(1, (byte)T.getControlPoint());
  86. digitalWrite(13, LOW);
  87. }
  88. /**
  89. * Standard arduino setup routine
  90. */
  91. void setup() {
  92. Serial.begin(115200);
  93. randomSeed(analogRead(0)+analogRead(5));
  94. pinMode(13, OUTPUT);
  95. digitalWrite(13, LOW);
  96. Serial.println("WDT heartbeat test");
  97. Serial.print("Last task before reset="); Serial.println(EEPROM.read(0));
  98. Serial.print("Last control point before reset="); Serial.println(EEPROM.read(1));
  99. delay(2000);
  100. tHB.enableDelayed();
  101. }
  102. /**
  103. * Not much is left for the loop()
  104. */
  105. void loop() {
  106. ts.execute();
  107. }