From cd124ecacefbbbf5f80185ed84684ad001977044 Mon Sep 17 00:00:00 2001 From: Thomas Pfister Date: Fri, 4 Oct 2024 11:41:03 +0200 Subject: [PATCH 1/5] Add getResetReason() by palmerr23 --- cores/rp2040/RP2040Support.h | 25 +++++++ docs/rp2040.rst | 5 ++ .../examples/RestartReason/RestartReason.ino | 65 +++++++++++++++++++ 3 files changed, 95 insertions(+) create mode 100644 libraries/rp2040/examples/RestartReason/RestartReason.ino diff --git a/cores/rp2040/RP2040Support.h b/cores/rp2040/RP2040Support.h index 5368ecb7a..dc7cc6589 100644 --- a/cores/rp2040/RP2040Support.h +++ b/cores/rp2040/RP2040Support.h @@ -22,6 +22,7 @@ #include #include #include +#include "hardware/regs/vreg_and_chip_reset.h" #include #include #include @@ -352,6 +353,30 @@ class RP2040 { watchdog_update(); } + enum resetReason_t {UNKNOWN_RESET, PWRON_RESET, RUN_PIN_RESET, SOFT_RESET, WDT_RESET, DEBUG_RESET}; + + resetReason_t getResetReason(void) { + io_rw_32 *WD_reason_reg = (io_rw_32 *)(WATCHDOG_BASE + WATCHDOG_REASON_OFFSET); + io_rw_32 *rrp = (io_rw_32 *)(VREG_AND_CHIP_RESET_BASE + VREG_AND_CHIP_RESET_CHIP_RESET_OFFSET); + + if (watchdog_caused_reboot() && watchdog_enable_caused_reboot()) // watchdog timer + return WDT_RESET; + + if (*WD_reason_reg & WATCHDOG_REASON_TIMER_BITS) // soft reset() or reboot() + return SOFT_RESET; + + if (*rrp & VREG_AND_CHIP_RESET_CHIP_RESET_HAD_POR_BITS) // POR: power-on reset or brown-out detection + return PWRON_RESET; + + if (*rrp & VREG_AND_CHIP_RESET_CHIP_RESET_HAD_RUN_BITS) // RUN pin + return RUN_PIN_RESET; + + if (*rrp & VREG_AND_CHIP_RESET_CHIP_RESET_HAD_PSM_RESTART_BITS) // DEBUG port + return DEBUG_RESET; // **** untested **** debug reset may just cause a rebootToBootloader() + + return UNKNOWN_RESET; + } + const char *getChipID() { static char id[2 * PICO_UNIQUE_BOARD_ID_SIZE_BYTES + 1] = { 0 }; if (!id[0]) { diff --git a/docs/rp2040.rst b/docs/rp2040.rst index 67deb493e..b8e14d2f8 100644 --- a/docs/rp2040.rst +++ b/docs/rp2040.rst @@ -57,6 +57,11 @@ void rp2040.wdt_reset() ~~~~~~~~~~~~~~~~~~~~~~~ Reloads the watchdog's counter with the amount of time set by wdt_begin. +RP2040::resetReason_t rp2040.getResetReason() +~~~~~~~~~~~~~~~~~~~~~~~ +Gives you the reason for the last reset, defined in enum ``RP2040::resetReason_t``. +See example ```ResetReason``` for some details. + Memory Information ------------------ diff --git a/libraries/rp2040/examples/RestartReason/RestartReason.ino b/libraries/rp2040/examples/RestartReason/RestartReason.ino new file mode 100644 index 000000000..37c84b9fa --- /dev/null +++ b/libraries/rp2040/examples/RestartReason/RestartReason.ino @@ -0,0 +1,65 @@ +// This sketch will cycle thru some possible restart reasons and shall help you understanding the rp2040.getResetReason() function +// Author: palmerr23 + +#include +#define NTESTS 5 // Number of tests, Debug port test not enabled +char resetReasonText[][24] = { "Unknown", "Power On / Brownout", "Run pin", "Software", "Watchdog Timer", "Debug reset" }; +char testText[][128] = { "Run pin\n\tShort Run pin to ground", "Power On / Brownout\n\tDisconnect / reconnect power (i.e. USB)", "Software reBOOT in 5 Secs", "Watchdog Timer in 7 Secs", "Software reSTART in 5 Secs\n\tUSB Serial does not always restart", "Debug port - do something!" }; + +// Small function that will send one dot every second over Serial, forever. +void delayCount(void) { + int t = 1; + while (1) { + Serial.print("."); + if (t % 50 == 0) + Serial.println(); + delay(1000); + } +} + +void setup() { + Serial.begin(115200); + while (!Serial) + delay(10); + delay(1000); + Serial.println("Reset reason:"); + + RP2040::resetReason_t rr = rp2040.getResetReason(); + Serial.printf("RR %i %s\n\n", rr, resetReasonText[rr]); + + EEPROM.begin(512); + byte test = EEPROM.read(0); + if (test >= NTESTS) // un-initialised EEPROM read is random + test = -1; + test = (test + 1) % NTESTS; // Go to next test, but limit to NTESTS-1 + Serial.printf("Test %i: %s\n", test, testText[test]); + EEPROM.write(0, test); + EEPROM.commit(); + delay(5000); + switch (test) { + case 0: // Run pin + delayCount(); + break; // Break to avoid compiler warnings + case 1: // Power On + delayCount(); + break; + case 2: // reboot comand + rp2040.reboot(); + delayCount(); + break; + case 3: // watchdog + rp2040.wdt_begin(2000); + rp2040.wdt_reset(); + delayCount(); + break; + case 4: // restart command + rp2040.restart(); + delayCount(); + break; + } +} + +// never gets here +void loop() { + delay(100); +} \ No newline at end of file From 18545c685f84202a6deb9bd7c96904d9e5f330c4 Mon Sep 17 00:00:00 2001 From: Thomas Pfister Date: Fri, 4 Oct 2024 11:47:58 +0200 Subject: [PATCH 2/5] Small fix in doc --- docs/rp2040.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/rp2040.rst b/docs/rp2040.rst index b8e14d2f8..ea3707064 100644 --- a/docs/rp2040.rst +++ b/docs/rp2040.rst @@ -59,7 +59,7 @@ Reloads the watchdog's counter with the amount of time set by wdt_begin. RP2040::resetReason_t rp2040.getResetReason() ~~~~~~~~~~~~~~~~~~~~~~~ -Gives you the reason for the last reset, defined in enum ``RP2040::resetReason_t``. +Returns the reason for the last reset, defined in enum ``RP2040::resetReason_t``. See example ```ResetReason``` for some details. From 145e0a9514fa3341ead904a8d690ab24041dafe4 Mon Sep 17 00:00:00 2001 From: Thomas Pfister Date: Fri, 4 Oct 2024 19:00:57 +0200 Subject: [PATCH 3/5] Fixes for CI (1/x) --- cores/rp2040/RP2040Support.h | 2 +- libraries/rp2040/examples/RestartReason/RestartReason.ino | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cores/rp2040/RP2040Support.h b/cores/rp2040/RP2040Support.h index dc7cc6589..79f68e34b 100644 --- a/cores/rp2040/RP2040Support.h +++ b/cores/rp2040/RP2040Support.h @@ -22,7 +22,7 @@ #include #include #include -#include "hardware/regs/vreg_and_chip_reset.h" +#include #include #include #include diff --git a/libraries/rp2040/examples/RestartReason/RestartReason.ino b/libraries/rp2040/examples/RestartReason/RestartReason.ino index 37c84b9fa..9684c8e13 100644 --- a/libraries/rp2040/examples/RestartReason/RestartReason.ino +++ b/libraries/rp2040/examples/RestartReason/RestartReason.ino @@ -43,7 +43,7 @@ void setup() { case 1: // Power On delayCount(); break; - case 2: // reboot comand + case 2: // reboot command rp2040.reboot(); delayCount(); break; From f0cbc0aa51f0e05c8b795d0885f15239e5d61b5a Mon Sep 17 00:00:00 2001 From: Thomas Pfister Date: Fri, 4 Oct 2024 22:05:12 +0200 Subject: [PATCH 4/5] Fixes for CI (2/x) --- .../rp2040/examples/RestartReason/RestartReason.ino | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/libraries/rp2040/examples/RestartReason/RestartReason.ino b/libraries/rp2040/examples/RestartReason/RestartReason.ino index 9684c8e13..db62c6460 100644 --- a/libraries/rp2040/examples/RestartReason/RestartReason.ino +++ b/libraries/rp2040/examples/RestartReason/RestartReason.ino @@ -11,16 +11,18 @@ void delayCount(void) { int t = 1; while (1) { Serial.print("."); - if (t % 50 == 0) + if (t % 50 == 0) { Serial.println(); + } delay(1000); } } void setup() { Serial.begin(115200); - while (!Serial) + while (!Serial) { delay(10); + } delay(1000); Serial.println("Reset reason:"); @@ -29,8 +31,9 @@ void setup() { EEPROM.begin(512); byte test = EEPROM.read(0); - if (test >= NTESTS) // un-initialised EEPROM read is random + if (test >= NTESTS) { // un-initialised EEPROM read is random test = -1; + } test = (test + 1) % NTESTS; // Go to next test, but limit to NTESTS-1 Serial.printf("Test %i: %s\n", test, testText[test]); EEPROM.write(0, test); From 975560a56a647088d797ff47686bc69fb550ad2f Mon Sep 17 00:00:00 2001 From: Thomas Pfister Date: Fri, 4 Oct 2024 22:05:29 +0200 Subject: [PATCH 5/5] Add support for RP2350 --- cores/rp2040/RP2040Support.h | 51 ++++++++++++++++++++++++++++++------ 1 file changed, 43 insertions(+), 8 deletions(-) diff --git a/cores/rp2040/RP2040Support.h b/cores/rp2040/RP2040Support.h index 79f68e34b..42e732df0 100644 --- a/cores/rp2040/RP2040Support.h +++ b/cores/rp2040/RP2040Support.h @@ -22,7 +22,11 @@ #include #include #include +#ifdef PICO_RP2350 +#include +#else #include +#endif #include #include #include @@ -353,27 +357,58 @@ class RP2040 { watchdog_update(); } - enum resetReason_t {UNKNOWN_RESET, PWRON_RESET, RUN_PIN_RESET, SOFT_RESET, WDT_RESET, DEBUG_RESET}; + enum resetReason_t {UNKNOWN_RESET, PWRON_RESET, RUN_PIN_RESET, SOFT_RESET, WDT_RESET, DEBUG_RESET, GLITCH_RESET, BROWNOUT_RESET}; resetReason_t getResetReason(void) { io_rw_32 *WD_reason_reg = (io_rw_32 *)(WATCHDOG_BASE + WATCHDOG_REASON_OFFSET); - io_rw_32 *rrp = (io_rw_32 *)(VREG_AND_CHIP_RESET_BASE + VREG_AND_CHIP_RESET_CHIP_RESET_OFFSET); - if (watchdog_caused_reboot() && watchdog_enable_caused_reboot()) // watchdog timer + if (watchdog_caused_reboot() && watchdog_enable_caused_reboot()) { // watchdog timer return WDT_RESET; + } - if (*WD_reason_reg & WATCHDOG_REASON_TIMER_BITS) // soft reset() or reboot() + if (*WD_reason_reg & WATCHDOG_REASON_TIMER_BITS) { // soft reset() or reboot() return SOFT_RESET; + } + +#ifdef PICO_RP2350 + // **** RP2350 is untested **** + io_rw_32 *rrp = (io_rw_32 *)(POWMAN_BASE + POWMAN_CHIP_RESET_OFFSET); - if (*rrp & VREG_AND_CHIP_RESET_CHIP_RESET_HAD_POR_BITS) // POR: power-on reset or brown-out detection + if (*rrp & POWMAN_CHIP_RESET_HAD_POR_BITS) { // POR: power-on reset (brownout is separately detected on RP2350) return PWRON_RESET; + } - if (*rrp & VREG_AND_CHIP_RESET_CHIP_RESET_HAD_RUN_BITS) // RUN pin + if (*rrp & POWMAN_CHIP_RESET_HAD_RUN_LOW_BITS) { // RUN pin return RUN_PIN_RESET; + } - if (*rrp & VREG_AND_CHIP_RESET_CHIP_RESET_HAD_PSM_RESTART_BITS) // DEBUG port - return DEBUG_RESET; // **** untested **** debug reset may just cause a rebootToBootloader() + if ((*rrp & POWMAN_CHIP_RESET_HAD_DP_RESET_REQ_BITS) || (*rrp & POWMAN_CHIP_RESET_HAD_RESCUE_BITS) || (*rrp & POWMAN_CHIP_RESET_HAD_HZD_SYS_RESET_REQ_BITS)) { // DEBUG port + return DEBUG_RESET; + } + + if (*rrp & POWMAN_CHIP_RESET_HAD_GLITCH_DETECT_BITS) { // power supply glitch + return GLITCH_RESET; + } + if (*rrp & POWMAN_CHIP_RESET_HAD_BOR_BITS) { // power supply brownout reset + return BROWNOUT_RESET; + } + +#else + io_rw_32 *rrp = (io_rw_32 *)(VREG_AND_CHIP_RESET_BASE + VREG_AND_CHIP_RESET_CHIP_RESET_OFFSET); + + if (*rrp & VREG_AND_CHIP_RESET_CHIP_RESET_HAD_POR_BITS) { // POR: power-on reset or brown-out detection + return PWRON_RESET; + } + + if (*rrp & VREG_AND_CHIP_RESET_CHIP_RESET_HAD_RUN_BITS) { // RUN pin + return RUN_PIN_RESET; + } + + if (*rrp & VREG_AND_CHIP_RESET_CHIP_RESET_HAD_PSM_RESTART_BITS) { // DEBUG port + return DEBUG_RESET; // **** untested **** debug reset may just cause a rebootToBootloader() + } +#endif return UNKNOWN_RESET; }