diff --git a/libraries/RTC/examples/Example1_Get_Time/Example1_Get_Time.ino b/libraries/RTC/examples/Example1_Get_Time/Example1_Get_Time.ino index 5f4af7a4..1c85b5fa 100644 --- a/libraries/RTC/examples/Example1_Get_Time/Example1_Get_Time.ino +++ b/libraries/RTC/examples/Example1_Get_Time/Example1_Get_Time.ino @@ -3,7 +3,7 @@ Created: Septempter 27th, 2019 This example demonstrates how to initialize and read from the on-board RTC. - + Most SparkFun Artemis boards have the necessary external 32kHz crystal to enable the RTC. If you are using the Artemis module bare you will either need an external 32kHz xtal or use the internal LFRC. Read the datasheet @@ -12,7 +12,7 @@ This example is based on the Ambiq SDK EVB2 RTC example. */ -/* +/* // This file is subject to the terms and conditions defined in // file 'LICENSE.md', which is part of this source code package. */ @@ -25,28 +25,28 @@ void setup() Serial.println("SparkFun RTC Example"); // Easily set RTC using the system __DATE__ and __TIME__ macros from compiler - RTC.setToCompilerTime(); + rtc.setToCompilerTime(); - // // Manually set RTC date and time - // RTC.setTime(0, 50, 59, 12, 3, 6, 20); // 12:59:50.000, June 3rd, 2020 (hund, ss, mm, hh, dd, mm, yy) + // Manually set RTC date and time + // rtc.setTime(0, 50, 59, 12, 3, 6, 20); // 12:59:50.000, June 3rd, 2020 (hund, ss, mm, hh, dd, mm, yy) } void loop() { - RTC.getTime(); + rtc.getTime(); Serial.printf("It is now "); - Serial.printf("%d:", RTC.hour); - Serial.printf("%02d:", RTC.minute); - Serial.printf("%02d.", RTC.seconds); - Serial.printf("%02d", RTC.hundredths); + Serial.printf("%d:", rtc.hour); + Serial.printf("%02d:", rtc.minute); + Serial.printf("%02d.", rtc.seconds); + Serial.printf("%02d", rtc.hundredths); - Serial.printf(" %02d/", RTC.month); - Serial.printf("%02d/", RTC.dayOfMonth); - Serial.printf("%02d", RTC.year); + Serial.printf(" %02d/", rtc.month); + Serial.printf("%02d/", rtc.dayOfMonth); + Serial.printf("%02d", rtc.year); - Serial.printf(" Day of week: %d =", RTC.weekday); - Serial.printf(" %s", RTC.textWeekday); + Serial.printf(" Day of week: %d =", rtc.weekday); + Serial.printf(" %s", rtc.textWeekday); Serial.println(); diff --git a/libraries/RTC/examples/Example2_Set_Alarms/Example2_Set_Alarms.ino b/libraries/RTC/examples/Example2_Set_Alarms/Example2_Set_Alarms.ino index 3669da7f..a2af583a 100644 --- a/libraries/RTC/examples/Example2_Set_Alarms/Example2_Set_Alarms.ino +++ b/libraries/RTC/examples/Example2_Set_Alarms/Example2_Set_Alarms.ino @@ -28,13 +28,13 @@ void setup() Serial.println("SparkFun RTC Set Alarm Example"); // // Easily set RTC using the system __DATE__ and __TIME__ macros from compiler - // RTC.setToCompilerTime(); + // rtc.setToCompilerTime(); // Manually set RTC date and time - RTC.setTime(0, 50, 59, 12, 3, 6, 20); // 12:59:50.000, June 3rd, 2020 (hund, ss, mm, hh, dd, mm, yy) + rtc.setTime(0, 50, 59, 12, 3, 6, 20); // 12:59:50.000, June 3rd, 2020 (hund, ss, mm, hh, dd, mm, yy) // Set the RTC's alarm - RTC.setAlarm(0, 0, 0, 13, 3, 6); // 13:00:00.000, June 3rd (hund, ss, mm, hh, dd, mm). Note: No year alarm register + rtc.setAlarm(0, 0, 0, 13, 3, 6); // 13:00:00.000, June 3rd (hund, ss, mm, hh, dd, mm). Note: No year alarm register // Set the RTC alarm mode /* @@ -47,8 +47,8 @@ void setup() 6: Alarm match every minute (hundredths, seconds) 7: Alarm match every second (hundredths) */ - RTC.setAlarmMode(6); // Set the RTC alarm to match on minutes rollover - RTC.attachInterrupt(); // Attach RTC alarm interrupt + rtc.setAlarmMode(6); // Set the RTC alarm to match on minutes rollover + rtc.attachInterrupt(); // Attach RTC alarm interrupt // Print the RTC's alarm date and time Serial.print("Next alarm: "); printAlarm(); @@ -77,31 +77,29 @@ void loop() // Print the RTC's current date and time void printDateTime() { - RTC.getTime(); - char dateTimeBuffer[25]; - sprintf(dateTimeBuffer, "20%02d-%02d-%02d %02d:%02d:%02d.%03d", - RTC.year, RTC.month, RTC.dayOfMonth, - RTC.hour, RTC.minute, RTC.seconds, RTC.hundredths); - Serial.println(dateTimeBuffer); + rtc.getTime(); + Serial.printf("20%02d-%02d-%02d %02d:%02d:%02d.%03d\n", + rtc.year, rtc.month, rtc.dayOfMonth, + rtc.hour, rtc.minute, rtc.seconds, rtc.hundredths); } // Print the RTC's alarm void printAlarm() { - RTC.getAlarm(); - char alarmBuffer[25]; - sprintf(alarmBuffer, "2020-%02d-%02d %02d:%02d:%02d.%03d", - RTC.alarmMonth, RTC.alarmDayOfMonth, - RTC.alarmHour, RTC.alarmMinute, - RTC.alarmSeconds, RTC.alarmHundredths); - Serial.println(alarmBuffer); + rtc.getAlarm(); + + Serial.printf("2020-%02d-%02d %02d:%02d:%02d.%03d\n", + rtc.alarmMonth, rtc.alarmDayOfMonth, + rtc.alarmHour, rtc.alarmMinute, + rtc.alarmSeconds, rtc.alarmHundredths); + Serial.println(); } // 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); + rtc.clearInterrupt(); // Set alarm flag alarmFlag = true; diff --git a/libraries/RTC/examples/Example3_Test_RTC/Example3_Test_RTC.ino b/libraries/RTC/examples/Example3_Test_RTC/Example3_Test_RTC.ino index 79bb2c49..5bddffbf 100644 --- a/libraries/RTC/examples/Example3_Test_RTC/Example3_Test_RTC.ino +++ b/libraries/RTC/examples/Example3_Test_RTC/Example3_Test_RTC.ino @@ -21,13 +21,13 @@ void setup() Serial.println("Artemis RTC Testing"); // Manually set RTC date and time to the start of 2020 so that RTC contains valid times - RTC.setTime(0, 59, 59, 23, 1, 1, 20); // Set to 1 second before midnight Jan 1 + rtc.setTime(0, 59, 59, 23, 1, 1, 20); // Set to 1 second before midnight Jan 1 } void loop() { - RTC.setTime(99, 59, 59, 23, RTC.dayOfMonth, RTC.month, RTC.year); // Manually set RTC 1/100th of a second from the next day - previousDay = RTC.weekday; + rtc.setTime(99, 59, 59, 23, rtc.dayOfMonth, rtc.month, rtc.year); // Manually set RTC 1/100th of a second from the next day + previousDay = rtc.weekday; delay(11); //Allow us to roll from midnight the night before to the new day printArtemisTime(); @@ -38,8 +38,8 @@ void printArtemisTime() char buf[50]; char weekdayBuf[4]; - RTC.getTime(); - int i = RTC.weekday + 1; + rtc.getTime(); + int i = rtc.weekday + 1; switch (i) { case (1): @@ -69,15 +69,15 @@ void printArtemisTime() break; } - sprintf(buf, "%02d-%02d-%02d (%s) %02d:%02d:%02d.%02d", RTC.year, RTC.month, RTC.dayOfMonth, weekdayBuf, RTC.hour, RTC.minute, RTC.seconds, RTC.hundredths); + sprintf(buf, "%02d-%02d-%02d (%s) %02d:%02d:%02d.%02d", rtc.year, rtc.month, rtc.dayOfMonth, weekdayBuf, rtc.hour, rtc.minute, rtc.seconds, rtc.hundredths); Serial.print(buf); //Move the previous day forward one day and make sure it matches today - if ((previousDay + 1) % 7 != RTC.weekday) + if ((previousDay + 1) % 7 != rtc.weekday) { - Serial.printf(" Error! previousDay: %d today: %d\n", previousDay, RTC.weekday); + Serial.printf(" Error! previousDay: %d today: %d\n", previousDay, rtc.weekday); while (1){}; } Serial.println(); -} \ No newline at end of file +} diff --git a/libraries/RTC/examples/Example4_Set_Epoch/Example4_Set_Epoch.ino b/libraries/RTC/examples/Example4_Set_Epoch/Example4_Set_Epoch.ino index 9cf4541e..12959d28 100644 --- a/libraries/RTC/examples/Example4_Set_Epoch/Example4_Set_Epoch.ino +++ b/libraries/RTC/examples/Example4_Set_Epoch/Example4_Set_Epoch.ino @@ -18,13 +18,13 @@ void setup() Serial.println("SparkFun RTC Set UNIX Epoch Time Example"); // Set the RTC time using UNIX Epoch time - RTC.setEpoch(1591185600); // E.g. 12:00:00, June 3rd, 2020 + rtc.setEpoch(1591185600); // E.g. 12:00:00, June 3rd, 2020 } void loop() { // Print UNIX Epoch timestamp - Serial.print("Epoch time: "); Serial.println(RTC.getEpoch()); + Serial.print("Epoch time: "); Serial.println(rtc.getEpoch()); // Print RTC's date and time Serial.print("Timestamp: "); printDateTime(); @@ -35,10 +35,9 @@ void loop() // Print the RTC's current date and time void printDateTime() { - RTC.getTime(); - char dateTime[20]; - sprintf(dateTime, "20%02d-%02d-%02d %02d:%02d:%02d", - RTC.year, RTC.month, RTC.dayOfMonth, - RTC.hour, RTC.minute, RTC.seconds); - Serial.println(dateTime); + rtc.getTime(); + Serial.printf("20%02d-%02d-%02d %02d:%02d:%02d\n", + rtc.year, rtc.month, rtc.dayOfMonth, + rtc.hour, rtc.minute, rtc.seconds); + Serial.println(); } diff --git a/libraries/RTC/examples/Example5_Rolling_Alarms/Example5_Rolling_Alarms.ino b/libraries/RTC/examples/Example5_Rolling_Alarms/Example5_Rolling_Alarms.ino index 5a82bf20..aac0bd3c 100644 --- a/libraries/RTC/examples/Example5_Rolling_Alarms/Example5_Rolling_Alarms.ino +++ b/libraries/RTC/examples/Example5_Rolling_Alarms/Example5_Rolling_Alarms.ino @@ -2,17 +2,17 @@ Author: Adam Garbo and Nathan Seidle Created: June 3rdrd, 2020 - This example demonstrates how to read and set rolling RTC alarms. Each time - the alarm triggers, a user-specified additional amount of time (seconds, - minutes or hours) can be added to create a rolling RTC alarm. Second, + This example demonstrates how to read and set rolling RTC alarms. Each time + the alarm triggers, a user-specified additional amount of time (seconds, + minutes or hours) can be added to create a rolling RTC alarm. Second, minute and hour rollovers are handled using modulo calculations. - The current code is configured as a 5-second rolling RTC alarm. + The current code is configured as a 5-second rolling RTC alarm. */ -/* -// This file is subject to the terms and conditions defined in -// file 'LICENSE.md', which is part of this source code package. +/* + // This file is subject to the terms and conditions defined in + // file 'LICENSE.md', which is part of this source code package. */ #include "RTC.h" @@ -31,10 +31,10 @@ void setup() // RTC.setToCompilerTime(); // Manually set RTC date and time - RTC.setTime(0, 50, 59, 12, 3, 6, 20); // 12:59:50.000, June 3rd, 2020 (hund, ss, mm, hh, dd, mm, yy) + rtc.setTime(0, 50, 59, 12, 3, 6, 20); // 12:59:50.000, June 3rd, 2020 (hund, ss, mm, hh, dd, mm, yy) // Set the RTC's alarm - RTC.setAlarm(0, 0, 0, 13, 3, 6); // 13:00:00.000, June 3rd (hund, ss, mm, hh, dd, mm). Note: No year alarm register + rtc.setAlarm(0, 0, 0, 13, 3, 6); // 13:00:00.000, June 3rd (hund, ss, mm, hh, dd, mm). Note: No year alarm register // Set the RTC alarm mode /* @@ -47,8 +47,8 @@ void setup() 6: Alarm match every minute (hundredths, seconds) 7: Alarm match every second (hundredths) */ - RTC.setAlarmMode(6); // Set the RTC alarm to match on minutes rollover - RTC.attachInterrupt(); // Attach RTC alarm interrupt + rtc.setAlarmMode(6); // Set the RTC alarm to match on minutes rollover + rtc.attachInterrupt(); // Attach RTC alarm interrupt // Print the RTC's alarm date and time Serial.print("Next alarm: "); printAlarm(); @@ -66,13 +66,13 @@ void loop() alarmFlag = false; // Set the RTC's rolling alarm - RTC.setAlarm(0, - (RTC.seconds + alarmSeconds) % 60, - (RTC.minute + alarmMinutes) % 60, - (RTC.hour + alarmHours) % 24, - RTC.dayOfMonth, - RTC.month); - RTC.setAlarmMode(6); + rtc.setAlarm(0, + (rtc.seconds + alarmSeconds) % 60, + (rtc.minute + alarmMinutes) % 60, + (rtc.hour + alarmHours) % 24, + rtc.dayOfMonth, + rtc.month); + rtc.setAlarmMode(6); // Print next RTC alarm date and time Serial.print("Next rolling alarm: "); printAlarm(); @@ -82,31 +82,29 @@ void loop() // Print the RTC's current date and time void printDateTime() { - RTC.getTime(); - char dateTimeBuffer[25]; - sprintf(dateTimeBuffer, "20%02d-%02d-%02d %02d:%02d:%02d.%03d", - RTC.year, RTC.month, RTC.dayOfMonth, - RTC.hour, RTC.minute, RTC.seconds, RTC.hundredths); - Serial.println(dateTimeBuffer); + rtc.getTime(); + Serial.printf("20%02d-%02d-%02d %02d:%02d:%02d.%03d\n", + rtc.year, rtc.month, rtc.dayOfMonth, + rtc.hour, rtc.minute, rtc.seconds, rtc.hundredths); + Serial.println(); } // Print the RTC's alarm void printAlarm() { - RTC.getAlarm(); - char alarmBuffer[25]; - sprintf(alarmBuffer, "2020-%02d-%02d %02d:%02d:%02d.%03d", - RTC.alarmMonth, RTC.alarmDayOfMonth, - RTC.alarmHour, RTC.alarmMinute, - RTC.alarmSeconds, RTC.alarmHundredths); - Serial.println(alarmBuffer); + rtc.getAlarm(); + Serial.printf("2020-%02d-%02d %02d:%02d:%02d.%03d\n", + rtc.alarmMonth, rtc.alarmDayOfMonth, + rtc.alarmHour, rtc.alarmMinute, + rtc.alarmSeconds, rtc.alarmHundredths); + Serial.println(); } // 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); + rtc.clearInterrupt(); // Set alarm flag alarmFlag = true; diff --git a/libraries/RTC/examples/Example6_LowPower_Alarm/Example6_LowPower_Alarm.ino b/libraries/RTC/examples/Example6_LowPower_Alarm/Example6_LowPower_Alarm.ino index f59ab51e..9cbcecfd 100644 --- a/libraries/RTC/examples/Example6_LowPower_Alarm/Example6_LowPower_Alarm.ino +++ b/libraries/RTC/examples/Example6_LowPower_Alarm/Example6_LowPower_Alarm.ino @@ -16,8 +16,6 @@ // file 'LICENSE.md', which is part of this source code package. */ -#ifdef I_WANT_TO_BRICK_MY_BOARD - #include "RTC.h" void setup() @@ -29,10 +27,10 @@ void setup() // RTC.setToCompilerTime(); // Manually set RTC date and time - RTC.setTime(0, 50, 59, 12, 3, 6, 20); // 12:59:50.000, June 3rd, 2020 (hund, ss, mm, hh, dd, mm, yy) + rtc.setTime(0, 50, 59, 12, 3, 6, 20); // 12:59:50.000, June 3rd, 2020 (hund, ss, mm, hh, dd, mm, yy) // Set the RTC's alarm - RTC.setAlarm(0, 0, 0, 13, 3, 6); // 13:00:00.000, June 3rd (hund, ss, mm, hh, dd, mm). Note: No year alarm register + rtc.setAlarm(0, 0, 0, 13, 3, 6); // 13:00:00.000, June 3rd (hund, ss, mm, hh, dd, mm). Note: No year alarm register // Set the RTC alarm mode /* @@ -45,8 +43,8 @@ void setup() 6: Alarm match every minute (hundredths, seconds) 7: Alarm match every second (hundredths) */ - RTC.setAlarmMode(6); // Set the RTC alarm to match on minutes rollover - RTC.attachInterrupt(); // Attach RTC alarm interrupt + rtc.setAlarmMode(6); // Set the RTC alarm to match on minutes rollover + rtc.attachInterrupt(); // Attach RTC alarm interrupt } void loop() @@ -61,12 +59,12 @@ void loop() // Print the RTC's current date and time void printDateTime() { - RTC.getTime(); - char dateTimeBuffer[25]; - sprintf(dateTimeBuffer, "20%02d-%02d-%02d %02d:%02d:%02d.%03d", - RTC.year, RTC.month, RTC.dayOfMonth, - RTC.hour, RTC.minute, RTC.seconds, RTC.hundredths); - Serial.println(dateTimeBuffer); + rtc.getTime(); + + Serial.printf("20%02d-%02d-%02d %02d:%02d:%02d.%03d\n", + rtc.year, rtc.month, rtc.dayOfMonth, + rtc.hour, rtc.minute, rtc.seconds, rtc.hundredths); + Serial.println(); } // Power down gracefully @@ -89,16 +87,14 @@ void goToSleep() am_hal_pwrctrl_periph_disable(AM_HAL_PWRCTRL_PERIPH_UART0); am_hal_pwrctrl_periph_disable(AM_HAL_PWRCTRL_PERIPH_UART1); - // Disable all pads + // Disable all pads (except UART TX/RX) 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) - + //Power down CACHE, flashand SRAM + am_hal_pwrctrl_memory_deepsleep_powerdown(AM_HAL_PWRCTRL_MEM_ALL); // Turn off CACHE and flash + am_hal_pwrctrl_memory_deepsleep_retain(AM_HAL_PWRCTRL_MEM_SRAM_384K); // Retain all SRAM (0.6 uA) + // 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); @@ -112,6 +108,10 @@ void goToSleep() // Power up gracefully void wakeUp() { + // 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); + // Power up SRAM, turn on entire Flash am_hal_pwrctrl_memory_deepsleep_powerdown(AM_HAL_PWRCTRL_MEM_MAX); @@ -119,6 +119,13 @@ void wakeUp() am_hal_stimer_config(AM_HAL_STIMER_CFG_CLEAR | AM_HAL_STIMER_CFG_FREEZE); am_hal_stimer_config(AM_HAL_STIMER_HFRC_3MHZ); + // Renable UART0 pins + am_hal_gpio_pinconfig(48, g_AM_BSP_GPIO_COM_UART_TX); + am_hal_gpio_pinconfig(49, g_AM_BSP_GPIO_COM_UART_RX); + + // Renable power to UART0 + am_hal_pwrctrl_periph_enable(AM_HAL_PWRCTRL_PERIPH_UART0); + // Enable ADC initializeADC(); @@ -130,7 +137,5 @@ void wakeUp() extern "C" void am_rtc_isr(void) { // Clear the RTC alarm interrupt - am_hal_rtc_int_clear(AM_HAL_RTC_INT_ALM); + rtc.clearInterrupt(); } - -#endif // I_WANT_TO_BRICK_MY_BOARD diff --git a/libraries/RTC/keywords.txt b/libraries/RTC/keywords.txt index cf6b8a56..ed80925c 100644 --- a/libraries/RTC/keywords.txt +++ b/libraries/RTC/keywords.txt @@ -15,6 +15,7 @@ setAlarm KEYWORD2 setAlarmMode KEYWORD2 attachInterrupt KEYWORD2 detachInterrupt KEYWORD2 +clearInterrupt KEYWORD2 # Structures (KEYWORD3) @@ -40,4 +41,4 @@ alarmMinute LITERAL2 alarmSeconds LITERAL2 alarmHundredths LITERAL2 alarmTextWeekday LITERAL2 -RTC LITERAL2 +rtc LITERAL2 diff --git a/libraries/RTC/src/RTC.cpp b/libraries/RTC/src/RTC.cpp index 4eeb8b68..a3deb6d2 100644 --- a/libraries/RTC/src/RTC.cpp +++ b/libraries/RTC/src/RTC.cpp @@ -6,7 +6,7 @@ #include "RTC.h" #include -Apollo3RTC RTC; +Apollo3RTC rtc; am_hal_rtc_time_t hal_time; am_hal_rtc_time_t alm_time; @@ -201,6 +201,11 @@ void Apollo3RTC::detachInterrupt() { am_hal_rtc_int_disable(AM_HAL_RTC_INT_ALM); } +void Apollo3RTC::clearInterrupt() { + // Clear the RTC alarm interrupt + am_hal_rtc_int_clear(AM_HAL_RTC_INT_ALM); +} + // mthToIndex() converts a string indicating a month to an index value. // The return value is a value 0-12, with 0-11 indicating the month given // by the string, and 12 indicating that the string is not a month. diff --git a/libraries/RTC/src/RTC.h b/libraries/RTC/src/RTC.h index 75d38dd2..3a165fd3 100644 --- a/libraries/RTC/src/RTC.h +++ b/libraries/RTC/src/RTC.h @@ -8,8 +8,8 @@ #include -#ifdef RTC -#undef RTC +#ifdef rtc +#undef rtc #endif class Apollo3RTC { @@ -34,6 +34,7 @@ class Apollo3RTC { void setAlarmMode(uint8_t mode); //Set the RTC alarm repeat interval void attachInterrupt(); //Attach the RTC alarm interrupt void detachInterrupt(); //Detach the RTC alarm interrupt + void clearInterrupt(); //Clear RTC alarm interrupt uint32_t weekday; //0 to 6 representing the day of the week uint32_t century; @@ -56,6 +57,6 @@ class Apollo3RTC { const char *alarmTextWeekday; }; -extern Apollo3RTC RTC; +extern Apollo3RTC rtc; #endif // _APOLLO3_LIBRARIES_RTC_H_ 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..64f7a105 --- /dev/null +++ b/libraries/WDT/examples/Example1_WDT_Basic/Example1_WDT_Basic.ino @@ -0,0 +1,79 @@ +/* + Author: Adam Garbo + Created: February 1st, 2021 + 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. + + 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 "WDT.h" + +volatile bool watchdogFlag = false; // Watchdog Timer ISR flag +volatile int watchdogInterrupt = 0; // Watchdog interrupt counter +unsigned long currentMillis = 0, + previousMillis = 0; + +void setup() { + + Serial.begin(115200); + + Serial.println("Artemis Watchdog Timer Example"); + + // Start the watchdog + wdt.start(); +} + +void loop() +{ + // Check for watchdog interrupts + if (watchdogFlag) + { + // Calculate duration between watchdog interrupts + currentMillis = millis() - previousMillis; + previousMillis = millis(); + + 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(1); +} + +// 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 ( watchdogInterrupt < 4 ) + { + wdt.restart(); // "Pet" the dog + } + else { + digitalWrite(LED_BUILTIN, HIGH); // Visual indication of system reset trigger + } + + watchdogFlag = true; // Set watchdog flag + 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 new file mode 100644 index 00000000..92ab12fd --- /dev/null +++ b/libraries/WDT/examples/Example2_WDT_Config/Example2_WDT_Config.ino @@ -0,0 +1,108 @@ +/* + Author: Adam Garbo + Created: February 1st, 2021 + 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 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 "WDT.h" + +volatile bool watchdogFlag = false; // Watchdog Timer ISR flag +volatile int watchdogInterrupt = 0; // Watchdog interrupt counter + +unsigned long currentMillis = 0, + previousMillis = 0; + +void setup() +{ + Serial.begin(115200); + + Serial.println("Artemis Watchdog Timer Example"); + + // Configure the watchdog + /* + 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) + // 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 +} + +void loop() +{ + // Check for watchdog interrupts + if (watchdogFlag) + { + // Calculate duration between watchdog interrupts + currentMillis = millis() - previousMillis; + previousMillis = millis(); + + 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(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); +} + +// Interrupt handler for the watchdog +extern "C" void am_watchdog_isr(void) +{ + // Clear the watchdog interrupt + wdt.clear(); + + // 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 system reset trigger + } + + watchdogFlag = true; // Set watchdog flag + 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 new file mode 100644 index 00000000..cec1cbaf --- /dev/null +++ b/libraries/WDT/examples/Example3_WDT_LowPower/Example3_WDT_LowPower.ino @@ -0,0 +1,171 @@ +/* + Author: Adam Garbo + Created: March 26, 2021 + 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 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 "RTC.h" +#include "WDT.h" + +volatile bool alarmFlag = false; // RTC ISR flag +volatile bool watchdogFlag = false; // Watchdog Timer ISR flag +volatile int watchdogInterrupt = 0; // Watchdog interrupt counter + +void setup() +{ + Serial.begin(115200); + + 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 timer + // See Example2_WDT_Config for more information on how to configure the watchdog + wdt.configure(WDT_16HZ, 160, 240); // 16 Hz clock, 10-second interrupt period, 15-second reset period + + // Start the watchdog + wdt.start(); +} + +void loop() +{ + // Check for alarm interrupt + if (alarmFlag) + { + Serial.print("Alarm interrupt: "); + printDateTime(); // Print RTC's date and time + alarmFlag = false; + + wdt.restart(); // "Pet" the dog + watchdogInterrupt = 0; // Reset watchdog interrupt counter + } + + // Check for watchdog interrupt + if (watchdogFlag) + { + 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 +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); + Serial.println(); +} + +// Power down gracefully +void goToSleep() +{ + // Disable UART + Serial.end(); + + // Disable ADC + powerControlADC(false); + + // 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 (except UART TX/RX) + for (int x = 0 ; x < 50 ; x++) + am_hal_gpio_pinconfig(x, g_AM_HAL_GPIO_DISABLE); + + //Power down CACHE, flashand SRAM + am_hal_pwrctrl_memory_deepsleep_powerdown(AM_HAL_PWRCTRL_MEM_ALL); // Turn off CACHE and flash + am_hal_pwrctrl_memory_deepsleep_retain(AM_HAL_PWRCTRL_MEM_SRAM_384K); // Retain all SRAM (0.6 uA) + + // 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() +{ + // 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); + + // Renable UART0 pins + am_hal_gpio_pinconfig(48, g_AM_BSP_GPIO_COM_UART_TX); + am_hal_gpio_pinconfig(49, g_AM_BSP_GPIO_COM_UART_RX); + + // Renable power to UART0 + am_hal_pwrctrl_periph_enable(AM_HAL_PWRCTRL_PERIPH_UART0); + + // Enable ADC + initializeADC(); + + // Enable ADC + initializeADC(); + + // Enable Serial + Serial.begin(115200); +} + +// Interrupt handler for the RTC +extern "C" void am_rtc_isr(void) +{ + // Clear the RTC alarm interrupt + rtc.clearInterrupt(); + + 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 10 watchdog interrupts (should not occur) + if ( watchdogInterrupt < 10 ) + { + wdt.restart(); // "Pet" the dog + } + else { + while (1); // Wait for reset to occur + } + + watchdogFlag = true; // Set the watchdog flag + watchdogInterrupt++; // Increment watchdog interrupt counter +} diff --git a/libraries/WDT/keywords.txt b/libraries/WDT/keywords.txt new file mode 100644 index 00000000..12d296c6 --- /dev/null +++ b/libraries/WDT/keywords.txt @@ -0,0 +1,29 @@ +# Syntax Coloring Map For 'libraries/WDT' + +# Datatypes (KEYWORD1) +Apollo3WDT KEYWORD1 + +# Functions (KEYWORD2) +configure KEYWORD2 +start KEYWORD2 +stop KEYWORD2 +restart KEYWORD2 +clear KEYWORD2 +getCounter KEYWORD2 +configure KEYWORD2 +setClock KEYWORD2 +setInterrupt KEYWORD2 +setReset KEYWORD2 + +# Structures (KEYWORD3) + +# Constants (LITERAL1) +_APOLLO3_LIBRARIES_WDT_H_ LITERAL1 + +# Properties (LITERAL2) +WDT_OFF KEYWORD2 +WDT_128HZ KEYWORD2 +WDT_16 KEYWORD2 +WDT_1HZ KEYWORD2 +WDT1_16HZ KEYWORD2 +wdt LITERAL2 diff --git a/libraries/WDT/library.properties b/libraries/WDT/library.properties new file mode 100644 index 00000000..dff958c4 --- /dev/null +++ b/libraries/WDT/library.properties @@ -0,0 +1,9 @@ +name=WDT +version=2.0.0 +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 diff --git a/libraries/WDT/src/WDT.cpp b/libraries/WDT/src/WDT.cpp new file mode 100644 index 00000000..e2c673f5 --- /dev/null +++ b/libraries/WDT/src/WDT.cpp @@ -0,0 +1,100 @@ +/* +// This file is subject to the terms and conditions defined in +// file 'LICENSE.md', which is part of this source code package. +*/ + +#include "WDT.h" + +Apollo3WDT wdt; + +// Constructor +Apollo3WDT::Apollo3WDT() +{ + // 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 +// 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 Apollo3WDT::configure(uint8_t clock, uint8_t interrupt, uint8_t reset) +{ + 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 Apollo3WDT::setClock(uint8_t 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 +void Apollo3WDT::setInterrupt(uint8_t interrupt) +{ + WDT->CFG_b.INTVAL = interrupt; +} + +// Set number of watchdog timer ticks allowed before the watchdog will issue a system reset +void Apollo3WDT::setReset(uint8_t reset) +{ + WDT->CFG_b.RESVAL = reset; +} + +// Enable the watchdog +void Apollo3WDT::start() +{ + 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(); +} + +// Disable the watchdog +void Apollo3WDT::stop() +{ + // Disable the interrupt for the watchdog in the NVIC + NVIC_DisableIRQ(WDT_IRQn); + // Disable the watchdog timer tick by clearing the 'enable' bit in the + // watchdog configuration register + am_hal_wdt_halt(); +} + +// Restart the watchdog +void Apollo3WDT::restart() +{ + am_hal_wdt_restart(); +} + +// Clear the watchdog interrupt +void Apollo3WDT::clear() +{ + am_hal_wdt_int_clear(); +} + +// Read the current value of watch dog timer counter register +uint32_t Apollo3WDT::getCounter() +{ + return am_hal_wdt_counter_get(); +} \ No newline at end of file diff --git a/libraries/WDT/src/WDT.h b/libraries/WDT/src/WDT.h new file mode 100644 index 00000000..1ecf8e77 --- /dev/null +++ b/libraries/WDT/src/WDT.h @@ -0,0 +1,56 @@ +/* +// This file is subject to the terms and conditions defined in +// file 'LICENSE.md', which is part of this source code package. +*/ + +#ifndef _APOLLO3_LIBRARIES_WDT_H_ +#define _APOLLO3_LIBRARIES_WDT_H_ + +#include + +#ifdef wdt +#undef wdt +#endif + +// 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 Apollo3WDT { +private: + +protected: + +public: + Apollo3WDT(); + + // 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 * 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 * 8 // Set WDT reset timeout for 8 seconds (16 * 8 ) / 16 = 8 + }; + + 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 +}; + +extern Apollo3WDT wdt; + +#endif // _APOLLO3_LIBRARIES_RTC_H_ \ No newline at end of file