Now works on reload.

This commit is contained in:
Bill Sideris 2023-02-15 21:54:53 +02:00
parent 2077bb9da9
commit fa302b2e29
No known key found for this signature in database
GPG Key ID: 1BEF1BCEBA58EA33
1 changed files with 48 additions and 54 deletions

102
main.c
View File

@ -122,9 +122,13 @@
uint8_t value_out = 0; uint8_t value_out = 0;
#endif #endif
#if MICROPY_ENABLE_PYSTACK && CIRCUITPY_OS_GETENV #if MICROPY_ENABLE_PYSTACK
supervisor_allocation *pystack;
mp_int_t pystack_size = 0; // 0 indicated 'not allocated'
#if CIRCUITPY_OS_GETENV
#include "shared-module/os/__init__.h" #include "shared-module/os/__init__.h"
#endif #endif
#endif
static void reset_devices(void) { static void reset_devices(void) {
#if CIRCUITPY_BLEIO_HCI #if CIRCUITPY_BLEIO_HCI
@ -132,7 +136,31 @@ static void reset_devices(void) {
#endif #endif
} }
STATIC void start_mp(supervisor_allocation *heap, supervisor_allocation *pystack, int pystack_size) { #if MICROPY_ENABLE_PYSTACK
STATIC void alloc_pystack(void) {
mp_int_t old_pystack_size = pystack_size;
pystack_size = CIRCUITPY_PYSTACK_SIZE; // Use build default for now.
// Fetch value if exists from settings.toml
#if CIRCUITPY_OS_GETENV
// Leaves size to build default on any failure
(void)common_hal_os_getenv_int("CIRCUITPY_PYSTACK_SIZE", &pystack_size);
// Check if value is valid
if ((CIRCUITPY_PYSTACK_SIZE != pystack_size) && ((pystack_size < 1) || (pystack_size % sizeof(size_t) != 0))) {
pystack_size = CIRCUITPY_PYSTACK_SIZE; // Reset to build default
// TODO: Find a way to inform the user about it.
// Perhaps safemode? Or is it too much?
}
#endif
if (old_pystack_size != pystack_size) {
if (old_pystack_size != 0) {
free_memory(pystack);
}
pystack = allocate_memory(pystack_size, false, false);
}
}
#endif
STATIC void start_mp(supervisor_allocation *heap) {
supervisor_workflow_reset(); supervisor_workflow_reset();
// Stack limit should be less than real stack size, so we have a chance // Stack limit should be less than real stack size, so we have a chance
@ -363,7 +391,7 @@ STATIC void print_code_py_status_message(safe_mode_t safe_mode) {
} }
} }
STATIC bool run_code_py(safe_mode_t safe_mode, bool *simulate_reset, supervisor_allocation *pystack, int pystack_size) { STATIC bool run_code_py(safe_mode_t safe_mode, bool *simulate_reset) {
bool serial_connected_at_start = serial_connected(); bool serial_connected_at_start = serial_connected();
bool printed_safe_mode_message = false; bool printed_safe_mode_message = false;
#if CIRCUITPY_AUTORELOAD_DELAY_MS > 0 #if CIRCUITPY_AUTORELOAD_DELAY_MS > 0
@ -399,13 +427,11 @@ STATIC bool run_code_py(safe_mode_t safe_mode, bool *simulate_reset, supervisor_
}; };
#endif #endif
#if MICROPY_ENABLE_PYSTACK
alloc_pystack();
#endif
supervisor_allocation *heap = allocate_remaining_memory(); supervisor_allocation *heap = allocate_remaining_memory();
start_mp(heap);
// Prepare the VM state.
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" // stackless doesn't want allocations.
start_mp(heap, pystack, pystack_size);
#pragma GCC diagnostic pop
#if CIRCUITPY_USB #if CIRCUITPY_USB
usb_setup_with_vm(); usb_setup_with_vm();
@ -733,7 +759,7 @@ STATIC bool run_code_py(safe_mode_t safe_mode, bool *simulate_reset, supervisor_
vstr_t *boot_output; vstr_t *boot_output;
STATIC void run_boot_py(safe_mode_t safe_mode, supervisor_allocation *pystack, int pystack_size) { STATIC void run_boot_py(safe_mode_t safe_mode) {
if (safe_mode == NO_HEAP) { if (safe_mode == NO_HEAP) {
return; return;
} }
@ -749,11 +775,11 @@ STATIC void run_boot_py(safe_mode_t safe_mode, supervisor_allocation *pystack, i
// Do USB setup even if boot.py is not run. // Do USB setup even if boot.py is not run.
#if MICROPY_ENABLE_PYSTACK
alloc_pystack();
#endif
supervisor_allocation *heap = allocate_remaining_memory(); supervisor_allocation *heap = allocate_remaining_memory();
#pragma GCC diagnostic push start_mp(heap);
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" // stackless doesn't want allocations.
start_mp(heap, pystack, pystack_size);
#pragma GCC diagnostic pop
#if CIRCUITPY_USB #if CIRCUITPY_USB
// Set up default USB values after boot.py VM starts but before running boot.py. // Set up default USB values after boot.py VM starts but before running boot.py.
@ -850,15 +876,15 @@ STATIC void run_boot_py(safe_mode_t safe_mode, supervisor_allocation *pystack, i
#endif #endif
} }
STATIC int run_repl(supervisor_allocation *pystack, int pystack_size) { STATIC int run_repl(void) {
int exit_code = PYEXEC_FORCED_EXIT; int exit_code = PYEXEC_FORCED_EXIT;
stack_resize(); stack_resize();
filesystem_flush(); filesystem_flush();
#if MICROPY_ENABLE_PYSTACK
alloc_pystack();
#endif
supervisor_allocation *heap = allocate_remaining_memory(); supervisor_allocation *heap = allocate_remaining_memory();
#pragma GCC diagnostic push start_mp(heap);
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" // stackless doesn't want allocations.
start_mp(heap, pystack, pystack_size);
#pragma GCC diagnostic pop
#if CIRCUITPY_USB #if CIRCUITPY_USB
usb_setup_with_vm(); usb_setup_with_vm();
@ -978,38 +1004,6 @@ int __attribute__((used)) main(void) {
alarm_reset(); alarm_reset();
#endif #endif
// Pystack variables have to exist even in stackless for the function calls
supervisor_allocation *pystack;
mp_int_t pystack_size = CIRCUITPY_PYSTACK_SIZE; // Use build default for now.
#if MICROPY_ENABLE_PYSTACK
// Allocate default at least temporarily, needed for getenv
pystack = allocate_memory(CIRCUITPY_PYSTACK_SIZE, false, false);
// Fetch value if exists from settings.toml
#if CIRCUITPY_OS_GETENV
// Init needed.
supervisor_allocation *heap = allocate_remaining_memory();
// Leaves size to build default on any failure
(void)common_hal_os_getenv_int("CIRCUITPY_PYSTACK_SIZE", &pystack_size);
free_memory(heap);
// Convert frame count to allocation size, 384 is the default for 1536 bytes
pystack_size = pystack_size * sizeof(size_t);
// Check if value is valid
if ((CIRCUITPY_PYSTACK_SIZE != pystack_size) && (pystack_size < 1)) {
pystack_size = CIRCUITPY_PYSTACK_SIZE; // Reset to build default
// TODO: Find a way to inform the user about it.
// Perhaps safemode?
}
if (CIRCUITPY_PYSTACK_SIZE != pystack_size) {
free_memory(pystack); // Free the temporary
pystack = allocate_memory(pystack_size, false, false); // Allocate new pystack
}
#endif
#endif
// Reset everything and prep MicroPython to run boot.py. // Reset everything and prep MicroPython to run boot.py.
reset_port(); reset_port();
// Port-independent devices, like CIRCUITPY_BLEIO_HCI. // Port-independent devices, like CIRCUITPY_BLEIO_HCI.
@ -1032,7 +1026,7 @@ int __attribute__((used)) main(void) {
filesystem_set_internal_concurrent_write_protection(true); filesystem_set_internal_concurrent_write_protection(true);
filesystem_set_internal_writable_by_usb(CIRCUITPY_USB == 1); filesystem_set_internal_writable_by_usb(CIRCUITPY_USB == 1);
run_boot_py(safe_mode, pystack, pystack_size); run_boot_py(safe_mode);
supervisor_workflow_start(); supervisor_workflow_start();
@ -1046,7 +1040,7 @@ int __attribute__((used)) main(void) {
bool simulate_reset = true; bool simulate_reset = true;
for (;;) { for (;;) {
if (!skip_repl) { if (!skip_repl) {
exit_code = run_repl(pystack, pystack_size); exit_code = run_repl();
supervisor_set_run_reason(RUN_REASON_REPL_RELOAD); supervisor_set_run_reason(RUN_REASON_REPL_RELOAD);
} }
if (exit_code == PYEXEC_FORCED_EXIT) { if (exit_code == PYEXEC_FORCED_EXIT) {
@ -1057,7 +1051,7 @@ int __attribute__((used)) main(void) {
// If code.py did a fake deep sleep, pretend that we // If code.py did a fake deep sleep, pretend that we
// are running code.py for the first time after a hard // are running code.py for the first time after a hard
// reset. This will preserve any alarm information. // reset. This will preserve any alarm information.
skip_repl = run_code_py(safe_mode, &simulate_reset, pystack, pystack_size); skip_repl = run_code_py(safe_mode, &simulate_reset);
} else { } else {
skip_repl = false; skip_repl = false;
} }