Skip to content

Commit b617f99

Browse files
committed
Create Watchdog Timer (WDT) library
1 parent 57ce244 commit b617f99

File tree

7 files changed

+547
-0
lines changed

7 files changed

+547
-0
lines changed
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/*
2+
Author: Adam Garbo
3+
Created: February 1st, 2021
4+
License: MIT. See SparkFun Arduino Apollo3 Project for more information
5+
6+
This example demonstrates a simple configuration of the Artemis Watchdog Timer.
7+
8+
The code will configure the watchdog for both interrupt and reset generation,
9+
and immediately start the watchdog timer.
10+
11+
The watchdog ISR provided will 'pet' the watchdog four times. On the fifth
12+
interrupt, the watchdog will not be pet, so the 'reset' action can occur.
13+
On the sixth timeout event, the WDT will issue a system reset, and the
14+
program will start over from the beginning.
15+
16+
The watchdogCounter will show the number of ticks before the watchdog
17+
reset occurs.
18+
19+
This example is based on the Ambiq SDK 2.4.2 watchdog.c example.
20+
21+
Tested with SparkFun Artemis Redboard.
22+
*/
23+
24+
#include "WDT.h"
25+
26+
volatile bool watchdogFlag = false; // Watchdog Timer ISR flag
27+
volatile int watchdogInterrupt = 0; // Watchdog interrupt counter
28+
unsigned long currentMillis = 0,
29+
previousMillis = 0;
30+
31+
void setup() {
32+
33+
Serial.begin(115200);
34+
35+
Serial.println("Artemis Watchdog Timer Example");
36+
37+
// Start the watchdog
38+
WDT.start();
39+
}
40+
41+
void loop()
42+
{
43+
// Check for watchdog interrupts
44+
if (watchdogFlag)
45+
{
46+
// Calculate duration between watchdog interrupts
47+
currentMillis = millis() - previousMillis;
48+
previousMillis = millis();
49+
50+
Serial.print("Interrupt: "); Serial.print(watchdogInterrupt);
51+
Serial.print(" Period: "); Serial.print(currentMillis); Serial.println(" ms ");
52+
53+
if (watchdogInterrupt == 5)
54+
{
55+
Serial.println("Warning: Watchdog has triggered a system reset");
56+
}
57+
}
58+
watchdogFlag = false; // Clear watchdog flag
59+
delay(1);
60+
}
61+
62+
// Interrupt handler for the watchdog
63+
extern "C" void am_watchdog_isr(void)
64+
{
65+
// Clear the watchdog interrupt
66+
WDT.clear();
67+
68+
// Catch the first four watchdog interrupts, but let the fifth through untouched
69+
if ( watchdogInterrupt < 4 )
70+
{
71+
WDT.restart(); // "Pet" the dog
72+
}
73+
else {
74+
digitalWrite(LED_BUILTIN, HIGH); // Visual indication of system reset trigger
75+
}
76+
77+
watchdogFlag = true; // Set watchdog flag
78+
watchdogInterrupt++; // Increment watchdog interrupt counter
79+
}
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
/*
2+
Author: Adam Garbo
3+
Created: February 1st, 2021
4+
License: MIT. See SparkFun Arduino Apollo3 Project for more information
5+
6+
This example demonstrates how to modify the configuration of the Artemis
7+
Watchdog Timer (WDT).
8+
9+
The watchdog timer is controlled by a clock divider, interrupt ticks and
10+
reset ticks. To achieve desired watchdog timing, a simple calculation can be made:
11+
12+
period = # ticks / clock divider frequency
13+
14+
Examples:
15+
128 interrupt ticks / 128 Hz clock = 1 second
16+
64 interrupt ticks / 16 Hz clock = 4 seconds
17+
32 interrupt ticks / 1 Hz clock = 32 seconds
18+
16 interrupt ticks / 1/16 Hz clock = 256 seconds
19+
20+
The following code will configure the watchdog for both interrupt and reset
21+
generation, and immediately start the watchdog timer.
22+
The watchdog ISR provided will 'pet' the watchdog four times. On the fifth
23+
interrupt, the watchdog will not be pet, so the 'reset' action can occur.
24+
On the sixth timeout event, the WDT will issue a system reset, and the
25+
program will start over from the beginning.
26+
27+
This example is based on the Ambiq SDK 2.4.2 watchdog.c example.
28+
29+
Tested with SparkFun Artemis Redboard.
30+
*/
31+
32+
#include "WDT.h"
33+
34+
volatile bool watchdogFlag = false; // Watchdog Timer ISR flag
35+
volatile int watchdogInterrupt = 0; // Watchdog interrupt counter
36+
37+
unsigned long currentMillis = 0,
38+
previousMillis = 0;
39+
40+
void setup()
41+
{
42+
Serial.begin(115200);
43+
44+
Serial.println("Artemis Watchdog Timer Example");
45+
46+
// Configure the watchdog
47+
/*
48+
Available watchdog timer clock dividers.
49+
Users can choose either the clock definition (i.e. WDT_128HZ) or Apoll3 core enumeration (i.e. 1)
50+
WDT_OFF = 0 = Low Power Mode. This setting disables the watch dog timer
51+
WDT_128HZ = 1 = 128 Hz
52+
WDT_16HZ = 2 = 16 Hz
53+
WDT_1HZ = 3 = 1 Hz
54+
WDT1_16HZ = 4 = 1/16th Hz
55+
*/
56+
// Set watchdog timer clock to 128 Hz
57+
// Set watchdog interrupt to 1 seconds (128 ticks / 128 Hz = 1 second)
58+
// Set watchdog reset ~2 seconds (255 ticks / 128 Hz = 1.99 seconds)
59+
// Note: Ticks are limited to 255 (8-bit)
60+
WDT.configure(WDT_128HZ, 128, 255); // Equivalent to: wdt.configure(1, 128, 255);
61+
WDT.start(); // Start the watchdog
62+
}
63+
64+
void loop()
65+
{
66+
// Check for watchdog interrupts
67+
if (watchdogFlag)
68+
{
69+
// Calculate duration between watchdog interrupts
70+
currentMillis = millis() - previousMillis;
71+
previousMillis = millis();
72+
73+
Serial.print("Interrupt: "); Serial.print(watchdogInterrupt);
74+
Serial.print(" Period: "); Serial.print(currentMillis); Serial.println(" ms");
75+
76+
// The watchdog configurations can also be set individually
77+
WDT.setClock(WDT_16HZ); // Set watchdog timer clock to 16 Hz
78+
WDT.setInterrupt(64); // Set watchdog interrupt to 4 second (64 ticks / 16 Hz = 4 seconds)
79+
WDT.setReset(96); // Set watchdog reset to 8 seconds (96 ticks / 16 Hz = 8 seconds)
80+
81+
if (watchdogInterrupt == 9)
82+
{
83+
Serial.println("Warning: Watchdog has triggered a system reset");
84+
}
85+
}
86+
watchdogFlag = false; // Clear watchdog flag
87+
delay(1);
88+
}
89+
90+
// Interrupt handler for the watchdog
91+
extern "C" void am_watchdog_isr(void)
92+
{
93+
// Clear the watchdog interrupt
94+
WDT.clear();
95+
96+
// Catch the first eight watchdog interrupts, but let the ninth through untouched
97+
if ( watchdogInterrupt < 8 )
98+
{
99+
WDT.restart(); // "Pet" the dog
100+
}
101+
else
102+
{
103+
digitalWrite(LED_BUILTIN, HIGH); // Visual indication of system reset trigger
104+
}
105+
106+
watchdogFlag = true; // Set watchdog flag
107+
watchdogInterrupt++; // Increment watchdog interrupt counter
108+
}
Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
/*
2+
Author: Adam Garbo
3+
Created: February 1st, 2021
4+
License: MIT. See SparkFun Arduino Apollo3 Project for more information
5+
6+
This example demonstrates the combined use of the Artemis Watchdog Timer (WDT)
7+
and real-time clock (RTC).
8+
9+
Both RTC and WDT interrupts will wake the system, print the date and time,
10+
and then re-enter deep sleep.
11+
12+
The WDT is configured to trigger every 10 seconds. If the WDT is not "pet"
13+
after 100 seconds, a system reset will be triggered.
14+
15+
The RTC alarm is configured to trigger every minute and enter deep sleep
16+
between interrupts. Alarm interuptswill also restart the WDT and reset
17+
the watchdog interrput counter.
18+
*/
19+
20+
#include "RTC.h"
21+
#include "WDT.h"
22+
23+
volatile bool alarmFlag = false; // RTC ISR flag
24+
volatile bool watchdogFlag = false; // Watchdog Timer ISR flag
25+
volatile int watchdogInterrupt = 0; // Watchdog interrupt counter
26+
27+
void setup()
28+
{
29+
Serial.begin(115200);
30+
31+
Serial.println("Artemis Watchdog Low Power Example");
32+
33+
// Set the RTC time using UNIX Epoch time
34+
RTC.setEpoch(1596240000); // Saturday, August 1, 2020 00:00:00
35+
36+
// Set the RTC's alarm
37+
RTC.setAlarm(0, 0, 0, 0, 0, 0); // Set alarm (hund, ss, mm, hh, dd, mm)
38+
RTC.setAlarmMode(6); // Set the RTC alarm to trigger every minute
39+
RTC.attachInterrupt(); // Attach RTC alarm interrupt
40+
41+
// Configure the watchdog timer
42+
// See Example2_WDT_Config for more information on how to configure the watchdog
43+
WDT.configure(WDT_16HZ, 160, 240); // 16 Hz clock, 10-second interrupt period, 15-second reset period
44+
45+
// Start the watchdog
46+
WDT.start();
47+
}
48+
49+
void loop()
50+
{
51+
// Check for alarm interrupt
52+
if (alarmFlag)
53+
{
54+
Serial.print("Alarm interrupt: ");
55+
printDateTime(); // Print RTC's date and time
56+
alarmFlag = false;
57+
58+
wdt.restart(); // "Pet" the dog
59+
watchdogInterrupt = 0; // Reset watchdog interrupt counter
60+
}
61+
62+
// Check for watchdog interrupt
63+
if (watchdogFlag)
64+
{
65+
Serial.print("Watchdog interrupt: ");
66+
printDateTime(); // Print RTC's date and time
67+
watchdogFlag = false; // Clear watchdog flag
68+
}
69+
70+
goToSleep(); // Enter deep sleep
71+
}
72+
73+
// Print the RTC's current date and time
74+
void printDateTime()
75+
{
76+
rtc.getTime();
77+
Serial.printf("20%02d-%02d-%02d %02d:%02d:%02d.%02d\n",
78+
rtc.year, rtc.month, rtc.dayOfMonth,
79+
rtc.hour, rtc.minute, rtc.seconds, rtc.hundredths);
80+
}
81+
82+
// Power down gracefully
83+
void goToSleep()
84+
{
85+
// Disable UART
86+
Serial.end();
87+
88+
// Disable ADC
89+
power_adc_disable();
90+
91+
// Force the peripherals off
92+
am_hal_pwrctrl_periph_disable(AM_HAL_PWRCTRL_PERIPH_IOM0);
93+
am_hal_pwrctrl_periph_disable(AM_HAL_PWRCTRL_PERIPH_IOM1);
94+
am_hal_pwrctrl_periph_disable(AM_HAL_PWRCTRL_PERIPH_IOM2);
95+
am_hal_pwrctrl_periph_disable(AM_HAL_PWRCTRL_PERIPH_IOM3);
96+
am_hal_pwrctrl_periph_disable(AM_HAL_PWRCTRL_PERIPH_IOM4);
97+
am_hal_pwrctrl_periph_disable(AM_HAL_PWRCTRL_PERIPH_IOM5);
98+
am_hal_pwrctrl_periph_disable(AM_HAL_PWRCTRL_PERIPH_ADC);
99+
am_hal_pwrctrl_periph_disable(AM_HAL_PWRCTRL_PERIPH_UART0);
100+
am_hal_pwrctrl_periph_disable(AM_HAL_PWRCTRL_PERIPH_UART1);
101+
102+
// Disable all pads
103+
for (int x = 0 ; x < 50 ; x++)
104+
am_hal_gpio_pinconfig(x, g_AM_HAL_GPIO_DISABLE);
105+
106+
//Power down Flash, SRAM, cache
107+
am_hal_pwrctrl_memory_deepsleep_powerdown(AM_HAL_PWRCTRL_MEM_CACHE); // Turn off CACHE
108+
am_hal_pwrctrl_memory_deepsleep_powerdown(AM_HAL_PWRCTRL_MEM_FLASH_512K); // Turn off everything but lower 512k
109+
am_hal_pwrctrl_memory_deepsleep_powerdown(AM_HAL_PWRCTRL_MEM_SRAM_64K_DTCM); // Turn off everything but lower 64k
110+
//am_hal_pwrctrl_memory_deepsleep_powerdown(AM_HAL_PWRCTRL_MEM_ALL); //Turn off all memory (doesn't recover)
111+
112+
// Keep the 32kHz clock running for RTC
113+
am_hal_stimer_config(AM_HAL_STIMER_CFG_CLEAR | AM_HAL_STIMER_CFG_FREEZE);
114+
am_hal_stimer_config(AM_HAL_STIMER_XTAL_32KHZ);
115+
116+
am_hal_sysctrl_sleep(AM_HAL_SYSCTRL_SLEEP_DEEP); // Sleep forever
117+
118+
// And we're back!
119+
wakeUp();
120+
}
121+
122+
// Power up gracefully
123+
void wakeUp()
124+
{
125+
// Power up SRAM, turn on entire Flash
126+
am_hal_pwrctrl_memory_deepsleep_powerdown(AM_HAL_PWRCTRL_MEM_MAX);
127+
128+
// Go back to using the main clock
129+
am_hal_stimer_config(AM_HAL_STIMER_CFG_CLEAR | AM_HAL_STIMER_CFG_FREEZE);
130+
am_hal_stimer_config(AM_HAL_STIMER_HFRC_3MHZ);
131+
132+
// Enable ADC
133+
ap3_adc_setup();
134+
135+
// Enable Serial
136+
Serial.begin(115200);
137+
}
138+
139+
// Interrupt handler for the RTC
140+
extern "C" void am_rtc_isr(void)
141+
{
142+
// Clear the RTC alarm interrupt
143+
RTC.clearInterrupt();
144+
145+
alarmFlag = true; // Set alarm flag
146+
}
147+
148+
// Interrupt handler for the watchdog.
149+
extern "C" void am_watchdog_isr(void)
150+
{
151+
// Clear the watchdog interrupt
152+
WDT.clear();
153+
154+
// Perform system reset after 10 watchdog interrupts (should not occur)
155+
if ( watchdogInterrupt < 10 )
156+
{
157+
WDT.restart(); // "Pet" the dog
158+
}
159+
else {
160+
digitalWrite(LED_BUILTIN, HIGH); // Visual indication of system reset trigger
161+
}
162+
163+
watchdogFlag = true; // Set the watchdog flag
164+
watchdogInterrupt++; // Increment watchdog interrupt counter
165+
}

