Implement safemode.py
This commit is contained in:
parent
795e46cedd
commit
d8231f1588
14
README.rst
14
README.rst
@ -138,6 +138,14 @@ Behavior
|
||||
- Adds a safe mode that does not run user code after a hard crash or brown out. This makes it
|
||||
possible to fix code that causes nasty crashes by making it available through mass storage after
|
||||
the crash. A reset (the button) is needed after it's fixed to get back into normal mode.
|
||||
- Safe mode may be handled programmatically by providing a ``safemode.py``.
|
||||
``safemode.py`` is run if the board has reset due to entering safe mode. USB is not
|
||||
available so nothing can be printed. ``safemode.py`` can determine why the safe mode occurred
|
||||
using ``supervisor.runtime.safe_mode_reason``, and take appropriate action. For instance,
|
||||
if a hard crash occurred, ``safemode.py`` may do a ``microcontroller.reset()``
|
||||
to automatically restart despite the crash.
|
||||
If the battery is low, but is being charged, ``safemode.py`` may put the board in deep sleep
|
||||
for a while. Or it may simply reset, and have ``code.py`` check the voltage and do the sleep.
|
||||
- RGB status LED indicating CircuitPython state.
|
||||
- One green flash - code completed without error.
|
||||
- Two red flashes - code ended due to an exception.
|
||||
@ -145,9 +153,9 @@ Behavior
|
||||
- Re-runs ``code.py`` or other main file after file system writes by a workflow. (Disable with
|
||||
``supervisor.disable_autoreload()``)
|
||||
- Autoreload is disabled while the REPL is active.
|
||||
- Main is one of these: ``code.txt``, ``code.py``, ``main.py``,
|
||||
``main.txt``
|
||||
- Boot is one of these: ``boot.py``, ``boot.txt``
|
||||
- ``code.py`` may also be named``code.txt``, ``main.py``, or ``main.txt``.
|
||||
- ``boot.py`` may also be named ``boot.txt``.
|
||||
- ``safemode.py`` may also be named ``safemode.txt``.
|
||||
|
||||
API
|
||||
~~~
|
||||
|
@ -35,6 +35,12 @@ msgid ""
|
||||
"https://github.com/adafruit/circuitpython/issues\n"
|
||||
msgstr ""
|
||||
|
||||
#: supervisor/shared/safe_mode.c
|
||||
msgid ""
|
||||
"\n"
|
||||
"To exit, reset the board without requesting safe mode."
|
||||
msgstr ""
|
||||
|
||||
#: py/obj.c
|
||||
msgid " File \"%q\""
|
||||
msgstr ""
|
||||
@ -85,7 +91,7 @@ msgstr ""
|
||||
#: ports/raspberrypi/common-hal/alarm/__init__.c
|
||||
#: ports/raspberrypi/common-hal/analogio/AnalogOut.c
|
||||
#: ports/raspberrypi/common-hal/rtc/RTC.c ports/stm/common-hal/alarm/__init__.c
|
||||
#: ports/stm/common-hal/rtc/RTC.c
|
||||
#: ports/stm/common-hal/canio/Listener.c ports/stm/common-hal/rtc/RTC.c
|
||||
msgid "%q"
|
||||
msgstr ""
|
||||
|
||||
@ -589,13 +595,6 @@ msgstr ""
|
||||
msgid "Both RX and TX required for flow control"
|
||||
msgstr ""
|
||||
|
||||
#: ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.h
|
||||
#: ports/atmel-samd/boards/circuitplayground_express_crickit/mpconfigboard.h
|
||||
#: ports/atmel-samd/boards/circuitplayground_express_displayio/mpconfigboard.h
|
||||
#: ports/atmel-samd/boards/meowmeow/mpconfigboard.h
|
||||
msgid "Both buttons were pressed at start up.\n"
|
||||
msgstr ""
|
||||
|
||||
#: ports/atmel-samd/common-hal/rotaryio/IncrementalEncoder.c
|
||||
msgid "Both pins must support hardware interrupts"
|
||||
msgstr ""
|
||||
@ -661,12 +660,6 @@ msgstr ""
|
||||
msgid "Bus pin %d is already in use"
|
||||
msgstr ""
|
||||
|
||||
#: ports/espressif/boards/m5stack_core_basic/mpconfigboard.h
|
||||
#: ports/espressif/boards/m5stack_core_fire/mpconfigboard.h
|
||||
#: ports/espressif/boards/m5stack_stick_c/mpconfigboard.h
|
||||
msgid "Button A was pressed at start up.\n"
|
||||
msgstr ""
|
||||
|
||||
#: shared-bindings/_bleio/UUID.c
|
||||
msgid "Byte buffer must be 16 bytes."
|
||||
msgstr ""
|
||||
@ -934,6 +927,10 @@ msgstr ""
|
||||
msgid "Error in regex"
|
||||
msgstr ""
|
||||
|
||||
#: supervisor/shared/safe_mode.c
|
||||
msgid "Error in safemode.py."
|
||||
msgstr ""
|
||||
|
||||
#: shared-bindings/socketpool/Socket.c shared-bindings/ssl/SSLSocket.c
|
||||
msgid "Error: Failure to bind"
|
||||
msgstr ""
|
||||
@ -1006,10 +1003,6 @@ msgstr ""
|
||||
msgid "Failed to write internal flash."
|
||||
msgstr ""
|
||||
|
||||
#: supervisor/shared/safe_mode.c
|
||||
msgid "Fatal error."
|
||||
msgstr ""
|
||||
|
||||
#: py/moduerrno.c
|
||||
msgid "File exists"
|
||||
msgstr ""
|
||||
@ -1209,6 +1202,10 @@ msgstr ""
|
||||
msgid "Internal watchdog timer expired."
|
||||
msgstr ""
|
||||
|
||||
#: supervisor/shared/safe_mode.c
|
||||
msgid "Interrupt error."
|
||||
msgstr ""
|
||||
|
||||
#: py/argcheck.c shared-bindings/digitalio/DigitalInOut.c
|
||||
msgid "Invalid %q"
|
||||
msgstr ""
|
||||
@ -1257,10 +1254,6 @@ msgstr ""
|
||||
msgid "Invalid format chunk size"
|
||||
msgstr ""
|
||||
|
||||
#: supervisor/shared/safe_mode.c
|
||||
msgid "Invalid memory access."
|
||||
msgstr ""
|
||||
|
||||
#: ports/espressif/common-hal/wifi/Radio.c
|
||||
msgid "Invalid multicast MAC address"
|
||||
msgstr ""
|
||||
@ -1549,10 +1542,6 @@ msgstr ""
|
||||
msgid "No timer available"
|
||||
msgstr ""
|
||||
|
||||
#: supervisor/shared/safe_mode.c
|
||||
msgid "Nordic system firmware failure assertion."
|
||||
msgstr ""
|
||||
|
||||
#: ports/nrf/common-hal/_bleio/__init__.c
|
||||
msgid "Nordic system firmware out of memory"
|
||||
msgstr ""
|
||||
@ -2003,24 +1992,12 @@ msgstr ""
|
||||
msgid "Temperature read timed out"
|
||||
msgstr ""
|
||||
|
||||
#: supervisor/shared/safe_mode.c
|
||||
msgid "The BOOT button was pressed at start up.\n"
|
||||
msgstr ""
|
||||
|
||||
#: supervisor/shared/safe_mode.c
|
||||
msgid ""
|
||||
"The CircuitPython heap was corrupted because the stack was too small.\n"
|
||||
"Increase the stack size if you know how. If not:"
|
||||
msgstr ""
|
||||
|
||||
#: ports/espressif/boards/adafruit_feather_esp32_v2/mpconfigboard.h
|
||||
msgid "The SW38 button was pressed at start up.\n"
|
||||
msgstr ""
|
||||
|
||||
#: ports/espressif/boards/hardkernel_odroid_go/mpconfigboard.h
|
||||
msgid "The VOLUME button was pressed at start up.\n"
|
||||
msgstr ""
|
||||
|
||||
#: supervisor/shared/safe_mode.c
|
||||
msgid ""
|
||||
"The `microcontroller` module was used to boot into safe mode. Press reset to "
|
||||
@ -2031,17 +2008,6 @@ msgstr ""
|
||||
msgid "The above exception was the direct cause of the following exception:"
|
||||
msgstr ""
|
||||
|
||||
#: ports/espressif/boards/m5stack_atom_echo/mpconfigboard.h
|
||||
#: ports/espressif/boards/m5stack_atom_lite/mpconfigboard.h
|
||||
#: ports/espressif/boards/m5stack_atom_matrix/mpconfigboard.h
|
||||
#: ports/espressif/boards/m5stack_atom_u/mpconfigboard.h
|
||||
msgid "The central button was pressed at start up.\n"
|
||||
msgstr ""
|
||||
|
||||
#: ports/nrf/boards/aramcon2_badge/mpconfigboard.h
|
||||
msgid "The left button was pressed at start up.\n"
|
||||
msgstr ""
|
||||
|
||||
#: shared-bindings/rgbmatrix/RGBMatrix.c
|
||||
msgid "The length of rgb_pins must be 6, 12, 18, 24, or 30"
|
||||
msgstr ""
|
||||
@ -2069,6 +2035,10 @@ msgstr ""
|
||||
msgid "The sample's signedness does not match the mixer's"
|
||||
msgstr ""
|
||||
|
||||
#: supervisor/shared/safe_mode.c
|
||||
msgid "Third-party firmware fatal error."
|
||||
msgstr ""
|
||||
|
||||
#: shared-module/imagecapture/ParallelImageCapture.c
|
||||
msgid "This microcontroller does not support continuous capture."
|
||||
msgstr ""
|
||||
@ -2101,10 +2071,6 @@ msgstr ""
|
||||
msgid "Timeout is too long: Maximum timeout length is %d seconds"
|
||||
msgstr ""
|
||||
|
||||
#: supervisor/shared/safe_mode.c
|
||||
msgid "To exit, please reset the board without requesting safe mode."
|
||||
msgstr ""
|
||||
|
||||
#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c
|
||||
msgid "Too many channels in sample"
|
||||
msgstr ""
|
||||
@ -2405,9 +2371,44 @@ msgstr ""
|
||||
msgid "You are in safe mode because:\n"
|
||||
msgstr ""
|
||||
|
||||
#: ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.h
|
||||
#: ports/atmel-samd/boards/circuitplayground_express_crickit/mpconfigboard.h
|
||||
#: ports/atmel-samd/boards/circuitplayground_express_displayio/mpconfigboard.h
|
||||
#: ports/atmel-samd/boards/meowmeow/mpconfigboard.h
|
||||
msgid "You pressed both buttons at start up."
|
||||
msgstr ""
|
||||
|
||||
#: ports/espressif/boards/m5stack_core_basic/mpconfigboard.h
|
||||
#: ports/espressif/boards/m5stack_core_fire/mpconfigboard.h
|
||||
#: ports/espressif/boards/m5stack_stick_c/mpconfigboard.h
|
||||
msgid "You pressed button A at start up."
|
||||
msgstr ""
|
||||
|
||||
#: supervisor/shared/safe_mode.c
|
||||
msgid ""
|
||||
"You pressed the reset button during boot. Press again to exit safe mode."
|
||||
msgid "You pressed the BOOT button at start up."
|
||||
msgstr ""
|
||||
|
||||
#: ports/espressif/boards/adafruit_feather_esp32_v2/mpconfigboard.h
|
||||
msgid "You pressed the SW38 button at start up."
|
||||
msgstr ""
|
||||
|
||||
#: ports/espressif/boards/hardkernel_odroid_go/mpconfigboard.h
|
||||
msgid "You pressed the VOLUME button at start up."
|
||||
msgstr ""
|
||||
|
||||
#: ports/espressif/boards/m5stack_atom_echo/mpconfigboard.h
|
||||
#: ports/espressif/boards/m5stack_atom_lite/mpconfigboard.h
|
||||
#: ports/espressif/boards/m5stack_atom_matrix/mpconfigboard.h
|
||||
#: ports/espressif/boards/m5stack_atom_u/mpconfigboard.h
|
||||
msgid "You pressed the central button at start up."
|
||||
msgstr ""
|
||||
|
||||
#: ports/nrf/boards/aramcon2_badge/mpconfigboard.h
|
||||
msgid "You pressed the left button at start up."
|
||||
msgstr ""
|
||||
|
||||
#: supervisor/shared/safe_mode.c
|
||||
msgid "You pressed the reset button during boot."
|
||||
msgstr ""
|
||||
|
||||
#: py/objtype.c
|
||||
|
65
main.c
65
main.c
@ -358,7 +358,7 @@ STATIC void print_code_py_status_message(safe_mode_t safe_mode) {
|
||||
} else {
|
||||
serial_write_compressed(translate("Auto-reload is off.\n"));
|
||||
}
|
||||
if (safe_mode != NO_SAFE_MODE) {
|
||||
if (safe_mode != SAFE_MODE_NONE) {
|
||||
serial_write_compressed(translate("Running in safe mode! Not running saved code.\n"));
|
||||
}
|
||||
}
|
||||
@ -384,11 +384,11 @@ STATIC bool run_code_py(safe_mode_t safe_mode, bool *simulate_reset) {
|
||||
|
||||
// Do the filesystem flush check before reload in case another write comes
|
||||
// in while we're doing the flush.
|
||||
if (safe_mode == NO_SAFE_MODE) {
|
||||
if (safe_mode == SAFE_MODE_NONE) {
|
||||
stack_resize();
|
||||
filesystem_flush();
|
||||
}
|
||||
if (safe_mode == NO_SAFE_MODE && !autoreload_pending()) {
|
||||
if (safe_mode == SAFE_MODE_NONE && !autoreload_pending()) {
|
||||
static const char *const supported_filenames[] = {
|
||||
"code.txt", "code.py", "main.py", "main.txt"
|
||||
};
|
||||
@ -510,7 +510,7 @@ STATIC bool run_code_py(safe_mode_t safe_mode, bool *simulate_reset) {
|
||||
} else
|
||||
#endif
|
||||
if (_exec_result.return_code != PYEXEC_EXCEPTION) {
|
||||
if (safe_mode == NO_SAFE_MODE) {
|
||||
if (safe_mode == SAFE_MODE_NONE) {
|
||||
color = ALL_DONE;
|
||||
blink_count = ALL_DONE_BLINKS;
|
||||
} else {
|
||||
@ -730,8 +730,32 @@ STATIC bool run_code_py(safe_mode_t safe_mode, bool *simulate_reset) {
|
||||
|
||||
vstr_t *boot_output;
|
||||
|
||||
#if CIRCUITPY_SAFEMODE_PY
|
||||
STATIC void __attribute__ ((noinline)) run_safemode_py(safe_mode_t safe_mode) {
|
||||
// Don't run if we aren't in safe mode or we won't be able to find safemode.py.
|
||||
if (safe_mode == SAFE_MODE_NONE || !filesystem_present()) {
|
||||
return;
|
||||
}
|
||||
|
||||
supervisor_allocation *heap = allocate_remaining_memory();
|
||||
start_mp(heap);
|
||||
|
||||
static const char *const safemode_py_filenames[] = {"safemode.py", "safemode.txt"};
|
||||
maybe_run_list(safemode_py_filenames, MP_ARRAY_SIZE(safemode_py_filenames));
|
||||
|
||||
// If safemode.py itself caused an error, change the safe_mode state to indicate that.
|
||||
if (_exec_result.exception != MP_OBJ_NULL &&
|
||||
_exec_result.exception != MP_OBJ_SENTINEL) {
|
||||
set_safe_mode(SAFE_MODE_SAFEMODE_PY_ERROR);
|
||||
}
|
||||
|
||||
cleanup_after_vm(heap, _exec_result.exception);
|
||||
_exec_result.exception = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
STATIC void __attribute__ ((noinline)) run_boot_py(safe_mode_t safe_mode) {
|
||||
if (safe_mode == NO_HEAP) {
|
||||
if (safe_mode == SAFE_MODE_NO_HEAP) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -739,7 +763,7 @@ STATIC void __attribute__ ((noinline)) run_boot_py(safe_mode_t safe_mode) {
|
||||
|
||||
// There is USB setup to do even if boot.py is not actually run.
|
||||
const bool ok_to_run = filesystem_present()
|
||||
&& safe_mode == NO_SAFE_MODE
|
||||
&& safe_mode == SAFE_MODE_NONE
|
||||
&& MP_STATE_VM(vfs_mount_table) != NULL;
|
||||
|
||||
static const char *const boot_py_filenames[] = {"boot.py", "boot.txt"};
|
||||
@ -913,7 +937,7 @@ STATIC int run_repl(void) {
|
||||
|
||||
int __attribute__((used)) main(void) {
|
||||
// initialise the cpu and peripherals
|
||||
safe_mode_t safe_mode = port_init();
|
||||
set_safe_mode(port_init());
|
||||
|
||||
// Turn on RX and TX LEDs if we have them.
|
||||
init_rxtx_leds();
|
||||
@ -926,8 +950,8 @@ int __attribute__((used)) main(void) {
|
||||
#endif
|
||||
|
||||
// Wait briefly to give a reset window where we'll enter safe mode after the reset.
|
||||
if (safe_mode == NO_SAFE_MODE) {
|
||||
safe_mode = wait_for_safe_mode_reset();
|
||||
if (get_safe_mode() == SAFE_MODE_NONE) {
|
||||
set_safe_mode(wait_for_safe_mode_reset());
|
||||
}
|
||||
|
||||
stack_init();
|
||||
@ -956,8 +980,8 @@ int __attribute__((used)) main(void) {
|
||||
|
||||
// Check whether CIRCUITPY is available. No need to reset to get safe mode
|
||||
// since we haven't run user code yet.
|
||||
if (!filesystem_init(safe_mode == NO_SAFE_MODE, false)) {
|
||||
safe_mode = NO_CIRCUITPY;
|
||||
if (!filesystem_init(get_safe_mode() == SAFE_MODE_NONE, false)) {
|
||||
set_safe_mode(SAFE_MODE_NO_CIRCUITPY);
|
||||
}
|
||||
|
||||
#if CIRCUITPY_ALARM
|
||||
@ -982,16 +1006,23 @@ int __attribute__((used)) main(void) {
|
||||
supervisor_set_run_reason(RUN_REASON_STARTUP);
|
||||
|
||||
// If not in safe mode turn on autoreload by default but before boot.py in case it wants to change it.
|
||||
if (safe_mode == NO_SAFE_MODE) {
|
||||
if (get_safe_mode() == SAFE_MODE_NONE) {
|
||||
autoreload_enable();
|
||||
}
|
||||
|
||||
// By default our internal flash is readonly to local python code and
|
||||
// writable over USB. Set it here so that boot.py can change it.
|
||||
// writable over USB. Set it here so that safemode.py or boot.py can change it.
|
||||
filesystem_set_internal_concurrent_write_protection(true);
|
||||
filesystem_set_internal_writable_by_usb(CIRCUITPY_USB == 1);
|
||||
|
||||
run_boot_py(safe_mode);
|
||||
#if CIRCUITPY_SAFEMODE_PY
|
||||
// Run safemode.py if we ARE in safe mode.
|
||||
// If safemode.py does not do a hard reset, and exits normally, we will continue on
|
||||
// and report the safe mode as usual.
|
||||
run_safemode_py(get_safe_mode());
|
||||
#endif
|
||||
|
||||
run_boot_py(get_safe_mode());
|
||||
|
||||
supervisor_workflow_start();
|
||||
|
||||
@ -1016,7 +1047,7 @@ int __attribute__((used)) main(void) {
|
||||
// If code.py did a fake deep sleep, pretend that we
|
||||
// are running code.py for the first time after a hard
|
||||
// reset. This will preserve any alarm information.
|
||||
skip_repl = run_code_py(safe_mode, &simulate_reset);
|
||||
skip_repl = run_code_py(get_safe_mode(), &simulate_reset);
|
||||
} else {
|
||||
skip_repl = false;
|
||||
}
|
||||
@ -1076,14 +1107,14 @@ void gc_collect(void) {
|
||||
}
|
||||
|
||||
void NORETURN nlr_jump_fail(void *val) {
|
||||
reset_into_safe_mode(MICROPY_NLR_JUMP_FAIL);
|
||||
reset_into_safe_mode(SAFE_MODE_NLR_JUMP_FAIL);
|
||||
while (true) {
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
static void NORETURN __fatal_error(const char *msg) {
|
||||
reset_into_safe_mode(MICROPY_FATAL_ERROR);
|
||||
reset_into_safe_mode(SAFE_MODE_HARD_FAULT);
|
||||
while (true) {
|
||||
}
|
||||
}
|
||||
|
@ -23,7 +23,7 @@
|
||||
#define CALIBRATE_CRYSTALLESS 1
|
||||
|
||||
// Explanation of how a user got into safe mode.
|
||||
#define BOARD_USER_SAFE_MODE_ACTION translate("Both buttons were pressed at start up.\n")
|
||||
#define BOARD_USER_SAFE_MODE_ACTION translate("You pressed both buttons at start up.")
|
||||
|
||||
// Increase stack size slightly due to CPX library import nesting
|
||||
#define CIRCUITPY_DEFAULT_STACK_SIZE (4248) // divisible by 8
|
||||
|
@ -23,7 +23,7 @@
|
||||
#define CALIBRATE_CRYSTALLESS 1
|
||||
|
||||
// Explanation of how a user got into safe mode.
|
||||
#define BOARD_USER_SAFE_MODE_ACTION translate("Both buttons were pressed at start up.\n")
|
||||
#define BOARD_USER_SAFE_MODE_ACTION translate("You pressed both buttons at start up.")
|
||||
|
||||
// Increase stack size slightly due to CPX library import nesting
|
||||
#define CIRCUITPY_DEFAULT_STACK_SIZE (4248) // divisible by 8
|
||||
|
@ -23,7 +23,7 @@
|
||||
#define CALIBRATE_CRYSTALLESS 1
|
||||
|
||||
// Explanation of how a user got into safe mode.
|
||||
#define BOARD_USER_SAFE_MODE_ACTION translate("Both buttons were pressed at start up.\n")
|
||||
#define BOARD_USER_SAFE_MODE_ACTION translate("You pressed both buttons at start up.")
|
||||
|
||||
// Increase stack size slightly due to CPX library import nesting.
|
||||
#define CIRCUITPY_DEFAULT_STACK_SIZE (4248) // divisible by 8
|
||||
|
@ -6,7 +6,7 @@
|
||||
#define CALIBRATE_CRYSTALLESS 1
|
||||
|
||||
// Explanation of how a user got into safe mode.
|
||||
#define BOARD_USER_SAFE_MODE_ACTION translate("Both buttons were pressed at start up.\n")
|
||||
#define BOARD_USER_SAFE_MODE_ACTION translate("You pressed both buttons at start up.")
|
||||
|
||||
#define DEFAULT_I2C_BUS_SCL (&pin_PA01)
|
||||
#define DEFAULT_I2C_BUS_SDA (&pin_PA00)
|
||||
|
@ -51,9 +51,8 @@ void common_hal_mcu_disable_interrupts(void) {
|
||||
|
||||
void common_hal_mcu_enable_interrupts(void) {
|
||||
if (nesting_count == 0) {
|
||||
// This is very very bad because it means there was mismatched disable/enables so we
|
||||
// "HardFault".
|
||||
HardFault_Handler();
|
||||
// This is very very bad because it means there was mismatched disable/enables.
|
||||
reset_into_safe_mode(SAFE_MODE_INTERRUPT_ERROR);
|
||||
}
|
||||
nesting_count--;
|
||||
if (nesting_count > 0) {
|
||||
@ -76,7 +75,7 @@ void common_hal_mcu_on_next_reset(mcu_runmode_t runmode) {
|
||||
_bootloader_dbl_tap = DBL_TAP_MAGIC_QUICK_BOOT;
|
||||
}
|
||||
if (runmode == RUNMODE_SAFE_MODE) {
|
||||
safe_mode_on_next_reset(PROGRAMMATIC_SAFE_MODE);
|
||||
safe_mode_on_next_reset(SAFE_MODE_PROGRAMMATIC);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -368,20 +368,20 @@ safe_mode_t port_init(void) {
|
||||
|
||||
#ifdef SAMD21
|
||||
if (PM->RCAUSE.bit.BOD33 == 1 || PM->RCAUSE.bit.BOD12 == 1) {
|
||||
return BROWNOUT;
|
||||
return SAFE_MODE_BROWNOUT;
|
||||
}
|
||||
#endif
|
||||
#ifdef SAM_D5X_E5X
|
||||
if (RSTC->RCAUSE.bit.BODVDD == 1 || RSTC->RCAUSE.bit.BODCORE == 1) {
|
||||
return BROWNOUT;
|
||||
return SAFE_MODE_BROWNOUT;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (board_requests_safe_mode()) {
|
||||
return USER_SAFE_MODE;
|
||||
return SAFE_MODE_USER;
|
||||
}
|
||||
|
||||
return NO_SAFE_MODE;
|
||||
return SAFE_MODE_NONE;
|
||||
}
|
||||
|
||||
void reset_port(void) {
|
||||
@ -720,7 +720,7 @@ __attribute__((used)) void HardFault_Handler(void) {
|
||||
REG_MTB_MASTER = 0x00000000 + 6;
|
||||
#endif
|
||||
|
||||
reset_into_safe_mode(HARD_CRASH);
|
||||
reset_into_safe_mode(SAFE_MODE_HARD_FAULT);
|
||||
while (true) {
|
||||
asm ("nop;");
|
||||
}
|
||||
|
@ -46,7 +46,7 @@ void common_hal_mcu_disable_interrupts(void) {
|
||||
|
||||
void common_hal_mcu_enable_interrupts(void) {
|
||||
if (nesting_count == 0) {
|
||||
// reset_into_safe_mode(LOCKING_ERROR);
|
||||
// reset_into_safe_mode(SAFE_MODE_INTERRUPT_ERROR);
|
||||
}
|
||||
nesting_count--;
|
||||
if (nesting_count > 0) {
|
||||
|
@ -78,10 +78,10 @@ safe_mode_t port_init(void) {
|
||||
// Check brownout.
|
||||
|
||||
if (board_requests_safe_mode()) {
|
||||
return USER_SAFE_MODE;
|
||||
return SAFE_MODE_USER;
|
||||
}
|
||||
|
||||
return NO_SAFE_MODE;
|
||||
return SAFE_MODE_NONE;
|
||||
}
|
||||
|
||||
void reset_port(void) {
|
||||
|
@ -74,7 +74,7 @@ void common_hal_mcu_on_next_reset(mcu_runmode_t runmode) {
|
||||
if (runmode == RUNMODE_BOOTLOADER) {
|
||||
mp_raise_ValueError(translate("Cannot reset into bootloader because no bootloader is present"));
|
||||
} else if (runmode == RUNMODE_SAFE_MODE) {
|
||||
safe_mode_on_next_reset(PROGRAMMATIC_SAFE_MODE);
|
||||
safe_mode_on_next_reset(SAFE_MODE_PROGRAMMATIC);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -66,10 +66,10 @@ safe_mode_t port_init(void) {
|
||||
heap_size = size / sizeof(uint32_t);
|
||||
|
||||
if (board_requests_safe_mode()) {
|
||||
return USER_SAFE_MODE;
|
||||
return SAFE_MODE_USER;
|
||||
}
|
||||
|
||||
return NO_SAFE_MODE;
|
||||
return SAFE_MODE_NONE;
|
||||
}
|
||||
|
||||
void reset_cpu(void) {
|
||||
|
@ -47,7 +47,7 @@
|
||||
#define CIRCUITPY_BOOT_BUTTON (&pin_GPIO38)
|
||||
|
||||
// Explanation of how a user got into safe mode
|
||||
#define BOARD_USER_SAFE_MODE_ACTION translate("The SW38 button was pressed at start up.\n")
|
||||
#define BOARD_USER_SAFE_MODE_ACTION translate("You pressed the SW38 button at start up.")
|
||||
|
||||
// UART pins attached to the USB-serial converter chip
|
||||
#define CIRCUITPY_CONSOLE_UART_TX (&pin_GPIO1)
|
||||
|
@ -35,7 +35,7 @@
|
||||
#define CIRCUITPY_BOOT_BUTTON (&pin_GPIO0)
|
||||
|
||||
// Explanation of how a user got into safe mode
|
||||
#define BOARD_USER_SAFE_MODE_ACTION translate("The VOLUME button was pressed at start up.\n")
|
||||
#define BOARD_USER_SAFE_MODE_ACTION translate("You pressed the VOLUME button at start up.")
|
||||
|
||||
// UART pins attached to the USB-serial converter chip
|
||||
#define CIRCUITPY_CONSOLE_UART_TX (&pin_GPIO1)
|
||||
|
@ -38,7 +38,7 @@
|
||||
#define CIRCUITPY_BOOT_BUTTON (&pin_GPIO39)
|
||||
|
||||
// Explanation of how a user got into safe mode
|
||||
#define BOARD_USER_SAFE_MODE_ACTION translate("The central button was pressed at start up.\n")
|
||||
#define BOARD_USER_SAFE_MODE_ACTION translate("You pressed the central button at start up.")
|
||||
|
||||
// UART pins attached to the USB-serial converter chip
|
||||
#define CIRCUITPY_CONSOLE_UART_TX (&pin_GPIO1)
|
||||
|
@ -42,7 +42,7 @@
|
||||
#define CIRCUITPY_BOOT_BUTTON (&pin_GPIO39)
|
||||
|
||||
// Explanation of how a user got into safe mode
|
||||
#define BOARD_USER_SAFE_MODE_ACTION translate("The central button was pressed at start up.\n")
|
||||
#define BOARD_USER_SAFE_MODE_ACTION translate("You pressed the central button at start up.")
|
||||
|
||||
// UART pins attached to the USB-serial converter chip
|
||||
#define CIRCUITPY_CONSOLE_UART_TX (&pin_GPIO1)
|
||||
|
@ -42,7 +42,7 @@
|
||||
#define CIRCUITPY_BOOT_BUTTON (&pin_GPIO39)
|
||||
|
||||
// Explanation of how a user got into safe mode
|
||||
#define BOARD_USER_SAFE_MODE_ACTION translate("The central button was pressed at start up.\n")
|
||||
#define BOARD_USER_SAFE_MODE_ACTION translate("You pressed the central button at start up.")
|
||||
|
||||
// UART pins attached to the USB-serial converter chip
|
||||
#define CIRCUITPY_CONSOLE_UART_TX (&pin_GPIO1)
|
||||
|
@ -41,7 +41,7 @@
|
||||
#define CIRCUITPY_BOOT_BUTTON (&pin_GPIO39)
|
||||
|
||||
// Explanation of how a user got into safe mode
|
||||
#define BOARD_USER_SAFE_MODE_ACTION translate("The central button was pressed at start up.\n")
|
||||
#define BOARD_USER_SAFE_MODE_ACTION translate("You pressed the central button at start up.")
|
||||
|
||||
// UART pins attached to the USB-serial converter chip
|
||||
#define CIRCUITPY_CONSOLE_UART_TX (&pin_GPIO1)
|
||||
|
@ -42,7 +42,7 @@
|
||||
#define CIRCUITPY_BOOT_BUTTON (&pin_GPIO39)
|
||||
|
||||
// Explanation of how a user got into safe mode
|
||||
#define BOARD_USER_SAFE_MODE_ACTION translate("Button A was pressed at start up.\n")
|
||||
#define BOARD_USER_SAFE_MODE_ACTION translate("You pressed button A at start up.")
|
||||
|
||||
// UART pins attached to the USB-serial converter chip
|
||||
#define CIRCUITPY_CONSOLE_UART_TX (&pin_GPIO1)
|
||||
|
@ -43,7 +43,7 @@
|
||||
#define CIRCUITPY_BOOT_BUTTON (&pin_GPIO39)
|
||||
|
||||
// Explanation of how a user got into safe mode
|
||||
#define BOARD_USER_SAFE_MODE_ACTION translate("Button A was pressed at start up.\n")
|
||||
#define BOARD_USER_SAFE_MODE_ACTION translate("You pressed button A at start up.")
|
||||
|
||||
// UART pins attached to the USB-serial converter chip
|
||||
#define CIRCUITPY_CONSOLE_UART_TX (&pin_GPIO1)
|
||||
|
@ -39,7 +39,7 @@
|
||||
#define CIRCUITPY_BOOT_BUTTON (&pin_GPIO37)
|
||||
|
||||
// Explanation of how a user got into safe mode
|
||||
#define BOARD_USER_SAFE_MODE_ACTION translate("Button A was pressed at start up.\n")
|
||||
#define BOARD_USER_SAFE_MODE_ACTION translate("You pressed button A at start up.")
|
||||
|
||||
// UART pins attached to the USB-serial converter chip
|
||||
#define CIRCUITPY_CONSOLE_UART_TX (&pin_GPIO1)
|
||||
|
@ -108,7 +108,7 @@ void common_hal_mcu_on_next_reset(mcu_runmode_t runmode) {
|
||||
break;
|
||||
case RUNMODE_SAFE_MODE:
|
||||
// enter safe mode on next boot
|
||||
safe_mode_on_next_reset(PROGRAMMATIC_SAFE_MODE);
|
||||
safe_mode_on_next_reset(SAFE_MODE_PROGRAMMATIC);
|
||||
break;
|
||||
case RUNMODE_BOOTLOADER:
|
||||
// DFU download
|
||||
|
@ -318,25 +318,25 @@ safe_mode_t port_init(void) {
|
||||
}
|
||||
if (heap == NULL) {
|
||||
heap_size = 0;
|
||||
return NO_HEAP;
|
||||
return SAFE_MODE_NO_HEAP;
|
||||
}
|
||||
|
||||
esp_reset_reason_t reason = esp_reset_reason();
|
||||
switch (reason) {
|
||||
case ESP_RST_BROWNOUT:
|
||||
return BROWNOUT;
|
||||
return SAFE_MODE_BROWNOUT;
|
||||
case ESP_RST_PANIC:
|
||||
return HARD_CRASH;
|
||||
return SAFE_MODE_HARD_FAULT;
|
||||
case ESP_RST_INT_WDT:
|
||||
// The interrupt watchdog is used internally to make sure that latency sensitive
|
||||
// interrupt code isn't blocked. User watchdog resets come through ESP_RST_WDT.
|
||||
return WATCHDOG_RESET;
|
||||
return SAFE_MODE_WATCHDOG;
|
||||
case ESP_RST_WDT:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return NO_SAFE_MODE;
|
||||
return SAFE_MODE_NONE;
|
||||
}
|
||||
|
||||
void reset_port(void) {
|
||||
|
@ -70,9 +70,8 @@ void common_hal_mcu_disable_interrupts(void) {
|
||||
__attribute__((section(".ramtext")))
|
||||
void common_hal_mcu_enable_interrupts(void) {
|
||||
if (nesting_count == 0) {
|
||||
// This is very very bad because it means there was mismatched disable/enables so we
|
||||
// "HardFault".
|
||||
asm ("ebreak");
|
||||
// This is very very bad because it means there was mismatched disable/enables.
|
||||
reset_into_safe_mode(SAFE_MODE_INTERRUPT_ERROR);
|
||||
}
|
||||
nesting_count--;
|
||||
if (nesting_count > 0) {
|
||||
@ -83,7 +82,7 @@ void common_hal_mcu_enable_interrupts(void) {
|
||||
|
||||
void common_hal_mcu_on_next_reset(mcu_runmode_t runmode) {
|
||||
if (runmode == RUNMODE_SAFE_MODE) {
|
||||
safe_mode_on_next_reset(PROGRAMMATIC_SAFE_MODE);
|
||||
safe_mode_on_next_reset(SAFE_MODE_PROGRAMMATIC);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -71,7 +71,7 @@ safe_mode_t port_init(void) {
|
||||
irq_setmask(0);
|
||||
irq_setie(1);
|
||||
tick_init();
|
||||
return NO_SAFE_MODE;
|
||||
return SAFE_MODE_NONE;
|
||||
}
|
||||
|
||||
extern uint32_t _ebss;
|
||||
|
@ -52,12 +52,10 @@ void common_hal_mcu_disable_interrupts(void) {
|
||||
nesting_count++;
|
||||
}
|
||||
|
||||
void HardFault_Handler(void);
|
||||
void common_hal_mcu_enable_interrupts(void) {
|
||||
if (nesting_count == 0) {
|
||||
// This is very very bad because it means there was mismatched disable/enables so we
|
||||
// "HardFault".
|
||||
HardFault_Handler();
|
||||
// This is very very bad because it means there was mismatched disable/enables
|
||||
reset_into_safe_mode(SAFE_MODE_INTERRUPT_ERROR);
|
||||
}
|
||||
nesting_count--;
|
||||
if (nesting_count > 0) {
|
||||
@ -80,7 +78,7 @@ void common_hal_mcu_on_next_reset(mcu_runmode_t runmode) {
|
||||
DBL_TAP_REG = DBL_TAP_MAGIC_QUICK_BOOT;
|
||||
}
|
||||
if (runmode == RUNMODE_SAFE_MODE) {
|
||||
safe_mode_on_next_reset(PROGRAMMATIC_SAFE_MODE);
|
||||
safe_mode_on_next_reset(SAFE_MODE_PROGRAMMATIC);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -259,10 +259,10 @@ safe_mode_t port_init(void) {
|
||||
// run yet, which uses `never_reset` to protect critical pins from being reset by `reset_port`.
|
||||
|
||||
if (board_requests_safe_mode()) {
|
||||
return USER_SAFE_MODE;
|
||||
return SAFE_MODE_USER;
|
||||
}
|
||||
|
||||
return NO_SAFE_MODE;
|
||||
return SAFE_MODE_NONE;
|
||||
}
|
||||
|
||||
void reset_port(void) {
|
||||
@ -419,7 +419,7 @@ void port_idle_until_interrupt(void) {
|
||||
*/
|
||||
void MemManage_Handler(void);
|
||||
__attribute__((used)) void MemManage_Handler(void) {
|
||||
reset_into_safe_mode(MEM_MANAGE);
|
||||
reset_into_safe_mode(SAFE_MODE_HARD_FAULT);
|
||||
while (true) {
|
||||
asm ("nop;");
|
||||
}
|
||||
@ -430,7 +430,7 @@ __attribute__((used)) void MemManage_Handler(void) {
|
||||
*/
|
||||
void BusFault_Handler(void);
|
||||
__attribute__((used)) void BusFault_Handler(void) {
|
||||
reset_into_safe_mode(MEM_MANAGE);
|
||||
reset_into_safe_mode(SAFE_MODE_HARD_FAULT);
|
||||
while (true) {
|
||||
asm ("nop;");
|
||||
}
|
||||
@ -441,7 +441,7 @@ __attribute__((used)) void BusFault_Handler(void) {
|
||||
*/
|
||||
void UsageFault_Handler(void);
|
||||
__attribute__((used)) void UsageFault_Handler(void) {
|
||||
reset_into_safe_mode(MEM_MANAGE);
|
||||
reset_into_safe_mode(SAFE_MODE_HARD_FAULT);
|
||||
while (true) {
|
||||
asm ("nop;");
|
||||
}
|
||||
@ -452,7 +452,7 @@ __attribute__((used)) void UsageFault_Handler(void) {
|
||||
*/
|
||||
void HardFault_Handler(void);
|
||||
__attribute__((used)) void HardFault_Handler(void) {
|
||||
reset_into_safe_mode(HARD_CRASH);
|
||||
reset_into_safe_mode(SAFE_MODE_HARD_FAULT);
|
||||
while (true) {
|
||||
asm ("nop;");
|
||||
}
|
||||
|
@ -52,7 +52,7 @@
|
||||
|
||||
#define CIRCUITPY_BOOT_BUTTON (&pin_P0_29)
|
||||
|
||||
#define BOARD_USER_SAFE_MODE_ACTION translate("The left button was pressed at start up.\n")
|
||||
#define BOARD_USER_SAFE_MODE_ACTION translate("You pressed the left button at start up.")
|
||||
|
||||
#define CIRCUITPY_INTERNAL_NVM_SIZE (4096)
|
||||
|
||||
|
@ -91,7 +91,7 @@ const nvm_bytearray_obj_t common_hal_bleio_nvm_obj = {
|
||||
};
|
||||
|
||||
STATIC void softdevice_assert_handler(uint32_t id, uint32_t pc, uint32_t info) {
|
||||
reset_into_safe_mode(NORDIC_SOFT_DEVICE_ASSERT);
|
||||
reset_into_safe_mode(SAFE_MODE_SDK_FATAL_ERROR);
|
||||
}
|
||||
|
||||
bleio_connection_internal_t bleio_connections[BLEIO_TOTAL_CONNECTION_COUNT];
|
||||
|
@ -68,9 +68,8 @@ void common_hal_mcu_disable_interrupts() {
|
||||
|
||||
void common_hal_mcu_enable_interrupts() {
|
||||
if (nesting_count == 0) {
|
||||
// This is very very bad because it means there was mismatched disable/enables so we
|
||||
// crash.
|
||||
reset_into_safe_mode(HARD_CRASH);
|
||||
// This is very very bad because it means there was mismatched disable/enables.
|
||||
reset_into_safe_mode(SAFE_MODE_INTERRUPT_ERROR);
|
||||
}
|
||||
nesting_count--;
|
||||
if (nesting_count > 0) {
|
||||
@ -88,7 +87,7 @@ void common_hal_mcu_on_next_reset(mcu_runmode_t runmode) {
|
||||
sd_power_gpregret_set(0,0);
|
||||
}
|
||||
if (runmode == RUNMODE_SAFE_MODE) {
|
||||
safe_mode_on_next_reset(PROGRAMMATIC_SAFE_MODE);
|
||||
safe_mode_on_next_reset(SAFE_MODE_PROGRAMMATIC);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -75,7 +75,7 @@ void port_internal_flash_flush(void) {
|
||||
// Skip if data is the same
|
||||
if (memcmp(_flash_cache, (void *)_flash_page_addr, FLASH_PAGE_SIZE) != 0) {
|
||||
if (!nrf_nvm_safe_flash_page_write(_flash_page_addr, _flash_cache)) {
|
||||
reset_into_safe_mode(FLASH_WRITE_FAIL);
|
||||
reset_into_safe_mode(SAFE_MODE_FLASH_WRITE_FAIL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -77,7 +77,7 @@ extern void qspi_disable(void);
|
||||
#endif
|
||||
|
||||
static void power_warning_handler(void) {
|
||||
reset_into_safe_mode(BROWNOUT);
|
||||
reset_into_safe_mode(SAFE_MODE_BROWNOUT);
|
||||
}
|
||||
|
||||
uint32_t reset_reason_saved = 0;
|
||||
@ -204,11 +204,11 @@ safe_mode_t port_init(void) {
|
||||
// If USB is connected, then the user might be editing `code.py`,
|
||||
// in which case we should reboot into Safe Mode.
|
||||
if (usb_reg & POWER_USBREGSTATUS_VBUSDETECT_Msk) {
|
||||
return WATCHDOG_RESET;
|
||||
return SAFE_MODE_WATCHDOG;
|
||||
}
|
||||
}
|
||||
|
||||
return NO_SAFE_MODE;
|
||||
return SAFE_MODE_NONE;
|
||||
}
|
||||
|
||||
void reset_port(void) {
|
||||
@ -399,7 +399,7 @@ void port_idle_until_interrupt(void) {
|
||||
|
||||
extern void HardFault_Handler(void);
|
||||
void HardFault_Handler(void) {
|
||||
reset_into_safe_mode(HARD_CRASH);
|
||||
reset_into_safe_mode(SAFE_MODE_HARD_FAULT);
|
||||
while (true) {
|
||||
asm ("nop;");
|
||||
}
|
||||
|
@ -60,7 +60,7 @@ void common_hal_mcu_disable_interrupts(void) {
|
||||
|
||||
void common_hal_mcu_enable_interrupts(void) {
|
||||
if (nesting_count == 0) {
|
||||
// reset_into_safe_mode(LOCKING_ERROR);
|
||||
// reset_into_safe_mode(SAFE_MODE_INTERRUPT_ERROR);
|
||||
}
|
||||
nesting_count--;
|
||||
if (nesting_count > 0) {
|
||||
@ -79,7 +79,7 @@ void common_hal_mcu_on_next_reset(mcu_runmode_t runmode) {
|
||||
next_reset_to_bootloader = true;
|
||||
break;
|
||||
case RUNMODE_SAFE_MODE:
|
||||
safe_mode_on_next_reset(PROGRAMMATIC_SAFE_MODE);
|
||||
safe_mode_on_next_reset(SAFE_MODE_PROGRAMMATIC);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -161,10 +161,10 @@ safe_mode_t port_init(void) {
|
||||
}
|
||||
#endif
|
||||
if (board_requests_safe_mode()) {
|
||||
return USER_SAFE_MODE;
|
||||
return SAFE_MODE_USER;
|
||||
}
|
||||
|
||||
return NO_SAFE_MODE;
|
||||
return SAFE_MODE_NONE;
|
||||
}
|
||||
|
||||
void reset_port(void) {
|
||||
@ -312,7 +312,7 @@ __attribute__((used)) void HardFault_Handler(void) {
|
||||
REG_MTB_MASTER = 0x00000000 + 6;
|
||||
#endif
|
||||
|
||||
reset_into_safe_mode(HARD_CRASH);
|
||||
reset_into_safe_mode(SAFE_MODE_HARD_FAULT);
|
||||
while (true) {
|
||||
asm ("nop;");
|
||||
}
|
||||
|
@ -105,8 +105,7 @@ STATIC int next_filter(canio_can_obj_t *can) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
reset_into_safe_mode(MICROPY_FATAL_ERROR);
|
||||
return -1;
|
||||
mp_raise_msg_varg(&mp_type_RuntimeError, translate("%q"), MP_QSTR_Listener);
|
||||
}
|
||||
|
||||
// IDE = "extended ID" flag of packet header. We always add this bit to the
|
||||
|
@ -61,9 +61,8 @@ void common_hal_mcu_disable_interrupts(void) {
|
||||
|
||||
void common_hal_mcu_enable_interrupts(void) {
|
||||
if (nesting_count == 0) {
|
||||
// This is very very bad because it means there was mismatched disable/enables so we
|
||||
// "HardFault".
|
||||
asm ("bkpt");
|
||||
// This is very very bad because it means there was mismatched disable/enables.
|
||||
reset_into_safe_mode(SAFE_MODE_INTERRUPT_ERROR);
|
||||
}
|
||||
nesting_count--;
|
||||
if (nesting_count > 0) {
|
||||
@ -77,7 +76,7 @@ static bool next_reset_to_bootloader = false;
|
||||
|
||||
void common_hal_mcu_on_next_reset(mcu_runmode_t runmode) {
|
||||
if (runmode == RUNMODE_SAFE_MODE) {
|
||||
safe_mode_on_next_reset(PROGRAMMATIC_SAFE_MODE);
|
||||
safe_mode_on_next_reset(SAFE_MODE_PROGRAMMATIC);
|
||||
}
|
||||
if (runmode == RUNMODE_BOOTLOADER) {
|
||||
next_reset_to_bootloader = true;
|
||||
|
@ -215,7 +215,7 @@ void port_internal_flash_flush(void) {
|
||||
EraseInitStruct.NbSectors = 1;
|
||||
#endif
|
||||
if (sector_size > sizeof(_flash_cache) || sector_start_addr == 0xffffffff) {
|
||||
reset_into_safe_mode(FLASH_WRITE_FAIL);
|
||||
reset_into_safe_mode(SAFE_MODE_FLASH_WRITE_FAIL);
|
||||
}
|
||||
|
||||
// Skip if data is the same
|
||||
@ -228,7 +228,7 @@ void port_internal_flash_flush(void) {
|
||||
if (HAL_FLASHEx_Erase(&EraseInitStruct, &SectorError) != HAL_OK) {
|
||||
// error occurred during sector erase
|
||||
HAL_FLASH_Lock(); // lock the flash
|
||||
reset_into_safe_mode(FLASH_WRITE_FAIL);
|
||||
reset_into_safe_mode(SAFE_MODE_FLASH_WRITE_FAIL);
|
||||
}
|
||||
|
||||
uint32_t *cache_addr = (uint32_t *)_flash_cache;
|
||||
@ -240,7 +240,7 @@ void port_internal_flash_flush(void) {
|
||||
(uint32_t)cache_addr) != HAL_OK) {
|
||||
// error occurred during flash write
|
||||
HAL_FLASH_Lock(); // lock the flash
|
||||
reset_into_safe_mode(FLASH_WRITE_FAIL);
|
||||
reset_into_safe_mode(SAFE_MODE_FLASH_WRITE_FAIL);
|
||||
}
|
||||
// RAM memory is by word (4 byte), but flash memory is by byte
|
||||
cache_addr += 8;
|
||||
@ -253,7 +253,7 @@ void port_internal_flash_flush(void) {
|
||||
*(uint64_t *)cache_addr) != HAL_OK) {
|
||||
// error occurred during flash write
|
||||
HAL_FLASH_Lock(); // lock the flash
|
||||
reset_into_safe_mode(FLASH_WRITE_FAIL);
|
||||
reset_into_safe_mode(SAFE_MODE_FLASH_WRITE_FAIL);
|
||||
}
|
||||
// RAM memory is by word (4 byte), but flash memory is by byte
|
||||
cache_addr += 2;
|
||||
@ -267,7 +267,7 @@ void port_internal_flash_flush(void) {
|
||||
(uint64_t)*cache_addr) != HAL_OK) {
|
||||
// error occurred during flash write
|
||||
HAL_FLASH_Lock(); // lock the flash
|
||||
reset_into_safe_mode(FLASH_WRITE_FAIL);
|
||||
reset_into_safe_mode(SAFE_MODE_FLASH_WRITE_FAIL);
|
||||
}
|
||||
// RAM memory is by word (4 byte), but flash memory is by byte
|
||||
cache_addr += 1;
|
||||
@ -335,7 +335,7 @@ mp_uint_t supervisor_flash_write_blocks(const uint8_t *src, uint32_t block_num,
|
||||
|
||||
// Fail for any sector outside what's supported by the cache
|
||||
if (sector_size > sizeof(_flash_cache)) {
|
||||
reset_into_safe_mode(FLASH_WRITE_FAIL);
|
||||
reset_into_safe_mode(SAFE_MODE_FLASH_WRITE_FAIL);
|
||||
}
|
||||
|
||||
// Find how many blocks are left in the sector
|
||||
|
@ -211,7 +211,7 @@ safe_mode_t port_init(void) {
|
||||
// Turn off SysTick
|
||||
SysTick->CTRL = 0;
|
||||
|
||||
return NO_SAFE_MODE;
|
||||
return SAFE_MODE_NONE;
|
||||
}
|
||||
|
||||
void HAL_Delay(uint32_t delay_ms) {
|
||||
@ -357,28 +357,28 @@ uint32_t port_get_saved_word(void) {
|
||||
}
|
||||
|
||||
__attribute__((used)) void MemManage_Handler(void) {
|
||||
reset_into_safe_mode(MEM_MANAGE);
|
||||
reset_into_safe_mode(SAFE_MODE_HARD_FAULT);
|
||||
while (true) {
|
||||
asm ("nop;");
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((used)) void BusFault_Handler(void) {
|
||||
reset_into_safe_mode(MEM_MANAGE);
|
||||
reset_into_safe_mode(SAFE_MODE_HARD_FAULT);
|
||||
while (true) {
|
||||
asm ("nop;");
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((used)) void UsageFault_Handler(void) {
|
||||
reset_into_safe_mode(MEM_MANAGE);
|
||||
reset_into_safe_mode(SAFE_MODE_HARD_FAULT);
|
||||
while (true) {
|
||||
asm ("nop;");
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((used)) void HardFault_Handler(void) {
|
||||
reset_into_safe_mode(HARD_CRASH);
|
||||
reset_into_safe_mode(SAFE_MODE_HARD_FAULT);
|
||||
while (true) {
|
||||
asm ("nop;");
|
||||
}
|
||||
|
@ -525,6 +525,7 @@ $(filter $(SRC_PATTERNS), \
|
||||
qrio/PixelPolicy.c \
|
||||
qrio/QRInfo.c \
|
||||
supervisor/RunReason.c \
|
||||
supervisor/SafeModeReason.c \
|
||||
supervisor/StatusBar.c \
|
||||
wifi/AuthMode.c \
|
||||
wifi/Packet.c \
|
||||
|
@ -372,6 +372,10 @@ CFLAGS += -DCIRCUITPY_ROTARYIO_SOFTENCODER=$(CIRCUITPY_ROTARYIO_SOFTENCODER)
|
||||
CIRCUITPY_RTC ?= 1
|
||||
CFLAGS += -DCIRCUITPY_RTC=$(CIRCUITPY_RTC)
|
||||
|
||||
# Enable support for safemode.py
|
||||
CIRCUITPY_SAFEMODE_PY ?= 1
|
||||
CFLAGS += -DCIRCUITPY_SAFEMODE_PY=$(CIRCUITPY_SAFEMODE_PY)
|
||||
|
||||
# CIRCUITPY_SAMD is handled in the atmel-samd tree.
|
||||
# Only for SAMD chips.
|
||||
# Assume not a SAMD build.
|
||||
|
4
py/gc.c
4
py/gc.c
@ -518,7 +518,7 @@ void *gc_alloc(size_t n_bytes, unsigned int alloc_flags, bool long_lived) {
|
||||
}
|
||||
|
||||
if (MP_STATE_MEM(gc_pool_start) == 0) {
|
||||
reset_into_safe_mode(GC_ALLOC_OUTSIDE_VM);
|
||||
reset_into_safe_mode(SAFE_MODE_GC_ALLOC_OUTSIDE_VM);
|
||||
}
|
||||
|
||||
GC_ENTER();
|
||||
@ -712,7 +712,7 @@ void gc_free(void *ptr) {
|
||||
GC_EXIT();
|
||||
} else {
|
||||
if (MP_STATE_MEM(gc_pool_start) == 0) {
|
||||
reset_into_safe_mode(GC_ALLOC_OUTSIDE_VM);
|
||||
reset_into_safe_mode(SAFE_MODE_GC_ALLOC_OUTSIDE_VM);
|
||||
}
|
||||
// get the GC block number corresponding to this pointer
|
||||
assert(VERIFY_PTR(ptr));
|
||||
|
@ -42,7 +42,7 @@ MAKE_ENUM_VALUE(mcu_reset_reason_type, reset_reason, RESCUE_DEBUG, RESET_REASON_
|
||||
//| """The reason the microntroller was last reset"""
|
||||
//|
|
||||
//| POWER_ON: object
|
||||
//| """The microntroller was started from power off."""
|
||||
//| """The microcontroller was started from power off."""
|
||||
//|
|
||||
//| BROWNOUT: object
|
||||
//| """The microntroller was reset due to too low a voltage."""
|
||||
|
@ -32,6 +32,7 @@
|
||||
|
||||
#include "shared-bindings/supervisor/RunReason.h"
|
||||
#include "shared-bindings/supervisor/Runtime.h"
|
||||
#include "shared-bindings/supervisor/SafeModeReason.h"
|
||||
|
||||
#include "supervisor/shared/reload.h"
|
||||
#include "supervisor/shared/stack.h"
|
||||
@ -106,7 +107,7 @@ void supervisor_set_run_reason(supervisor_run_reason_t run_reason) {
|
||||
}
|
||||
|
||||
//| run_reason: RunReason
|
||||
//| """Why CircuitPython started running this particular time."""
|
||||
//| """Why CircuitPython started running this particular time (read-only)."""
|
||||
STATIC mp_obj_t supervisor_runtime_get_run_reason(mp_obj_t self) {
|
||||
return cp_enum_find(&supervisor_run_reason_type, _run_reason);
|
||||
}
|
||||
@ -115,6 +116,20 @@ MP_DEFINE_CONST_FUN_OBJ_1(supervisor_runtime_get_run_reason_obj, supervisor_runt
|
||||
MP_PROPERTY_GETTER(supervisor_runtime_run_reason_obj,
|
||||
(mp_obj_t)&supervisor_runtime_get_run_reason_obj);
|
||||
|
||||
//| safe_mode_reason: SafeModeReason
|
||||
//| """Why CircuitPython went into safe mode this particular time (read-only)."""
|
||||
STATIC mp_obj_t supervisor_runtime_get_safe_mode_reason(mp_obj_t self) {
|
||||
#if CIRCUITPY_SAFEMODE_PY
|
||||
return cp_enum_find(&supervisor_safe_mode_reason_type, get_safe_mode());
|
||||
#else
|
||||
mp_raise_NotImplementedError(NULL);
|
||||
#endif
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(supervisor_runtime_get_safe_mode_reason_obj, supervisor_runtime_get_safe_mode_reason);
|
||||
|
||||
MP_PROPERTY_GETTER(supervisor_runtime_safe_mode_reason_obj,
|
||||
(mp_obj_t)&supervisor_runtime_get_safe_mode_reason_obj);
|
||||
|
||||
//| autoreload: bool
|
||||
//| """Whether CircuitPython may autoreload based on workflow writes to the filesystem."""
|
||||
//|
|
||||
@ -218,6 +233,7 @@ STATIC const mp_rom_map_elem_t supervisor_runtime_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_serial_connected), MP_ROM_PTR(&supervisor_runtime_serial_connected_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_serial_bytes_available), MP_ROM_PTR(&supervisor_runtime_serial_bytes_available_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_run_reason), MP_ROM_PTR(&supervisor_runtime_run_reason_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_safe_mode_reason), MP_ROM_PTR(&supervisor_runtime_safe_mode_reason_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_autoreload), MP_ROM_PTR(&supervisor_runtime_autoreload_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_ble_workflow), MP_ROM_PTR(&supervisor_runtime_ble_workflow_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_next_stack_limit), MP_ROM_PTR(&supervisor_runtime_next_stack_limit_obj) },
|
||||
|
@ -31,12 +31,16 @@
|
||||
#include "py/obj.h"
|
||||
|
||||
#include "shared-bindings/supervisor/RunReason.h"
|
||||
#include "shared-bindings/supervisor/SafeModeReason.h"
|
||||
|
||||
extern const mp_obj_type_t supervisor_runtime_type;
|
||||
|
||||
supervisor_run_reason_t supervisor_get_run_reason(void);
|
||||
void supervisor_set_run_reason(supervisor_run_reason_t run_reason);
|
||||
|
||||
safe_mode_t supervisor_get_safe_mode(void);
|
||||
void supervisor_set_safe_mode(safe_mode_t safe_mode);
|
||||
|
||||
bool common_hal_supervisor_runtime_get_serial_connected(void);
|
||||
|
||||
bool common_hal_supervisor_runtime_get_serial_bytes_available(void);
|
||||
|
156
shared-bindings/supervisor/SafeModeReason.c
Normal file
156
shared-bindings/supervisor/SafeModeReason.c
Normal file
@ -0,0 +1,156 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2023 Dan Halbert for Adafruit Industries
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "py/enum.h"
|
||||
|
||||
#include "shared-bindings/supervisor/SafeModeReason.h"
|
||||
|
||||
// Reuse the non-Python safe_mode_t enum
|
||||
#include "supervisor/shared/safe_mode.h"
|
||||
|
||||
#if CIRCUITPY_SAFEMODE_PY
|
||||
MAKE_ENUM_VALUE(supervisor_safe_mode_reason_type, safe_mode_reason, NONE, SAFE_MODE_NONE);
|
||||
MAKE_ENUM_VALUE(supervisor_safe_mode_reason_type, safe_mode_reason, BROWNOUT, SAFE_MODE_BROWNOUT);
|
||||
// alphabetical from here down
|
||||
MAKE_ENUM_VALUE(supervisor_safe_mode_reason_type, safe_mode_reason, FLASH_WRITE_FAIL, SAFE_MODE_FLASH_WRITE_FAIL);
|
||||
MAKE_ENUM_VALUE(supervisor_safe_mode_reason_type, safe_mode_reason, GC_ALLOC_OUTSIDE_VM, SAFE_MODE_GC_ALLOC_OUTSIDE_VM);
|
||||
MAKE_ENUM_VALUE(supervisor_safe_mode_reason_type, safe_mode_reason, HARD_FAULT, SAFE_MODE_HARD_FAULT);
|
||||
MAKE_ENUM_VALUE(supervisor_safe_mode_reason_type, safe_mode_reason, INTERRUPT_ERROR, SAFE_MODE_INTERRUPT_ERROR);
|
||||
MAKE_ENUM_VALUE(supervisor_safe_mode_reason_type, safe_mode_reason, NLR_JUMP_FAIL, SAFE_MODE_NLR_JUMP_FAIL);
|
||||
MAKE_ENUM_VALUE(supervisor_safe_mode_reason_type, safe_mode_reason, NO_CIRCUITPY, SAFE_MODE_NO_CIRCUITPY);
|
||||
MAKE_ENUM_VALUE(supervisor_safe_mode_reason_type, safe_mode_reason, NO_HEAP, SAFE_MODE_NO_HEAP);
|
||||
MAKE_ENUM_VALUE(supervisor_safe_mode_reason_type, safe_mode_reason, PROGRAMMATIC, SAFE_MODE_PROGRAMMATIC);
|
||||
MAKE_ENUM_VALUE(supervisor_safe_mode_reason_type, safe_mode_reason, SDK_FATAL_ERROR, SAFE_MODE_SDK_FATAL_ERROR);
|
||||
MAKE_ENUM_VALUE(supervisor_safe_mode_reason_type, safe_mode_reason, STACK_OVERFLOW, SAFE_MODE_STACK_OVERFLOW);
|
||||
MAKE_ENUM_VALUE(supervisor_safe_mode_reason_type, safe_mode_reason, USB_BOOT_DEVICE_NOT_INTERFACE_ZERO, SAFE_MODE_USB_BOOT_DEVICE_NOT_INTERFACE_ZERO);
|
||||
MAKE_ENUM_VALUE(supervisor_safe_mode_reason_type, safe_mode_reason, USB_TOO_MANY_ENDPOINTS, SAFE_MODE_USB_TOO_MANY_ENDPOINTS);
|
||||
MAKE_ENUM_VALUE(supervisor_safe_mode_reason_type, safe_mode_reason, USB_TOO_MANY_INTERFACE_NAMES, SAFE_MODE_USB_TOO_MANY_INTERFACE_NAMES);
|
||||
MAKE_ENUM_VALUE(supervisor_safe_mode_reason_type, safe_mode_reason, USER, SAFE_MODE_USER);
|
||||
MAKE_ENUM_VALUE(supervisor_safe_mode_reason_type, safe_mode_reason, WATCHDOG, SAFE_MODE_WATCHDOG);
|
||||
#endif
|
||||
|
||||
|
||||
//| class SafeModeReason:
|
||||
//| """The reason that CircuitPython went into safe mode."""
|
||||
//|
|
||||
MAKE_ENUM_MAP(supervisor_safe_mode_reason) {
|
||||
|
||||
#if CIRCUITPY_SAFEMODE_PY
|
||||
|
||||
//| NONE: object
|
||||
//| """CircuitPython is not in safe mode."""
|
||||
//|
|
||||
MAKE_ENUM_MAP_ENTRY(safe_mode_reason, NONE),
|
||||
|
||||
//| BROWNOUT: object
|
||||
//| """The microcontroller voltage dropped too low."""
|
||||
//|
|
||||
MAKE_ENUM_MAP_ENTRY(safe_mode_reason, BROWNOUT),
|
||||
|
||||
// alphabetical from here down
|
||||
|
||||
//| FLASH_WRITE_FAIL: object
|
||||
//| """Could not write to flash memory."""
|
||||
//|
|
||||
MAKE_ENUM_MAP_ENTRY(safe_mode_reason, FLASH_WRITE_FAIL),
|
||||
|
||||
//| GC_ALLOC_OUTSIDE_VM: object
|
||||
//| """CircuitPython tried to allocate storage when its virtual machine was not running."""
|
||||
//|
|
||||
MAKE_ENUM_MAP_ENTRY(safe_mode_reason, GC_ALLOC_OUTSIDE_VM),
|
||||
|
||||
//| HARD_FAULT: object
|
||||
//| """The microcontroller detected a fault, such as an out-of-bounds memory write."""
|
||||
//|
|
||||
MAKE_ENUM_MAP_ENTRY(safe_mode_reason, HARD_FAULT),
|
||||
|
||||
//| INTERRUPT_ERROR: object
|
||||
//| """Internal error related to interrupts."""
|
||||
//|
|
||||
MAKE_ENUM_MAP_ENTRY(safe_mode_reason, INTERRUPT_ERROR),
|
||||
|
||||
//| NLR_JUMP_FAIL: object
|
||||
//| """An error occurred during exception handling, possibly due to memory corruption."""
|
||||
//|
|
||||
MAKE_ENUM_MAP_ENTRY(safe_mode_reason, NLR_JUMP_FAIL),
|
||||
|
||||
//| NO_CIRCUITPY: object
|
||||
//| """The CIRCUITPY drive was not available."""
|
||||
//|
|
||||
MAKE_ENUM_MAP_ENTRY(safe_mode_reason, NO_CIRCUITPY),
|
||||
|
||||
//| NO_HEAP: object
|
||||
//| """Heap storage was not present."""
|
||||
//|
|
||||
MAKE_ENUM_MAP_ENTRY(safe_mode_reason, NO_HEAP),
|
||||
|
||||
//| PROGRAMMATIC: object
|
||||
//| """The program entered safe mode using the `supervisor` module."""
|
||||
//|
|
||||
MAKE_ENUM_MAP_ENTRY(safe_mode_reason, PROGRAMMATIC),
|
||||
|
||||
//| SDK_FATAL_ERROR: object
|
||||
//| """Third party firmware reported a fatal error."""
|
||||
//|
|
||||
MAKE_ENUM_MAP_ENTRY(safe_mode_reason, SDK_FATAL_ERROR),
|
||||
|
||||
//| STACK_OVERFLOW: object
|
||||
//| """The CircuitPython heap was corrupted because the stack was too small."""
|
||||
//|
|
||||
MAKE_ENUM_MAP_ENTRY(safe_mode_reason, STACK_OVERFLOW),
|
||||
|
||||
//| USB_BOOT_DEVICE_NOT_INTERFACE_ZERO: object
|
||||
//| """The USB HID boot device was not set up to be the first device, on interface #0."""
|
||||
//|
|
||||
MAKE_ENUM_MAP_ENTRY(safe_mode_reason, USB_BOOT_DEVICE_NOT_INTERFACE_ZERO),
|
||||
|
||||
//| USB_TOO_MANY_ENDPOINTS: object
|
||||
//| """USB devices need more endpoints than are available."""
|
||||
//|
|
||||
MAKE_ENUM_MAP_ENTRY(safe_mode_reason, USB_TOO_MANY_ENDPOINTS),
|
||||
|
||||
//| USB_TOO_MANY_INTERFACE_NAMES: object
|
||||
//| """USB devices specify too many interface names."""
|
||||
//|
|
||||
MAKE_ENUM_MAP_ENTRY(safe_mode_reason, USB_TOO_MANY_INTERFACE_NAMES),
|
||||
|
||||
//| USER: object
|
||||
//| """The user pressed one or more buttons to enter safe mode."""
|
||||
//|
|
||||
MAKE_ENUM_MAP_ENTRY(safe_mode_reason, USER),
|
||||
|
||||
//| SAFE_MODE_WATCHDOG: object
|
||||
//| """An internal watchdog timer expired."""
|
||||
//|
|
||||
MAKE_ENUM_MAP_ENTRY(safe_mode_reason, WATCHDOG),
|
||||
#endif
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(supervisor_safe_mode_reason_locals_dict, supervisor_safe_mode_reason_locals_table);
|
||||
|
||||
MAKE_PRINTER(supervisor, supervisor_safe_mode_reason);
|
||||
|
||||
MAKE_ENUM_TYPE(supervisor, SafeModeReason, supervisor_safe_mode_reason);
|
31
shared-bindings/supervisor/SafeModeReason.h
Normal file
31
shared-bindings/supervisor/SafeModeReason.h
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2023 Dan Halbert for Adafruit Industries
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "supervisor/shared/safe_mode.h"
|
||||
|
||||
extern const mp_obj_type_t supervisor_safe_mode_reason_type;
|
@ -336,6 +336,11 @@ STATIC const mp_rom_map_elem_t supervisor_module_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_runtime), MP_ROM_PTR(&common_hal_supervisor_runtime_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_reload), MP_ROM_PTR(&supervisor_reload_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_RunReason), MP_ROM_PTR(&supervisor_run_reason_type) },
|
||||
#if CIRCUITPY_SAFEMODE_PY
|
||||
{ MP_ROM_QSTR(MP_QSTR_SafeModeReason), MP_ROM_PTR(&supervisor_safe_mode_reason_type) },
|
||||
#else
|
||||
{ MP_ROM_QSTR(MP_QSTR_SafeModeReason), mp_const_none },
|
||||
#endif
|
||||
{ MP_ROM_QSTR(MP_QSTR_set_next_code_file), MP_ROM_PTR(&supervisor_set_next_code_file_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_ticks_ms), MP_ROM_PTR(&supervisor_ticks_ms_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_get_previous_traceback), MP_ROM_PTR(&supervisor_get_previous_traceback_obj) },
|
||||
|
@ -1,99 +0,0 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef MICROPY_SUPERVISOR_MESSAGES_DEFAULT_H
|
||||
#define MICROPY_SUPERVISOR_MESSAGES_DEFAULT_H
|
||||
|
||||
#ifndef MSG_OUTPUT_SUFFIX
|
||||
#define MSG_OUTPUT_SUFFIX " output:\r\n"
|
||||
#endif
|
||||
|
||||
#ifndef MSG_NEWLINE
|
||||
#define MSG_NEWLINE "\r\n"
|
||||
#endif
|
||||
|
||||
#ifndef MSG_AUTORELOAD_ON
|
||||
#define MSG_AUTORELOAD_ON "Auto-reload is on. Simply save files over USB to run them or enter REPL to disable.\r\n"
|
||||
#endif
|
||||
|
||||
#ifndef MSG_AUTORELOAD_OFF
|
||||
#define MSG_AUTORELOAD_OFF "Auto-reload is off.\r\n"
|
||||
#endif
|
||||
|
||||
#ifndef MSG_SAFE_MODE_ON
|
||||
#define MSG_SAFE_MODE_ON "Running in safe mode! Auto-reload is off.\r\n"
|
||||
#endif
|
||||
|
||||
#ifndef MSG_SAFE_MODE_NO_MAIN
|
||||
#define MSG_SAFE_MODE_NO_MAIN "Running in safe mode! Not running saved code.\r\n"
|
||||
#endif
|
||||
|
||||
#ifndef MSG_SAFE_MODE_USER_REQUESTED
|
||||
#define MSG_SAFE_MODE_USER_REQUESTED "You requested starting safe mode by "
|
||||
#endif
|
||||
|
||||
#ifndef MSG_SAFE_MODE_USER_EXIT
|
||||
#define MSG_SAFE_MODE_USER_EXIT "To exit, please reset the board without "
|
||||
#endif
|
||||
|
||||
#ifndef MSG_BAD_SAFE_MODE
|
||||
#define MSG_BAD_SAFE_MODE "You are running in safe mode which means something really bad happened."
|
||||
#endif
|
||||
|
||||
#ifndef MSG_SAFE_MODE_CRASH
|
||||
#define MSG_SAFE_MODE_CRASH "Looks like our core CircuitPython code crashed hard. Whoops!"
|
||||
#endif
|
||||
|
||||
#ifndef MSG_SAFE_MODE_FILE_ISSUE
|
||||
#define MSG_SAFE_MODE_FILE_ISSUE "Please file an issue here with the contents of your CIRCUITPY drive:"
|
||||
#endif
|
||||
|
||||
#ifndef MSG_SAFE_MODE_ISSUE_LINK
|
||||
#define MSG_SAFE_MODE_ISSUE_LINK "https://github.com/adafruit/circuitpython/issues"
|
||||
#endif
|
||||
|
||||
#ifndef MSG_SAFE_MODE_BROWN_OUT_LINE_1
|
||||
#define MSG_SAFE_MODE_BROWN_OUT_LINE_1 "The microcontroller's power dipped. Please make sure your power supply provides"
|
||||
#endif
|
||||
|
||||
#ifndef MSG_SAFE_MODE_BROWN_OUT_LINE_2
|
||||
#define MSG_SAFE_MODE_BROWN_OUT_LINE_2 "enough power for the whole circuit and press reset (after ejecting CIRCUITPY)."
|
||||
#endif
|
||||
|
||||
#ifndef MSG_WAIT_BEFORE_REPL
|
||||
#define MSG_WAIT_BEFORE_REPL "Press any key to enter the REPL. Use CTRL-D to reload."
|
||||
#endif
|
||||
|
||||
// Be careful, some tools depend on this.
|
||||
#ifndef MSG_SOFT_REBOOT
|
||||
#define MSG_SOFT_REBOOT "soft reboot"
|
||||
#endif
|
||||
|
||||
#ifndef MSG_DOUBLE_FILE_EXTENSION
|
||||
#define MSG_DOUBLE_FILE_EXTENSION "WARNING: Your code filename has two extensions\r\n"
|
||||
#endif
|
||||
|
||||
#endif // MICROPY_SUPERVISOR_MESSAGES_DEFAULT_H
|
@ -43,20 +43,28 @@
|
||||
#define SAFE_MODE_DATA_GUARD 0xad0000af
|
||||
#define SAFE_MODE_DATA_GUARD_MASK 0xff0000ff
|
||||
|
||||
static safe_mode_t current_safe_mode;
|
||||
static safe_mode_t _safe_mode;
|
||||
|
||||
safe_mode_t get_safe_mode(void) {
|
||||
return _safe_mode;
|
||||
}
|
||||
|
||||
void set_safe_mode(safe_mode_t safe_mode) {
|
||||
_safe_mode = safe_mode;
|
||||
}
|
||||
|
||||
safe_mode_t wait_for_safe_mode_reset(void) {
|
||||
uint32_t reset_state = port_get_saved_word();
|
||||
safe_mode_t safe_mode = NO_SAFE_MODE;
|
||||
safe_mode_t safe_mode = SAFE_MODE_NONE;
|
||||
if ((reset_state & SAFE_MODE_DATA_GUARD_MASK) == SAFE_MODE_DATA_GUARD) {
|
||||
safe_mode = (reset_state & ~SAFE_MODE_DATA_GUARD_MASK) >> 8;
|
||||
}
|
||||
if (safe_mode != NO_SAFE_MODE) {
|
||||
if (safe_mode != SAFE_MODE_NONE) {
|
||||
port_set_saved_word(SAFE_MODE_DATA_GUARD);
|
||||
current_safe_mode = safe_mode;
|
||||
_safe_mode = safe_mode;
|
||||
return safe_mode;
|
||||
} else {
|
||||
current_safe_mode = 0;
|
||||
_safe_mode = SAFE_MODE_NONE;
|
||||
}
|
||||
|
||||
const mcu_reset_reason_t reset_reason = common_hal_mcu_processor_get_reset_reason();
|
||||
@ -64,12 +72,12 @@ safe_mode_t wait_for_safe_mode_reset(void) {
|
||||
reset_reason != RESET_REASON_RESET_PIN &&
|
||||
reset_reason != RESET_REASON_UNKNOWN &&
|
||||
reset_reason != RESET_REASON_SOFTWARE) {
|
||||
return NO_SAFE_MODE;
|
||||
return SAFE_MODE_NONE;
|
||||
}
|
||||
#if CIRCUITPY_SKIP_SAFE_MODE_WAIT
|
||||
return NO_SAFE_MODE;
|
||||
return SAFE_MODE_NONE;
|
||||
#endif
|
||||
port_set_saved_word(SAFE_MODE_DATA_GUARD | (MANUAL_SAFE_MODE << 8));
|
||||
port_set_saved_word(SAFE_MODE_DATA_GUARD | (SAFE_MODE_USER << 8));
|
||||
// Wait for a while to allow for reset.
|
||||
|
||||
#if CIRCUITPY_STATUS_LED
|
||||
@ -106,11 +114,11 @@ safe_mode_t wait_for_safe_mode_reset(void) {
|
||||
status_led_deinit();
|
||||
#endif
|
||||
if (boot_in_safe_mode) {
|
||||
return USER_SAFE_MODE;
|
||||
return SAFE_MODE_USER;
|
||||
}
|
||||
// Restore the original state of the saved word if no reset occured during our wait period.
|
||||
port_set_saved_word(reset_state);
|
||||
return NO_SAFE_MODE;
|
||||
return SAFE_MODE_NONE;
|
||||
}
|
||||
|
||||
void safe_mode_on_next_reset(safe_mode_t reason) {
|
||||
@ -119,7 +127,7 @@ void safe_mode_on_next_reset(safe_mode_t reason) {
|
||||
|
||||
// Don't inline this so it's easy to break on it from GDB.
|
||||
void __attribute__((noinline,)) reset_into_safe_mode(safe_mode_t reason) {
|
||||
if (current_safe_mode > BROWNOUT && reason > BROWNOUT) {
|
||||
if (_safe_mode > SAFE_MODE_BROWNOUT && reason > SAFE_MODE_BROWNOUT) {
|
||||
while (true) {
|
||||
// This very bad because it means running in safe mode didn't save us. Only ignore brownout
|
||||
// because it may be due to a switch bouncing.
|
||||
@ -133,7 +141,7 @@ void __attribute__((noinline,)) reset_into_safe_mode(safe_mode_t reason) {
|
||||
|
||||
|
||||
void print_safe_mode_message(safe_mode_t reason) {
|
||||
if (reason == NO_SAFE_MODE) {
|
||||
if (reason == SAFE_MODE_NONE) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -145,43 +153,42 @@ void print_safe_mode_message(safe_mode_t reason) {
|
||||
// First check for safe mode reasons that do not necessarily reflect bugs.
|
||||
|
||||
switch (reason) {
|
||||
case USER_SAFE_MODE:
|
||||
case SAFE_MODE_BROWNOUT:
|
||||
message = translate("The microcontroller's power dipped. Make sure your power supply provides\nenough power for the whole circuit and press reset (after ejecting CIRCUITPY).");
|
||||
break;
|
||||
case SAFE_MODE_USER:
|
||||
#if defined(BOARD_USER_SAFE_MODE_ACTION)
|
||||
message = BOARD_USER_SAFE_MODE_ACTION;
|
||||
#elif defined(CIRCUITPY_BOOT_BUTTON)
|
||||
message = translate("The BOOT button was pressed at start up.\n");
|
||||
message = translate("You pressed the BOOT button at start up.");
|
||||
#else
|
||||
message = translate("You pressed the reset button during boot.");
|
||||
#endif
|
||||
#if defined(BOARD_USER_SAFE_MODE_ACTION) || defined(CIRCUITPY_BOOT_BUTTON)
|
||||
// Output a user safe mode string if it's set.
|
||||
serial_write_compressed(message);
|
||||
message = translate("To exit, please reset the board without requesting safe mode.");
|
||||
message = translate("\nTo exit, reset the board without requesting safe mode.");
|
||||
// The final piece is printed below.
|
||||
#endif
|
||||
break;
|
||||
case MANUAL_SAFE_MODE:
|
||||
message = translate("You pressed the reset button during boot. Press again to exit safe mode.");
|
||||
case SAFE_MODE_NO_CIRCUITPY:
|
||||
message = translate("CIRCUITPY drive could not be found or created.");
|
||||
break;
|
||||
case PROGRAMMATIC_SAFE_MODE:
|
||||
case SAFE_MODE_PROGRAMMATIC:
|
||||
message = translate("The `microcontroller` module was used to boot into safe mode. Press reset to exit safe mode.");
|
||||
break;
|
||||
case BROWNOUT:
|
||||
message = translate("The microcontroller's power dipped. Make sure your power supply provides\nenough power for the whole circuit and press reset (after ejecting CIRCUITPY).");
|
||||
case SAFE_MODE_SAFEMODE_PY_ERROR:
|
||||
message = translate("Error in safemode.py.");
|
||||
break;
|
||||
case USB_TOO_MANY_ENDPOINTS:
|
||||
case SAFE_MODE_USB_TOO_MANY_ENDPOINTS:
|
||||
message = translate("USB devices need more endpoints than are available.");
|
||||
break;
|
||||
case USB_TOO_MANY_INTERFACE_NAMES:
|
||||
case SAFE_MODE_USB_TOO_MANY_INTERFACE_NAMES:
|
||||
message = translate("USB devices specify too many interface names.");
|
||||
break;
|
||||
case USB_BOOT_DEVICE_NOT_INTERFACE_ZERO:
|
||||
case SAFE_MODE_USB_BOOT_DEVICE_NOT_INTERFACE_ZERO:
|
||||
message = translate("Boot device must be first device (interface #0).");
|
||||
break;
|
||||
case WATCHDOG_RESET:
|
||||
case SAFE_MODE_WATCHDOG:
|
||||
message = translate("Internal watchdog timer expired.");
|
||||
break;
|
||||
case NO_CIRCUITPY:
|
||||
message = translate("CIRCUITPY drive could not be found or created.");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -197,36 +204,29 @@ void print_safe_mode_message(safe_mode_t reason) {
|
||||
serial_write_compressed(translate("CircuitPython core code crashed hard. Whoops!\n"));
|
||||
|
||||
switch (reason) {
|
||||
case HARD_CRASH:
|
||||
message = translate("Crash into the HardFault_Handler.");
|
||||
break;
|
||||
case MICROPY_NLR_JUMP_FAIL:
|
||||
message = translate("NLR jump failed. Likely memory corruption.");
|
||||
break;
|
||||
case MICROPY_FATAL_ERROR:
|
||||
message = translate("Fatal error.");
|
||||
break;
|
||||
case NO_HEAP:
|
||||
message = translate("CircuitPython was unable to allocate the heap.");
|
||||
break;
|
||||
case HEAP_OVERWRITTEN:
|
||||
message = translate("The CircuitPython heap was corrupted because the stack was too small.\nIncrease the stack size if you know how. If not:");
|
||||
break;
|
||||
case GC_ALLOC_OUTSIDE_VM:
|
||||
case SAFE_MODE_GC_ALLOC_OUTSIDE_VM:
|
||||
message = translate("Attempted heap allocation when VM not running.");
|
||||
break;
|
||||
#ifdef SOFTDEVICE_PRESENT
|
||||
// defined in ports/nrf/bluetooth/bluetooth_common.mk
|
||||
// will print "Unknown reason" if somehow encountered on other ports
|
||||
case NORDIC_SOFT_DEVICE_ASSERT:
|
||||
message = translate("Nordic system firmware failure assertion.");
|
||||
break;
|
||||
#endif
|
||||
case FLASH_WRITE_FAIL:
|
||||
case SAFE_MODE_FLASH_WRITE_FAIL:
|
||||
message = translate("Failed to write internal flash.");
|
||||
break;
|
||||
case MEM_MANAGE:
|
||||
message = translate("Invalid memory access.");
|
||||
case SAFE_MODE_HARD_FAULT:
|
||||
message = translate("Crash into the HardFault_Handler.");
|
||||
break;
|
||||
case SAFE_MODE_INTERRUPT_ERROR:
|
||||
message = translate("Interrupt error.");
|
||||
break;
|
||||
case SAFE_MODE_NLR_JUMP_FAIL:
|
||||
message = translate("NLR jump failed. Likely memory corruption.");
|
||||
break;
|
||||
case SAFE_MODE_NO_HEAP:
|
||||
message = translate("CircuitPython was unable to allocate the heap.");
|
||||
break;
|
||||
case SAFE_MODE_SDK_FATAL_ERROR:
|
||||
message = translate("Third-party firmware fatal error.");
|
||||
break;
|
||||
case SAFE_MODE_STACK_OVERFLOW:
|
||||
message = translate("The CircuitPython heap was corrupted because the stack was too small.\nIncrease the stack size if you know how. If not:");
|
||||
break;
|
||||
default:
|
||||
message = translate("Unknown reason.");
|
||||
|
@ -30,27 +30,32 @@
|
||||
#include "py/mpconfig.h"
|
||||
|
||||
typedef enum {
|
||||
NO_SAFE_MODE = 0,
|
||||
BROWNOUT,
|
||||
HARD_CRASH,
|
||||
USER_SAFE_MODE,
|
||||
HEAP_OVERWRITTEN,
|
||||
MANUAL_SAFE_MODE,
|
||||
MICROPY_NLR_JUMP_FAIL,
|
||||
MICROPY_FATAL_ERROR,
|
||||
GC_ALLOC_OUTSIDE_VM,
|
||||
PROGRAMMATIC_SAFE_MODE,
|
||||
NORDIC_SOFT_DEVICE_ASSERT,
|
||||
FLASH_WRITE_FAIL,
|
||||
MEM_MANAGE,
|
||||
WATCHDOG_RESET,
|
||||
USB_TOO_MANY_ENDPOINTS,
|
||||
USB_TOO_MANY_INTERFACE_NAMES,
|
||||
USB_BOOT_DEVICE_NOT_INTERFACE_ZERO,
|
||||
NO_HEAP,
|
||||
NO_CIRCUITPY,
|
||||
SAFE_MODE_NONE = 0,
|
||||
// BROWNOUT should be lowest after SAFE_MODE_NONE.
|
||||
SAFE_MODE_BROWNOUT,
|
||||
// alphabetical from here down
|
||||
SAFE_MODE_FLASH_WRITE_FAIL,
|
||||
SAFE_MODE_GC_ALLOC_OUTSIDE_VM,
|
||||
SAFE_MODE_HARD_FAULT,
|
||||
SAFE_MODE_INTERRUPT_ERROR,
|
||||
SAFE_MODE_MANUAL,
|
||||
SAFE_MODE_NLR_JUMP_FAIL,
|
||||
SAFE_MODE_NO_CIRCUITPY,
|
||||
SAFE_MODE_NO_HEAP,
|
||||
SAFE_MODE_PROGRAMMATIC,
|
||||
SAFE_MODE_SAFEMODE_PY_ERROR,
|
||||
SAFE_MODE_SDK_FATAL_ERROR,
|
||||
SAFE_MODE_STACK_OVERFLOW,
|
||||
SAFE_MODE_USB_BOOT_DEVICE_NOT_INTERFACE_ZERO,
|
||||
SAFE_MODE_USB_TOO_MANY_ENDPOINTS,
|
||||
SAFE_MODE_USB_TOO_MANY_INTERFACE_NAMES,
|
||||
SAFE_MODE_USER,
|
||||
SAFE_MODE_WATCHDOG,
|
||||
} safe_mode_t;
|
||||
|
||||
safe_mode_t get_safe_mode(void);
|
||||
void set_safe_mode(safe_mode_t safe_mode);
|
||||
|
||||
safe_mode_t wait_for_safe_mode_reset(void);
|
||||
|
||||
void safe_mode_on_next_reset(safe_mode_t reason);
|
||||
|
@ -74,7 +74,7 @@ inline bool stack_ok(void) {
|
||||
|
||||
inline void assert_heap_ok(void) {
|
||||
if (!stack_ok()) {
|
||||
reset_into_safe_mode(HEAP_OVERWRITTEN);
|
||||
reset_into_safe_mode(SAFE_MODE_STACK_OVERFLOW);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -228,7 +228,7 @@ static void usb_build_configuration_descriptor(void) {
|
||||
if (usb_hid_boot_device() > 0 && descriptor_counts.current_interface > 0) {
|
||||
// Hosts using boot devices generally to expect them to be at interface zero,
|
||||
// and will not work properly otherwise.
|
||||
reset_into_safe_mode(USB_BOOT_DEVICE_NOT_INTERFACE_ZERO);
|
||||
reset_into_safe_mode(SAFE_MODE_USB_BOOT_DEVICE_NOT_INTERFACE_ZERO);
|
||||
}
|
||||
descriptor_buf_remaining += usb_hid_add_descriptor(
|
||||
descriptor_buf_remaining, &descriptor_counts, ¤t_interface_string,
|
||||
@ -258,14 +258,14 @@ static void usb_build_configuration_descriptor(void) {
|
||||
if (descriptor_counts.current_endpoint > USB_NUM_ENDPOINT_PAIRS ||
|
||||
descriptor_counts.num_in_endpoints > USB_NUM_IN_ENDPOINTS ||
|
||||
descriptor_counts.num_out_endpoints > USB_NUM_OUT_ENDPOINTS) {
|
||||
reset_into_safe_mode(USB_TOO_MANY_ENDPOINTS);
|
||||
reset_into_safe_mode(SAFE_MODE_USB_TOO_MANY_ENDPOINTS);
|
||||
}
|
||||
}
|
||||
|
||||
// str must not be on the heap.
|
||||
void usb_add_interface_string(uint8_t interface_string_index, const char str[]) {
|
||||
if (interface_string_index > MAX_INTERFACE_STRINGS) {
|
||||
reset_into_safe_mode(USB_TOO_MANY_INTERFACE_NAMES);
|
||||
reset_into_safe_mode(SAFE_MODE_USB_TOO_MANY_INTERFACE_NAMES);
|
||||
}
|
||||
|
||||
collected_interface_strings[interface_string_index].char_str = str;
|
||||
|
@ -29,7 +29,7 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
safe_mode_t wait_for_safe_mode_reset(void) {
|
||||
return NO_SAFE_MODE;
|
||||
return SAFE_MODE_NONE;
|
||||
}
|
||||
|
||||
void reset_into_safe_mode(safe_mode_t reason) {
|
||||
|
Loading…
Reference in New Issue
Block a user