Skip to content

Commit 73a813b

Browse files
committed
Add WDT configuration
1 parent e1a7d9b commit 73a813b

File tree

6 files changed

+139
-68
lines changed

6 files changed

+139
-68
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
Author: Adam Garbo
3-
Created: July 31st, 2020
3+
Created: August 1st, 2020
44
License: MIT. See SparkFun Arduino Apollo3 Project for more information
55
66
This example demonstrates a simple configuration of the Artemis Watchdog Timer.
@@ -10,20 +10,23 @@
1010
1111
The watchdog ISR provided will 'pet' the watchdog four times. On the fifth
1212
interrupt, the watchdog will not be pet, so the 'reset' action can occur.
13-
1413
On the sixth timeout event, the WDT will issue a system reset, and the
1514
program will start over from the beginning.
1615
16+
The watchdogCounter will show the number of ticks before the watchdog
17+
reset occurs.
18+
1719
This example is based on the Ambiq SDK 2.4.2 watchdog.c example.
20+
21+
Tested with SparkFun Artemis Redboard.
1822
*/
1923

2024
#include <WDT.h>
2125

2226
APM3_WDT wdt;
2327

2428
volatile bool watchdogFlag = false; // Watchdog Timer ISR flag
25-
volatile int watchdogCounter = 0; // Watchdog interrupt counter
26-
29+
volatile int watchdogInterrupt = 0; // Watchdog interrupt counter
2730
unsigned long currentMillis = 0,
2831
previousMillis = 0;
2932

@@ -33,42 +36,47 @@ void setup() {
3336

3437
Serial.println("Artemis Watchdog Timer Example");
3538

36-
// Configure the watchdog
37-
wdt.configure(); // Default interrupt: 5 seconds. Default reset: 15 seconds
38-
wdt.enable(); // Enable the watchdog
39+
// Start the watchdog
40+
wdt.start();
3941
}
4042