libraries/WDT/keywords.txt

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# Syntax Coloring Map For 'libraries/WDT'
2+
3+
# Datatypes (KEYWORD1)
4+
Apollo3WDT KEYWORD1
5+
6+
# Functions (KEYWORD2)
7+
configure KEYWORD2
8+
start KEYWORD2
9+
stop KEYWORD2
10+
restart KEYWORD2
11+
clear KEYWORD2
12+
getCounter KEYWORD2
13+
configure KEYWORD2
14+
setClock KEYWORD2
15+
setInterrupt KEYWORD2
16+
setReset KEYWORD2
17+
18+
# Structures (KEYWORD3)
19+
20+
# Constants (LITERAL1)
21+
_APOLLO3_LIBRARIES_WDT_H_ LITERAL1
22+
23+
# Properties (LITERAL2)
24+
WDT_OFF KEYWORD2
25+
WDT_128HZ KEYWORD2
26+
WDT_16 KEYWORD2
27+
WDT_1HZ KEYWORD2
28+
WDT1_16HZ KEYWORD2
29+
WDT LITERAL2

libraries/WDT/library.properties

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
name=WDT
2+
version=2.0.0
3+
author=SparkFun Electronics
4+
maintainer=SparkFun Electronics <sparkfun.com>
5+
sentence=Watchdog Timer (WDT) library for the SparkFun Artemis
6+
paragraph=Enables the setting and reading of the internal Watchdog Timer built into Apollo based modules like the Artemis.
7+
category=
8+
url=
9+
architectures=apollo3

0 commit comments

Comments
 (0)