add watchdog_enable_caused_reboot (minor compatibility issue) (#594)

add watchdog_enable_caused_reboot. Note there is a small backwards incompatibility in so far as watchdog_enable sets scratch[4] to a magic value not 0 now, however this behavior was not documented before.
This commit is contained in:
Graham Sanderson 2021-10-20 17:30:24 -05:00 committed by GitHub
parent 68571ad33e
commit 9320d192c3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 32 additions and 3 deletions

View File

@ -8,6 +8,7 @@
#define _HARDWARE_WATCHDOG_H #define _HARDWARE_WATCHDOG_H
#include "pico.h" #include "pico.h"
#include "hardware/structs/watchdog.h"
/** \file hardware/watchdog.h /** \file hardware/watchdog.h
* \defgroup hardware_watchdog hardware_watchdog * \defgroup hardware_watchdog hardware_watchdog
@ -66,6 +67,11 @@ void watchdog_update(void);
* *
* By default the SDK assumes a 12MHz XOSC and sets the \ref watchdog_start_tick appropriately. * By default the SDK assumes a 12MHz XOSC and sets the \ref watchdog_start_tick appropriately.
* *
* This method sets a marker in the watchdog scratch register 4 that is checked by \ref watchdog_enable_caused_reboot.
* If the device is subsequently reset via a call to watchdog_reboot (including for example by dragging a UF2
* onto the RPI-RP2), then this value will be cleared, and so \ref watchdog_enable_caused_reboot will
* return false.
*
* \param delay_ms Number of milliseconds before watchdog will reboot without watchdog_update being called. Maximum of 0x7fffff, which is approximately 8.3 seconds * \param delay_ms Number of milliseconds before watchdog will reboot without watchdog_update being called. Maximum of 0x7fffff, which is approximately 8.3 seconds
* \param pause_on_debug If the watchdog should be paused when the debugger is stepping through code * \param pause_on_debug If the watchdog should be paused when the debugger is stepping through code
*/ */
@ -80,6 +86,23 @@ void watchdog_enable(uint32_t delay_ms, bool pause_on_debug);
*/ */
bool watchdog_caused_reboot(void); bool watchdog_caused_reboot(void);
/**
* \brief Did watchdog_enable cause the last reboot?
* \ingroup hardware_watchdog
*
* Perform additional checking along with \ref watchdog_caused_reboot to determine if a watchdog timeout initiated by
* \ref watchdog_enable caused the last reboot.
*
* This method checks for a special value in watchdog scratch register 4 placed there by \ref watchdog_enable.
* This would not be present if a watchdog reset is initiated by \ref watchdog_reboot or by the RP2040 bootrom
* (e.g. dragging a UF2 onto the RPI-RP2 drive).
*
* @return true if the watchdog timer or a watchdog force caused (see \reg watchdog_caused_reboot) the last reboot
* and the watchdog reboot happened after \ref watchdog_enable was called
* @return false there has been no watchdog reboot since run has been
*/
bool watchdog_enable_caused_reboot(void);
/** /**
* @brief Returns the number of microseconds before the watchdog will reboot the chip. * @brief Returns the number of microseconds before the watchdog will reboot the chip.
* \ingroup hardware_watchdog * \ingroup hardware_watchdog

View File

@ -65,10 +65,12 @@ void _watchdog_enable(uint32_t delay_ms, bool pause_on_debug) {
} }
// end::watchdog_enable[] // end::watchdog_enable[]
#define WATCHDOG_NON_REBOOT_MAGIC 0x6ab73121
void watchdog_enable(uint32_t delay_ms, bool pause_on_debug) { void watchdog_enable(uint32_t delay_ms, bool pause_on_debug) {
// This watchdog enable doesn't reboot so clear scratch register // update scratch[4] to distinguish from magic used for reboot to specific address, or 0 used to reboot
// with magic word to jump into code // into regular flash path
watchdog_hw->scratch[4] = 0; watchdog_hw->scratch[4] = WATCHDOG_NON_REBOOT_MAGIC;
_watchdog_enable(delay_ms, pause_on_debug); _watchdog_enable(delay_ms, pause_on_debug);
} }
@ -98,3 +100,7 @@ bool watchdog_caused_reboot(void) {
// If any reason bits are set this is true // If any reason bits are set this is true
return watchdog_hw->reason; return watchdog_hw->reason;
} }
bool watchdog_enable_caused_reboot(void) {
return watchdog_hw->reason && watchdog_hw->scratch[4] == WATCHDOG_NON_REBOOT_MAGIC;
}