diff --git a/locale/circuitpython.pot b/locale/circuitpython.pot index abadd83b6a..a0bc751ccb 100644 --- a/locale/circuitpython.pot +++ b/locale/circuitpython.pot @@ -28,6 +28,14 @@ msgid "" "Code stopped by auto-reload. Reloading soon.\n" msgstr "" +#: main.c +msgid "" +"\n" +"Invalid CIRCUITPY_PYSTACK_SIZE\n" +"\n" +"\r" +msgstr "" + #: supervisor/shared/safe_mode.c msgid "" "\n" @@ -2391,6 +2399,10 @@ msgstr "" msgid "You pressed the GPIO0 button at start up." msgstr "" +#: ports/espressif/boards/espressif_esp32_lyrat/mpconfigboard.h +msgid "You pressed the Rec button at start up." +msgstr "" + #: ports/espressif/boards/adafruit_feather_esp32_v2/mpconfigboard.h msgid "You pressed the SW38 button at start up." msgstr "" diff --git a/main.c b/main.c index ee08726425..18f145c334 100644 --- a/main.c +++ b/main.c @@ -122,8 +122,8 @@ uint8_t value_out = 0; #endif -#if MICROPY_ENABLE_PYSTACK -static size_t PLACE_IN_DTCM_BSS(_pystack[CIRCUITPY_PYSTACK_SIZE / sizeof(size_t)]); +#if MICROPY_ENABLE_PYSTACK && CIRCUITPY_OS_GETENV +#include "shared-module/os/__init__.h" #endif static void reset_devices(void) { @@ -132,7 +132,32 @@ static void reset_devices(void) { #endif } -STATIC void start_mp(supervisor_allocation *heap) { +#if MICROPY_ENABLE_PYSTACK +STATIC supervisor_allocation *allocate_pystack(safe_mode_t safe_mode) { + mp_int_t pystack_size = CIRCUITPY_PYSTACK_SIZE; + #if CIRCUITPY_OS_GETENV && CIRCUITPY_SETTABLE_PYSTACK + // Fetch value if exists from settings.toml + // Leaves size to build default on any failure + if (safe_mode == SAFE_MODE_NONE || safe_mode == SAFE_MODE_USER) { + (void)common_hal_os_getenv_int("CIRCUITPY_PYSTACK_SIZE", &pystack_size); + // Check if value is valid + pystack_size = pystack_size - pystack_size % sizeof(size_t); // Round down to multiple of 4. + if ((pystack_size < 384) || (pystack_size > 900000)) { + serial_write_compressed(translate("\nInvalid CIRCUITPY_PYSTACK_SIZE\n\n\r")); + pystack_size = CIRCUITPY_PYSTACK_SIZE; // Reset + } + } + #endif + supervisor_allocation *pystack = allocate_memory(pystack_size, false, false); + if (pystack == NULL) { + serial_write_compressed(translate("\nInvalid CIRCUITPY_PYSTACK_SIZE\n\n\r")); + pystack = allocate_memory(CIRCUITPY_PYSTACK_SIZE, false, false); + } + return pystack; +} +#endif + +STATIC void start_mp(supervisor_allocation *heap, supervisor_allocation *pystack) { supervisor_workflow_reset(); // 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) { readline_init0(); #if MICROPY_ENABLE_PYSTACK - mp_pystack_init(_pystack, _pystack + (sizeof(_pystack) / sizeof(size_t))); + mp_pystack_init(pystack->ptr, pystack->ptr + get_allocation_length(pystack) / sizeof(size_t)); #endif #if MICROPY_ENABLE_GC @@ -264,7 +289,7 @@ STATIC void count_strn(void *data, const char *str, size_t len) { *(size_t *)data += len; } -STATIC void cleanup_after_vm(supervisor_allocation *heap, mp_obj_t exception) { +STATIC void cleanup_after_vm(supervisor_allocation *heap, supervisor_allocation *pystack, mp_obj_t exception) { // Get the traceback of any exception from this run off the heap. // MP_OBJ_SENTINEL means "this run does not contribute to traceback storage, don't touch it" // 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) { filesystem_flush(); stop_mp(); free_memory(heap); + #if MICROPY_ENABLE_PYSTACK + free_memory(pystack); + #endif supervisor_move_memory(); // 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) { }; #endif + supervisor_allocation *pystack = NULL; + #if MICROPY_ENABLE_PYSTACK + pystack = allocate_pystack(safe_mode); + #endif supervisor_allocation *heap = allocate_remaining_memory(); - - // Prepare the VM state. - start_mp(heap); + start_mp(heap, pystack); #if CIRCUITPY_USB usb_setup_with_vm(); @@ -450,7 +480,7 @@ STATIC bool run_code_py(safe_mode_t safe_mode, bool *simulate_reset) { // Finished executing python code. Cleanup includes filesystem flush and a board reset. - cleanup_after_vm(heap, _exec_result.exception); + cleanup_after_vm(heap, pystack, _exec_result.exception); _exec_result.exception = NULL; // 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) { return; } + supervisor_allocation *pystack = NULL; + #if MICROPY_ENABLE_PYSTACK + pystack = allocate_pystack(safe_mode); + #endif supervisor_allocation *heap = allocate_remaining_memory(); - start_mp(heap); + start_mp(heap, pystack); static const char *const safemode_py_filenames[] = {"safemode.py", "safemode.txt"}; 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) { set_safe_mode(SAFE_MODE_SAFEMODE_PY_ERROR); } - cleanup_after_vm(heap, _exec_result.exception); + cleanup_after_vm(heap, pystack, _exec_result.exception); _exec_result.exception = NULL; } #endif @@ -772,9 +806,12 @@ STATIC void __attribute__ ((noinline)) run_boot_py(safe_mode_t safe_mode) { // Do USB setup even if boot.py is not run. + supervisor_allocation *pystack = NULL; + #if MICROPY_ENABLE_PYSTACK + pystack = allocate_pystack(safe_mode); + #endif supervisor_allocation *heap = allocate_remaining_memory(); - - start_mp(heap); + start_mp(heap, pystack); #if CIRCUITPY_USB // 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) { port_post_boot_py(true); - cleanup_after_vm(heap, _exec_result.exception); + cleanup_after_vm(heap, pystack, _exec_result.exception); _exec_result.exception = NULL; port_post_boot_py(false); @@ -871,12 +908,16 @@ STATIC void __attribute__ ((noinline)) run_boot_py(safe_mode_t safe_mode) { #endif } -STATIC int run_repl(void) { +STATIC int run_repl(safe_mode_t safe_mode) { int exit_code = PYEXEC_FORCED_EXIT; stack_resize(); filesystem_flush(); + supervisor_allocation *pystack = NULL; + #if MICROPY_ENABLE_PYSTACK + pystack = allocate_pystack(safe_mode); + #endif supervisor_allocation *heap = allocate_remaining_memory(); - start_mp(heap); + start_mp(heap, pystack); #if CIRCUITPY_USB usb_setup_with_vm(); @@ -919,7 +960,7 @@ STATIC int run_repl(void) { exit_code = PYEXEC_DEEP_SLEEP; } #endif - cleanup_after_vm(heap, MP_OBJ_SENTINEL); + cleanup_after_vm(heap, pystack, MP_OBJ_SENTINEL); // Also reset bleio. The above call omits it in case workflows should continue. In this case, // we're switching straight to another VM so we want to reset. @@ -938,6 +979,7 @@ STATIC int run_repl(void) { } int __attribute__((used)) main(void) { + // initialise the cpu and peripherals set_safe_mode(port_init()); @@ -1038,7 +1080,7 @@ int __attribute__((used)) main(void) { bool simulate_reset = true; for (;;) { if (!skip_repl) { - exit_code = run_repl(); + exit_code = run_repl(get_safe_mode()); supervisor_set_run_reason(RUN_REASON_REPL_RELOAD); } if (exit_code == PYEXEC_FORCED_EXIT) { diff --git a/ports/atmel-samd/boards/kicksat-sprite/mpconfigboard.mk b/ports/atmel-samd/boards/kicksat-sprite/mpconfigboard.mk index 9bc50ab429..9ca9259747 100644 --- a/ports/atmel-samd/boards/kicksat-sprite/mpconfigboard.mk +++ b/ports/atmel-samd/boards/kicksat-sprite/mpconfigboard.mk @@ -20,11 +20,13 @@ CIRCUITPY_BLEIO_HCI = 0 CIRCUITPY_DISPLAYIO = 0 CIRCUITPY_FLOPPYIO = 0 CIRCUITPY_FRAMEBUFFERIO = 0 +CIRCUITPY_PIXELMAP = 0 CIRCUITPY_GETPASS = 0 CIRCUITPY_KEYPAD = 0 CIRCUITPY_MSGPACK = 0 CIRCUITPY_PS2IO = 0 CIRCUITPY_RGBMATRIX = 0 +CIRCUITPY_RAINBOWIO = 0 CIRCUITPY_ROTARYIO = 0 CIRCUITPY_TOUCHIO = 0 CIRCUITPY_USB_HID = 0 diff --git a/ports/espressif/boards/espressif_esp32_lyrat/board.c b/ports/espressif/boards/espressif_esp32_lyrat/board.c new file mode 100644 index 0000000000..8c0c8b8b0b --- /dev/null +++ b/ports/espressif/boards/espressif_esp32_lyrat/board.c @@ -0,0 +1,34 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2023 Radio Sound, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "supervisor/board.h" +#include "mpconfigboard.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "components/driver/include/driver/gpio.h" +#include "components/hal/include/hal/gpio_hal.h" +#include "common-hal/microcontroller/Pin.h" + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/espressif/boards/espressif_esp32_lyrat/mpconfigboard.h b/ports/espressif/boards/espressif_esp32_lyrat/mpconfigboard.h new file mode 100644 index 0000000000..7835e93f21 --- /dev/null +++ b/ports/espressif/boards/espressif_esp32_lyrat/mpconfigboard.h @@ -0,0 +1,50 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2023 Radio Sound, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +// Micropython setup + +#define MICROPY_HW_BOARD_NAME "Espressif ESP32-LyraT" +#define MICROPY_HW_MCU_NAME "ESP32" + +#define MICROPY_HW_LED_STATUS (&pin_GPIO22) + +#define CIRCUITPY_BOARD_I2C (1) +#define CIRCUITPY_BOARD_I2C_PIN {{.scl = &pin_GPIO23, .sda = &pin_GPIO18}} + +#define CIRCUITPY_BOARD_SPI (1) +#define CIRCUITPY_BOARD_SPI_PIN {{.clock = &pin_GPIO14, .mosi = &pin_GPIO13, .miso = &pin_GPIO12}} + +#define CIRCUITPY_BOARD_UART (0) + +// For entering safe mode, use Rec button +#define CIRCUITPY_BOOT_BUTTON (&pin_GPIO36) + +// Explanation of how a user got into safe mode +#define BOARD_USER_SAFE_MODE_ACTION translate("You pressed the Rec button at start up.") + +// UART pins attached to the USB-serial converter chip +#define CIRCUITPY_CONSOLE_UART_TX (&pin_GPIO1) +#define CIRCUITPY_CONSOLE_UART_RX (&pin_GPIO3) diff --git a/ports/espressif/boards/espressif_esp32_lyrat/mpconfigboard.mk b/ports/espressif/boards/espressif_esp32_lyrat/mpconfigboard.mk new file mode 100644 index 0000000000..e9fcd24e61 --- /dev/null +++ b/ports/espressif/boards/espressif_esp32_lyrat/mpconfigboard.mk @@ -0,0 +1,10 @@ +CIRCUITPY_CREATOR_ID = 0x000C303A +CIRCUITPY_CREATION_ID = 0x0032A000 + +IDF_TARGET = esp32 + +CIRCUITPY_ESP_FLASH_MODE = dio +CIRCUITPY_ESP_FLASH_FREQ = 40m +CIRCUITPY_ESP_FLASH_SIZE = 4MB + +CIRCUITPY_ESPCAMERA = 0 diff --git a/ports/espressif/boards/espressif_esp32_lyrat/pins.c b/ports/espressif/boards/espressif_esp32_lyrat/pins.c new file mode 100644 index 0000000000..afef90e480 --- /dev/null +++ b/ports/espressif/boards/espressif_esp32_lyrat/pins.c @@ -0,0 +1,56 @@ +#include "shared-bindings/board/__init__.h" + +STATIC const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + // External pins are in silkscreen order, from top to bottom, left side, then right side + { MP_ROM_QSTR(MP_QSTR_CS0), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_D15), MP_ROM_PTR(&pin_GPIO15) }, + + { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_D13), MP_ROM_PTR(&pin_GPIO13) }, + + { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_D12), MP_ROM_PTR(&pin_GPIO12) }, + + { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_D14), MP_ROM_PTR(&pin_GPIO14) }, + + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_GPIO1) }, + + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_D3), MP_ROM_PTR(&pin_GPIO3) }, + + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO23) }, + { MP_ROM_QSTR(MP_QSTR_D23), MP_ROM_PTR(&pin_GPIO23) }, + + { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_D18), MP_ROM_PTR(&pin_GPIO18) }, + + { MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_GPIO0) }, + + { MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_GPIO5) }, + + { MP_ROM_QSTR(MP_QSTR_D25), MP_ROM_PTR(&pin_GPIO25) }, + + { MP_ROM_QSTR(MP_QSTR_D26), MP_ROM_PTR(&pin_GPIO26) }, + + { MP_ROM_QSTR(MP_QSTR_D35), MP_ROM_PTR(&pin_GPIO35) }, + + { MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pin_GPIO22) }, + { MP_ROM_QSTR(MP_QSTR_L), MP_ROM_PTR(&pin_GPIO22) }, + { MP_ROM_QSTR(MP_QSTR_D22), MP_ROM_PTR(&pin_GPIO22) }, + + { MP_ROM_QSTR(MP_QSTR_BUTTON), MP_ROM_PTR(&pin_GPIO36) }, + { MP_ROM_QSTR(MP_QSTR_REC), MP_ROM_PTR(&pin_GPIO36) }, + { MP_ROM_QSTR(MP_QSTR_SW36), MP_ROM_PTR(&pin_GPIO36) }, + + { MP_ROM_QSTR(MP_QSTR_BUTTON), MP_ROM_PTR(&pin_GPIO39) }, + { MP_ROM_QSTR(MP_QSTR_MODE), MP_ROM_PTR(&pin_GPIO39) }, + { MP_ROM_QSTR(MP_QSTR_SW39), MP_ROM_PTR(&pin_GPIO39) }, + + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) } +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/espressif/boards/espressif_esp32_lyrat/sdkconfig b/ports/espressif/boards/espressif_esp32_lyrat/sdkconfig new file mode 100644 index 0000000000..4b2981ba62 --- /dev/null +++ b/ports/espressif/boards/espressif_esp32_lyrat/sdkconfig @@ -0,0 +1,37 @@ +CONFIG_ESP32_SPIRAM_SUPPORT=y +# SPI RAM config +# +CONFIG_SPIRAM_TYPE_AUTO=y +# CONFIG_SPIRAM_TYPE_ESPPSRAM16 is not set +# CONFIG_SPIRAM_TYPE_ESPPSRAM32 is not set +# CONFIG_SPIRAM_TYPE_ESPPSRAM64 is not set +CONFIG_SPIRAM_SIZE=4194304 +CONFIG_SPIRAM_SPEED_40M=y +CONFIG_SPIRAM=y +CONFIG_SPIRAM_BOOT_INIT=y +CONFIG_SPIRAM_IGNORE_NOTFOUND=y +CONFIG_SPIRAM_USE_MEMMAP=y +# CONFIG_SPIRAM_USE_CAPS_ALLOC is not set +# CONFIG_SPIRAM_USE_MALLOC is not set +CONFIG_SPIRAM_MEMTEST=y +# CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY is not set +# CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY is not set +CONFIG_SPIRAM_CACHE_WORKAROUND=y + +# Uncomment (remove ###) to send ESP_LOG output to TX/RX pins +### # +### # ESP System Settings +### # +### CONFIG_ESP_SYSTEM_PANIC_PRINT_HALT=y +### # CONFIG_ESP_SYSTEM_PANIC_SILENT_REBOOT is not set +### CONFIG_ESP_CONSOLE_UART_CUSTOM=y +### # CONFIG_ESP_CONSOLE_NONE is not set +### CONFIG_ESP_CONSOLE_UART=y +### CONFIG_ESP_CONSOLE_UART_CUSTOM_NUM_0=y +### # CONFIG_ESP_CONSOLE_UART_CUSTOM_NUM_1 is not set +### CONFIG_ESP_CONSOLE_UART_NUM=0 +### CONFIG_ESP_CONSOLE_UART_TX_GPIO=8 +### CONFIG_ESP_CONSOLE_UART_RX_GPIO=7 +### CONFIG_ESP_CONSOLE_UART_BAUDRATE=115200 +### # CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL_5 is not set +### # end of ESP System Settings diff --git a/py/circuitpy_mpconfig.h b/py/circuitpy_mpconfig.h index 8bfb69297a..95a95fa12f 100644 --- a/py/circuitpy_mpconfig.h +++ b/py/circuitpy_mpconfig.h @@ -145,6 +145,7 @@ extern void common_hal_mcu_enable_interrupts(void); #define MICROPY_REPL_AUTO_INDENT (1) #define MICROPY_REPL_EVENT_DRIVEN (0) #define MICROPY_ENABLE_PYSTACK (1) +#define CIRCUITPY_SETTABLE_PYSTACK (1) #define MICROPY_STACK_CHECK (1) #define MICROPY_STREAMS_NON_BLOCK (1) #ifndef MICROPY_USE_INTERNAL_PRINTF