diff options
| -rwxr-xr-x | main.c | 4 | ||||
| -rw-r--r-- | ports/atmel-samd/background.c | 11 | ||||
| -rw-r--r-- | ports/atmel-samd/background.h | 1 | ||||
| -rw-r--r-- | ports/atmel-samd/common-hal/nvm/ByteArray.c | 3 | ||||
| -rw-r--r-- | ports/atmel-samd/mpconfigport.h | 11 | ||||
| -rw-r--r-- | ports/atmel-samd/supervisor/port.c | 15 | ||||
| -rw-r--r-- | py/obj.c | 4 | ||||
| -rwxr-xr-x | supervisor/shared/stack.c | 17 | ||||
| -rwxr-xr-x | supervisor/shared/stack.h | 5 |
9 files changed, 62 insertions, 9 deletions
@@ -220,8 +220,8 @@ bool run_code_py(safe_mode_t safe_mode) { rgb_status_animation_t animation; prep_rgb_status_animation(&result, found_main, safe_mode, &animation); while (true) { - #ifdef MICROPY_VM_HOOK_LOOP - MICROPY_VM_HOOK_LOOP + #ifdef CIRCUITPY_SUPERVISOR_BACKGROUND + CIRCUITPY_SUPERVISOR_BACKGROUND #endif if (reload_requested) { return true; diff --git a/ports/atmel-samd/background.c b/ports/atmel-samd/background.c index 099cb8b23..94763bc43 100644 --- a/ports/atmel-samd/background.c +++ b/ports/atmel-samd/background.c @@ -29,11 +29,15 @@ #include "tick.h" #include "supervisor/usb.h" +#include "py/runtime.h" #include "shared-module/displayio/__init__.h" #include "shared-module/network/__init__.h" +#include "supervisor/shared/stack.h" volatile uint64_t last_finished_tick = 0; +bool stack_ok_so_far = true; + void run_background_tasks(void) { #if (defined(SAMD21) && defined(PIN_PA02)) || defined(SAMD51) audio_dma_background(); @@ -41,6 +45,7 @@ void run_background_tasks(void) { #ifdef CIRCUITPY_DISPLAYIO displayio_refresh_display(); #endif + #if MICROPY_PY_NETWORK network_module_background(); #endif @@ -49,6 +54,12 @@ void run_background_tasks(void) { last_finished_tick = ticks_ms; } +void run_background_vm_tasks(void) { + assert_heap_ok(); + run_background_tasks(); + assert_heap_ok(); +} + bool background_tasks_ok(void) { return ticks_ms - last_finished_tick < 1000; } diff --git a/ports/atmel-samd/background.h b/ports/atmel-samd/background.h index e841049a4..8d1316e73 100644 --- a/ports/atmel-samd/background.h +++ b/ports/atmel-samd/background.h @@ -30,6 +30,7 @@ #include <stdbool.h> void run_background_tasks(void); +void run_background_vm_tasks(void); bool background_tasks_ok(void); #endif // MICROPY_INCLUDED_ATMEL_SAMD_BACKGROUND_H diff --git a/ports/atmel-samd/common-hal/nvm/ByteArray.c b/ports/atmel-samd/common-hal/nvm/ByteArray.c index ab9cd7d80..12a127f53 100644 --- a/ports/atmel-samd/common-hal/nvm/ByteArray.c +++ b/ports/atmel-samd/common-hal/nvm/ByteArray.c @@ -28,6 +28,8 @@ #include "hal_flash.h" +#include "supervisor/shared/stack.h" + #include <stdint.h> #include <string.h> @@ -42,6 +44,7 @@ bool common_hal_nvm_bytearray_set_bytes(nvm_bytearray_obj_t *self, struct flash_descriptor desc; desc.dev.hw = NVMCTRL; flash_write(&desc, (uint32_t) self->start_address + start_index, values, len); + assert_heap_ok(); return true; } diff --git a/ports/atmel-samd/mpconfigport.h b/ports/atmel-samd/mpconfigport.h index 8df56ec4e..4fc32157c 100644 --- a/ports/atmel-samd/mpconfigport.h +++ b/ports/atmel-samd/mpconfigport.h @@ -182,7 +182,7 @@ typedef long mp_off_t; #define MICROPY_PY_SYS_PLATFORM "MicroChip SAMD51" #define PORT_HEAP_SIZE (0x20000) // 128KiB #define SPI_FLASH_MAX_BAUDRATE 24000000 -#define CIRCUITPY_DEFAULT_STACK_SIZE 8192 +#define CIRCUITPY_DEFAULT_STACK_SIZE 0x6000 #define MICROPY_CPYTHON_COMPAT (1) #define MICROPY_MODULE_WEAK_LINKS (1) #define MICROPY_PY_BUILTINS_NOTIMPLEMENTED (1) @@ -432,10 +432,6 @@ extern const struct _mp_obj_module_t wiznet_module; #define MP_STATE_PORT MP_STATE_VM -void run_background_tasks(void); -#define MICROPY_VM_HOOK_LOOP run_background_tasks(); -#define MICROPY_VM_HOOK_RETURN run_background_tasks(); - #include "peripherals/samd/dma.h" #include "supervisor/flash_root_pointers.h" @@ -454,6 +450,11 @@ void run_background_tasks(void); mp_obj_t gamepad_singleton; \ NETWORK_ROOT_POINTERS \ +void run_background_tasks(void); +void run_background_vm_tasks(void); +#define MICROPY_VM_HOOK_LOOP run_background_vm_tasks(); +#define MICROPY_VM_HOOK_RETURN run_background_vm_tasks(); +#define CIRCUITPY_SUPERVISOR_BACKGROUND run_background_tasks(); #define CIRCUITPY_AUTORELOAD_DELAY_MS 500 #define CIRCUITPY_BOOT_OUTPUT_FILE "/boot_out.txt" diff --git a/ports/atmel-samd/supervisor/port.c b/ports/atmel-samd/supervisor/port.c index 9f951b035..7b51400ef 100644 --- a/ports/atmel-samd/supervisor/port.c +++ b/ports/atmel-samd/supervisor/port.c @@ -80,7 +80,7 @@ extern volatile bool mp_msc_enabled; #define TRACE_BUFFER_SIZE (1 << (TRACE_BUFFER_MAGNITUDE_PACKETS + 1)) // Size in bytes. 4 bytes per uint32_t. #define TRACE_BUFFER_SIZE_BYTES (TRACE_BUFFER_SIZE << 2) -__attribute__((__aligned__(TRACE_BUFFER_SIZE_BYTES))) uint32_t mtb[TRACE_BUFFER_SIZE]; +__attribute__((__aligned__(TRACE_BUFFER_SIZE_BYTES))) uint32_t mtb[TRACE_BUFFER_SIZE] = {0}; #endif safe_mode_t port_init(void) { @@ -285,6 +285,19 @@ void reset_to_bootloader(void) { */ __attribute__((used)) void HardFault_Handler(void) { +#ifdef ENABLE_MICRO_TRACE_BUFFER + // Turn off the micro trace buffer so we don't fill it up in the infinite + // loop below. + REG_MTB_MASTER = 0x00000000 + 6; +#endif +#ifdef CIRCUITPY_CANARY_WORD + // If the canary is intact, then kill it and reset so we have a chance to + // read our files. + if (_ezero == CIRCUITPY_CANARY_WORD) { + _ezero = CIRCUITPY_SAFE_RESTART_WORD; + NVIC_SystemReset(); + } +#endif while (true) { asm(""); } @@ -33,10 +33,12 @@ #include "py/objtype.h" #include "py/objint.h" #include "py/objstr.h" +#include "py/qstr.h" #include "py/runtime.h" #include "py/stackctrl.h" #include "py/stream.h" // for mp_obj_print +#include "supervisor/shared/stack.h" #include "supervisor/shared/translate.h" mp_obj_type_t *mp_obj_get_type(mp_const_obj_t o_in) { @@ -81,7 +83,7 @@ void mp_obj_print(mp_obj_t o_in, mp_print_kind_t kind) { // helper function to print an exception with traceback void mp_obj_print_exception(const mp_print_t *print, mp_obj_t exc) { - if (mp_obj_is_exception_instance(exc)) { + if (mp_obj_is_exception_instance(exc) && stack_ok()) { size_t n, *values; mp_obj_exception_get_traceback(exc, &n, &values); if (n > 0) { diff --git a/supervisor/shared/stack.c b/supervisor/shared/stack.c index 6b74742eb..8f4da4ce6 100755 --- a/supervisor/shared/stack.c +++ b/supervisor/shared/stack.c @@ -27,6 +27,7 @@ #include "stack.h" #include "py/mpconfig.h" +#include "py/runtime.h" #include "supervisor/cpu.h" extern uint32_t _estack; @@ -37,6 +38,8 @@ supervisor_allocation* stack_alloc = NULL; #define EXCEPTION_STACK_SIZE 1024 +#define STACK_CANARY_VALUE 0x017829ef + void allocate_stack(void) { mp_uint_t regs[10]; mp_uint_t sp = cpu_get_regs_and_sp(regs); @@ -50,6 +53,19 @@ void allocate_stack(void) { } else { current_stack_size = next_stack_size; } + *stack_alloc->ptr = STACK_CANARY_VALUE; +} + +inline bool stack_ok(void) { + return *stack_alloc->ptr == STACK_CANARY_VALUE; +} + +inline void assert_heap_ok(void) { + if (!stack_ok()) { + asm("nop"); + while(true) {} + mp_raise_RuntimeError(translate("Stack clobbered heap.")); + } } void stack_init(void) { @@ -58,6 +74,7 @@ void stack_init(void) { void stack_resize(void) { if (next_stack_size == current_stack_size) { + *stack_alloc->ptr = STACK_CANARY_VALUE; return; } free_memory(stack_alloc); diff --git a/supervisor/shared/stack.h b/supervisor/shared/stack.h index 3a5c18e7d..8f1e881f2 100755 --- a/supervisor/shared/stack.h +++ b/supervisor/shared/stack.h @@ -37,5 +37,10 @@ void stack_init(void); void stack_resize(void); void set_next_stack_size(uint32_t size); uint32_t get_current_stack_size(void); +bool stack_ok(void); + +// Use this after any calls into a library which may use a lot of stack. This will raise a Python +// exception when the stack has likely overwritten a portio of the heap. +void assert_heap_ok(void); #endif // MICROPY_INCLUDED_SUPERVISOR_STACK_H |
