From 2ca5c57f368104b0112035403e52710504d63040 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Fri, 26 Jun 2020 13:51:36 -0600 Subject: [PATCH 01/17] Create keywords.txt --- keywords.txt | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 keywords.txt diff --git a/keywords.txt b/keywords.txt new file mode 100644 index 00000000..b4bd5ad9 --- /dev/null +++ b/keywords.txt @@ -0,0 +1,39 @@ +####################################### +# Syntax Coloring Map For Wire +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +enableBurstMode KEYWORD2 +disableBurstMode KEYWORD2 +getCpuFreqMHz KEYWORD2 + +getInternalTemp KEYWORD2 + +analogWriteResolution KEYWORD2 +analogWriteFrameWidth KEYWORD2 +analogWriteFrequency KEYWORD2 +servoWrite KEYWORD2 + +enableFastShift KEYWORD2 +fastShiftOut KEYWORD2 +fastShiftIn KEYWORD2 + +secs KEYWORD2 +systicks KEYWORD2 +sysoverflows KEYWORD2 + +####################################### +# Instances (KEYWORD2) +####################################### + +####################################### +# Constants (LITERAL1) +####################################### + From 9072743637d085c4f272d17cf83377aeb49fa1a5 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Fri, 10 Jul 2020 16:19:03 -0600 Subject: [PATCH 02/17] Correct typo in HAL --- cores/arduino/am_sdk_ap3/mcu/apollo3/hal/am_hal_uart.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cores/arduino/am_sdk_ap3/mcu/apollo3/hal/am_hal_uart.h b/cores/arduino/am_sdk_ap3/mcu/apollo3/hal/am_hal_uart.h index 6e515f57..4bb78a8e 100644 --- a/cores/arduino/am_sdk_ap3/mcu/apollo3/hal/am_hal_uart.h +++ b/cores/arduino/am_sdk_ap3/mcu/apollo3/hal/am_hal_uart.h @@ -172,8 +172,8 @@ am_hal_uart_transfer_t; // Flow control #define AM_HAL_UART_FLOW_CTRL_NONE 0 -#define AM_HAL_UART_FLOW_CTRL_CTS_ONLY UART_CR_CTSEN_Msk -#define AM_HAL_UART_FLOW_CTRL_RTS_ONLY UART_CR_RTSEN_Msk +#define AM_HAL_UART_FLOW_CTRL_CTS_ONLY UART0_CR_CTSEN_Msk +#define AM_HAL_UART_FLOW_CTRL_RTS_ONLY UART0_CR_RTSEN_Msk #define AM_HAL_UART_FLOW_CTRL_RTS_CTS (UART0_CR_CTSEN_Msk | \ UART0_CR_RTSEN_Msk) // FIFO enable/disable. From ddda09eda92c339e8e6c0737cefaf4ab0d1ffbec Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Fri, 10 Jul 2020 16:19:39 -0600 Subject: [PATCH 03/17] Add checking of RTS/CTS pins to enable flow control. Fix typo in _begin(). --- cores/arduino/ard_sup/uart/ap3_uart.cpp | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/cores/arduino/ard_sup/uart/ap3_uart.cpp b/cores/arduino/ard_sup/uart/ap3_uart.cpp index 0724371a..2ba32cd5 100644 --- a/cores/arduino/ard_sup/uart/ap3_uart.cpp +++ b/cores/arduino/ard_sup/uart/ap3_uart.cpp @@ -296,6 +296,22 @@ ap3_err_t Uart::set_config(HardwareSerial_Config_e HWSconfig) retval = AP3_INVALID_ARG; break; } + + //Setup flow control + _config.ui32FlowControl = AM_HAL_UART_FLOW_CTRL_NONE; + if(_pinRTS != AP3_UART_PIN_UNUSED && _pinCTS != AP3_UART_PIN_UNUSED) + { + _config.ui32FlowControl = AM_HAL_UART_FLOW_CTRL_RTS_CTS; + } + else if(_pinRTS != AP3_UART_PIN_UNUSED) + { + _config.ui32FlowControl = AM_HAL_UART_FLOW_CTRL_RTS_ONLY; + } + else if(_pinCTS != AP3_UART_PIN_UNUSED) + { + _config.ui32FlowControl = AM_HAL_UART_FLOW_CTRL_CTS_ONLY; + } + return retval; } @@ -375,7 +391,7 @@ ap3_err_t Uart::_begin(void) if (_pinRTS != AP3_UART_PIN_UNUSED) { - retval = ap3_uart_pad_funcsel(_instance, AP3_UART_TX, ap3_gpio_pin2pad(_pinRTS), &funcsel); + retval = ap3_uart_pad_funcsel(_instance, AP3_UART_RTS, ap3_gpio_pin2pad(_pinRTS), &funcsel); if (retval != AP3_OK) { return retval; @@ -391,7 +407,7 @@ ap3_err_t Uart::_begin(void) if (_pinCTS != AP3_UART_PIN_UNUSED) { - retval = ap3_uart_pad_funcsel(_instance, AP3_UART_RX, ap3_gpio_pin2pad(_pinCTS), &funcsel); + retval = ap3_uart_pad_funcsel(_instance, AP3_UART_CTS, ap3_gpio_pin2pad(_pinCTS), &funcsel); if (retval != AP3_OK) { return retval; From ece522dd49b016d16cf14f736b1682c3cc08c9a1 Mon Sep 17 00:00:00 2001 From: stephenf7072 <57785167+stephenf7072@users.noreply.github.com> Date: Fri, 24 Jul 2020 09:36:28 +1000 Subject: [PATCH 04/17] Removed code using non-core library (ie. Epoch stuff) I hate to undo even a little bit of Adam's good work, but in the interests of a robust core, I think it's best the references to time.h are removed, and the Epoch set/get along with it. RTC.cpp included , which caused a compilation error when these are also included in code: #include #include Some possible issues with Window lack of case sensitivity, refer here: https://forum.arduino.cc/index.php?topic=451360.0 Also with time.h (or Time.h?) being an optional extra install library to the Arduino IDE, best to leave it out of the core, especially if it can cause compilation errors. --- .../Example4_Set_Epoch/Example4_Set_Epoch.ino | 41 ------------------- libraries/RTC/keywords.txt | 2 - libraries/RTC/src/RTC.cpp | 41 ------------------- libraries/RTC/src/RTC.h | 2 - 4 files changed, 86 deletions(-) delete mode 100644 libraries/RTC/examples/Example4_Set_Epoch/Example4_Set_Epoch.ino diff --git a/libraries/RTC/examples/Example4_Set_Epoch/Example4_Set_Epoch.ino b/libraries/RTC/examples/Example4_Set_Epoch/Example4_Set_Epoch.ino deleted file mode 100644 index 04dd33d5..00000000 --- a/libraries/RTC/examples/Example4_Set_Epoch/Example4_Set_Epoch.ino +++ /dev/null @@ -1,41 +0,0 @@ -/* - Author: Adam Garbo and Nathan Seidle - Created: June 3rd, 2020 - License: MIT. See SparkFun Arduino Apollo3 Project for more information - - This example demonstrates how to set the RTC using UNIX Epoch time. -*/ - -#include "RTC.h" // Include RTC library included with the Aruino_Apollo3 core -APM3_RTC myRTC; // Create instance of RTC class - -void setup() -{ - Serial.begin(115200); - Serial.println("SparkFun RTC Set UNIX Epoch Time Example"); - - // Set the RTC time using UNIX Epoch time - myRTC.setEpoch(1591185600); // E.g. 12:00:00, June 3rd, 2020 -} - -void loop() -{ - // Print UNIX Epoch timestamp - Serial.print("Epoch time: "); Serial.println(myRTC.getEpoch()); - - // Print RTC's date and time - Serial.print("Timestamp: "); printDateTime(); - - delay(1000); -} - -// Print the RTC's current date and time -void printDateTime() -{ - myRTC.getTime(); - char dateTime[20]; - sprintf(dateTime, "20%02d-%02d-%02d %02d:%02d:%02d", - myRTC.year, myRTC.month, myRTC.dayOfMonth, - myRTC.hour, myRTC.minute, myRTC.seconds); - Serial.println(dateTime); -} diff --git a/libraries/RTC/keywords.txt b/libraries/RTC/keywords.txt index 6b719deb..e6831ec9 100644 --- a/libraries/RTC/keywords.txt +++ b/libraries/RTC/keywords.txt @@ -13,11 +13,9 @@ RTC KEYWORD1 ####################################### getTime KEYWORD2 -getEpoch KEYWORD2 setTime KEYWORD2 setTimeToCompiler KEYWORD2 -setEpoch KEYWORD2 getAlarm KEYWORD2 setAlarm KEYWORD2 diff --git a/libraries/RTC/src/RTC.cpp b/libraries/RTC/src/RTC.cpp index c15eec3c..6ec16a53 100644 --- a/libraries/RTC/src/RTC.cpp +++ b/libraries/RTC/src/RTC.cpp @@ -3,7 +3,6 @@ */ #include "RTC.h" -#include am_hal_rtc_time_t hal_time; am_hal_rtc_time_t alm_time; @@ -89,28 +88,6 @@ void APM3_RTC::setToCompilerTime() getTime(); } -void APM3_RTC::setEpoch(uint32_t ts) -{ - if (ts < EPOCH_TIME) { - ts = EPOCH_TIME; - } - - struct tm tm; - - time_t t = ts; - struct tm* tmp = gmtime(&t); - hal_time.ui32Weekday = 0; - hal_time.ui32Century = 0; - hal_time.ui32Year = tmp->tm_year - 100; - hal_time.ui32Month = tmp->tm_mon + 1; - hal_time.ui32DayOfMonth = tmp->tm_mday; - hal_time.ui32Hour = tmp->tm_hour; - hal_time.ui32Minute = tmp->tm_min; - hal_time.ui32Second = tmp->tm_sec; - hal_time.ui32Hundredths = 0; - - am_hal_rtc_time_set(&hal_time); //Initialize the RTC with this date/time -} void APM3_RTC::getTime() { @@ -127,24 +104,6 @@ void APM3_RTC::getTime() hundredths = hal_time.ui32Hundredths; } -uint32_t APM3_RTC::getEpoch() -{ - am_hal_rtc_time_get(&hal_time); - - struct tm tm; - - tm.tm_isdst = -1; - tm.tm_yday = 0; - tm.tm_wday = 0; - tm.tm_year = hal_time.ui32Year + 100; //Number of years since 1900. - tm.tm_mon = hal_time.ui32Month - 1; //mktime is expecting 0 to 11 months - tm.tm_mday = hal_time.ui32DayOfMonth; - tm.tm_hour = hal_time.ui32Hour; - tm.tm_min = hal_time.ui32Minute; - tm.tm_sec = hal_time.ui32Second; - - return mktime(&tm); -} void APM3_RTC::getAlarm() { diff --git a/libraries/RTC/src/RTC.h b/libraries/RTC/src/RTC.h index 93cede37..f52cbee6 100644 --- a/libraries/RTC/src/RTC.h +++ b/libraries/RTC/src/RTC.h @@ -9,12 +9,10 @@ class APM3_RTC APM3_RTC(); void getTime(); //Query the RTC for the current time/date - uint32_t getEpoch(); //Return the current RTC time/date as UNIX Epoch time void setTime(uint8_t hour, uint8_t min, uint8_t sec, uint8_t hund, uint8_t dayOfMonth, uint8_t month, uint16_t year); //Set current time to provided hundredths/seconds/etc void setToCompilerTime(); //Set to time when sketch was compiled - void setEpoch(uint32_t ts); //Set current time to provided UNIX Epoch time void getAlarm(); //Query the RTC for the current alarm time/date void setAlarm(uint8_t hour, uint8_t min, uint8_t sec, uint8_t hund, uint8_t dayOfMonth, uint8_t month); //Set alarm time to provided hundredths/seconds/etc From 847eb3d6dd3ee33e2b3ea506d95056bf23d64dc8 Mon Sep 17 00:00:00 2001 From: stephenf7072 <57785167+stephenf7072@users.noreply.github.com> Date: Fri, 24 Jul 2020 11:32:07 +1000 Subject: [PATCH 05/17] Create Example8_ResetsAndWatchdog.ino --- .../Example8_ResetsAndWatchdog.ino | 196 ++++++++++++++++++ 1 file changed, 196 insertions(+) create mode 100644 libraries/Examples/examples/Example8_ResetsAndWatchdog/Example8_ResetsAndWatchdog.ino diff --git a/libraries/Examples/examples/Example8_ResetsAndWatchdog/Example8_ResetsAndWatchdog.ino b/libraries/Examples/examples/Example8_ResetsAndWatchdog/Example8_ResetsAndWatchdog.ino new file mode 100644 index 00000000..81a1e0d5 --- /dev/null +++ b/libraries/Examples/examples/Example8_ResetsAndWatchdog/Example8_ResetsAndWatchdog.ino @@ -0,0 +1,196 @@ +/* Author: Stephen Fordyce (adapted from WDT example code by Adam Garbo - https://forum.sparkfun.com/viewtopic.php?f=169&t=52431&p=213296&hilit=watchdog#p213296) + Created: 24th July 2020 + License: MIT. See SparkFun Arduino Apollo3 Project for more information + + This example demonstrates use of the watchdog timer, also different ways of resetting the Artemis as well as how to determine the last reset type +*/ + +// Global variables +volatile uint8_t watchdogCounter = 0; // Watchdog interrupt counter +uint32_t resetStatus = 0; // Reset status register +bool testWatchdogResetFlag = false; +bool watchdogInterruptCallsEmergencyReset = false; +bool resetWDTEveryLoop = true; + +// Watchdog timer configuration structure. +am_hal_wdt_config_t g_sWatchdogConfig = { + //Substitude other values for AM_HAL_WDT_LFRC_CLK_16HZ to increase/decrease the range + .ui32Config = AM_HAL_WDT_LFRC_CLK_16HZ | AM_HAL_WDT_ENABLE_RESET | AM_HAL_WDT_ENABLE_INTERRUPT, // Configuration values for generated watchdog timer event. + //****** EVEN THOUGH THESE IMPLY 16-BIT, THEY ARE ONLY 8-BIT - 255 MAX! + .ui16InterruptCount = 120, //MAX 255! // Set WDT interrupt timeout for 5 seconds (120 / 16 = 8). // Number of watchdog timer ticks allowed before a watchdog interrupt event is generated. + .ui16ResetCount = 160 //MAX 255! // Set WDT reset timeout for 15 seconds (160 / 16 = 10). // Number of watchdog timer ticks allowed before the watchdog will issue a system reset. +}; + +void setup(void) +{ + pinMode(LED_BUILTIN, OUTPUT); + Serial.begin(115200); delay(10); + Serial.println();Serial.println(); + Serial.println("****Artemis Reset & Watchdog Reset Example****"); + + printResetReason(); //Explain reason for reset + am_hal_reset_control(AM_HAL_RESET_CONTROL_STATUSCLEAR, 0); // Clear reset status register for next time we reset. + delay(1000); + + startWatchdogTimer(); //Initialise and start the watchdog timer, in case the program gets stuck in a while loop or waiting for user input + printWatchdogDetails(); + delay(2000); + + Serial.println("\nRunning a time-consuming loop with watchdog running"); + for(int i=0; i<5; i++) + { + delay(1000); //Phew, a bunch of hard processing + printWatchdogValue(); + } + Serial.println("Yikes, the time kept increasing, even though we were doing legitimate work\n"); + + Serial.println("\nRunning a time-consuming loop that restarts the watchdog timer each loop"); + for(int i=0; i<5; i++) + { + delay(1000); //Phew, a bunch of hard processing + printWatchdogValue(); + am_hal_wdt_restart(); // "Pet" the dog. // Restart the watchdog. + } + Serial.println("Plenty of time, but the watchdog timer will still catch a freeze\n"); + delay(2000); +} + +void loop(void) +{ + Serial.println("Start of loop()"); + if(resetWDTEveryLoop) + am_hal_wdt_restart(); // "Pet" the dog. // Restart the watchdog. (every loop run seems good) + + if(resetWDTEveryLoop) + { + Serial.println("Enter 'r' to do a scheduled software reset"); + Serial.println("Enter 's' to stop resetting the watchdog timer each loop"); + delay(1000); + char option = Serial.read(); + if(option == 'r') + myScheduledReset(); + if(option == 's') + { + Serial.println("I take no responsibility for the consequences!"); + Serial.println("(the watchdog interrupt routine when triggered will reset the timer 3 times, watch the timer values to see when it's reset by the ISR)"); + delay(2000); + resetWDTEveryLoop = false; + } + } + + if(resetWDTEveryLoop == false) + { + Serial.println("Enter 'e' to let the watchdog interrupt call emergencyReset()"); + delay(1000); + char option = Serial.read(); + if(option == 'e') + { + Serial.println("Cool, that'll happen in a sec"); delay(20); + watchdogInterruptCallsEmergencyReset = true; + } + } + + if(testWatchdogResetFlag) + { + Serial.println("Just about to go down the rabbit hole..."); + delay(20); //Let serial buffer clear + while(1); //Intentionally get stuck, and hope that the watchdog timer saves the day + } + + printWatchdogValue(); + Serial.println(); + delay(10); + + //Optional code for sleeping - just halt the WDT before you disable everything, then re-initialise the WDT after waking up. Tested elsewhere, and does not have any appreciable impact on sleep currents or performance + //am_hal_wdt_halt(); + //sleepForABit(); + //startWatchdog(); +} + +// Interrupt handler for the watchdog. +extern "C" void am_watchdog_isr(void) +{ + am_hal_wdt_int_clear(); // Clear the watchdog interrupt. + if(watchdogInterruptCallsEmergencyReset) + emergencyReset(); + + if ( watchdogCounter < 3 ) // Catch the first three watchdog interrupts, but let the fourth through untouched. + { + digitalWrite(LED_BUILTIN, LOW); + am_hal_wdt_restart(); // "Pet" the dog (reset the timer) + } + else + { + digitalWrite(LED_BUILTIN, HIGH); // Indicator that a reset will occur. + testWatchdogResetFlag = true; + } + + watchdogCounter++; // Increment the number of watchdog interrupts. +} + +void startWatchdogTimer() +{ + am_hal_clkgen_control(AM_HAL_CLKGEN_CONTROL_LFRC_START, 0); // LFRC must be turned on for this example as the watchdog only runs off of the LFRC. + am_hal_wdt_init(&g_sWatchdogConfig); // Configure the watchdog. + NVIC_EnableIRQ(WDT_IRQn); // Enable the interrupt for the watchdog in the NVIC. + am_hal_interrupt_master_enable(); + am_hal_wdt_start(); // Enable the watchdog. +} + +//IMPORTANT: IF THIS IS CALLED BY THE WATCHDOG TIMER INTERRUPT ROUTINE, IT NEEDS TO BE QUICK (NO PRINTING TO SERIAL OR DELAYS) +void emergencyReset() +{ + //Optional: write some bits to flash/EEPROM to help with recovery + + am_hal_reset_control(AM_HAL_RESET_CONTROL_SWPOI,0); //Reset with option "Software Power On Initialization" SWPOI +// am_hal_reset_control(AM_HAL_RESET_CONTROL_SWPOR,0); //Reset with option SWPOR (same as SWPOI but different am_hal_reset_status bit) +} + +void myScheduledReset() +{ + //Optional: write some bits to flash/EEPROM to help with recovery + +// am_hal_reset_control(AM_HAL_RESET_CONTROL_SWPOI,0); //Reset with option "Software Power On Initialization" SWPOI + am_hal_reset_control(AM_HAL_RESET_CONTROL_SWPOR,0); //Reset with option SWPOR (same as SWPOI but different am_hal_reset_status bit) +} + +void printWatchdogDetails() +{ + Serial.print("Interrupt Count = "); Serial.print(g_sWatchdogConfig.ui16InterruptCount ); Serial.println(" ticks"); + Serial.print("Reset Count = "); Serial.print(g_sWatchdogConfig.ui16ResetCount); Serial.println(" ticks"); + + // Print out reset status register. + am_hal_reset_status_t sStatus; // (Note: See am_hal_reset.h for RESET status structure) + am_hal_reset_status_get(&sStatus); + resetStatus = sStatus.eStatus; + char rStatus[30]; + sprintf(rStatus, "Reset Status Register = 0x%x", resetStatus); // (Note: Watch Dog Timer reset = 0x40) + Serial.println(rStatus); +} + +void printWatchdogValue() +{ + Serial.print("Watchdog timer:"); + Serial.println(am_hal_wdt_counter_get()); +} + +void printResetReason() +{ + am_hal_reset_status_t resetResult; + uint32_t resultOk = am_hal_reset_status_get(&resetResult); + Serial.print("Reset reason: "); + if(resultOk == AM_HAL_STATUS_FAIL) Serial.println("Failed to get reset status"); + if(resetResult.bEXTStat) Serial.println("External reset"); + if(resetResult.bPORStat) Serial.println("Power-On reset"); + if(resetResult.bBODStat) Serial.println("Brown-Out reset"); + if(resetResult.bSWPORStat) Serial.println("SW Power-On reset or AIRCR reset - in this example, indicates reset by myScheduledReset()"); + if(resetResult.bSWPOIStat) Serial.println("SW Power On Initialization reset - in this example, indicates reset by emergencyReset()"); + if(resetResult.bDBGRStat) Serial.println("Debugger reset"); + if(resetResult.bWDTStat) Serial.println("Watch Dog Timer reset - nothing in the Watchdog Timer Interrupt routine got to restarting the Watchdog Timer"); + if(resetResult.bBOUnregStat) Serial.println("Unregulated Supply Brownout event"); + if(resetResult.bBOCOREStat) Serial.println("Core Regulator Brownout event"); + if(resetResult.bBOMEMStat) Serial.println("Memory Regulator Brownout event"); + if(resetResult.bBOBLEStat) Serial.println("BLE/Burst Regulator Brownout event"); +// am_hal_reset_control(AM_HAL_RESET_CONTROL_STATUSCLEAR, 0); // (do this in setup() Clear reset status register for next time we reset. + Serial.println(); +} From 38d783d864a4bcdd4b9c9e909e82fd8b0c4592fb Mon Sep 17 00:00:00 2001 From: Adam Date: Mon, 27 Jul 2020 15:10:05 -0400 Subject: [PATCH 06/17] Create WDT.h --- libraries/WDT/src/WDT.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 libraries/WDT/src/WDT.h diff --git a/libraries/WDT/src/WDT.h b/libraries/WDT/src/WDT.h new file mode 100644 index 00000000..d405d340 --- /dev/null +++ b/libraries/WDT/src/WDT.h @@ -0,0 +1,12 @@ +#ifndef WDT_H +#define WDT_H + +#include + +class APM3_WDT +{ +public: + APM3_WDT(); + +}; +#endif //WDT_H From d9139331ed92467183d4180a0b971f1ef959546d Mon Sep 17 00:00:00 2001 From: Adam Date: Mon, 27 Jul 2020 15:10:07 -0400 Subject: [PATCH 07/17] Create WDT.cpp --- libraries/WDT/src/WDT.cpp | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 libraries/WDT/src/WDT.cpp diff --git a/libraries/WDT/src/WDT.cpp b/libraries/WDT/src/WDT.cpp new file mode 100644 index 00000000..5057dab7 --- /dev/null +++ b/libraries/WDT/src/WDT.cpp @@ -0,0 +1,6 @@ +/* + +*/ + +#include "WDT.h" + From f8d1fb9ddcf87c3f100ecc286bb862c0da9e68b4 Mon Sep 17 00:00:00 2001 From: Adam Date: Mon, 27 Jul 2020 15:10:09 -0400 Subject: [PATCH 08/17] Create library.properties --- libraries/WDT/library.properties | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 libraries/WDT/library.properties diff --git a/libraries/WDT/library.properties b/libraries/WDT/library.properties new file mode 100644 index 00000000..bc7d8dab --- /dev/null +++ b/libraries/WDT/library.properties @@ -0,0 +1,9 @@ +name=WDT +version=0.1 +author=SparkFun Electronics +maintainer=SparkFun Electronics +sentence=Watchdog Timer (WDT) library for the SparkFun Artemis +paragraph=Enables the setting and reading of the internal Watchdog Timer built into Apollo based modules like the Artemis. +category= +url= +architectures=apollo3 From fd8e357bd8d9fbf51c577c6931942053d1f116bd Mon Sep 17 00:00:00 2001 From: Adam Date: Mon, 27 Jul 2020 15:10:12 -0400 Subject: [PATCH 09/17] Create keywords.txt --- libraries/WDT/keywords.txt | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 libraries/WDT/keywords.txt diff --git a/libraries/WDT/keywords.txt b/libraries/WDT/keywords.txt new file mode 100644 index 00000000..93e703fb --- /dev/null +++ b/libraries/WDT/keywords.txt @@ -0,0 +1,18 @@ +####################################### +# Syntax Coloring Map +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +WDT KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + + +####################################### +# Constants (LITERAL1) +####################################### From 57c81bdb20f211b6943cf811c964f6b8e4e1e2e8 Mon Sep 17 00:00:00 2001 From: stephenf7072 <57785167+stephenf7072@users.noreply.github.com> Date: Thu, 30 Jul 2020 13:56:53 +1000 Subject: [PATCH 10/17] Revert "Removed code using non-core library (ie. Epoch stuff)" This reverts commit ece522dd49b016d16cf14f736b1682c3cc08c9a1. --- .../Example4_Set_Epoch/Example4_Set_Epoch.ino | 41 +++++++++++++++++++ libraries/RTC/keywords.txt | 2 + libraries/RTC/src/RTC.cpp | 41 +++++++++++++++++++ libraries/RTC/src/RTC.h | 2 + 4 files changed, 86 insertions(+) create mode 100644 libraries/RTC/examples/Example4_Set_Epoch/Example4_Set_Epoch.ino diff --git a/libraries/RTC/examples/Example4_Set_Epoch/Example4_Set_Epoch.ino b/libraries/RTC/examples/Example4_Set_Epoch/Example4_Set_Epoch.ino new file mode 100644 index 00000000..04dd33d5 --- /dev/null +++ b/libraries/RTC/examples/Example4_Set_Epoch/Example4_Set_Epoch.ino @@ -0,0 +1,41 @@ +/* + Author: Adam Garbo and Nathan Seidle + Created: June 3rd, 2020 + License: MIT. See SparkFun Arduino Apollo3 Project for more information + + This example demonstrates how to set the RTC using UNIX Epoch time. +*/ + +#include "RTC.h" // Include RTC library included with the Aruino_Apollo3 core +APM3_RTC myRTC; // Create instance of RTC class + +void setup() +{ + Serial.begin(115200); + Serial.println("SparkFun RTC Set UNIX Epoch Time Example"); + + // Set the RTC time using UNIX Epoch time + myRTC.setEpoch(1591185600); // E.g. 12:00:00, June 3rd, 2020 +} + +void loop() +{ + // Print UNIX Epoch timestamp + Serial.print("Epoch time: "); Serial.println(myRTC.getEpoch()); + + // Print RTC's date and time + Serial.print("Timestamp: "); printDateTime(); + + delay(1000); +} + +// Print the RTC's current date and time +void printDateTime() +{ + myRTC.getTime(); + char dateTime[20]; + sprintf(dateTime, "20%02d-%02d-%02d %02d:%02d:%02d", + myRTC.year, myRTC.month, myRTC.dayOfMonth, + myRTC.hour, myRTC.minute, myRTC.seconds); + Serial.println(dateTime); +} diff --git a/libraries/RTC/keywords.txt b/libraries/RTC/keywords.txt index e6831ec9..6b719deb 100644 --- a/libraries/RTC/keywords.txt +++ b/libraries/RTC/keywords.txt @@ -13,9 +13,11 @@ RTC KEYWORD1 ####################################### getTime KEYWORD2 +getEpoch KEYWORD2 setTime KEYWORD2 setTimeToCompiler KEYWORD2 +setEpoch KEYWORD2 getAlarm KEYWORD2 setAlarm KEYWORD2 diff --git a/libraries/RTC/src/RTC.cpp b/libraries/RTC/src/RTC.cpp index 6ec16a53..c15eec3c 100644 --- a/libraries/RTC/src/RTC.cpp +++ b/libraries/RTC/src/RTC.cpp @@ -3,6 +3,7 @@ */ #include "RTC.h" +#include am_hal_rtc_time_t hal_time; am_hal_rtc_time_t alm_time; @@ -88,6 +89,28 @@ void APM3_RTC::setToCompilerTime() getTime(); } +void APM3_RTC::setEpoch(uint32_t ts) +{ + if (ts < EPOCH_TIME) { + ts = EPOCH_TIME; + } + + struct tm tm; + + time_t t = ts; + struct tm* tmp = gmtime(&t); + hal_time.ui32Weekday = 0; + hal_time.ui32Century = 0; + hal_time.ui32Year = tmp->tm_year - 100; + hal_time.ui32Month = tmp->tm_mon + 1; + hal_time.ui32DayOfMonth = tmp->tm_mday; + hal_time.ui32Hour = tmp->tm_hour; + hal_time.ui32Minute = tmp->tm_min; + hal_time.ui32Second = tmp->tm_sec; + hal_time.ui32Hundredths = 0; + + am_hal_rtc_time_set(&hal_time); //Initialize the RTC with this date/time +} void APM3_RTC::getTime() { @@ -104,6 +127,24 @@ void APM3_RTC::getTime() hundredths = hal_time.ui32Hundredths; } +uint32_t APM3_RTC::getEpoch() +{ + am_hal_rtc_time_get(&hal_time); + + struct tm tm; + + tm.tm_isdst = -1; + tm.tm_yday = 0; + tm.tm_wday = 0; + tm.tm_year = hal_time.ui32Year + 100; //Number of years since 1900. + tm.tm_mon = hal_time.ui32Month - 1; //mktime is expecting 0 to 11 months + tm.tm_mday = hal_time.ui32DayOfMonth; + tm.tm_hour = hal_time.ui32Hour; + tm.tm_min = hal_time.ui32Minute; + tm.tm_sec = hal_time.ui32Second; + + return mktime(&tm); +} void APM3_RTC::getAlarm() { diff --git a/libraries/RTC/src/RTC.h b/libraries/RTC/src/RTC.h index f52cbee6..93cede37 100644 --- a/libraries/RTC/src/RTC.h +++ b/libraries/RTC/src/RTC.h @@ -9,10 +9,12 @@ class APM3_RTC APM3_RTC(); void getTime(); //Query the RTC for the current time/date + uint32_t getEpoch(); //Return the current RTC time/date as UNIX Epoch time void setTime(uint8_t hour, uint8_t min, uint8_t sec, uint8_t hund, uint8_t dayOfMonth, uint8_t month, uint16_t year); //Set current time to provided hundredths/seconds/etc void setToCompilerTime(); //Set to time when sketch was compiled + void setEpoch(uint32_t ts); //Set current time to provided UNIX Epoch time void getAlarm(); //Query the RTC for the current alarm time/date void setAlarm(uint8_t hour, uint8_t min, uint8_t sec, uint8_t hund, uint8_t dayOfMonth, uint8_t month); //Set alarm time to provided hundredths/seconds/etc From 66b6e6e17fd9c5dcc71e5ade7a1f4d4827912f48 Mon Sep 17 00:00:00 2001 From: Adam Date: Thu, 30 Jul 2020 10:03:40 -0400 Subject: [PATCH 11/17] Update WDT.h --- libraries/WDT/src/WDT.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libraries/WDT/src/WDT.h b/libraries/WDT/src/WDT.h index d405d340..b592a45c 100644 --- a/libraries/WDT/src/WDT.h +++ b/libraries/WDT/src/WDT.h @@ -8,5 +8,11 @@ class APM3_WDT public: APM3_WDT(); + void configure(uint32_t clock, uint16_t interrupt, uint16_t reset); // Configure watchdog + void enable(); // Enable the watchdog + void disable(); // Disable the watchdog + void restart(); // Restart the watchdog + void clear() // Clear the watchdog interrupt + }; #endif //WDT_H From 331b8d767f4d8a09fb093254dccb9a2481d17a6d Mon Sep 17 00:00:00 2001 From: Adam Date: Thu, 30 Jul 2020 10:03:44 -0400 Subject: [PATCH 12/17] Update WDT.cpp --- libraries/WDT/src/WDT.cpp | 41 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/libraries/WDT/src/WDT.cpp b/libraries/WDT/src/WDT.cpp index 5057dab7..6e21738f 100644 --- a/libraries/WDT/src/WDT.cpp +++ b/libraries/WDT/src/WDT.cpp @@ -4,3 +4,44 @@ #include "WDT.h" +// Constructor +APM3_WDT::APM3_WDT() +{ + // The watchdog only runs off of the LFRC + am_hal_clkgen_control(AM_HAL_CLKGEN_CONTROL_LFRC_START, 0); +} + + +// Configure the watchdog +void APM3_WDT::configure(clock, interrupt, reset) +{ + +} + +// Enable the watchdog +void APM3_WDT::enable() +{ + // Enable the interrupt for the watchdog in the NVIC + NVIC_EnableIRQ(WDT_IRQn); + am_hal_wdt_start(); +} + +// Disable the watchdog +void APM3_WDT::disable() +{ + // Enable the interrupt for the watchdog in the NVIC + NVIC_DisableIRQ(WDT_IRQn); + am_hal_wdt_int_disable(); +} + +// Restart the watchdog +void APM3_WDT::restart() +{ + am_hal_wdt_restart(); +} + +// Clear the watchdog interrupt +void APM3_WDT::clear() +{ + am_hal_wdt_int_clear(); +} \ No newline at end of file From 453196de0ab15c53297eb8100b605061d93c8c8b Mon Sep 17 00:00:00 2001 From: oclyke Date: Thu, 30 Jul 2020 09:17:42 -0600 Subject: [PATCH 13/17] rename example this keeps room around for the legacy BLE led example --- .../Example8_ResetsAndWatchdog.ino | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename libraries/Examples/examples/{Example8_ResetsAndWatchdog => Example9_ResetsAndWatchdog}/Example8_ResetsAndWatchdog.ino (100%) diff --git a/libraries/Examples/examples/Example8_ResetsAndWatchdog/Example8_ResetsAndWatchdog.ino b/libraries/Examples/examples/Example9_ResetsAndWatchdog/Example8_ResetsAndWatchdog.ino similarity index 100% rename from libraries/Examples/examples/Example8_ResetsAndWatchdog/Example8_ResetsAndWatchdog.ino rename to libraries/Examples/examples/Example9_ResetsAndWatchdog/Example8_ResetsAndWatchdog.ino From 03ae6404db944a241a8c2edf14614ec88ae35a2b Mon Sep 17 00:00:00 2001 From: oclyke Date: Thu, 30 Jul 2020 09:19:58 -0600 Subject: [PATCH 14/17] rename the actual file --- ...mple8_ResetsAndWatchdog.ino => Example9_ResetsAndWatchdog.ino} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename libraries/Examples/examples/Example9_ResetsAndWatchdog/{Example8_ResetsAndWatchdog.ino => Example9_ResetsAndWatchdog.ino} (100%) diff --git a/libraries/Examples/examples/Example9_ResetsAndWatchdog/Example8_ResetsAndWatchdog.ino b/libraries/Examples/examples/Example9_ResetsAndWatchdog/Example9_ResetsAndWatchdog.ino similarity index 100% rename from libraries/Examples/examples/Example9_ResetsAndWatchdog/Example8_ResetsAndWatchdog.ino rename to libraries/Examples/examples/Example9_ResetsAndWatchdog/Example9_ResetsAndWatchdog.ino From e1a7d9b4bb6065e6521b8a524a60ab7622704cb0 Mon Sep 17 00:00:00 2001 From: Adam Date: Fri, 31 Jul 2020 17:15:33 -0400 Subject: [PATCH 15/17] Add examples --- .../Example1_WDT_Basic/Example1_WDT_Basic.ino | 74 ++++++++ .../Example2_WDT_Config.ino | 76 ++++++++ .../Example3_WDT_LowPower.ino | 163 ++++++++++++++++++ libraries/WDT/keywords.txt | 5 + libraries/WDT/src/WDT.cpp | 14 +- libraries/WDT/src/WDT.h | 23 ++- 6 files changed, 344 insertions(+), 11 deletions(-) create mode 100644 libraries/WDT/examples/Example1_WDT_Basic/Example1_WDT_Basic.ino create mode 100644 libraries/WDT/examples/Example2_WDT_Config/Example2_WDT_Config.ino create mode 100644 libraries/WDT/examples/Example3_WDT_LowPower/Example3_WDT_LowPower.ino diff --git a/libraries/WDT/examples/Example1_WDT_Basic/Example1_WDT_Basic.ino b/libraries/WDT/examples/Example1_WDT_Basic/Example1_WDT_Basic.ino new file mode 100644 index 00000000..1f37e948 --- /dev/null +++ b/libraries/WDT/examples/Example1_WDT_Basic/Example1_WDT_Basic.ino @@ -0,0 +1,74 @@ +/* + Author: Adam Garbo + Created: July 31st, 2020 + License: MIT. See SparkFun Arduino Apollo3 Project for more information + + This example demonstrates a simple configuration of the Artemis Watchdog Timer. + + The code will configure the watchdog for both interrupt and reset generation, + and immediately start the watchdog timer. + + The watchdog ISR provided will 'pet' the watchdog four times. On the fifth + interrupt, the watchdog will not be pet, so the 'reset' action can occur. + + On the sixth timeout event, the WDT will issue a system reset, and the + program will start over from the beginning. + + This example is based on the Ambiq SDK 2.4.2 watchdog.c example. +*/ + +#include + +APM3_WDT wdt; + +volatile bool watchdogFlag = false; // Watchdog Timer ISR flag +volatile int watchdogCounter = 0; // Watchdog interrupt counter + +unsigned long currentMillis = 0, + previousMillis = 0; + +void setup() { + + Serial.begin(115200); + + Serial.println("Artemis Watchdog Timer Example"); + + // Configure the watchdog + wdt.configure(); // Default interrupt: 5 seconds. Default reset: 15 seconds + wdt.enable(); // Enable the watchdog +} + +void loop() { + + // Check for watchdog interrupts + if (watchdogFlag) { + + // Calculate duration between watchdog interrupts + currentMillis = millis() - previousMillis; + previousMillis = millis(); + + Serial.print("Interrupt: "); Serial.print(watchdogCounter); + Serial.print(" Period: "); Serial.println(currentMillis); Serial.print(" ms"); + } + + watchdogFlag = false; // Clear watchdog flag + delay(10); +} + +// Interrupt handler for the watchdog +extern "C" void am_watchdog_isr(void) { + + // Clear the watchdog interrupt + wdt.clear(); + + // Catch the first four watchdog interrupts, but let the fifth through untouched + if ( watchdogCounter < 4 ) { + wdt.restart(); // "Pet" the dog + } + else { + digitalWrite(LED_BUILTIN, HIGH); // Visual indication of imminent system reset + } + + watchdogFlag = true; // Set watchdog flag + watchdogCounter++; // Increment watchdog interrupt counter +} diff --git a/libraries/WDT/examples/Example2_WDT_Config/Example2_WDT_Config.ino b/libraries/WDT/examples/Example2_WDT_Config/Example2_WDT_Config.ino new file mode 100644 index 00000000..5623a867 --- /dev/null +++ b/libraries/WDT/examples/Example2_WDT_Config/Example2_WDT_Config.ino @@ -0,0 +1,76 @@ +/* + Author: Adam Garbo + Created: July 31st, 2020 + License: MIT. See SparkFun Arduino Apollo3 Project for more information + + This example demonstrates how to modify the configuration of the Artemis + Watchdog Timer (WDT). + + The code will configure the watchdog for both interrupt and reset generation, + and immediately start the watchdog timer. + + The watchdog ISR provided will 'pet' the watchdog four times. On the fifth + interrupt, the watchdog will not be pet, so the 'reset' action can occur. + + On the sixth timeout event, the WDT will issue a system reset, and the + program will start over from the beginning. + + This example is based on the Ambiq SDK 2.4.2 watchdog.c example. +*/ + +#include + +APM3_WDT wdt; + +volatile bool watchdogFlag = false; // Watchdog Timer ISR flag +volatile int watchdogCounter = 0; // Watchdog interrupt counter + +unsigned long currentMillis = 0, + previousMillis = 0; + +void setup() +{ + Serial.begin(115200); + + Serial.println("Artemis Watchdog Timer Example"); + + // Configure the watchdog + wdt.configure(); // Default interrupt: 5 seconds. Default reset: 15 seconds + wdt.start(); // Enable the watchdog +} + +void loop() +{ + // Check for watchdog interrupts + if (watchdogFlag) + { + // Calculate duration between watchdog interrupts + currentMillis = millis() - previousMillis; + previousMillis = millis(); + + Serial.print("Interrupt: "); Serial.print(watchdogCounter); + Serial.print(" Period: "); Serial.print(currentMillis); Serial.println(" ms"); + } + watchdogFlag = false; // Clear watchdog flag + delay(10); +} + +// Interrupt handler for the watchdog +extern "C" void am_watchdog_isr(void) +{ + // Clear the watchdog interrupt + wdt.clear(); + + // Catch the first four watchdog interrupts, but let the fifth through untouched + if ( watchdogCounter < 4 ) + { + wdt.restart(); // "Pet" the dog + } + else + { + digitalWrite(LED_BUILTIN, HIGH); // Visual indication of imminent system reset + } + + watchdogFlag = true; // Set watchdog flag + watchdogCounter++; // Increment watchdog interrupt counter +} diff --git a/libraries/WDT/examples/Example3_WDT_LowPower/Example3_WDT_LowPower.ino b/libraries/WDT/examples/Example3_WDT_LowPower/Example3_WDT_LowPower.ino new file mode 100644 index 00000000..b47cb229 --- /dev/null +++ b/libraries/WDT/examples/Example3_WDT_LowPower/Example3_WDT_LowPower.ino @@ -0,0 +1,163 @@ +/* + Author: Adam Garbo + Created: July 31st, 2020 + License: MIT. See SparkFun Arduino Apollo3 Project for more information + + This example demonstrates the combined use of the Artemis Watchdog Timer (WDT) + and real-time clock (RTC). + + Both RTC and WDT interrupts will wake the system, print the date and time, + and then re-enter deep sleep. + + The code is configured to trigger the RTC alarm every minute and enter + deep sleep between interrupts. Alarm interupts also restart the WDT and reset + the watchdog counter. + + If the WDT is not restarted after 75 seconds, a system reset will occur. +*/ + +#include +#include + +APM3_RTC rtc; +APM3_WDT wdt; + +volatile bool alarmFlag = false; // RTC ISR flag +volatile bool watchdogFlag = false; // Watchdog Timer ISR flag +volatile int watchdogCounter = 0; // Watchdog interrupt counter + +void setup() +{ + Serial.begin(115200); + + Serial.println("Artemis Watchdog Low Power Example"); + + // Set the RTC's alarm + rtc.setAlarm(0, 0, 0, 0, 0, 0); // Set alarm (hund, ss, mm, hh, dd, mm) + rtc.setAlarmMode(6); // Set the RTC alarm to trigger every minute + rtc.attachInterrupt(); // Attach RTC alarm interrupt + + // Configure the watchdog + wdt.configure(); // Default interrupt: 5 seconds. Default reset: 15 seconds + + // Enable the watchdog + wdt.enable(); +} + +void loop() +{ + // Check for alarm interrupt + if (alarmFlag) + { + Serial.print("Alarm triggered: "); + printDateTime(); // Print RTC's date and time + alarmFlag = false; + + wdt.restart(); // "Pet" the dog + watchdogCounter = 0; // Reset watchdog interrupt counter + } + + // Check for watchdog interrupt + if (watchdogFlag) + { + Serial.print("Watchdog triggered: "); + printDateTime(); // Print RTC's date and time + watchdogFlag = false; // Clear watchdog flag + } + + goToSleep(); // Enter deep sleep + +} + +// Print the RTC's current date and time +void printDateTime() +{ + rtc.getTime(); + Serial.printf("20%02d-%02d-%02d %02d:%02d:%02d.%02d\n", + rtc.year, rtc.month, rtc.dayOfMonth, + rtc.hour, rtc.minute, rtc.seconds, rtc.hundredths); +} + +// Power down gracefully +void goToSleep() +{ + // Disable UART + Serial.end(); + + // Disable ADC + power_adc_disable(); + + // Force the peripherals off + am_hal_pwrctrl_periph_disable(AM_HAL_PWRCTRL_PERIPH_IOM0); + am_hal_pwrctrl_periph_disable(AM_HAL_PWRCTRL_PERIPH_IOM1); + am_hal_pwrctrl_periph_disable(AM_HAL_PWRCTRL_PERIPH_IOM2); + am_hal_pwrctrl_periph_disable(AM_HAL_PWRCTRL_PERIPH_IOM3); + am_hal_pwrctrl_periph_disable(AM_HAL_PWRCTRL_PERIPH_IOM4); + am_hal_pwrctrl_periph_disable(AM_HAL_PWRCTRL_PERIPH_IOM5); + am_hal_pwrctrl_periph_disable(AM_HAL_PWRCTRL_PERIPH_ADC); + am_hal_pwrctrl_periph_disable(AM_HAL_PWRCTRL_PERIPH_UART0); + am_hal_pwrctrl_periph_disable(AM_HAL_PWRCTRL_PERIPH_UART1); + + // Disable all pads + for (int x = 0 ; x < 50 ; x++) + am_hal_gpio_pinconfig(x, g_AM_HAL_GPIO_DISABLE); + + //Power down Flash, SRAM, cache + am_hal_pwrctrl_memory_deepsleep_powerdown(AM_HAL_PWRCTRL_MEM_CACHE); // Turn off CACHE + am_hal_pwrctrl_memory_deepsleep_powerdown(AM_HAL_PWRCTRL_MEM_FLASH_512K); // Turn off everything but lower 512k + am_hal_pwrctrl_memory_deepsleep_powerdown(AM_HAL_PWRCTRL_MEM_SRAM_64K_DTCM); // Turn off everything but lower 64k + //am_hal_pwrctrl_memory_deepsleep_powerdown(AM_HAL_PWRCTRL_MEM_ALL); //Turn off all memory (doesn't recover) + + // Keep the 32kHz clock running for RTC + am_hal_stimer_config(AM_HAL_STIMER_CFG_CLEAR | AM_HAL_STIMER_CFG_FREEZE); + am_hal_stimer_config(AM_HAL_STIMER_XTAL_32KHZ); + + am_hal_sysctrl_sleep(AM_HAL_SYSCTRL_SLEEP_DEEP); // Sleep forever + + // And we're back! + wakeUp(); +} + +// Power up gracefully +void wakeUp() +{ + // Power up SRAM, turn on entire Flash + am_hal_pwrctrl_memory_deepsleep_powerdown(AM_HAL_PWRCTRL_MEM_MAX); + + // Go back to using the main clock + am_hal_stimer_config(AM_HAL_STIMER_CFG_CLEAR | AM_HAL_STIMER_CFG_FREEZE); + am_hal_stimer_config(AM_HAL_STIMER_HFRC_3MHZ); + + // Enable ADC + ap3_adc_setup(); + + // Enable Serial + Serial.begin(115200); +} + +// Interrupt handler for the RTC +extern "C" void am_rtc_isr(void) +{ + // Clear the RTC alarm interrupt + am_hal_rtc_int_clear(AM_HAL_RTC_INT_ALM); + + alarmFlag = true; // Set alarm flag +} + +// Interrupt handler for the watchdog. +extern "C" void am_watchdog_isr(void) { + + // Clear the watchdog interrupt + wdt.clear(); + + // Perform system reset after 15 watchdog interrupts (15 * 5 seconds = 75 seconds) + if ( watchdogCounter < 20 ) { + wdt.restart(); // "Pet" the dog + } + else { + digitalWrite(LED_BUILTIN, HIGH); // Visual indication of system reset + } + + watchdogFlag = true; // Set the watchdog flag + watchdogCounter++; // Increment watchdog interrupt counter +} diff --git a/libraries/WDT/keywords.txt b/libraries/WDT/keywords.txt index 93e703fb..8da692b7 100644 --- a/libraries/WDT/keywords.txt +++ b/libraries/WDT/keywords.txt @@ -12,6 +12,11 @@ WDT KEYWORD1 # Methods and Functions (KEYWORD2) ####################################### +configure KEYWORD2 +start KEYWORD2 +stop KEYWORD2 +restart KEYWORD2 +clear KEYWORD2 ####################################### # Constants (LITERAL1) diff --git a/libraries/WDT/src/WDT.cpp b/libraries/WDT/src/WDT.cpp index 6e21738f..c2c8bd07 100644 --- a/libraries/WDT/src/WDT.cpp +++ b/libraries/WDT/src/WDT.cpp @@ -13,13 +13,13 @@ APM3_WDT::APM3_WDT() // Configure the watchdog -void APM3_WDT::configure(clock, interrupt, reset) +void APM3_WDT::configure() { - + am_hal_wdt_init(&watchdogConfig); } // Enable the watchdog -void APM3_WDT::enable() +void APM3_WDT::start() { // Enable the interrupt for the watchdog in the NVIC NVIC_EnableIRQ(WDT_IRQn); @@ -27,11 +27,13 @@ void APM3_WDT::enable() } // Disable the watchdog -void APM3_WDT::disable() +void APM3_WDT::stop() { - // Enable the interrupt for the watchdog in the NVIC + // Disable the interrupt for the watchdog in the NVIC NVIC_DisableIRQ(WDT_IRQn); - am_hal_wdt_int_disable(); + // Disable the watchdog timer tick by clearing the 'enable' bit in the + // watchdog configuration register + am_hal_wdt_halt(); } // Restart the watchdog diff --git a/libraries/WDT/src/WDT.h b/libraries/WDT/src/WDT.h index b592a45c..46baadfe 100644 --- a/libraries/WDT/src/WDT.h +++ b/libraries/WDT/src/WDT.h @@ -8,11 +8,24 @@ class APM3_WDT public: APM3_WDT(); - void configure(uint32_t clock, uint16_t interrupt, uint16_t reset); // Configure watchdog - void enable(); // Enable the watchdog - void disable(); // Disable the watchdog - void restart(); // Restart the watchdog - void clear() // Clear the watchdog interrupt + // Watchdog timer configuration structure + am_hal_wdt_config_t watchdogConfig = { + + // Configuration values for generated watchdog timer event. + .ui32Config = AM_HAL_WDT_LFRC_CLK_16HZ | AM_HAL_WDT_ENABLE_RESET | AM_HAL_WDT_ENABLE_INTERRUPT, + + // Number of watchdog timer ticks allowed before a watchdog interrupt event is generated + .ui16InterruptCount = 16 * 5, // Set WDT interrupt timeout for 5 seconds (16 * 5) / 16 = 5 + + // Number of watchdog timer ticks allowed before the watchdog will issue a system reset + .ui16ResetCount = 16 * 10 // Set WDT reset timeout for 15 seconds (16 * 10 ) / 16 = 10 + }; + + void configure(); // Configure watchdog + void start(); // Starts the watchdog timer + void stop(); // Disables the watchdog timer + void restart(); // Restarts the watchdog timer ("Pets" the dog) + void clear(); // Clears the watchdog interrupt }; #endif //WDT_H From 73a813bd4bdfe05434de6dedd0eaf4edf5dbc86d Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 1 Aug 2020 10:37:48 -0400 Subject: [PATCH 16/17] Add WDT configuration --- .../Example1_WDT_Basic/Example1_WDT_Basic.ino | 46 ++++++++------- .../Example2_WDT_Config.ino | 57 ++++++++++++++----- .../Example3_WDT_LowPower.ino | 47 ++++++++------- libraries/WDT/keywords.txt | 5 ++ libraries/WDT/src/WDT.cpp | 39 ++++++++++--- libraries/WDT/src/WDT.h | 13 +++-- 6 files changed, 139 insertions(+), 68 deletions(-) diff --git a/libraries/WDT/examples/Example1_WDT_Basic/Example1_WDT_Basic.ino b/libraries/WDT/examples/Example1_WDT_Basic/Example1_WDT_Basic.ino index 1f37e948..f392d228 100644 --- a/libraries/WDT/examples/Example1_WDT_Basic/Example1_WDT_Basic.ino +++ b/libraries/WDT/examples/Example1_WDT_Basic/Example1_WDT_Basic.ino @@ -1,6 +1,6 @@ /* Author: Adam Garbo - Created: July 31st, 2020 + Created: August 1st, 2020 License: MIT. See SparkFun Arduino Apollo3 Project for more information This example demonstrates a simple configuration of the Artemis Watchdog Timer. @@ -10,11 +10,15 @@ The watchdog ISR provided will 'pet' the watchdog four times. On the fifth interrupt, the watchdog will not be pet, so the 'reset' action can occur. - On the sixth timeout event, the WDT will issue a system reset, and the program will start over from the beginning. + The watchdogCounter will show the number of ticks before the watchdog + reset occurs. + This example is based on the Ambiq SDK 2.4.2 watchdog.c example. + + Tested with SparkFun Artemis Redboard. */ #include @@ -22,8 +26,7 @@ APM3_WDT wdt; volatile bool watchdogFlag = false; // Watchdog Timer ISR flag -volatile int watchdogCounter = 0; // Watchdog interrupt counter - +volatile int watchdogInterrupt = 0; // Watchdog interrupt counter unsigned long currentMillis = 0, previousMillis = 0; @@ -33,42 +36,47 @@ void setup() { Serial.println("Artemis Watchdog Timer Example"); - // Configure the watchdog - wdt.configure(); // Default interrupt: 5 seconds. Default reset: 15 seconds - wdt.enable(); // Enable the watchdog + // Start the watchdog + wdt.start(); } -void loop() { - +void loop() +{ // Check for watchdog interrupts - if (watchdogFlag) { - + if (watchdogFlag) + { // Calculate duration between watchdog interrupts currentMillis = millis() - previousMillis; previousMillis = millis(); - Serial.print("Interrupt: "); Serial.print(watchdogCounter); - Serial.print(" Period: "); Serial.println(currentMillis); Serial.print(" ms"); + Serial.print("Interrupt: "); Serial.print(watchdogInterrupt); + Serial.print(" Period: "); Serial.print(currentMillis); Serial.println(" ms "); + + if (watchdogInterrupt == 5) + { + Serial.println("Warning: Watchdog has triggered a system reset"); + } } watchdogFlag = false; // Clear watchdog flag - delay(10); + delay(1); } // Interrupt handler for the watchdog -extern "C" void am_watchdog_isr(void) { - +extern "C" void am_watchdog_isr(void) +{ // Clear the watchdog interrupt wdt.clear(); // Catch the first four watchdog interrupts, but let the fifth through untouched - if ( watchdogCounter < 4 ) { + if ( watchdogInterrupt < 4 ) + { wdt.restart(); // "Pet" the dog } else { - digitalWrite(LED_BUILTIN, HIGH); // Visual indication of imminent system reset + digitalWrite(LED_BUILTIN, HIGH); // Visual indication of system reset trigger } watchdogFlag = true; // Set watchdog flag - watchdogCounter++; // Increment watchdog interrupt counter + watchdogInterrupt++; // Increment watchdog interrupt counter } diff --git a/libraries/WDT/examples/Example2_WDT_Config/Example2_WDT_Config.ino b/libraries/WDT/examples/Example2_WDT_Config/Example2_WDT_Config.ino index 5623a867..ec6aa678 100644 --- a/libraries/WDT/examples/Example2_WDT_Config/Example2_WDT_Config.ino +++ b/libraries/WDT/examples/Example2_WDT_Config/Example2_WDT_Config.ino @@ -1,21 +1,32 @@ /* Author: Adam Garbo - Created: July 31st, 2020 + Created: August 1st, 2020 License: MIT. See SparkFun Arduino Apollo3 Project for more information - This example demonstrates how to modify the configuration of the Artemis + This example demonstrates how to modify the configuration of the Artemis Watchdog Timer (WDT). - The code will configure the watchdog for both interrupt and reset generation, - and immediately start the watchdog timer. + The watchdog timer is controlled by a clock divider, interrupt ticks and + reset ticks. To achieve desired watchdog timing, a simple calculation can be made: + period = # ticks / clock divider frequency + + Examples: + 128 interrupt ticks / 128 Hz clock = 1 second + 64 interrupt ticks / 16 Hz clock = 4 seconds + 32 interrupt ticks / 1 Hz clock = 32 seconds + 16 interrupt ticks / 1/16 Hz clock = 256 seconds + + The following code will configure the watchdog for both interrupt and reset + generation, and immediately start the watchdog timer. The watchdog ISR provided will 'pet' the watchdog four times. On the fifth interrupt, the watchdog will not be pet, so the 'reset' action can occur. - On the sixth timeout event, the WDT will issue a system reset, and the program will start over from the beginning. This example is based on the Ambiq SDK 2.4.2 watchdog.c example. + + Tested with SparkFun Artemis Redboard. */ #include @@ -23,20 +34,31 @@ APM3_WDT wdt; volatile bool watchdogFlag = false; // Watchdog Timer ISR flag -volatile int watchdogCounter = 0; // Watchdog interrupt counter +volatile int watchdogInterrupt = 0; // Watchdog interrupt counter unsigned long currentMillis = 0, previousMillis = 0; -void setup() +void setup() { Serial.begin(115200); Serial.println("Artemis Watchdog Timer Example"); // Configure the watchdog - wdt.configure(); // Default interrupt: 5 seconds. Default reset: 15 seconds - wdt.start(); // Enable the watchdog + /* + Available watchdog timer clock dividers: + 0 = Low Power Mode. This setting disables the watch dog timer + 1 = 128 Hz + 2 = 16 Hz + 3 = 1 Hz + 4 = 1/16th Hz + */ + // Set watchdog timer clock to 128 Hz + // Set watchdog interrupt to 1 seconds (128 ticks / 128 Hz = 1 second) + // Set watchdog reset ~2 seconds (255 ticks / 128 Hz = 1.99 seconds) + wdt.configure(1, 128, 255); // Note: Ticks are limited to 255 (8-bit) + wdt.start(); // Start the watchdog } void loop() @@ -48,11 +70,16 @@ void loop() currentMillis = millis() - previousMillis; previousMillis = millis(); - Serial.print("Interrupt: "); Serial.print(watchdogCounter); + Serial.print("Interrupt: "); Serial.print(watchdogInterrupt); Serial.print(" Period: "); Serial.print(currentMillis); Serial.println(" ms"); + + // The watchdog configurations can also be set individually + wdt.setClock(2); // Set watchdog timer clock to 16 Hz + wdt.setInterrupt(64); // Set watchdog interrupt to 4 second (64 ticks / 16 Hz = 4 seconds) + wdt.setReset(96); // Set watchdog reset to 8 seconds (96 ticks / 16 Hz = 8 seconds) } watchdogFlag = false; // Clear watchdog flag - delay(10); + delay(1); } // Interrupt handler for the watchdog @@ -61,16 +88,16 @@ extern "C" void am_watchdog_isr(void) // Clear the watchdog interrupt wdt.clear(); - // Catch the first four watchdog interrupts, but let the fifth through untouched - if ( watchdogCounter < 4 ) + // Catch the first eight watchdog interrupts, but let the ninth through untouched + if ( watchdogInterrupt < 8 ) { wdt.restart(); // "Pet" the dog } else { - digitalWrite(LED_BUILTIN, HIGH); // Visual indication of imminent system reset + digitalWrite(LED_BUILTIN, HIGH); // Visual indication of system reset trigger } watchdogFlag = true; // Set watchdog flag - watchdogCounter++; // Increment watchdog interrupt counter + watchdogInterrupt++; // Increment watchdog interrupt counter } diff --git a/libraries/WDT/examples/Example3_WDT_LowPower/Example3_WDT_LowPower.ino b/libraries/WDT/examples/Example3_WDT_LowPower/Example3_WDT_LowPower.ino index b47cb229..7b9e4b73 100644 --- a/libraries/WDT/examples/Example3_WDT_LowPower/Example3_WDT_LowPower.ino +++ b/libraries/WDT/examples/Example3_WDT_LowPower/Example3_WDT_LowPower.ino @@ -1,6 +1,6 @@ /* Author: Adam Garbo - Created: July 31st, 2020 + Created: August 1st, 2020 License: MIT. See SparkFun Arduino Apollo3 Project for more information This example demonstrates the combined use of the Artemis Watchdog Timer (WDT) @@ -9,11 +9,12 @@ Both RTC and WDT interrupts will wake the system, print the date and time, and then re-enter deep sleep. - The code is configured to trigger the RTC alarm every minute and enter - deep sleep between interrupts. Alarm interupts also restart the WDT and reset - the watchdog counter. - - If the WDT is not restarted after 75 seconds, a system reset will occur. + The WDT is configured to trigger every 10 seconds. If the WDT is not "pet" + after 100 seconds, a system reset will be triggered. + + The RTC alarm is configured to trigger every minute and enter deep sleep + between interrupts. Alarm interuptswill also restart the WDT and reset + the watchdog interrput counter. */ #include @@ -24,7 +25,7 @@ APM3_WDT wdt; volatile bool alarmFlag = false; // RTC ISR flag volatile bool watchdogFlag = false; // Watchdog Timer ISR flag -volatile int watchdogCounter = 0; // Watchdog interrupt counter +volatile int watchdogInterrupt = 0; // Watchdog interrupt counter void setup() { @@ -32,16 +33,20 @@ void setup() Serial.println("Artemis Watchdog Low Power Example"); + // Set the RTC time using UNIX Epoch time + rtc.setEpoch(1596240000); // Saturday, August 1, 2020 00:00:00 + // Set the RTC's alarm rtc.setAlarm(0, 0, 0, 0, 0, 0); // Set alarm (hund, ss, mm, hh, dd, mm) rtc.setAlarmMode(6); // Set the RTC alarm to trigger every minute rtc.attachInterrupt(); // Attach RTC alarm interrupt - // Configure the watchdog - wdt.configure(); // Default interrupt: 5 seconds. Default reset: 15 seconds + // Configure the watchdog timer + // See Example2_WDT_Config for more information on how to configure the watchdog + wdt.configure(2, 160, 240); // 16 Hz clock, 10-second interrupt period, 15-second reset period - // Enable the watchdog - wdt.enable(); + // Start the watchdog + wdt.start(); } void loop() @@ -49,24 +54,23 @@ void loop() // Check for alarm interrupt if (alarmFlag) { - Serial.print("Alarm triggered: "); + Serial.print("Alarm interrupt: "); printDateTime(); // Print RTC's date and time alarmFlag = false; wdt.restart(); // "Pet" the dog - watchdogCounter = 0; // Reset watchdog interrupt counter + watchdogInterrupt = 0; // Reset watchdog interrupt counter } // Check for watchdog interrupt if (watchdogFlag) { - Serial.print("Watchdog triggered: "); + Serial.print("Watchdog interrupt: "); printDateTime(); // Print RTC's date and time watchdogFlag = false; // Clear watchdog flag } goToSleep(); // Enter deep sleep - } // Print the RTC's current date and time @@ -145,19 +149,20 @@ extern "C" void am_rtc_isr(void) } // Interrupt handler for the watchdog. -extern "C" void am_watchdog_isr(void) { - +extern "C" void am_watchdog_isr(void) +{ // Clear the watchdog interrupt wdt.clear(); - // Perform system reset after 15 watchdog interrupts (15 * 5 seconds = 75 seconds) - if ( watchdogCounter < 20 ) { + // Perform system reset after 10 watchdog interrupts (should not occur) + if ( watchdogInterrupt < 10 ) + { wdt.restart(); // "Pet" the dog } else { - digitalWrite(LED_BUILTIN, HIGH); // Visual indication of system reset + digitalWrite(LED_BUILTIN, HIGH); // Visual indication of system reset trigger } watchdogFlag = true; // Set the watchdog flag - watchdogCounter++; // Increment watchdog interrupt counter + watchdogInterrupt++; // Increment watchdog interrupt counter } diff --git a/libraries/WDT/keywords.txt b/libraries/WDT/keywords.txt index 8da692b7..518d7f67 100644 --- a/libraries/WDT/keywords.txt +++ b/libraries/WDT/keywords.txt @@ -17,6 +17,11 @@ start KEYWORD2 stop KEYWORD2 restart KEYWORD2 clear KEYWORD2 +getCounter KEYWORD2 +configure KEYWORD2 +setClock KEYWORD2 +setInterrupt KEYWORD2 +setReset KEYWORD2 ####################################### # Constants (LITERAL1) diff --git a/libraries/WDT/src/WDT.cpp b/libraries/WDT/src/WDT.cpp index c2c8bd07..30d42d7d 100644 --- a/libraries/WDT/src/WDT.cpp +++ b/libraries/WDT/src/WDT.cpp @@ -1,7 +1,3 @@ -/* - -*/ - #include "WDT.h" // Constructor @@ -9,13 +5,33 @@ APM3_WDT::APM3_WDT() { // The watchdog only runs off of the LFRC am_hal_clkgen_control(AM_HAL_CLKGEN_CONTROL_LFRC_START, 0); + am_hal_wdt_init(&watchdogConfig); +} + +// Configure the watchdog timer +void APM3_WDT::configure(uint8_t clock, uint8_t interrupt, uint8_t reset) +{ + WDT->CFG_b.CLKSEL = clock; + WDT->CFG_b.INTVAL = interrupt; + WDT->CFG_b.RESVAL = reset; +} + +// Set the LFRC clock frequency of the watchdog timer +void APM3_WDT::setClock(uint8_t clock) +{ + WDT->CFG_b.CLKSEL = clock; } +// Set number of watchdog timer ticks allowed before a watchdog interrupt event is generated +void APM3_WDT::setInterrupt(uint8_t interrupt) +{ + WDT->CFG_b.INTVAL = interrupt; +} -// Configure the watchdog -void APM3_WDT::configure() +// Set number of watchdog timer ticks allowed before the watchdog will issue a system reset +void APM3_WDT::setReset(uint8_t reset) { - am_hal_wdt_init(&watchdogConfig); + WDT->CFG_b.RESVAL = reset; } // Enable the watchdog @@ -46,4 +62,11 @@ void APM3_WDT::restart() void APM3_WDT::clear() { am_hal_wdt_int_clear(); -} \ No newline at end of file +} + +// Read the current value of watch dog timer counter register +uint32_t APM3_WDT::getCounter() +{ + return am_hal_wdt_counter_get(); +} + diff --git a/libraries/WDT/src/WDT.h b/libraries/WDT/src/WDT.h index 46baadfe..55426941 100644 --- a/libraries/WDT/src/WDT.h +++ b/libraries/WDT/src/WDT.h @@ -8,24 +8,27 @@ class APM3_WDT public: APM3_WDT(); - // Watchdog timer configuration structure + // Default watchdog timer configuration structure am_hal_wdt_config_t watchdogConfig = { // Configuration values for generated watchdog timer event. .ui32Config = AM_HAL_WDT_LFRC_CLK_16HZ | AM_HAL_WDT_ENABLE_RESET | AM_HAL_WDT_ENABLE_INTERRUPT, // Number of watchdog timer ticks allowed before a watchdog interrupt event is generated - .ui16InterruptCount = 16 * 5, // Set WDT interrupt timeout for 5 seconds (16 * 5) / 16 = 5 + .ui16InterruptCount = 16 * 4, // Set WDT interrupt timeout for 4 seconds (16 * 4) / 16 = 4 // Number of watchdog timer ticks allowed before the watchdog will issue a system reset - .ui16ResetCount = 16 * 10 // Set WDT reset timeout for 15 seconds (16 * 10 ) / 16 = 10 + .ui16ResetCount = 16 * 8 // Set WDT reset timeout for 8 seconds (16 * 8 ) / 16 = 8 }; - void configure(); // Configure watchdog void start(); // Starts the watchdog timer void stop(); // Disables the watchdog timer void restart(); // Restarts the watchdog timer ("Pets" the dog) void clear(); // Clears the watchdog interrupt - + uint32_t getCounter(); // Reads the current value of watch dog timer counter register + void configure(uint8_t clock, uint8_t interrupt, uint8_t reset); + void setClock(uint8_t clock); // Set the clock frequency of the watchdog timer + void setInterrupt(uint8_t interrupt); // Set number of ticks before a watchdog interrupt event is generated + void setReset(uint8_t reset); // Set number of ticks before the watchdog will issue a system reset }; #endif //WDT_H From 38a241bb09f52e62145a08c96eda5e6a6ae4d2ba Mon Sep 17 00:00:00 2001 From: Adam Date: Tue, 4 Aug 2020 09:52:18 -0400 Subject: [PATCH 17/17] Minor updates Added simplied defintions and error checking to setClock() and configure(). More detailed comments. --- .../Example1_WDT_Basic/Example1_WDT_Basic.ino | 3 +- .../Example2_WDT_Config.ino | 33 +++++++++++-------- .../Example3_WDT_LowPower.ino | 6 ++-- libraries/WDT/keywords.txt | 7 +++- libraries/WDT/src/WDT.cpp | 30 ++++++++++++++--- libraries/WDT/src/WDT.h | 7 ++++ 6 files changed, 63 insertions(+), 23 deletions(-) diff --git a/libraries/WDT/examples/Example1_WDT_Basic/Example1_WDT_Basic.ino b/libraries/WDT/examples/Example1_WDT_Basic/Example1_WDT_Basic.ino index f392d228..7d9a7097 100644 --- a/libraries/WDT/examples/Example1_WDT_Basic/Example1_WDT_Basic.ino +++ b/libraries/WDT/examples/Example1_WDT_Basic/Example1_WDT_Basic.ino @@ -21,7 +21,7 @@ Tested with SparkFun Artemis Redboard. */ -#include +#include "WDT.h" APM3_WDT wdt; @@ -57,7 +57,6 @@ void loop() Serial.println("Warning: Watchdog has triggered a system reset"); } } - watchdogFlag = false; // Clear watchdog flag delay(1); } diff --git a/libraries/WDT/examples/Example2_WDT_Config/Example2_WDT_Config.ino b/libraries/WDT/examples/Example2_WDT_Config/Example2_WDT_Config.ino index ec6aa678..67733276 100644 --- a/libraries/WDT/examples/Example2_WDT_Config/Example2_WDT_Config.ino +++ b/libraries/WDT/examples/Example2_WDT_Config/Example2_WDT_Config.ino @@ -6,17 +6,17 @@ This example demonstrates how to modify the configuration of the Artemis Watchdog Timer (WDT). - The watchdog timer is controlled by a clock divider, interrupt ticks and + The watchdog timer is controlled by a clock divider, interrupt ticks and reset ticks. To achieve desired watchdog timing, a simple calculation can be made: - period = # ticks / clock divider frequency + period = # ticks / clock divider frequency - Examples: + Examples: 128 interrupt ticks / 128 Hz clock = 1 second 64 interrupt ticks / 16 Hz clock = 4 seconds 32 interrupt ticks / 1 Hz clock = 32 seconds 16 interrupt ticks / 1/16 Hz clock = 256 seconds - + The following code will configure the watchdog for both interrupt and reset generation, and immediately start the watchdog timer. The watchdog ISR provided will 'pet' the watchdog four times. On the fifth @@ -29,7 +29,7 @@ Tested with SparkFun Artemis Redboard. */ -#include +#include "WDT.h" APM3_WDT wdt; @@ -47,17 +47,19 @@ void setup() // Configure the watchdog /* - Available watchdog timer clock dividers: - 0 = Low Power Mode. This setting disables the watch dog timer - 1 = 128 Hz - 2 = 16 Hz - 3 = 1 Hz - 4 = 1/16th Hz + Available watchdog timer clock dividers. + Users can choose either the clock definition (i.e. WDT_128HZ) or Apoll3 core enumeration (i.e. 1) + WDT_OFF = 0 = Low Power Mode. This setting disables the watch dog timer + WDT_128HZ = 1 = 128 Hz + WDT_16HZ = 2 = 16 Hz + WDT_1HZ = 3 = 1 Hz + WDT1_16HZ = 4 = 1/16th Hz */ // Set watchdog timer clock to 128 Hz // Set watchdog interrupt to 1 seconds (128 ticks / 128 Hz = 1 second) // Set watchdog reset ~2 seconds (255 ticks / 128 Hz = 1.99 seconds) - wdt.configure(1, 128, 255); // Note: Ticks are limited to 255 (8-bit) + // Note: Ticks are limited to 255 (8-bit) + wdt.configure(WDT_128HZ, 128, 255); // Equivalent to: wdt.configure(1, 128, 255); wdt.start(); // Start the watchdog } @@ -74,9 +76,14 @@ void loop() Serial.print(" Period: "); Serial.print(currentMillis); Serial.println(" ms"); // The watchdog configurations can also be set individually - wdt.setClock(2); // Set watchdog timer clock to 16 Hz + wdt.setClock(WDT_16HZ); // Set watchdog timer clock to 16 Hz wdt.setInterrupt(64); // Set watchdog interrupt to 4 second (64 ticks / 16 Hz = 4 seconds) wdt.setReset(96); // Set watchdog reset to 8 seconds (96 ticks / 16 Hz = 8 seconds) + + if (watchdogInterrupt == 9) + { + Serial.println("Warning: Watchdog has triggered a system reset"); + } } watchdogFlag = false; // Clear watchdog flag delay(1); diff --git a/libraries/WDT/examples/Example3_WDT_LowPower/Example3_WDT_LowPower.ino b/libraries/WDT/examples/Example3_WDT_LowPower/Example3_WDT_LowPower.ino index 7b9e4b73..26cd6902 100644 --- a/libraries/WDT/examples/Example3_WDT_LowPower/Example3_WDT_LowPower.ino +++ b/libraries/WDT/examples/Example3_WDT_LowPower/Example3_WDT_LowPower.ino @@ -17,8 +17,8 @@ the watchdog interrput counter. */ -#include -#include +#include "RTC.h" +#include "WDT.h" APM3_RTC rtc; APM3_WDT wdt; @@ -43,7 +43,7 @@ void setup() // Configure the watchdog timer // See Example2_WDT_Config for more information on how to configure the watchdog - wdt.configure(2, 160, 240); // 16 Hz clock, 10-second interrupt period, 15-second reset period + wdt.configure(WDT_16HZ, 160, 240); // 16 Hz clock, 10-second interrupt period, 15-second reset period // Start the watchdog wdt.start(); diff --git a/libraries/WDT/keywords.txt b/libraries/WDT/keywords.txt index 518d7f67..b84d6784 100644 --- a/libraries/WDT/keywords.txt +++ b/libraries/WDT/keywords.txt @@ -22,7 +22,12 @@ configure KEYWORD2 setClock KEYWORD2 setInterrupt KEYWORD2 setReset KEYWORD2 - +WDT_OFF KEYWORD2 +WDT_128HZ KEYWORD2 +WDT_16 KEYWORD2 +WDT_1HZ KEYWORD2 +WDT1_16HZ KEYWORD2 + ####################################### # Constants (LITERAL1) ####################################### diff --git a/libraries/WDT/src/WDT.cpp b/libraries/WDT/src/WDT.cpp index 30d42d7d..3c11bcba 100644 --- a/libraries/WDT/src/WDT.cpp +++ b/libraries/WDT/src/WDT.cpp @@ -9,17 +9,39 @@ APM3_WDT::APM3_WDT() } // Configure the watchdog timer +// clock: set the LFRC clock frequency of the watchdog timer (see setClock below) +// interrupt: number of watchdog timer ticks allowed before a watchdog interrupt event is generated +// reset: number of watchdog timer ticks allowed before the watchdog will issue a system reset void APM3_WDT::configure(uint8_t clock, uint8_t interrupt, uint8_t reset) { - WDT->CFG_b.CLKSEL = clock; + if(clock <= 4) + { + WDT->CFG_b.CLKSEL = clock; + } + else + { + WDT->CFG_b.CLKSEL = WDT_CFG_CLKSEL_16HZ; // Default to 16Hz LFRC clock divider + } WDT->CFG_b.INTVAL = interrupt; WDT->CFG_b.RESVAL = reset; } // Set the LFRC clock frequency of the watchdog timer +// WDT_OFF WDT_CFG_CLKSEL_OFF // = 0 Low Power Mode. This setting disables the watch dog timer +// WDT_128HZ WDT_CFG_CLKSEL_128HZ // = 1, 128 Hz LFRC clock +// WDT_16HZ WDT_CFG_CLKSEL_16HZ // = 2 16 Hz LFRC clock +// WDT_1HZ WDT_CFG_CLKSEL_1HZ // = 3, 1 Hz LFRC clock +// WDT_1_16HZ WDT_CFG_CLKSEL_1_16HZ // = 4, 1/16th Hz LFRC clock void APM3_WDT::setClock(uint8_t clock) { - WDT->CFG_b.CLKSEL = clock; + if(clock <= 4) + { + WDT->CFG_b.CLKSEL = clock; + } + else + { + WDT->CFG_b.CLKSEL = WDT_CFG_CLKSEL_16HZ; // Default to 16Hz LFRC clock divider + } } // Set number of watchdog timer ticks allowed before a watchdog interrupt event is generated @@ -37,8 +59,8 @@ void APM3_WDT::setReset(uint8_t reset) // Enable the watchdog void APM3_WDT::start() { - // Enable the interrupt for the watchdog in the NVIC - NVIC_EnableIRQ(WDT_IRQn); + am_hal_interrupt_master_enable(); // Enable interrupts to the core + NVIC_EnableIRQ(WDT_IRQn); // Enable the interrupt for the watchdog in the NVIC am_hal_wdt_start(); } diff --git a/libraries/WDT/src/WDT.h b/libraries/WDT/src/WDT.h index 55426941..fc342146 100644 --- a/libraries/WDT/src/WDT.h +++ b/libraries/WDT/src/WDT.h @@ -3,6 +3,13 @@ #include +// Simplified WDT Clock Divider Selections +#define WDT_OFF WDT_CFG_CLKSEL_OFF // = 0 Low Power Mode. This setting disables the watch dog timer +#define WDT_128HZ WDT_CFG_CLKSEL_128HZ // = 1, 128 Hz LFRC clock +#define WDT_16HZ WDT_CFG_CLKSEL_16HZ // = 2 16 Hz LFRC clock +#define WDT_1HZ WDT_CFG_CLKSEL_1HZ // = 3, 1 Hz LFRC clock +#define WDT_1_16HZ WDT_CFG_CLKSEL_1_16HZ // = 4, 1/16th Hz LFRC clock + class APM3_WDT { public: