122
122
uint8_t value_out = 0 ;
123
123
#endif
124
124
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"
127
127
#endif
128
128
129
129
static void reset_devices (void ) {
@@ -132,7 +132,32 @@ static void reset_devices(void) {
132
132
#endif
133
133
}
134
134
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 ) {
136
161
supervisor_workflow_reset ();
137
162
138
163
// 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) {
160
185
readline_init0 ();
161
186
162
187
#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 ));
164
189
#endif
165
190
166
191
#if MICROPY_ENABLE_GC
@@ -264,7 +289,7 @@ STATIC void count_strn(void *data, const char *str, size_t len) {
264
289
* (size_t * )data += len ;
265
290
}
266
291
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 ) {
268
293
// Get the traceback of any exception from this run off the heap.
269
294
// MP_OBJ_SENTINEL means "this run does not contribute to traceback storage, don't touch it"
270
295
// 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) {
345
370
filesystem_flush ();
346
371
stop_mp ();
347
372
free_memory (heap );
373
+ #if MICROPY_ENABLE_PYSTACK
374
+ free_memory (pystack );
375
+ #endif
348
376
supervisor_move_memory ();
349
377
350
378
// 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) {
399
427
};
400
428
#endif
401
429
430
+ supervisor_allocation * pystack = NULL ;
431
+ #if MICROPY_ENABLE_PYSTACK
432
+ pystack = allocate_pystack (safe_mode );
433
+ #endif
402
434
supervisor_allocation * heap = allocate_remaining_memory ();
403
-
404
- // Prepare the VM state.
405
- start_mp (heap );
435
+ start_mp (heap , pystack );
406
436
407
437
#if CIRCUITPY_USB
408
438
usb_setup_with_vm ();
@@ -450,7 +480,7 @@ STATIC bool run_code_py(safe_mode_t safe_mode, bool *simulate_reset) {
450
480
451
481
452
482
// 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 );
454
484
_exec_result .exception = NULL ;
455
485
456
486
// 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) {
739
769
return ;
740
770
}
741
771
772
+ supervisor_allocation * pystack = NULL ;
773
+ #if MICROPY_ENABLE_PYSTACK
774
+ pystack = allocate_pystack (safe_mode );
775
+ #endif
742
776
supervisor_allocation * heap = allocate_remaining_memory ();
743
- start_mp (heap );
777
+ start_mp (heap , pystack );
744
778
745
779
static const char * const safemode_py_filenames [] = {"safemode.py" , "safemode.txt" };
746
780
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) {
751
785
set_safe_mode (SAFE_MODE_SAFEMODE_PY_ERROR );
752
786
}
753
787
754
- cleanup_after_vm (heap , _exec_result .exception );
788
+ cleanup_after_vm (heap , pystack , _exec_result .exception );
755
789
_exec_result .exception = NULL ;
756
790
}
757
791
#endif
@@ -772,9 +806,12 @@ STATIC void __attribute__ ((noinline)) run_boot_py(safe_mode_t safe_mode) {
772
806
773
807
// Do USB setup even if boot.py is not run.
774
808
809
+ supervisor_allocation * pystack = NULL ;
810
+ #if MICROPY_ENABLE_PYSTACK
811
+ pystack = allocate_pystack (safe_mode );
812
+ #endif
775
813
supervisor_allocation * heap = allocate_remaining_memory ();
776
-
777
- start_mp (heap );
814
+ start_mp (heap , pystack );
778
815
779
816
#if CIRCUITPY_USB
780
817
// 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) {
860
897
861
898
port_post_boot_py (true);
862
899
863
- cleanup_after_vm (heap , _exec_result .exception );
900
+ cleanup_after_vm (heap , pystack , _exec_result .exception );
864
901
_exec_result .exception = NULL ;
865
902
866
903
port_post_boot_py (false);
@@ -871,12 +908,16 @@ STATIC void __attribute__ ((noinline)) run_boot_py(safe_mode_t safe_mode) {
871
908
#endif
872
909
}
873
910
874
- STATIC int run_repl (void ) {
911
+ STATIC int run_repl (safe_mode_t safe_mode ) {
875
912
int exit_code = PYEXEC_FORCED_EXIT ;
876
913
stack_resize ();
877
914
filesystem_flush ();
915
+ supervisor_allocation * pystack = NULL ;
916
+ #if MICROPY_ENABLE_PYSTACK
917
+ pystack = allocate_pystack (safe_mode );
918
+ #endif
878
919
supervisor_allocation * heap = allocate_remaining_memory ();
879
- start_mp (heap );
920
+ start_mp (heap , pystack );
880
921
881
922
#if CIRCUITPY_USB
882
923
usb_setup_with_vm ();
@@ -919,7 +960,7 @@ STATIC int run_repl(void) {
919
960
exit_code = PYEXEC_DEEP_SLEEP ;
920
961
}
921
962
#endif
922
- cleanup_after_vm (heap , MP_OBJ_SENTINEL );
963
+ cleanup_after_vm (heap , pystack , MP_OBJ_SENTINEL );
923
964
924
965
// Also reset bleio. The above call omits it in case workflows should continue. In this case,
925
966
// we're switching straight to another VM so we want to reset.
@@ -938,6 +979,7 @@ STATIC int run_repl(void) {
938
979
}
939
980
940
981
int __attribute__((used )) main (void ) {
982
+
941
983
// initialise the cpu and peripherals
942
984
set_safe_mode (port_init ());
943
985
@@ -1038,7 +1080,7 @@ int __attribute__((used)) main(void) {
1038
1080
bool simulate_reset = true;
1039
1081
for (;;) {
1040
1082
if (!skip_repl ) {
1041
- exit_code = run_repl ();
1083
+ exit_code = run_repl (get_safe_mode () );
1042
1084
supervisor_set_run_reason (RUN_REASON_REPL_RELOAD );
1043
1085
}
1044
1086
if (exit_code == PYEXEC_FORCED_EXIT ) {
0 commit comments