Skip to content

Commit b67c0b7

Browse files
authored
Merge pull request #7585 from bill88t/settings-toml-pystack
Settings.toml-configurable pystack
2 parents 932b10f + 1d12014 commit b67c0b7

File tree

4 files changed

+71
-18
lines changed

4 files changed

+71
-18
lines changed

locale/circuitpython.pot

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,14 @@ msgid ""
2828
"Code stopped by auto-reload. Reloading soon.\n"
2929
msgstr ""
3030

31+
#: main.c
32+
msgid ""
33+
"\n"
34+
"Invalid CIRCUITPY_PYSTACK_SIZE\n"
35+
"\n"
36+
"\r"
37+
msgstr ""
38+
3139
#: supervisor/shared/safe_mode.c
3240
msgid ""
3341
"\n"

main.c

Lines changed: 60 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -122,8 +122,8 @@
122122
uint8_t value_out = 0;
123123
#endif
124124

125-
#if MICROPY_ENABLE_PYSTACK
126-
static size_t PLACE_IN_DTCM_BSS(_pystack[CIRCUITPY_PYSTACK_SIZE / sizeof(size_t)]);
125+
#if MICROPY_ENABLE_PYSTACK && CIRCUITPY_OS_GETENV
126+
#include "shared-module/os/__init__.h"
127127
#endif
128128