41-
void loop() {
42-
43+
void loop()
44+
{
4345
// Check for watchdog interrupts
44-
if (watchdogFlag) {
45-
46+
if (watchdogFlag)
47+
{
4648
// Calculate duration between watchdog interrupts
4749
currentMillis = millis() - previousMillis;
4850
previousMillis = millis();
4951

50-
Serial.print("Interrupt: "); Serial.print(watchdogCounter);
51-
Serial.print(" Period: "); Serial.println(currentMillis); Serial.print(" ms");
52+
Serial.print("Interrupt: "); Serial.print(watchdogInterrupt);
53+
Serial.print(" Period: "); Serial.print(currentMillis); Serial.println(" ms ");
54+
55+
if (watchdogInterrupt == 5)
56+
{
57+
Serial.println("Warning: Watchdog has triggered a system reset");
58+
}
5259
}
5360

5461
watchdogFlag = false; // Clear watchdog flag
55-
delay(10);
62+
delay(1);
5663
}
5764

5865
// Interrupt handler for the watchdog
59-
extern "C" void am_watchdog_isr(void) {
60-
66+
extern "C" void am_watchdog_isr(void)
67+
{
6168
// Clear the watchdog interrupt
6269
wdt.clear();
6370

6471
// Catch the first four watchdog interrupts, but let the fifth through untouched
65-
if ( watchdogCounter < 4 ) {
72+
if ( watchdogInterrupt < 4 )
73+
{
6674
wdt.restart(); // "Pet" the dog
6775
}
6876
else {
69-
digitalWrite(LED_BUILTIN, HIGH); // Visual indication of imminent system reset
77+
digitalWrite(LED_BUILTIN, HIGH); // Visual indication of system reset trigger
7078
}
7179

7280
watchdogFlag = true; // Set watchdog flag
73-
watchdogCounter++; // Increment watchdog interrupt counter
81+
watchdogInterrupt++; // Increment watchdog interrupt counter
7482
}
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,64 @@
11
/*
22
Author: Adam Garbo
3-
Created: July 31st, 2020
3+
Created: August 1st, 2020
44
License: MIT. See SparkFun Arduino Apollo3 Project for more information
55
6-
This example demonstrates how to modify the configuration of the Artemis
6+
This example demonstrates how to modify the configuration of the Artemis
77
Watchdog Timer (WDT).
88
9-
The code will configure the watchdog for both interrupt and reset generation,
10-
and immediately start the watchdog timer.
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:
1111
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.
1222
The watchdog ISR provided will 'pet' the watchdog four times. On the fifth
1323
interrupt, the watchdog will not be pet, so the 'reset' action can occur.
14-
1524
On the sixth timeout event, the WDT will issue a system reset, and the
1625
program will start over from the beginning.
1726
1827
This example is based on the Ambiq SDK 2.4.2 watchdog.c example.
28+
29+
Tested with SparkFun Artemis Redboard.
1930
*/
2031

2132
#include <WDT.h>
2233

2334
APM3_WDT wdt;
2435

2536
volatile bool watchdogFlag = false; // Watchdog Timer ISR flag
26-
volatile int watchdogCounter = 0; // Watchdog interrupt counter
37+
volatile int watchdogInterrupt = 0; // Watchdog interrupt counter
2738

2839
unsigned long currentMillis = 0,
2940
previousMillis = 0;
3041

31-
void setup()
42+
void setup()
3243
{
3344
Serial.begin(115200);
3445

3546
Serial.println("Artemis Watchdog Timer Example");
3647

3748
// Configure the watchdog
38-
wdt.configure(); // Default interrupt: 5 seconds. Default reset: 15 seconds
39-
wdt.start(); // Enable the watchdog
49+
/*
50+
Available watchdog timer clock dividers:
51+
0 = Low Power Mode. This setting disables the watch dog timer
52+
1 = 128 Hz
53+
2 = 16 Hz
54+
3 = 1 Hz
55+
4 = 1/16th Hz
56+
*/
57+
// Set watchdog timer clock to 128 Hz
58+
// Set watchdog interrupt to 1 seconds (128 ticks / 128 Hz = 1 second)
59+
// Set watchdog reset ~2 seconds (255 ticks / 128 Hz = 1.99 seconds)
60+
wdt.configure(1, 128, 255); // Note: Ticks are limited to 255 (8-bit)
61+
wdt.start(); // Start the watchdog
4062
}
4163

4264
void loop()
@@ -48,11 +70,16 @@ void loop()
4870
currentMillis = millis() - previousMillis;
4971
previousMillis = millis();
5072

51-
Serial.print("Interrupt: "); Serial.print(watchdogCounter);
73+
Serial.print("Interrupt: "); Serial.print(watchdogInterrupt);
5274
Serial.print(" Period: "); Serial.print(currentMillis); Serial.println(" ms");
75+
76+
// The watchdog configurations can also be set individually
77+
wdt.setClock(2); // 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)
5380
}
5481
watchdogFlag = false; // Clear watchdog flag
55-
delay(10);
82+
delay(1);
5683
}
5784

5885
// Interrupt handler for the watchdog
@@ -61,16 +88,16 @@ extern "C" void am_watchdog_isr(void)
6188
// Clear the watchdog interrupt
6289
wdt.clear();
6390

64-
// Catch the first four watchdog interrupts, but let the fifth through untouched
65-
if ( watchdogCounter < 4 )
91+
// Catch the first eight watchdog interrupts, but let the ninth through untouched
92+
if ( watchdogInterrupt < 8 )
6693
{
6794
wdt.restart(); // "Pet" the dog
6895
}
6996
else
7097
{
71-
digitalWrite(LED_BUILTIN, HIGH); // Visual indication of imminent system reset
98+
digitalWrite(LED_BUILTIN, HIGH); // Visual indication of system reset trigger
7299
}
73100

74101
watchdogFlag = true; // Set watchdog flag
75-
watchdogCounter++; // Increment watchdog interrupt counter
102+
watchdogInterrupt++; // Increment watchdog interrupt counter
76103
}

Diff for: libraries/WDT/examples/Example3_WDT_LowPower/Example3_WDT_LowPower.ino

+26-21
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
Author: Adam Garbo
3-
Created: July 31st, 2020
3+
Created: August 1st, 2020
44
License: MIT. See SparkFun Arduino Apollo3 Project for more information
55
66
This example demonstrates the combined use of the Artemis Watchdog Timer (WDT)
@@ -9,11 +9,12 @@
99
Both RTC and WDT interrupts will wake the system, print the date and time,
1010
and then re-enter deep sleep.
1111
12-
The code is configured to trigger the RTC alarm every minute and enter
13-
deep sleep between interrupts. Alarm interupts also restart the WDT and reset
14-
the watchdog counter.
15-
16-
If the WDT is not restarted after 75 seconds, a system reset will occur.
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.
1718
*/
1819

1920
#include <RTC.h>
@@ -24,49 +25,52 @@ APM3_WDT wdt;
2425

2526
volatile bool alarmFlag = false; // RTC ISR flag
2627
volatile bool watchdogFlag = false; // Watchdog Timer ISR flag
27-
volatile int watchdogCounter = 0; // Watchdog interrupt counter
28+
volatile int watchdogInterrupt = 0; // Watchdog interrupt counter
2829

2930
void setup()
3031
{
3132
Serial.begin(115200);
3233

3334
Serial.println("Artemis Watchdog Low Power Example");
3435

36+
// Set the RTC time using UNIX Epoch time
37+
rtc.setEpoch(1596240000); // Saturday, August 1, 2020 00:00:00
38+
3539
// Set the RTC's alarm
3640
rtc.setAlarm(0, 0, 0, 0, 0, 0); // Set alarm (hund, ss, mm, hh, dd, mm)
3741
rtc.setAlarmMode(6); // Set the RTC alarm to trigger every minute
3842
rtc.attachInterrupt(); // Attach RTC alarm interrupt
3943

40-
// Configure the watchdog
41-
wdt.configure(); // Default interrupt: 5 seconds. Default reset: 15 seconds
44+
// Configure the watchdog timer
45+
// See Example2_WDT_Config for more information on how to configure the watchdog
46+
wdt.configure(2, 160, 240); // 16 Hz clock, 10-second interrupt period, 15-second reset period
4247

43-
// Enable the watchdog
44-
wdt.enable();
48+
// Start the watchdog
49+
wdt.start();
4550
}
4651

4752
void loop()
4853
{
4954
// Check for alarm interrupt
5055
if (alarmFlag)
5156
{
52-
Serial.print("Alarm triggered: ");
57+
Serial.print("Alarm interrupt: ");
5358
printDateTime(); // Print RTC's date and time
5459
alarmFlag = false;
5560

5661
wdt.restart(); // "Pet" the dog
57-
watchdogCounter = 0; // Reset watchdog interrupt counter
62+
watchdogInterrupt = 0; // Reset watchdog interrupt counter
5863
}
5964

6065
// Check for watchdog interrupt
6166
if (watchdogFlag)
6267
{
63-
Serial.print("Watchdog triggered: ");
68+
Serial.print("Watchdog interrupt: ");
6469
printDateTime(); // Print RTC's date and time
6570
watchdogFlag = false; // Clear watchdog flag
6671
}
6772

6873
goToSleep(); // Enter deep sleep
69-
7074
}
7175

7276
// Print the RTC's current date and time
@@ -145,19 +149,20 @@ extern "C" void am_rtc_isr(void)
145149
}
146150

