Skip to content

Commit 80cad52

Browse files
committed
Simple Watchdog
1 parent 1a97ec4 commit 80cad52

File tree

5 files changed

+69
-12
lines changed

5 files changed

+69
-12
lines changed

hardware/arduino/avr/cores/arduino/Arduino.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include <avr/interrupt.h>
3131

3232
#include "binary.h"
33+
#include "watchdog.h"
3334

3435
#ifdef __cplusplus
3536
extern "C"{
@@ -73,7 +74,7 @@ void yield(void);
7374
#define INTERNAL INTERNAL1V1
7475
#define INTERNAL2V56 9
7576
#define INTERNAL2V56_EXTCAP 13
76-
#else
77+
#else
7778
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega644__) || defined(__AVR_ATmega644A__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644PA__)
7879
#define INTERNAL1V1 2
7980
#define INTERNAL2V56 3
@@ -171,7 +172,7 @@ extern const uint8_t PROGMEM digital_pin_to_timer_PGM[];
171172

172173
// Get the bit location within the hardware port of the given virtual pin.
173174
// This comes from the pins_*.c file for the active board configuration.
174-
//
175+
//
175176
// These perform slightly better as macros compared to inline functions
176177
//
177178
#define digitalPinToPort(P) ( pgm_read_byte( digital_pin_to_port_PGM + (P) ) )

hardware/arduino/avr/cores/arduino/main.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,14 +39,14 @@ int main(void)
3939
#if defined(USBCON)
4040
USBDevice.attach();
4141
#endif
42-
42+
4343
setup();
44-
44+
4545
for (;;) {
4646
loop();
4747
if (serialEventRun) serialEventRun();
48+
watchdogReset();
4849
}
49-
50+
5051
return 0;
5152
}
52-
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#include <Arduino.h>
2+
3+
#define RESET_VECTOR ((void(*)()) 0)
4+
#define DEFAULT_TIMEOUT 5000
5+
#define DEFAULT_ONTIMEOUT RESET_VECTOR
6+
7+
static volatile uint16_t ticks = DEFAULT_TIMEOUT;
8+
static volatile uint16_t timeout = DEFAULT_TIMEOUT;
9+
static void (*onTimeout)() = DEFAULT_ONTIMEOUT;
10+
11+
void watchdogTimeout(uint16_t ms)
12+
{
13+
noInterrupts();
14+
timeout = ms;
15+
ticks = ms;
16+
interrupts();
17+
}
18+
19+
void watchdogOnTimeout(void (*function)())
20+
{
21+
noInterrupts();
22+
onTimeout = function;
23+
interrupts();
24+
}
25+
26+
void watchdogReset()
27+
{
28+
noInterrupts();
29+
ticks = timeout;
30+
interrupts();
31+
}
32+
33+
void watchdogTick()
34+
{
35+
if (--ticks) return;
36+
onTimeout();
37+
RESET_VECTOR();
38+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#ifndef watchdog_h
2+
#define watchdog_h
3+
4+
#ifdef __cplusplus
5+
extern "C"{
6+
#endif
7+
8+
void watchdogTimeout(uint16_t ms);
9+
void watchdogOnTimeout(void (*function)());
10+
void watchdogReset();
11+
void watchdogTick();
12+
13+
#ifdef __cplusplus
14+
} // extern "C"
15+
#endif
16+
#endif

hardware/arduino/avr/cores/arduino/wiring.c

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
*/
2222

2323
#include "wiring_private.h"
24+
#include "watchdog.h"
2425

2526
// the prescaler is set so that timer0 ticks every 64 clock cycles, and the
2627
// the overflow handler is called every 256 ticks.
@@ -60,6 +61,7 @@ ISR(TIMER0_OVF_vect)
6061
timer0_fract = f;
6162
timer0_millis = m;
6263
timer0_overflow_count++;
64+
watchdogTick();
6365
}
6466

6567
unsigned long millis()
@@ -79,7 +81,7 @@ unsigned long millis()
7981
unsigned long micros() {
8082
unsigned long m;
8183
uint8_t oldSREG = SREG, t;
82-
84+
8385
cli();
8486
m = timer0_overflow_count;
8587
#if defined(TCNT0)
@@ -99,7 +101,7 @@ unsigned long micros() {
99101
#endif
100102

101103
SREG = oldSREG;
102-
104+
103105
return ((m << 8) + t) * (64 / clockCyclesPerMicrosecond());
104106
}
105107

@@ -226,7 +228,7 @@ void delayMicroseconds(unsigned int us)
226228
// per iteration, so execute it us/4 times
227229
// us is at least 4, divided by 4 gives us 1 (no zero delay bug)
228230
us >>= 2; // us div 4, = 4 cycles
229-
231+
230232

231233
#endif
232234

@@ -243,7 +245,7 @@ void init()
243245
// this needs to be called before setup() or some functions won't
244246
// work there
245247
sei();
246-
248+
247249
// on the ATmega168, timer 0 is also used for fast hardware pwm
248250
// (using phase-correct PWM would mean that timer 0 overflowed half as often
249251
// resulting in different millis() behavior on the ATmega8 and ATmega168)
@@ -333,7 +335,7 @@ void init()
333335
sbi(TCCR4B, CS42); // set timer4 prescale factor to 64
334336
sbi(TCCR4B, CS41);
335337
sbi(TCCR4B, CS40);
336-
sbi(TCCR4D, WGM40); // put timer 4 in phase- and frequency-correct PWM mode
338+
sbi(TCCR4D, WGM40); // put timer 4 in phase- and frequency-correct PWM mode
337339
sbi(TCCR4A, PWM4A); // enable PWM mode for comparator OCR4A
338340
sbi(TCCR4C, PWM4D); // enable PWM mode for comparator OCR4D
339341
#else /* beginning of timer4 block for ATMEGA1280 and ATMEGA2560 */
@@ -342,7 +344,7 @@ void init()
342344
sbi(TCCR4B, CS40);
343345
sbi(TCCR4A, WGM40); // put timer 4 in 8-bit phase correct pwm mode
344346
#endif
345-
#endif /* end timer4 block for ATMEGA1280/2560 and similar */
347+
#endif /* end timer4 block for ATMEGA1280/2560 and similar */
346348

347349
#if defined(TCCR5B) && defined(CS51) && defined(WGM50)
348350
sbi(TCCR5B, CS51); // set timer 5 prescale factor to 64

0 commit comments

Comments
 (0)