129129
static void reset_devices(void) {
@@ -132,7 +132,32 @@ static void reset_devices(void) {
132132
#endif
133133
}
134134

135-
STATIC void start_mp(supervisor_allocation *heap) {
135+
#if MICROPY_ENABLE_PYSTACK
136+
STATIC supervisor_allocation *allocate_pystack(safe_mode_t safe_mode) {
137+
mp_int_t pystack_size = CIRCUITPY_PYSTACK_SIZE;
138+
#if CIRCUITPY_OS_GETENV && CIRCUITPY_SETTABLE_PYSTACK
139+
// Fetch value if exists from settings.toml
140+
// Leaves size to build default on any failure
141+
if (safe_mode == SAFE_MODE_NONE || safe_mode == SAFE_MODE_USER) {
142+
(void)common_hal_os_getenv_int("CIRCUITPY_PYSTACK_SIZE", &pystack_size);
143+
// Check if value is valid
144+
pystack_size = pystack_size - pystack_size % sizeof(size_t); // Round down to multiple of 4.
145+
if ((pystack_size < 384) || (pystack_size > 900000)) {
146+
serial_write_compressed(translate("\nInvalid CIRCUITPY_PYSTACK_SIZE\n\n\r"));
147+
pystack_size = CIRCUITPY_PYSTACK_SIZE; // Reset
148+
}
149+
}
150+
#endif
151+
supervisor_allocation *pystack = allocate_memory(pystack_size, false, false);
152+
if (pystack == NULL) {
153+
serial_write_compressed(translate("\nInvalid CIRCUITPY_PYSTACK_SIZE\n\n\r"));
154+
pystack = allocate_memory(CIRCUITPY_PYSTACK_SIZE, false, false);
155+
}
156+
return pystack;
157+
}
158+
#endif
159+
160+
STATIC void start_mp(supervisor_allocation *heap, supervisor_allocation *pystack) {
136161
supervisor_workflow_reset();
137162

138163
// Stack limit should be less than real stack size, so we have a chance
@@ -160,7 +185,7 @@ STATIC void start_mp(supervisor_allocation *heap) {
160185
readline_init0();
161186

162187
#if MICROPY_ENABLE_PYSTACK
163-
mp_pystack_init(_pystack, _pystack + (sizeof(_pystack) / sizeof(size_t)));
188+
mp_pystack_init(pystack->ptr, pystack->ptr + get_allocation_length(pystack) / sizeof(size_t));
164189
#endif
165190

166191
#if MICROPY_ENABLE_GC
@@ -264,7 +289,7 @@ STATIC void count_strn(void *data, const char *str, size_t len) {
264289
*(size_t *)data += len;
265290
}
266291

267-
STATIC void cleanup_after_vm(supervisor_allocation *heap, mp_obj_t exception) {
292+
STATIC void cleanup_after_vm(supervisor_allocation *heap, supervisor_allocation *pystack, mp_obj_t exception) {
268293
// Get the traceback of any exception from this run off the heap.
269294
// MP_OBJ_SENTINEL means "this run does not contribute to traceback storage, don't touch it"
270295
// MP_OBJ_NULL (=0) means "this run completed successfully, clear any stored traceback"
@@ -345,6 +370,9 @@ STATIC void cleanup_after_vm(supervisor_allocation *heap, mp_obj_t exception) {
345370
filesystem_flush();
346371
stop_mp();
347372
free_memory(heap);
373+
#if MICROPY_ENABLE_PYSTACK
374+
free_memory(pystack);
375+
#endif
348376
supervisor_move_memory();
349377

350378
// Let the workflows know we've reset in case they want to restart.
@@ -399,10 +427,12 @@ STATIC bool run_code_py(safe_mode_t safe_mode, bool *simulate_reset) {
399427
};
400428
#endif
401429

430+
supervisor_allocation *pystack = NULL;
431+
#if MICROPY_ENABLE_PYSTACK
432+
pystack = allocate_pystack(safe_mode);
433+
#endif
402434
supervisor_allocation *heap = allocate_remaining_memory();
403-
404-
// Prepare the VM state.
405-
start_mp(heap);
435+
start_mp(heap, pystack);
406436

407437
#if CIRCUITPY_USB
408438
usb_setup_with_vm();
@@ -450,7 +480,7 @@ STATIC bool run_code_py(safe_mode_t safe_mode, bool *simulate_reset) {
450480

451481

452482
// Finished executing python code. Cleanup includes filesystem flush and a board reset.
453-
cleanup_after_vm(heap, _exec_result.exception);
483+
cleanup_after_vm(heap, pystack, _exec_result.exception);
454484
_exec_result.exception = NULL;
455485

456486
// If a new next code file was set, that is a reason to keep it (obviously). Stuff this into
@@ -739,8 +769,12 @@ STATIC void __attribute__ ((noinline)) run_safemode_py(safe_mode_t safe_mode) {
739769
return;
740770
}
741771

772+
supervisor_allocation *pystack = NULL;
773+
#if MICROPY_ENABLE_PYSTACK
774+
pystack = allocate_pystack(safe_mode);
775+
#endif
742776
supervisor_allocation *heap = allocate_remaining_memory();
743-
start_mp(heap);
777+
start_mp(heap, pystack);
744778

745779
static const char *const safemode_py_filenames[] = {"safemode.py", "safemode.txt"};
746780
maybe_run_list(safemode_py_filenames, MP_ARRAY_SIZE(safemode_py_filenames));
@@ -751,7 +785,7 @@ STATIC void __attribute__ ((noinline)) run_safemode_py(safe_mode_t safe_mode) {
751785
set_safe_mode(SAFE_MODE_SAFEMODE_PY_ERROR);
752786
}
753787

754-
cleanup_after_vm(heap, _exec_result.exception);
788+
cleanup_after_vm(heap, pystack, _exec_result.exception);
755789
_exec_result.exception = NULL;
756790
}
757791
#endif
@@ -772,9 +806,12 @@ STATIC void __attribute__ ((noinline)) run_boot_py(safe_mode_t safe_mode) {
772806

773807
// Do USB setup even if boot.py is not run.
774808

809+
supervisor_allocation *pystack = NULL;
810+
#if MICROPY_ENABLE_PYSTACK
811+
pystack = allocate_pystack(safe_mode);
812+
#endif
775813
supervisor_allocation *heap = allocate_remaining_memory();
776-
777-
start_mp(heap);
814+
start_mp(heap, pystack);
778815

779816
#if CIRCUITPY_USB
780817
// Set up default USB values after boot.py VM starts but before running boot.py.
@@ -860,7 +897,7 @@ STATIC void __attribute__ ((noinline)) run_boot_py(safe_mode_t safe_mode) {
860897

861898
port_post_boot_py(true);
862899

863-
cleanup_after_vm(heap, _exec_result.exception);
900+
cleanup_after_vm(heap, pystack, _exec_result.exception);
864901
_exec_result.exception = NULL;
865902

866903
port_post_boot_py(false);
@@ -871,12 +908,16 @@ STATIC void __attribute__ ((noinline)) run_boot_py(safe_mode_t safe_mode) {
871908
#endif
872909
}
873910

874-
STATIC int run_repl(void) {
911+
STATIC int run_repl(safe_mode_t safe_mode) {
875912
int exit_code = PYEXEC_FORCED_EXIT;
876913
stack_resize();
877914
filesystem_flush();
915+
supervisor_allocation *pystack = NULL;
916+
#if MICROPY_ENABLE_PYSTACK
917+
pystack = allocate_pystack(safe_mode);
918+
#endif
878919
supervisor_allocation *heap = allocate_remaining_memory();
879-
start_mp(heap);
920+
start_mp(heap, pystack);
880921

881922
#if CIRCUITPY_USB
882923
usb_setup_with_vm();
@@ -919,7 +960,7 @@ STATIC int run_repl(void) {
919960
exit_code = PYEXEC_DEEP_SLEEP;
920961
}
921962
#endif
922-
cleanup_after_vm(heap, MP_OBJ_SENTINEL);
963+
cleanup_after_vm(heap, pystack, MP_OBJ_SENTINEL);
923964

924965
// Also reset bleio. The above call omits it in case workflows should continue. In this case,
925966
// we're switching straight to another VM so we want to reset.
@@ -938,6 +979,7 @@ STATIC int run_repl(void) {
938979
}
939980

940981
int __attribute__((used)) main(void) {
982+
941983
// initialise the cpu and peripherals
942984
set_safe_mode(port_init());
943985

@@ -1038,7 +1080,7 @@ int __attribute__((used)) main(void) {
10381080
bool simulate_reset = true;
10391081
for (;;) {
10401082
if (!skip_repl) {
1041-
exit_code = run_repl();
1083+
exit_code = run_repl(get_safe_mode());
10421084
supervisor_set_run_reason(RUN_REASON_REPL_RELOAD);
10431085
}
10441086
if (exit_code == PYEXEC_FORCED_EXIT) {

ports/atmel-samd/boards/kicksat-sprite/mpconfigboard.mk

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,13 @@ CIRCUITPY_BLEIO_HCI = 0
2020
CIRCUITPY_DISPLAYIO = 0
2121
CIRCUITPY_FLOPPYIO = 0
2222
CIRCUITPY_FRAMEBUFFERIO = 0
23+
CIRCUITPY_PIXELMAP = 0
2324
CIRCUITPY_GETPASS = 0
2425
CIRCUITPY_KEYPAD = 0
2526
CIRCUITPY_MSGPACK = 0
2627
CIRCUITPY_PS2IO = 0
2728
CIRCUITPY_RGBMATRIX = 0
29+
CIRCUITPY_RAINBOWIO = 0
2830
CIRCUITPY_ROTARYIO = 0
2931
CIRCUITPY_TOUCHIO = 0
3032
CIRCUITPY_USB_HID = 0

py/circuitpy_mpconfig.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ extern void common_hal_mcu_enable_interrupts(void);
145145
#define MICROPY_REPL_AUTO_INDENT (1)
146146
#define MICROPY_REPL_EVENT_DRIVEN (0)
147147
#define MICROPY_ENABLE_PYSTACK (1)
148+
#define CIRCUITPY_SETTABLE_PYSTACK (1)
148149
#define MICROPY_STACK_CHECK (1)
149150
#define MICROPY_STREAMS_NON_BLOCK (1)
150151
#ifndef MICROPY_USE_INTERNAL_PRINTF

0 commit comments

Comments
 (0)