147151
// Interrupt handler for the watchdog.
148-
extern "C" void am_watchdog_isr(void) {
149-
152+
extern "C" void am_watchdog_isr(void)
153+
{
150154
// Clear the watchdog interrupt
151155
wdt.clear();
152156

153-
// Perform system reset after 15 watchdog interrupts (15 * 5 seconds = 75 seconds)
154-
if ( watchdogCounter < 20 ) {
157+
// Perform system reset after 10 watchdog interrupts (should not occur)
158+
if ( watchdogInterrupt < 10 )
159+
{
155160
wdt.restart(); // "Pet" the dog
156161
}
157162
else {
158-
digitalWrite(LED_BUILTIN, HIGH); // Visual indication of system reset
163+
digitalWrite(LED_BUILTIN, HIGH); // Visual indication of system reset trigger
159164
}
160165

161166
watchdogFlag = true; // Set the watchdog flag
162-
watchdogCounter++; // Increment watchdog interrupt counter
167+
watchdogInterrupt++; // Increment watchdog interrupt counter
163168
}

Diff for: libraries/WDT/keywords.txt

+5
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@ start KEYWORD2
1717
stop KEYWORD2
1818
restart KEYWORD2
1919
clear KEYWORD2
20+
getCounter KEYWORD2
21+
configure KEYWORD2
22+
setClock KEYWORD2
23+
setInterrupt KEYWORD2
24+
setReset KEYWORD2
2025

2126
#######################################
2227
# Constants (LITERAL1)

Diff for: libraries/WDT/src/WDT.cpp

+31-8
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,37 @@
1-
/*
2-
3-
*/
4-
51
#include "WDT.h"
62

73
// Constructor
84
APM3_WDT::APM3_WDT()
95
{
106
// The watchdog only runs off of the LFRC
117
am_hal_clkgen_control(AM_HAL_CLKGEN_CONTROL_LFRC_START, 0);
8+
am_hal_wdt_init(&watchdogConfig);
9+
}
10+
11+
// Configure the watchdog timer
12+
void APM3_WDT::configure(uint8_t clock, uint8_t interrupt, uint8_t reset)
13+
{
14+
WDT->CFG_b.CLKSEL = clock;
15+
WDT->CFG_b.INTVAL = interrupt;
16+
WDT->CFG_b.RESVAL = reset;
17+
}
18+
19+
// Set the LFRC clock frequency of the watchdog timer
20+
void APM3_WDT::setClock(uint8_t clock)
21+
{
22+
WDT->CFG_b.CLKSEL = clock;
1223
}
1324

25+
// Set number of watchdog timer ticks allowed before a watchdog interrupt event is generated
26+
void APM3_WDT::setInterrupt(uint8_t interrupt)
27+
{
28+
WDT->CFG_b.INTVAL = interrupt;
29+
}
1430

15-
// Configure the watchdog
16-
void APM3_WDT::configure()
31+
// Set number of watchdog timer ticks allowed before the watchdog will issue a system reset
32+
void APM3_WDT::setReset(uint8_t reset)
1733
{
18-
am_hal_wdt_init(&watchdogConfig);
34+
WDT->CFG_b.RESVAL = reset;
1935
}
2036

2137
// Enable the watchdog
@@ -46,4 +62,11 @@ void APM3_WDT::restart()
4662
void APM3_WDT::clear()
4763
{
4864
am_hal_wdt_int_clear();
49-
}
65+
}
66+
67+
// Read the current value of watch dog timer counter register
68+
uint32_t APM3_WDT::getCounter()
69+
{
70+
return am_hal_wdt_counter_get();
71+
}
72+

0 commit comments

Comments
 (0)