Skip to content

Commit 6ef8639

Browse files
committed
Rework safe mode and have heap overwrite trigger it.
This creates a common safe mode mechanic that ports can share. As a result, the nRF52 now has safe mode support as well. The common safe mode adds a 700ms delay at startup where a reset during that window will cause a reset into safe mode. This window is designated by a yellow status pixel and flashing the single led three times. A couple NeoPixel fixes are included for the nRF52 as well. Fixes adafruit#1034. Fixes adafruit#990. Fixes adafruit#615.
1 parent 7ad2e6a commit 6ef8639

48 files changed

Lines changed: 351 additions & 133 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

main.c

Lines changed: 18 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
#include "supervisor/shared/autoreload.h"
5252
#include "supervisor/shared/translate.h"
5353
#include "supervisor/shared/rgb_led_status.h"
54+
#include "supervisor/shared/safe_mode.h"
5455
#include "supervisor/shared/status_leds.h"
5556
#include "supervisor/shared/stack.h"
5657
#include "supervisor/serial.h"
@@ -140,12 +141,6 @@ const char* first_existing_file_in_list(const char ** filenames) {
140141
return NULL;
141142
}
142143

143-
void write_compressed(const compressed_string_t* compressed) {
144-
char decompressed[compressed->length];
145-
decompress(compressed, decompressed);
146-
serial_write(decompressed);
147-
}
148-
149144
bool maybe_run_list(const char ** filenames, pyexec_result_t* exec_result) {
150145
const char* filename = first_existing_file_in_list(filenames);
151146
if (filename == NULL) {
@@ -166,11 +161,11 @@ bool run_code_py(safe_mode_t safe_mode) {
166161
if (serial_connected_at_start) {
167162
serial_write("\n");
168163
if (autoreload_is_enabled()) {
169-
write_compressed(translate("Auto-reload is on. Simply save files over USB to run them or enter REPL to disable.\n"));
164+
serial_write_compressed(translate("Auto-reload is on. Simply save files over USB to run them or enter REPL to disable.\n"));
170165
} else if (safe_mode != NO_SAFE_MODE) {
171-
write_compressed(translate("Running in safe mode! Auto-reload is off.\n"));
166+
serial_write_compressed(translate("Running in safe mode! Auto-reload is off.\n"));
172167
} else if (!autoreload_is_enabled()) {
173-
write_compressed(translate("Auto-reload is off.\n"));
168+
serial_write_compressed(translate("Auto-reload is off.\n"));
174169
}
175170
}
176171
#endif
@@ -184,7 +179,7 @@ bool run_code_py(safe_mode_t safe_mode) {
184179
bool found_main = false;
185180

186181
if (safe_mode != NO_SAFE_MODE) {
187-
write_compressed(translate("Running in safe mode! Not running saved code.\n"));
182+
serial_write_compressed(translate("Running in safe mode! Not running saved code.\n"));
188183
} else {
189184
new_status_color(MAIN_RUNNING);
190185

@@ -200,7 +195,7 @@ bool run_code_py(safe_mode_t safe_mode) {
200195
if (!found_main){
201196
found_main = maybe_run_list(double_extension_filenames, &result);
202197
if (found_main) {
203-
write_compressed(translate("WARNING: Your code filename has two extensions\n"));
198+
serial_write_compressed(translate("WARNING: Your code filename has two extensions\n"));
204199
}
205200
}
206201
stop_mp();
@@ -239,37 +234,14 @@ bool run_code_py(safe_mode_t safe_mode) {
239234

240235
if (!serial_connected_at_start) {
241236
if (autoreload_is_enabled()) {
242-
write_compressed(translate("Auto-reload is on. Simply save files over USB to run them or enter REPL to disable.\n"));
237+
serial_write_compressed(translate("Auto-reload is on. Simply save files over USB to run them or enter REPL to disable.\n"));
243238
} else {
244-
write_compressed(translate("Auto-reload is off.\n"));
245-
}
246-
}
247-
// Output a user safe mode string if its set.
248-
#ifdef BOARD_USER_SAFE_MODE
249-
if (safe_mode == USER_SAFE_MODE) {
250-
serial_write("\n");
251-
write_compressed(translate("You requested starting safe mode by "));
252-
serial_write(BOARD_USER_SAFE_MODE_ACTION);
253-
serial_write("\n");
254-
write_compressed(translate("To exit, please reset the board without "));
255-
serial_write(BOARD_USER_SAFE_MODE_ACTION);
256-
serial_write("\n");
257-
} else
258-
#endif
259-
if (safe_mode != NO_SAFE_MODE) {
260-
serial_write("\n");
261-
write_compressed(translate("You are running in safe mode which means something really bad happened.\n"));
262-
if (safe_mode == HARD_CRASH) {
263-
write_compressed(translate("Looks like our core CircuitPython code crashed hard. Whoops!\n"));
264-
write_compressed(translate("Please file an issue here with the contents of your CIRCUITPY drive:\n"));
265-
serial_write("https://github.com/adafruit/circuitpython/issues\n");
266-
} else if (safe_mode == BROWNOUT) {
267-
write_compressed(translate("The microcontroller's power dipped. Please make sure your power supply provides\n"));
268-
write_compressed(translate("enough power for the whole circuit and press reset (after ejecting CIRCUITPY).\n"));
239+
serial_write_compressed(translate("Auto-reload is off.\n"));
269240
}
270241
}
242+
print_safe_mode_message(safe_mode);
271243
serial_write("\n");
272-
write_compressed(translate("Press any key to enter the REPL. Use CTRL-D to reload."));
244+
serial_write_compressed(translate("Press any key to enter the REPL. Use CTRL-D to reload."));
273245
}
274246
if (serial_connected_before_animation && !serial_connected()) {
275247
serial_connected_at_start = false;
@@ -394,6 +366,11 @@ int __attribute__((used)) main(void) {
394366
init_status_leds();
395367
rgb_led_status_init();
396368

369+
// Wait briefly to give a reset window where we'll enter safe mode after the reset.
370+
if (safe_mode == NO_SAFE_MODE) {
371+
safe_mode = wait_for_safe_mode_reset();
372+
}
373+
397374
stack_init();
398375

399376
// Create a new filesystem only if we're not in a safe mode.
@@ -427,7 +404,7 @@ int __attribute__((used)) main(void) {
427404
}
428405
if (exit_code == PYEXEC_FORCED_EXIT) {
429406
if (!first_run) {
430-
write_compressed(translate("soft reboot\n"));
407+
serial_write_compressed(translate("soft reboot\n"));
431408
}
432409
first_run = false;
433410
skip_repl = run_code_py(safe_mode);
@@ -455,12 +432,12 @@ void gc_collect(void) {
455432
}
456433

457434
void NORETURN nlr_jump_fail(void *val) {
458-
HardFault_Handler();
435+
reset_into_safe_mode(MICROPY_NLR_JUMP_FAIL);
459436
while (true) {}
460437
}
461438

462439
void NORETURN __fatal_error(const char *msg) {
463-
HardFault_Handler();
440+
reset_into_safe_mode(MICROPY_FATAL_ERROR);
464441
while (true) {}
465442
}
466443

ports/atmel-samd/boards/arduino_mkr1300/mpconfigboard.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
#define MICROPY_PORT_B (0)
66
#define MICROPY_PORT_C (0)
77

8+
#define MICROPY_HW_LED_STATUS (&pin_PB23)
9+
810
#define CIRCUITPY_INTERNAL_NVM_SIZE 0
911

1012
#define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - 0x010000)

ports/atmel-samd/boards/arduino_zero/mpconfigboard.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
#define MICROPY_HW_BOARD_NAME "Arduino Zero"
22
#define MICROPY_HW_MCU_NAME "samd21g18"
33

4-
// #define MICROPY_HW_LED_MSC &pin_PA17 // red
4+
#define MICROPY_HW_LED_STATUS (&pin_PA17)
5+
56
#define MICROPY_HW_LED_TX &pin_PA27
67
#define MICROPY_HW_LED_RX &pin_PB03
78

ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#define MICROPY_HW_BOARD_NAME "Adafruit CircuitPlayground Express"
22
#define MICROPY_HW_MCU_NAME "samd21g18"
33

4+
#define MICROPY_HW_LED_STATUS (&pin_PA17)
5+
46
// Don't allow touch on A0 (PA02), because it's connected to the speaker.
57
#define PA02_NO_TOUCH (true)
68

ports/atmel-samd/boards/circuitplayground_express_crickit/mpconfigboard.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#define MICROPY_HW_BOARD_NAME "Adafruit CircuitPlayground Express with Crickit libraries"
22
#define MICROPY_HW_MCU_NAME "samd21g18"
33

4+
#define MICROPY_HW_LED_STATUS (&pin_PA17)
5+
46
// No framebuf on CRICKit version to save space.
57
#define MICROPY_PY_FRAMEBUF (0)
68

ports/atmel-samd/boards/feather_m0_adalogger/mpconfigboard.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// LEDs
2-
//#define MICROPY_HW_LED_MSC PIN_PA17 // red
2+
#define MICROPY_HW_LED_STATUS (&pin_PA17)
3+
34
#define MICROPY_HW_BOARD_NAME "Adafruit Feather M0 Adalogger"
45
#define MICROPY_HW_MCU_NAME "samd21g18"
56

ports/atmel-samd/boards/feather_m0_basic/mpconfigboard.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// LEDs
2-
//#define MICROPY_HW_LED_MSC PIN_PA17 // red
2+
#define MICROPY_HW_LED_STATUS (&pin_PA17)
33

44
#define MICROPY_HW_BOARD_NAME "Adafruit Feather M0 Basic"
55
#define MICROPY_HW_MCU_NAME "samd21g18"

ports/atmel-samd/boards/feather_m0_express/mpconfigboard.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#define MICROPY_HW_BOARD_NAME "Adafruit Feather M0 Express"
22
#define MICROPY_HW_MCU_NAME "samd21g18"
33

4+
#define MICROPY_HW_LED_STATUS (&pin_PA17)
5+
46
#define MICROPY_HW_NEOPIXEL (&pin_PA06)
57

68
#define SPI_FLASH_MOSI_PIN &pin_PA08

ports/atmel-samd/boards/feather_m0_express_crickit/mpconfigboard.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#define MICROPY_HW_BOARD_NAME "Adafruit Feather M0 Express with Crickit libraries"
22
#define MICROPY_HW_MCU_NAME "samd21g18"
33

4+
#define MICROPY_HW_LED_STATUS (&pin_PA17)
5+
46
#define MICROPY_HW_NEOPIXEL (&pin_PA06)
57

68
#define SPI_FLASH_MOSI_PIN &pin_PA08

ports/atmel-samd/boards/feather_m0_rfm69/mpconfigboard.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// LEDs
2-
//#define MICROPY_HW_LED_MSC PIN_PA17 // red
2+
#define MICROPY_HW_LED_STATUS (&pin_PA17)
33

44
#define MICROPY_HW_BOARD_NAME "Adafruit Feather M0 RFM69"
55
#define MICROPY_HW_MCU_NAME "samd21g18"

0 commit comments

Comments
 (0)