@@ -126,35 +126,47 @@ uint8_t value_out = 0;
126126#include "shared-module/os/__init__.h"
127127#endif
128128
129+ typedef struct {
130+ #if MICROPY_ENABLE_PYSTACK
131+ supervisor_allocation * pystack ;
132+ #endif
133+ supervisor_allocation * heap ;
134+ } stacks ;
135+
129136static void reset_devices (void ) {
130137 #if CIRCUITPY_BLEIO_HCI
131138 bleio_reset ();
132139 #endif
133140}
134141
135142#if MICROPY_ENABLE_PYSTACK
136- STATIC supervisor_allocation __attribute__ ((noinline )) * alloc_pystack (void ) {
143+ STATIC stacks __attribute__ ((noinline )) alloc_stacks (void ) {
144+ stacks res ;
145+ #if MICROPY_ENABLE_PYSTACK
137146 mp_int_t pystack_size = CIRCUITPY_PYSTACK_SIZE ;
138147 #if CIRCUITPY_OS_GETENV
139148 // Fetch value if exists from settings.toml
140149 // Leaves size to build default on any failure
141150 (void )common_hal_os_getenv_int ("CIRCUITPY_PYSTACK_SIZE" , & pystack_size );
142151 // Check if value is valid
143- if ((CIRCUITPY_PYSTACK_SIZE != pystack_size ) && ((pystack_size < 384 ) || (pystack_size % sizeof (size_t ) != 0 ))) {
152+ pystack_size = pystack_size - pystack_size % sizeof (size_t ); // Round down to multiple of 4.
153+ if ((CIRCUITPY_PYSTACK_SIZE != pystack_size ) && (pystack_size < 384 )) {
144154 serial_write_compressed (translate ("\nWARNING: Invalid CIRCUITPY_PYSTACK_SIZE, defaulting back to build value.\n\n" ));
145155 pystack_size = CIRCUITPY_PYSTACK_SIZE ; // Reset
146156 }
147157 #endif
148- supervisor_allocation * pystack = allocate_memory (pystack_size , false, false);
149- if (pystack == NULL ) {
158+ res . pystack = allocate_memory (pystack_size , false, false);
159+ if (res . pystack == NULL ) {
150160 serial_write_compressed (translate ("\nWARNING: Allocating pystack failed, defaulting back to build value. \n\n" ));
151- pystack = allocate_memory (CIRCUITPY_PYSTACK_SIZE , false, false);
161+ res . pystack = allocate_memory (CIRCUITPY_PYSTACK_SIZE , false, false);
152162 }
153- return pystack ;
163+ #endif
164+ res .heap = allocate_remaining_memory ();
165+ return res ;
154166}
155167#endif
156168
157- STATIC void start_mp (supervisor_allocation * heap , supervisor_allocation * pystack ) {
169+ STATIC void start_mp (stacks combo ) {
158170 supervisor_workflow_reset ();
159171
160172 // Stack limit should be less than real stack size, so we have a chance
@@ -182,11 +194,11 @@ STATIC void start_mp(supervisor_allocation *heap, supervisor_allocation *pystack
182194 readline_init0 ();
183195
184196 #if MICROPY_ENABLE_PYSTACK
185- mp_pystack_init (pystack -> ptr , pystack -> ptr + ( get_allocation_length (pystack ) / sizeof (size_t ) ));
197+ mp_pystack_init (combo . pystack -> ptr , combo . pystack -> ptr + get_allocation_length (combo . pystack ) / sizeof (size_t ));
186198 #endif
187199
188200 #if MICROPY_ENABLE_GC
189- gc_init (heap -> ptr , heap -> ptr + get_allocation_length (heap ) / 4 );
201+ gc_init (combo . heap -> ptr , combo . heap -> ptr + get_allocation_length (combo . heap ) / 4 );
190202 #endif
191203 mp_init ();
192204 mp_obj_list_init ((mp_obj_list_t * )mp_sys_path , 0 );
@@ -286,7 +298,7 @@ STATIC void count_strn(void *data, const char *str, size_t len) {
286298 * (size_t * )data += len ;
287299}
288300
289- STATIC void cleanup_after_vm (supervisor_allocation * heap , supervisor_allocation * pystack , mp_obj_t exception ) {
301+ STATIC void cleanup_after_vm (stacks combo , mp_obj_t exception ) {
290302 // Get the traceback of any exception from this run off the heap.
291303 // MP_OBJ_SENTINEL means "this run does not contribute to traceback storage, don't touch it"
292304 // MP_OBJ_NULL (=0) means "this run completed successfully, clear any stored traceback"
@@ -366,8 +378,8 @@ STATIC void cleanup_after_vm(supervisor_allocation *heap, supervisor_allocation
366378 // Free the heap last because other modules may reference heap memory and need to shut down.
367379 filesystem_flush ();
368380 stop_mp ();
369- free_memory (heap );
370- free_memory (pystack );
381+ free_memory (combo . heap );
382+ free_memory (combo . pystack );
371383 supervisor_move_memory ();
372384
373385 // Let the workflows know we've reset in case they want to restart.
@@ -422,11 +434,8 @@ STATIC bool run_code_py(safe_mode_t safe_mode, bool *simulate_reset) {
422434 };
423435 #endif
424436
425- #if MICROPY_ENABLE_PYSTACK
426- supervisor_allocation * pystack = alloc_pystack ();
427- #endif
428- supervisor_allocation * heap = allocate_remaining_memory ();
429- start_mp (heap , pystack );
437+ stacks combo = alloc_stacks ();
438+ start_mp (combo );
430439
431440 #if CIRCUITPY_USB
432441 usb_setup_with_vm ();
@@ -474,7 +483,7 @@ STATIC bool run_code_py(safe_mode_t safe_mode, bool *simulate_reset) {
474483
475484
476485 // Finished executing python code. Cleanup includes filesystem flush and a board reset.
477- cleanup_after_vm (heap , pystack , _exec_result .exception );
486+ cleanup_after_vm (combo , _exec_result .exception );
478487 _exec_result .exception = NULL ;
479488
480489 // If a new next code file was set, that is a reason to keep it (obviously). Stuff this into
@@ -770,11 +779,8 @@ STATIC void __attribute__ ((noinline)) run_boot_py(safe_mode_t safe_mode) {
770779
771780 // Do USB setup even if boot.py is not run.
772781
773- #if MICROPY_ENABLE_PYSTACK
774- supervisor_allocation * pystack = alloc_pystack ();
775- #endif
776- supervisor_allocation * heap = allocate_remaining_memory ();
777- start_mp (heap , pystack );
782+ stacks combo = alloc_stacks ();
783+ start_mp (combo );
778784
779785 #if CIRCUITPY_USB
780786 // Set up default USB values after boot.py VM starts but before running boot.py.
@@ -860,7 +866,7 @@ STATIC void __attribute__ ((noinline)) run_boot_py(safe_mode_t safe_mode) {
860866
861867 port_post_boot_py (true);
862868
863- cleanup_after_vm (heap , pystack , _exec_result .exception );
869+ cleanup_after_vm (combo , _exec_result .exception );
864870 _exec_result .exception = NULL ;
865871
866872 port_post_boot_py (false);
@@ -875,11 +881,8 @@ STATIC int run_repl(void) {
875881 int exit_code = PYEXEC_FORCED_EXIT ;
876882 stack_resize ();
877883 filesystem_flush ();
878- #if MICROPY_ENABLE_PYSTACK
879- supervisor_allocation * pystack = alloc_pystack ();
880- #endif
881- supervisor_allocation * heap = allocate_remaining_memory ();
882- start_mp (heap , pystack );
884+ stacks combo = alloc_stacks ();
885+ start_mp (combo );
883886
884887 #if CIRCUITPY_USB
885888 usb_setup_with_vm ();
@@ -922,7 +925,7 @@ STATIC int run_repl(void) {
922925 exit_code = PYEXEC_DEEP_SLEEP ;
923926 }
924927 #endif
925- cleanup_after_vm (heap , pystack , MP_OBJ_SENTINEL );
928+ cleanup_after_vm (combo , MP_OBJ_SENTINEL );
926929
927930 // Also reset bleio. The above call omits it in case workflows should continue. In this case,
928931 // we're switching straight to another VM so we want to reset.
0 commit comments