Skip to content

Commit 2f55223

Browse files
authored
Add getResetReason() by palmerr23 (#2516)
* Add support for RP2350
1 parent 67bf5a7 commit 2f55223

File tree

3 files changed

+133
-0
lines changed

3 files changed

+133
-0
lines changed

cores/rp2040/RP2040Support.h

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,11 @@
2222
#include <hardware/irq.h>
2323
#include <hardware/pio.h>
2424
#include <pico/unique_id.h>
25+
#ifdef PICO_RP2350
26+
#include <hardware/regs/powman.h>
27+
#else
28+
#include <hardware/regs/vreg_and_chip_reset.h>
29+
#endif
2530
#include <hardware/exception.h>
2631
#include <hardware/watchdog.h>
2732
#include <hardware/structs/rosc.h>
@@ -352,6 +357,61 @@ class RP2040 {
352357
watchdog_update();
353358
}
354359

360+
enum resetReason_t {UNKNOWN_RESET, PWRON_RESET, RUN_PIN_RESET, SOFT_RESET, WDT_RESET, DEBUG_RESET, GLITCH_RESET, BROWNOUT_RESET};
361+
362+
resetReason_t getResetReason(void) {
363+
io_rw_32 *WD_reason_reg = (io_rw_32 *)(WATCHDOG_BASE + WATCHDOG_REASON_OFFSET);
364+
365+
if (watchdog_caused_reboot() && watchdog_enable_caused_reboot()) { // watchdog timer
366+
return WDT_RESET;
367+
}
368+
369+
if (*WD_reason_reg & WATCHDOG_REASON_TIMER_BITS) { // soft reset() or reboot()
370+
return SOFT_RESET;
371+
}
372+
373+
#ifdef PICO_RP2350
374+
// **** RP2350 is untested ****
375+
io_rw_32 *rrp = (io_rw_32 *)(POWMAN_BASE + POWMAN_CHIP_RESET_OFFSET);
376+
377+
if (*rrp & POWMAN_CHIP_RESET_HAD_POR_BITS) { // POR: power-on reset (brownout is separately detected on RP2350)
378+
return PWRON_RESET;
379+
}
380+
381+
if (*rrp & POWMAN_CHIP_RESET_HAD_RUN_LOW_BITS) { // RUN pin
382+
return RUN_PIN_RESET;
383+
}
384+
385+
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
386+
return DEBUG_RESET;
387+
}
388+
389+
if (*rrp & POWMAN_CHIP_RESET_HAD_GLITCH_DETECT_BITS) { // power supply glitch
390+
return GLITCH_RESET;
391+
}
392+
393+
if (*rrp & POWMAN_CHIP_RESET_HAD_BOR_BITS) { // power supply brownout reset
394+
return BROWNOUT_RESET;
395+
}
396+
397+
#else
398+
io_rw_32 *rrp = (io_rw_32 *)(VREG_AND_CHIP_RESET_BASE + VREG_AND_CHIP_RESET_CHIP_RESET_OFFSET);
399+
400+
if (*rrp & VREG_AND_CHIP_RESET_CHIP_RESET_HAD_POR_BITS) { // POR: power-on reset or brown-out detection
401+
return PWRON_RESET;
402+
}
403+
404+
if (*rrp & VREG_AND_CHIP_RESET_CHIP_RESET_HAD_RUN_BITS) { // RUN pin
405+
return RUN_PIN_RESET;
406+
}
407+
408+
if (*rrp & VREG_AND_CHIP_RESET_CHIP_RESET_HAD_PSM_RESTART_BITS) { // DEBUG port
409+
return DEBUG_RESET; // **** untested **** debug reset may just cause a rebootToBootloader()
410+
}
411+
#endif
412+
return UNKNOWN_RESET;
413+
}
414+
355415
const char *getChipID() {
356416
static char id[2 * PICO_UNIQUE_BOARD_ID_SIZE_BYTES + 1] = { 0 };
357417
if (!id[0]) {

docs/rp2040.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,11 @@ void rp2040.wdt_reset()
5757
~~~~~~~~~~~~~~~~~~~~~~~
5858
Reloads the watchdog's counter with the amount of time set by wdt_begin.
5959

60+
RP2040::resetReason_t rp2040.getResetReason()
61+
~~~~~~~~~~~~~~~~~~~~~~~
62+
Returns the reason for the last reset, defined in enum ``RP2040::resetReason_t``.
63+
See example ```ResetReason``` for some details.
64+
6065

6166
Memory Information
6267
------------------
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
// This sketch will cycle thru some possible restart reasons and shall help you understanding the rp2040.getResetReason() function
2+
// Author: palmerr23
3+
4+
#include <EEPROM.h>
5+
#define NTESTS 5 // Number of tests, Debug port test not enabled
6+
char resetReasonText[][24] = { "Unknown", "Power On / Brownout", "Run pin", "Software", "Watchdog Timer", "Debug reset" };
7+
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!" };
8+
9+
// Small function that will send one dot every second over Serial, forever.
10+
void delayCount(void) {
11+
int t = 1;
12+
while (1) {
13+
Serial.print(".");
14+
if (t % 50 == 0) {
15+
Serial.println();
16+
}
17+
delay(1000);
18+
}
19+
}
20+
21+
void setup() {
22+
Serial.begin(115200);
23+
while (!Serial) {
24+
delay(10);
25+
}
26+
delay(1000);
27+
Serial.println("Reset reason:");
28+
29+
RP2040::resetReason_t rr = rp2040.getResetReason();
30+
Serial.printf("RR %i %s\n\n", rr, resetReasonText[rr]);
31+
32+
EEPROM.begin(512);
33+
byte test = EEPROM.read(0);
34+
if (test >= NTESTS) { // un-initialised EEPROM read is random
35+
test = -1;
36+
}
37+
test = (test + 1) % NTESTS; // Go to next test, but limit to NTESTS-1
38+
Serial.printf("Test %i: %s\n", test, testText[test]);
39+
EEPROM.write(0, test);
40+
EEPROM.commit();
41+
delay(5000);
42+
switch (test) {
43+
case 0: // Run pin
44+
delayCount();
45+
break; // Break to avoid compiler warnings
46+
case 1: // Power On
47+
delayCount();
48+
break;
49+
case 2: // reboot command
50+
rp2040.reboot();
51+
delayCount();
52+
break;
53+
case 3: // watchdog
54+
rp2040.wdt_begin(2000);
55+
rp2040.wdt_reset();
56+
delayCount();
57+
break;
58+
case 4: // restart command
59+
rp2040.restart();
60+
delayCount();
61+
break;
62+
}
63+
}
64+
65+
// never gets here
66+
void loop() {
67+
delay(100);
68+
}

0 commit comments

Comments
 (0)