From f8ac1d9261c087d1f65886036289c2121c32cc0f Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Fri, 2 Dec 2022 14:54:42 -0800 Subject: [PATCH] Rework the coproc API It is now a generic `memorymap` API and an ESP specific `espulp` module. Fixes #7218. Fixes #3234. Fixes #7300. --- locale/circuitpython.pot | 42 +++-- ports/espressif/Makefile | 13 +- ports/espressif/bindings/espulp/ULP.c | 144 ++++++++++++++++++ .../espressif/bindings/espulp/ULP.h | 17 ++- .../espressif/bindings/espulp/ULPAlarm.c | 38 +++-- .../espressif/bindings/espulp/ULPAlarm.h | 9 +- ports/espressif/bindings/espulp/__init__.c | 91 +++++++++++ .../Coproc.h => bindings/espulp/__init__.h} | 15 +- ports/espressif/common-hal/alarm/__init__.c | 29 +++- ports/espressif/common-hal/alarm/__init__.h | 7 +- .../common-hal/alarm/coproc/CoprocAlarm.c | 132 ---------------- ports/espressif/common-hal/coproc/Coproc.c | 73 --------- .../{coproc/__init__.c => espulp/ULP.c} | 79 ++++++++-- .../{coproc/CoprocMemory.h => espulp/ULP.h} | 10 +- ports/espressif/common-hal/espulp/ULPAlarm.c | 110 +++++++++++++ .../CoprocAlarm.h => espulp/ULPAlarm.h} | 17 +-- ports/espressif/common-hal/espulp/__init__.c | 34 +++++ .../common-hal/memorymap/AddressRange.c | 107 +++++++++++++ .../common-hal/memorymap/AddressRange.h | 38 +++++ .../espressif/common-hal/memorymap/__init__.c | 1 + .../common-hal/microcontroller/Processor.c | 1 + ports/espressif/esp-idf | 2 +- ports/espressif/mpconfigport.mk | 7 +- ports/espressif/supervisor/port.c | 8 +- py/circuitpy_defns.mk | 14 +- py/circuitpy_mpconfig.mk | 8 +- shared-bindings/alarm/__init__.c | 24 +-- shared-bindings/alarm/coproc/CoprocAlarm.c | 87 ----------- shared-bindings/coproc/Coproc.c | 110 ------------- shared-bindings/coproc/CoprocMemory.h | 39 ----- shared-bindings/coproc/__init__.c | 115 -------------- .../AddressRange.c} | 115 ++++++++------ .../memorymap/AddressRange.h | 34 ++--- shared-bindings/memorymap/__init__.c | 52 +++++++ shared-bindings/memorymap/__init__.h | 30 ++++ supervisor/shared/reload.c | 2 + supervisor/shared/web_workflow/web_workflow.c | 9 ++ 37 files changed, 922 insertions(+), 741 deletions(-) create mode 100644 ports/espressif/bindings/espulp/ULP.c rename shared-bindings/coproc/__init__.h => ports/espressif/bindings/espulp/ULP.h (73%) rename shared-bindings/coproc/Coproc.h => ports/espressif/bindings/espulp/ULPAlarm.c (52%) rename shared-bindings/alarm/coproc/CoprocAlarm.h => ports/espressif/bindings/espulp/ULPAlarm.h (79%) create mode 100644 ports/espressif/bindings/espulp/__init__.c rename ports/espressif/{common-hal/coproc/Coproc.h => bindings/espulp/__init__.h} (75%) delete mode 100644 ports/espressif/common-hal/alarm/coproc/CoprocAlarm.c delete mode 100644 ports/espressif/common-hal/coproc/Coproc.c rename ports/espressif/common-hal/{coproc/__init__.c => espulp/ULP.c} (50%) rename ports/espressif/common-hal/{coproc/CoprocMemory.h => espulp/ULP.h} (82%) create mode 100644 ports/espressif/common-hal/espulp/ULPAlarm.c rename ports/espressif/common-hal/{alarm/coproc/CoprocAlarm.h => espulp/ULPAlarm.h} (71%) create mode 100644 ports/espressif/common-hal/espulp/__init__.c create mode 100644 ports/espressif/common-hal/memorymap/AddressRange.c create mode 100644 ports/espressif/common-hal/memorymap/AddressRange.h create mode 100644 ports/espressif/common-hal/memorymap/__init__.c delete mode 100644 shared-bindings/alarm/coproc/CoprocAlarm.c delete mode 100644 shared-bindings/coproc/Coproc.c delete mode 100644 shared-bindings/coproc/CoprocMemory.h delete mode 100644 shared-bindings/coproc/__init__.c rename shared-bindings/{coproc/CoprocMemory.c => memorymap/AddressRange.c} (59%) rename ports/espressif/common-hal/coproc/CoprocMemory.c => shared-bindings/memorymap/AddressRange.h (53%) create mode 100644 shared-bindings/memorymap/__init__.c create mode 100644 shared-bindings/memorymap/__init__.h diff --git a/locale/circuitpython.pot b/locale/circuitpython.pot index 56c2396d46..0cf1027239 100644 --- a/locale/circuitpython.pot +++ b/locale/circuitpython.pot @@ -100,6 +100,7 @@ msgstr "" msgid "%q failure: %d" msgstr "" +#: ports/espressif/common-hal/espulp/ULP.c #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c #: shared-bindings/digitalio/DigitalInOut.c #: shared-bindings/microcontroller/Pin.c @@ -180,7 +181,6 @@ msgstr "" #: ports/atmel-samd/common-hal/pulseio/PulseIn.c #: ports/cxd56/common-hal/pulseio/PulseIn.c -#: ports/espressif/common-hal/coproc/Coproc.c #: ports/nrf/common-hal/pulseio/PulseIn.c #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c #: ports/stm/common-hal/pulseio/PulseIn.c py/argcheck.c @@ -393,6 +393,10 @@ msgstr "" msgid "Address must be %d bytes long" msgstr "" +#: ports/espressif/common-hal/memorymap/AddressRange.c +msgid "Address range not allowed" +msgstr "" + #: ports/espressif/common-hal/canio/CAN.c msgid "All CAN peripherals are in use" msgstr "" @@ -473,7 +477,7 @@ msgstr "" msgid "Already have all-matches listener" msgstr "" -#: ports/espressif/common-hal/coproc/__init__.c +#: ports/espressif/common-hal/espulp/ULP.c #: shared-module/memorymonitor/AllocationAlarm.c #: shared-module/memorymonitor/AllocationSize.c msgid "Already running" @@ -497,7 +501,7 @@ msgstr "" msgid "Array must contain halfwords (type 'H')" msgstr "" -#: shared-bindings/alarm/SleepMemory.c shared-bindings/coproc/CoprocMemory.c +#: shared-bindings/alarm/SleepMemory.c shared-bindings/memorymap/AddressRange.c #: shared-bindings/nvm/ByteArray.c msgid "Array values should be single bytes." msgstr "" @@ -914,10 +918,10 @@ msgstr "" msgid "Error: Failure to bind" msgstr "" -#: py/enum.c shared-bindings/_bleio/__init__.c shared-bindings/aesio/aes.c -#: shared-bindings/alarm/__init__.c shared-bindings/alarm/coproc/CoprocAlarm.c -#: shared-bindings/busio/SPI.c shared-bindings/coproc/Coproc.c -#: shared-bindings/coproc/__init__.c shared-bindings/microcontroller/Pin.c +#: ports/espressif/bindings/espulp/ULP.c py/enum.c +#: shared-bindings/_bleio/__init__.c shared-bindings/aesio/aes.c +#: shared-bindings/alarm/__init__.c shared-bindings/busio/SPI.c +#: shared-bindings/microcontroller/Pin.c #: shared-bindings/neopixel_write/__init__.c msgid "Expected a %q" msgstr "" @@ -1020,7 +1024,6 @@ msgstr "" msgid "Firmware is invalid" msgstr "" -#: ports/espressif/common-hal/coproc/Coproc.c #: ports/espressif/common-hal/dualbank/__init__.c msgid "Firmware is too big" msgstr "" @@ -1628,11 +1631,14 @@ msgid "" "%d bpp given" msgstr "" -#: ports/espressif/common-hal/alarm/coproc/CoprocAlarm.c #: ports/espressif/common-hal/alarm/touch/TouchAlarm.c msgid "Only one %q can be set in deep sleep." msgstr "" +#: ports/espressif/common-hal/espulp/ULPAlarm.c +msgid "Only one %q can be set." +msgstr "" + #: ports/espressif/common-hal/i2ctarget/I2CTarget.c #: ports/raspberrypi/common-hal/i2ctarget/I2CTarget.c msgid "Only one address is allowed" @@ -1748,6 +1754,10 @@ msgid "" "constructor" msgstr "" +#: ports/espressif/common-hal/espulp/ULP.c +msgid "Pins 21+ not supported from ULP" +msgstr "" + #: ports/raspberrypi/common-hal/imagecapture/ParallelImageCapture.c msgid "Pins must be sequential" msgstr "" @@ -1792,6 +1802,10 @@ msgstr "" msgid "Program size invalid" msgstr "" +#: ports/espressif/common-hal/espulp/ULP.c +msgid "Program too long" +msgstr "" + #: shared-bindings/digitalio/DigitalInOut.c msgid "Pull not used when direction is output." msgstr "" @@ -1936,7 +1950,7 @@ msgstr "" msgid "Sleep Memory not available" msgstr "" -#: shared-bindings/alarm/SleepMemory.c shared-bindings/coproc/CoprocMemory.c +#: shared-bindings/alarm/SleepMemory.c shared-bindings/memorymap/AddressRange.c #: shared-bindings/nvm/ByteArray.c msgid "Slice and value different lengths." msgstr "" @@ -2210,8 +2224,8 @@ msgstr "" msgid "Unable to start mDNS query" msgstr "" -#: shared-bindings/coproc/CoprocMemory.c -msgid "Unable to write" +#: shared-bindings/memorymap/AddressRange.c +msgid "Unable to write to address." msgstr "" #: shared-bindings/nvm/ByteArray.c @@ -2467,7 +2481,7 @@ msgid "array has too many dimensions" msgstr "" #: py/objarray.c shared-bindings/alarm/SleepMemory.c -#: shared-bindings/coproc/CoprocMemory.c shared-bindings/nvm/ByteArray.c +#: shared-bindings/memorymap/AddressRange.c shared-bindings/nvm/ByteArray.c msgid "array/bytes required on right side" msgstr "" @@ -3725,7 +3739,7 @@ msgid "only sample_rate=16000 is supported" msgstr "" #: py/objarray.c py/objstr.c py/objstrunicode.c py/objtuple.c -#: shared-bindings/alarm/SleepMemory.c shared-bindings/coproc/CoprocMemory.c +#: shared-bindings/alarm/SleepMemory.c shared-bindings/memorymap/AddressRange.c #: shared-bindings/nvm/ByteArray.c msgid "only slices with step=1 (aka None) are supported" msgstr "" diff --git a/ports/espressif/Makefile b/ports/espressif/Makefile index 4e72e5c45a..ddfcaeeb6e 100644 --- a/ports/espressif/Makefile +++ b/ports/espressif/Makefile @@ -100,8 +100,6 @@ INC += \ -isystem esp-idf/components/soc/include \ -isystem esp-idf/components/soc/$(IDF_TARGET)/include \ -isystem esp-idf/components/spi_flash/include \ - -isystem esp-idf/components/ulp/include \ - -isystem esp-idf/components/ulp/ulp_riscv/include \ -isystem esp-idf/components/$(IDF_TARGET_ARCH)/include \ -isystem esp-idf/components/$(IDF_TARGET_ARCH)/$(IDF_TARGET)/include @@ -261,6 +259,15 @@ CFLAGS += -isystem esp32-camera/driver/include CFLAGS += -isystem esp32-camera/conversions/include endif +ifneq ($(CIRCUITPY_ESPULP),0) +SRC_ULP := \ + $(wildcard common-hal/espulp/*.c) \ + $(wildcard bindings/espulp/*.c) +SRC_C += $(SRC_ULP) +CFLAGS += -isystem esp-idf/components/ulp/include +CFLAGS += -isystem esp-idf/components/ulp/ulp_riscv/include +endif + SRC_COMMON_HAL_EXPANDED = \ $(addprefix shared-bindings/, $(SRC_COMMON_HAL)) \ $(addprefix shared-bindings/, $(SRC_BINDINGS_ENUMS)) \ @@ -364,7 +371,7 @@ ifneq ($(CIRCUITPY_BLEIO),0) BINARY_BLOBS += esp-idf/components/esp_phy/lib/$(IDF_TARGET)/libbtbb.a \ esp-idf/components/bt/controller/lib_esp32c3_family/$(IDF_TARGET)/libbtdm_app.a endif -ifneq ($(CIRCUITPY_COPROC),0) +ifneq ($(CIRCUITPY_ESPULP),0) ESP_IDF_COMPONENTS_LINK += ulp endif diff --git a/ports/espressif/bindings/espulp/ULP.c b/ports/espressif/bindings/espulp/ULP.c new file mode 100644 index 0000000000..6cd719277b --- /dev/null +++ b/ports/espressif/bindings/espulp/ULP.c @@ -0,0 +1,144 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2022 microDev + * + * 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 "shared-bindings/microcontroller/Pin.h" +#include "shared-bindings/util.h" +#include "bindings/espulp/ULP.h" + +#include "py/runtime.h" + +//| class ULP: +//| def __init__(self): +//| """The ultra-low-power processor. +//| +//| Raises an exception if another ULP has been instantiated. This +//| ensures that is is only used by one piece of code at a time.""" +//| ... +STATIC mp_obj_t espulp_ulp_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { + espulp_ulp_obj_t *self = m_new_obj(espulp_ulp_obj_t); + self->base.type = &espulp_ulp_type; + common_hal_espulp_ulp_construct(self); + return MP_OBJ_FROM_PTR(self); +} + +STATIC espulp_ulp_obj_t *get_ulp_obj(mp_obj_t self_in) { + if (!mp_obj_is_type(self_in, &espulp_ulp_type)) { + mp_raise_TypeError_varg(translate("Expected a %q"), MP_QSTR_ULP); + } + espulp_ulp_obj_t *self = MP_OBJ_TO_PTR(self_in); + if (common_hal_espulp_ulp_deinited(self)) { + raise_deinited_error(); + } + return self; +} + +//| def deinit(self) -> None: +//| """Deinitialises the camera and releases all memory resources for reuse.""" +//| ... +STATIC mp_obj_t espulp_ulp_deinit(mp_obj_t self_in) { + espulp_ulp_obj_t *self = get_ulp_obj(self_in); + common_hal_espulp_ulp_deinit(self); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(espulp_ulp_deinit_obj, espulp_ulp_deinit); + +//| def __enter__(self) -> ULP: +//| """No-op used by Context Managers.""" +//| ... +// Provided by context manager helper. + +//| def __exit__(self) -> None: +//| """Automatically deinitializes the hardware when exiting a context. See +//| :ref:`lifetime-and-contextmanagers` for more info.""" +//| ... +STATIC mp_obj_t espulp_ulp_obj___exit__(size_t n_args, const mp_obj_t *args) { + (void)n_args; + return espulp_ulp_deinit(args[0]); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(espulp_ulp___exit___obj, 4, 4, espulp_ulp_obj___exit__); + +//| def run( +//| self, program: ReadableBuffer, *, pins: Sequence[microcontroller.Pin] = () +//| ) -> None: +//| """Loads the program into ULP memory and then runs the program. The given pins are +//| claimed and not reset until `halt()` is called. +//| +//| The program will continue to run even when the running Python is halted.""" +//| ... +STATIC mp_obj_t espulp_ulp_run(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_program, ARG_pins }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_program, MP_ARG_REQUIRED | MP_ARG_OBJ}, + { MP_QSTR_pins, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_empty_tuple} }, + }; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + espulp_ulp_obj_t *self = get_ulp_obj(pos_args[0]); + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(args[ARG_program].u_obj, &bufinfo, MP_BUFFER_READ); + + mp_obj_t pins_in = args[ARG_pins].u_obj; + const size_t num_pins = (size_t)MP_OBJ_SMALL_INT_VALUE(mp_obj_len(pins_in)); + uint32_t pin_mask = 0; + + for (mp_uint_t i = 0; i < num_pins; i++) { + mp_obj_t pin_obj = mp_obj_subscr(pins_in, MP_OBJ_NEW_SMALL_INT(i), MP_OBJ_SENTINEL); + validate_obj_is_free_pin(pin_obj); + pin_mask |= 1 << ((const mcu_pin_obj_t *)pin_obj)->number; + } + + common_hal_espulp_ulp_run(self, bufinfo.buf, bufinfo.len, pin_mask); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(espulp_ulp_run_obj, 2, espulp_ulp_run); + +//| def halt(self) -> None: +//| """Halts the running program and releases the pins given in `run()`.""" +//| ... +//| +STATIC mp_obj_t espulp_ulp_halt(mp_obj_t self_in) { + common_hal_espulp_ulp_halt(get_ulp_obj(self_in)); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(espulp_ulp_halt_obj, espulp_ulp_halt); + +STATIC const mp_rom_map_elem_t espulp_ulp_locals_table[] = { + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&espulp_ulp_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&mp_identity_obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&espulp_ulp___exit___obj) }, + { MP_ROM_QSTR(MP_QSTR_run), MP_ROM_PTR(&espulp_ulp_run_obj) }, + { MP_ROM_QSTR(MP_QSTR_halt), MP_ROM_PTR(&espulp_ulp_halt_obj) }, +}; +STATIC MP_DEFINE_CONST_DICT(espulp_ulp_locals_dict, espulp_ulp_locals_table); + +const mp_obj_type_t espulp_ulp_type = { + { &mp_type_type }, + .name = MP_QSTR_ULP, + .make_new = espulp_ulp_make_new, + .locals_dict = (mp_obj_t)&espulp_ulp_locals_dict, +}; diff --git a/shared-bindings/coproc/__init__.h b/ports/espressif/bindings/espulp/ULP.h similarity index 73% rename from shared-bindings/coproc/__init__.h rename to ports/espressif/bindings/espulp/ULP.h index 6f2b2a56ae..9f9c3ecf7f 100644 --- a/shared-bindings/coproc/__init__.h +++ b/ports/espressif/bindings/espulp/ULP.h @@ -24,14 +24,17 @@ * THE SOFTWARE. */ -#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_COPROC___INIT___H -#define MICROPY_INCLUDED_SHARED_BINDINGS_COPROC___INIT___H +#pragma once #include "py/obj.h" -#include "common-hal/coproc/Coproc.h" +#include "common-hal/espulp/ULP.h" -extern void common_hal_coproc_run(coproc_coproc_obj_t *self); -extern void common_hal_coproc_halt(coproc_coproc_obj_t *self); -extern mp_obj_t common_hal_coproc_memory(coproc_coproc_obj_t *self); -#endif // MICROPY_INCLUDED_SHARED_BINDINGS_COPROC___INIT___H +extern const mp_obj_type_t espulp_ulp_type; + +void common_hal_espulp_ulp_construct(espulp_ulp_obj_t *self); +bool common_hal_espulp_ulp_deinited(espulp_ulp_obj_t *self); +void common_hal_espulp_ulp_deinit(espulp_ulp_obj_t *self); + +void common_hal_espulp_ulp_run(espulp_ulp_obj_t *self, uint32_t *program, size_t length, uint32_t pin_mask); +void common_hal_espulp_ulp_halt(espulp_ulp_obj_t *self); diff --git a/shared-bindings/coproc/Coproc.h b/ports/espressif/bindings/espulp/ULPAlarm.c similarity index 52% rename from shared-bindings/coproc/Coproc.h rename to ports/espressif/bindings/espulp/ULPAlarm.c index fbf9bd9ae0..e77fe7f834 100644 --- a/shared-bindings/coproc/Coproc.h +++ b/ports/espressif/bindings/espulp/ULPAlarm.c @@ -1,5 +1,5 @@ /* - * This file is part of the Micro Python project, http://micropython.org/ + * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * @@ -24,17 +24,33 @@ * THE SOFTWARE. */ -#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_COPROC_COPROC_H -#define MICROPY_INCLUDED_SHARED_BINDINGS_COPROC_COPROC_H +#include "bindings/espulp/ULPAlarm.h" -#include "common-hal/coproc/Coproc.h" +#include "py/runtime.h" -extern const mp_obj_type_t coproc_coproc_type; +//| class ULPAlarm: +//| """Trigger an alarm when the ULP requests wake-up.""" +//| +//| def __init__(self) -> None: +//| """Create an alarm that will be triggered when the ULP requests wake-up. +//| +//| The alarm is not active until it is passed to an `alarm`-enabling function, such as +//| `alarm.light_sleep_until_alarms()` or `alarm.exit_and_deep_sleep_until_alarms()`. +//| +//| """ +//| ... +//| +STATIC mp_obj_t espulp_ulpalarm_make_new(const mp_obj_type_t *type, + size_t n_args, size_t n_kw, const mp_obj_t *all_args) { -extern void common_hal_coproc_coproc_construct(coproc_coproc_obj_t *self, - const uint8_t *buf, const size_t buf_len, coproc_memory_obj_t *coproc_memory); + espulp_ulpalarm_obj_t *self = m_new_obj(espulp_ulpalarm_obj_t); + self->base.type = &espulp_ulpalarm_type; + common_hal_espulp_ulpalarm_construct(self); + return MP_OBJ_FROM_PTR(self); +} -extern void common_hal_coproc_coproc_deinit(coproc_coproc_obj_t *self); -extern bool common_hal_coproc_coproc_deinited(coproc_coproc_obj_t *self); - -#endif // MICROPY_INCLUDED_SHARED_BINDINGS_COPROC_COPROC_H +const mp_obj_type_t espulp_ulpalarm_type = { + { &mp_type_type }, + .name = MP_QSTR_ULPAlarm, + .make_new = espulp_ulpalarm_make_new, +}; diff --git a/shared-bindings/alarm/coproc/CoprocAlarm.h b/ports/espressif/bindings/espulp/ULPAlarm.h similarity index 79% rename from shared-bindings/alarm/coproc/CoprocAlarm.h rename to ports/espressif/bindings/espulp/ULPAlarm.h index 8f3a85de56..75e96c0a45 100644 --- a/shared-bindings/alarm/coproc/CoprocAlarm.h +++ b/ports/espressif/bindings/espulp/ULPAlarm.h @@ -24,11 +24,10 @@ * THE SOFTWARE. */ -#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_ALARM_COPROC_COPROCALARM_H -#define MICROPY_INCLUDED_SHARED_BINDINGS_ALARM_COPROC_COPROCALARM_H +#pragma once -#include "common-hal/alarm/coproc/CoprocAlarm.h" +#include "common-hal/espulp/ULPAlarm.h" -extern const mp_obj_type_t alarm_coproc_coprocalarm_type; +extern const mp_obj_type_t espulp_ulpalarm_type; -#endif // MICROPY_INCLUDED_SHARED_BINDINGS_ALARM_COPROC_COPROCALARM_H +void common_hal_espulp_ulpalarm_construct(espulp_ulpalarm_obj_t *self); diff --git a/ports/espressif/bindings/espulp/__init__.c b/ports/espressif/bindings/espulp/__init__.c new file mode 100644 index 0000000000..06c62175fa --- /dev/null +++ b/ports/espressif/bindings/espulp/__init__.c @@ -0,0 +1,91 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2022 microDev + * + * 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 "shared-bindings/util.h" +#include "bindings/espulp/__init__.h" +#include "bindings/espulp/ULP.h" +#include "bindings/espulp/ULPAlarm.h" + +#include "py/runtime.h" + +//| """ESP Ultra Low Power Processor Module +//| +//| The `espulp` module adds ability to load and run +//| programs on the ESP32-Sx's ultra-low-power RISC-V processor. +//| +//| .. code-block:: python +//| +//| import espulp +//| import memorymap +//| +//| shared_mem = memorymap.AddressRange(start=0x50000000, length=1024) +//| ulp = espulp.ULP() +//| +//| with open("program.bin", "rb") as f: +//| program = f.read() +//| +//| ulp.run(program) +//| print(shared_mem[0]) +//| # ulp.halt() +//| """ +//| ... +//| + +//| def get_rtc_gpio_number(pin: microcontroller.Pin) -> Optional[int]: +//| """Return the RTC GPIO number of the given pin or None if not connected +//| to RTC GPIO.""" +//| ... +//| + +STATIC mp_obj_t espulp_get_rtc_gpio_number(mp_obj_t pin_obj) { + const mcu_pin_obj_t *pin = validate_obj_is_pin(pin_obj); + mp_int_t number = common_hal_espulp_get_rtc_gpio_number(pin); + if (number < 0) { + return mp_const_none; + } + return MP_OBJ_NEW_SMALL_INT(number); +} +MP_DEFINE_CONST_FUN_OBJ_1(espulp_get_rtc_gpio_number_obj, espulp_get_rtc_gpio_number); + +STATIC const mp_rom_map_elem_t espulp_module_globals_table[] = { + // module name + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_espulp) }, + + // module functions + { MP_ROM_QSTR(MP_QSTR_get_rtc_gpio_number), MP_OBJ_FROM_PTR(&espulp_get_rtc_gpio_number_obj) }, + + // module classes + { MP_ROM_QSTR(MP_QSTR_ULP), MP_OBJ_FROM_PTR(&espulp_ulp_type) }, + { MP_ROM_QSTR(MP_QSTR_ULPAlarm), MP_OBJ_FROM_PTR(&espulp_ulpalarm_type) }, +}; +STATIC MP_DEFINE_CONST_DICT(espulp_module_globals, espulp_module_globals_table); + +const mp_obj_module_t espulp_module = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t *)&espulp_module_globals, +}; + +MP_REGISTER_MODULE(MP_QSTR_espulp, espulp_module, CIRCUITPY_ESPULP); diff --git a/ports/espressif/common-hal/coproc/Coproc.h b/ports/espressif/bindings/espulp/__init__.h similarity index 75% rename from ports/espressif/common-hal/coproc/Coproc.h rename to ports/espressif/bindings/espulp/__init__.h index 19082871cc..70daf53183 100644 --- a/ports/espressif/common-hal/coproc/Coproc.h +++ b/ports/espressif/bindings/espulp/__init__.h @@ -24,17 +24,10 @@ * THE SOFTWARE. */ -#ifndef MICROPY_INCLUDED_ESPRESSIF_COMMON_HAL_COPROC_COPROC_H -#define MICROPY_INCLUDED_ESPRESSIF_COMMON_HAL_COPROC_COPROC_H +#pragma once -#include "py/obj.h" -#include "common-hal/coproc/CoprocMemory.h" +#include "shared-bindings/microcontroller/Pin.h" -typedef struct { - mp_obj_base_t base; - uint8_t *buf; - size_t buf_len; - coproc_memory_obj_t *coproc_memory; -} coproc_coproc_obj_t; +void espulp_reset(void); -#endif // MICROPY_INCLUDED_ESPRESSIF_COMMON_HAL_COPROC_COPROC_H +mp_int_t common_hal_espulp_get_rtc_gpio_number(const mcu_pin_obj_t *pin); diff --git a/ports/espressif/common-hal/alarm/__init__.c b/ports/espressif/common-hal/alarm/__init__.c index 02ce3e1082..574fab0151 100644 --- a/ports/espressif/common-hal/alarm/__init__.c +++ b/ports/espressif/common-hal/alarm/__init__.c @@ -35,11 +35,14 @@ #include "shared-bindings/alarm/pin/PinAlarm.h" #include "shared-bindings/alarm/time/TimeAlarm.h" #include "shared-bindings/alarm/touch/TouchAlarm.h" -#include "shared-bindings/alarm/coproc/CoprocAlarm.h" #include "shared-bindings/wifi/__init__.h" #include "shared-bindings/microcontroller/__init__.h" +#if CIRCUITPY_ESPULP +#include "bindings/espulp/ULPAlarm.h" +#endif + #include "common-hal/digitalio/DigitalInOut.h" #include "supervisor/port.h" @@ -67,7 +70,9 @@ void alarm_reset(void) { alarm_pin_pinalarm_reset(); alarm_time_timealarm_reset(); alarm_touch_touchalarm_reset(); - alarm_coproc_coprocalarm_reset(); + #if CIRCUITPY_ESPULP + espulp_ulpalarm_reset(); + #endif esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_ALL); } @@ -82,9 +87,11 @@ STATIC esp_sleep_wakeup_cause_t _get_wakeup_cause(void) { if (alarm_touch_touchalarm_woke_this_cycle()) { return ESP_SLEEP_WAKEUP_TOUCHPAD; } - if (alarm_coproc_coprocalarm_woke_this_cycle()) { + #if CIRCUITPY_ESPULP + if (espulp_ulpalarm_woke_this_cycle()) { return ESP_SLEEP_WAKEUP_ULP; } + #endif // If waking from true deep sleep, modules will have lost their state, // so check the deep wakeup cause manually return esp_sleep_get_wakeup_cause(); @@ -113,9 +120,11 @@ mp_obj_t common_hal_alarm_record_wake_alarm(void) { return alarm_touch_touchalarm_record_wake_alarm(); } + #if CIRCUITPY_ESPULP case ESP_SLEEP_WAKEUP_ULP: { - return alarm_coproc_coprocalarm_record_wake_alarm(); + return espulp_ulpalarm_record_wake_alarm(); } + #endif case ESP_SLEEP_WAKEUP_UNDEFINED: default: @@ -130,7 +139,9 @@ STATIC void _setup_sleep_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t alarm_pin_pinalarm_set_alarms(deep_sleep, n_alarms, alarms); alarm_time_timealarm_set_alarms(deep_sleep, n_alarms, alarms); alarm_touch_touchalarm_set_alarm(deep_sleep, n_alarms, alarms); - alarm_coproc_coprocalarm_set_alarm(deep_sleep, n_alarms, alarms); + #if CIRCUITPY_ESPULP + espulp_ulpalarm_set_alarm(deep_sleep, n_alarms, alarms); + #endif } mp_obj_t common_hal_alarm_light_sleep_until_alarms(size_t n_alarms, const mp_obj_t *alarms) { @@ -157,10 +168,12 @@ mp_obj_t common_hal_alarm_light_sleep_until_alarms(size_t n_alarms, const mp_obj wake_alarm = alarm_touch_touchalarm_find_triggered_alarm(n_alarms,alarms); break; } + #if CIRCUITPY_ESPULP case ESP_SLEEP_WAKEUP_ULP: { - wake_alarm = alarm_coproc_coprocalarm_find_triggered_alarm(n_alarms,alarms); + wake_alarm = espulp_ulpalarm_find_triggered_alarm(n_alarms,alarms); break; } + #endif default: // Should not reach this, if all light sleep types are covered correctly break; @@ -187,7 +200,9 @@ void common_hal_alarm_set_deep_sleep_alarms(size_t n_alarms, const mp_obj_t *ala void NORETURN common_hal_alarm_enter_deep_sleep(void) { alarm_pin_pinalarm_prepare_for_deep_sleep(); alarm_touch_touchalarm_prepare_for_deep_sleep(); - alarm_coproc_coprocalarm_prepare_for_deep_sleep(); + #if CIRCUITPY_ESPULP + espulp_ulpalarm_prepare_for_deep_sleep(); + #endif // We no longer need to remember the pin preservations, since any pin resets are all done. clear_pin_preservations(); diff --git a/ports/espressif/common-hal/alarm/__init__.h b/ports/espressif/common-hal/alarm/__init__.h index 9f762f9c00..e0086ee61a 100644 --- a/ports/espressif/common-hal/alarm/__init__.h +++ b/ports/espressif/common-hal/alarm/__init__.h @@ -27,13 +27,16 @@ #pragma once #include "common-hal/alarm/SleepMemory.h" -#include "common-hal/alarm/coproc/CoprocAlarm.h" #include "common-hal/alarm/pin/PinAlarm.h" #include "common-hal/alarm/time/TimeAlarm.h" #include "common-hal/alarm/touch/TouchAlarm.h" +#if CIRCUITPY_ESPULP +#include "common-hal/espulp/ULPAlarm.h" +#endif + typedef union { - alarm_coproc_coprocalarm_obj_t coproc_alarm; + espulp_ulpalarm_obj_t ulp_alarm; alarm_pin_pinalarm_obj_t pin_alarm; alarm_time_timealarm_obj_t time_alarm; alarm_touch_touchalarm_obj_t touch_alarm; diff --git a/ports/espressif/common-hal/alarm/coproc/CoprocAlarm.c b/ports/espressif/common-hal/alarm/coproc/CoprocAlarm.c deleted file mode 100644 index 9ee187d27c..0000000000 --- a/ports/espressif/common-hal/alarm/coproc/CoprocAlarm.c +++ /dev/null @@ -1,132 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2022 microDev - * - * 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 "shared-bindings/alarm/__init__.h" -#include "shared-bindings/alarm/coproc/CoprocAlarm.h" -#include "shared-bindings/coproc/__init__.h" - -#if CIRCUITPY_COPROC - -#include "supervisor/port.h" - -#include "driver/rtc_cntl.h" -#include "soc/rtc_cntl_reg.h" - -#include "esp_sleep.h" - -static volatile bool woke_up = false; - -mp_obj_t alarm_coproc_coprocalarm_find_triggered_alarm(const size_t n_alarms, const mp_obj_t *alarms) { - for (size_t i = 0; i < n_alarms; i++) { - if (mp_obj_is_type(alarms[i], &alarm_coproc_coprocalarm_type)) { - return alarms[i]; - } - } - return mp_const_none; -} - -mp_obj_t alarm_coproc_coprocalarm_record_wake_alarm(void) { - alarm_coproc_coprocalarm_obj_t *const alarm = &alarm_wake_alarm.coproc_alarm; - - alarm->base.type = &alarm_coproc_coprocalarm_type; - return alarm; -} - -// This is used to wake the main CircuitPython task. -STATIC void coproc_interrupt(void *arg) { - (void)arg; - woke_up = true; - port_wake_main_task_from_isr(); -} - -void alarm_coproc_coprocalarm_set_alarm(const bool deep_sleep, const size_t n_alarms, const mp_obj_t *alarms) { - bool coproc_alarm_set = false; - alarm_coproc_coprocalarm_obj_t *coproc_alarm = MP_OBJ_NULL; - - for (size_t i = 0; i < n_alarms; i++) { - if (mp_obj_is_type(alarms[i], &alarm_coproc_coprocalarm_type)) { - if (deep_sleep && coproc_alarm_set) { - mp_raise_ValueError_varg(translate("Only one %q can be set in deep sleep."), MP_QSTR_CoprocAlarm); - } - coproc_alarm = MP_OBJ_TO_PTR(alarms[i]); - coproc_alarm_set = true; - } - } - - if (!coproc_alarm_set) { - return; - } - - // enable coproc interrupt - rtc_isr_register(&coproc_interrupt, NULL, RTC_CNTL_COCPU_INT_ST); - REG_SET_BIT(RTC_CNTL_INT_ENA_REG, RTC_CNTL_COCPU_INT_ENA); - - // start coproc program - common_hal_coproc_run(coproc_alarm->coproc); -} - -void alarm_coproc_coprocalarm_prepare_for_deep_sleep(void) { - // disbale coproc interrupt - rtc_isr_deregister(&coproc_interrupt, NULL); - REG_CLR_BIT(RTC_CNTL_INT_ENA_REG, RTC_CNTL_COCPU_INT_ENA); - - // enable coproc wakeup - esp_sleep_enable_ulp_wakeup(); - esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_SLOW_MEM, ESP_PD_OPTION_ON); -} - -bool alarm_coproc_coprocalarm_woke_this_cycle(void) { - return woke_up; -} - -void alarm_coproc_coprocalarm_reset(void) { - woke_up = false; -} - -#else // CIRCUITPY_COPROC - -mp_obj_t alarm_coproc_coprocalarm_find_triggered_alarm(const size_t n_alarms, const mp_obj_t *alarms) { - return mp_const_none; -} - -mp_obj_t alarm_coproc_coprocalarm_record_wake_alarm(void) { - return mp_const_none; -} - -void alarm_coproc_coprocalarm_set_alarm(const bool deep_sleep, const size_t n_alarms, const mp_obj_t *alarms) { -} - -void alarm_coproc_coprocalarm_prepare_for_deep_sleep(void) { -} - -bool alarm_coproc_coprocalarm_woke_this_cycle(void) { - return false; -} - -void alarm_coproc_coprocalarm_reset(void) { -} - -#endif // CIRCUITPY_COPROC diff --git a/ports/espressif/common-hal/coproc/Coproc.c b/ports/espressif/common-hal/coproc/Coproc.c deleted file mode 100644 index c2115c1e94..0000000000 --- a/ports/espressif/common-hal/coproc/Coproc.c +++ /dev/null @@ -1,73 +0,0 @@ -/* - * This file is part of the Micro Python project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2022 microDev - * - * 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 "shared-bindings/coproc/Coproc.h" -#include "shared-bindings/coproc/CoprocMemory.h" - -#include "py/runtime.h" - -#if defined(CONFIG_IDF_TARGET_ESP32S2) -#include "esp32s2/ulp.h" -#define ULP_COPROC_RESERVE_MEM (CONFIG_ESP32S2_ULP_COPROC_RESERVE_MEM) -#elif defined(CONFIG_IDF_TARGET_ESP32S3) -#include "esp32s3/ulp.h" -#define ULP_COPROC_RESERVE_MEM (CONFIG_ESP32S3_ULP_COPROC_RESERVE_MEM) -#endif - -#define RTC_SLOW_MEM_END ((uint32_t)RTC_SLOW_MEM + ULP_COPROC_RESERVE_MEM) - -void common_hal_coproc_coproc_construct(coproc_coproc_obj_t *self, - const uint8_t *buf, const size_t buf_len, coproc_memory_obj_t *coproc_memory) { - // set CoprocMemory object - if (coproc_memory != NULL) { - if (coproc_memory->address < ((uint32_t)RTC_SLOW_MEM + buf_len) || - coproc_memory->address > (RTC_SLOW_MEM_END - coproc_memory->len)) { - mp_raise_ValueError_varg(translate("%q out of range"), MP_QSTR_CoprocMemory); - } - } - self->coproc_memory = coproc_memory; - - // load buffer - if (buf_len > ULP_COPROC_RESERVE_MEM) { - mp_raise_RuntimeError(translate("Firmware is too big")); - } - self->buf_len = buf_len; - self->buf = (uint8_t *)m_malloc(self->buf_len, false); - memcpy(self->buf, buf, self->buf_len); -} - -bool common_hal_coproc_coproc_deinited(coproc_coproc_obj_t *self) { - return self->buf == NULL; -} - -void common_hal_coproc_coproc_deinit(coproc_coproc_obj_t *self) { - if (common_hal_coproc_coproc_deinited(self)) { - return; - } - m_free(self->buf); - self->buf = NULL; - self->coproc_memory = NULL; -} diff --git a/ports/espressif/common-hal/coproc/__init__.c b/ports/espressif/common-hal/espulp/ULP.c similarity index 50% rename from ports/espressif/common-hal/coproc/__init__.c rename to ports/espressif/common-hal/espulp/ULP.c index e372bfa235..8f80b5c9ec 100644 --- a/ports/espressif/common-hal/coproc/__init__.c +++ b/ports/espressif/common-hal/espulp/ULP.c @@ -24,49 +24,104 @@ * THE SOFTWARE. */ -#include "shared-bindings/coproc/__init__.h" +#include "bindings/espulp/__init__.h" +#include "bindings/espulp/ULP.h" #include "py/runtime.h" +#include "shared-bindings/microcontroller/Pin.h" + #if defined(CONFIG_IDF_TARGET_ESP32S2) #include "esp32s2/ulp.h" #include "esp32s2/ulp_riscv.h" +#define ULP_COPROC_RESERVE_MEM (CONFIG_ESP32S2_ULP_COPROC_RESERVE_MEM) #elif defined(CONFIG_IDF_TARGET_ESP32S3) #include "esp32s3/ulp.h" #include "esp32s3/ulp_riscv.h" +#define ULP_COPROC_RESERVE_MEM (CONFIG_ESP32S3_ULP_COPROC_RESERVE_MEM) #endif // To-do idf v5.0: remove following include #include "soc/rtc_cntl_reg.h" -void common_hal_coproc_run(coproc_coproc_obj_t *self) { +STATIC bool ulp_used = false; +STATIC uint32_t pins_used = 0; + +void espulp_reset(void) { + // NOTE: This *doesn't* disable the ULP. It'll keep running even when CircuitPython isn't. + ulp_used = false; +} + +void common_hal_espulp_ulp_run(espulp_ulp_obj_t *self, uint32_t *program, size_t length, uint32_t pin_mask) { + if (length > ULP_COPROC_RESERVE_MEM) { + mp_raise_ValueError(translate("Program too long")); + } if (GET_PERI_REG_MASK(RTC_CNTL_ULP_CP_TIMER_REG, RTC_CNTL_ULP_CP_SLP_TIMER_EN)) { mp_raise_RuntimeError(translate("Already running")); } - ulp_riscv_load_binary(self->buf, self->buf_len); - m_free(self->buf); - self->buf = (uint8_t *)RTC_SLOW_MEM; + if (pin_mask >= (1 << 22)) { + mp_raise_ValueError(translate("Pins 21+ not supported from ULP")); + } + for (uint8_t i = 0; i < 32; i++) { + if ((pin_mask & (1 << i)) != 0 && !pin_number_is_free(i)) { + mp_raise_ValueError_varg(translate("%q in use"), MP_QSTR_Pin); + } + } + + for (uint8_t i = 0; i < 32; i++) { + if ((pin_mask & (1 << i)) != 0) { + claim_pin_number(i); + never_reset_pin_number(i); + } + } + pins_used = pin_mask; + + + ulp_riscv_load_binary((const uint8_t *)program, length); + ulp_set_wakeup_period(0, 20000); ulp_riscv_run(); } -void common_hal_coproc_halt(coproc_coproc_obj_t *self) { - self->buf = (uint8_t *)m_malloc(self->buf_len, false); - memcpy(self->buf, (uint8_t *)RTC_SLOW_MEM, self->buf_len); - +void common_hal_espulp_ulp_halt(espulp_ulp_obj_t *self) { // To-do idf v5.0: use following functions // ulp_riscv_timer_stop(); // ulp_riscv_halt(); - // stop the ulp timer + // stop the ulp timer so that is doesn't restart the cpu CLEAR_PERI_REG_MASK(RTC_CNTL_ULP_CP_TIMER_REG, RTC_CNTL_ULP_CP_SLP_TIMER_EN); + // suspends the ulp operation SET_PERI_REG_MASK(RTC_CNTL_COCPU_CTRL_REG, RTC_CNTL_COCPU_DONE); + // resets the processor SET_PERI_REG_MASK(RTC_CNTL_COCPU_CTRL_REG, RTC_CNTL_COCPU_SHUT_RESET_EN); + + // Release pins we were using. + for (uint8_t i = 0; i < 32; i++) { + if ((pins_used & (1 << i)) != 0) { + reset_pin_number(i); + } + } } -mp_obj_t common_hal_coproc_memory(coproc_coproc_obj_t *self) { - return (self->coproc_memory) ? MP_OBJ_FROM_PTR(self->coproc_memory) : mp_const_none; +void common_hal_espulp_ulp_construct(espulp_ulp_obj_t *self) { + if (ulp_used) { + mp_raise_ValueError_varg(translate("%q in use"), MP_QSTR_ULP); + } + self->inited = true; +} + +bool common_hal_espulp_ulp_deinited(espulp_ulp_obj_t *self) { + return !self->inited; +} + +void common_hal_espulp_ulp_deinit(espulp_ulp_obj_t *self) { + if (common_hal_espulp_ulp_deinited(self)) { + return; + } + common_hal_espulp_ulp_halt(self); + self->inited = false; + ulp_used = false; } diff --git a/ports/espressif/common-hal/coproc/CoprocMemory.h b/ports/espressif/common-hal/espulp/ULP.h similarity index 82% rename from ports/espressif/common-hal/coproc/CoprocMemory.h rename to ports/espressif/common-hal/espulp/ULP.h index c4aa088394..f73b21d123 100644 --- a/ports/espressif/common-hal/coproc/CoprocMemory.h +++ b/ports/espressif/common-hal/espulp/ULP.h @@ -24,15 +24,11 @@ * THE SOFTWARE. */ -#ifndef MICROPY_INCLUDED_ESPRESSIF_COMMON_HAL_COPROC_COPROCMEMORY_H -#define MICROPY_INCLUDED_ESPRESSIF_COMMON_HAL_COPROC_COPROCMEMORY_H +#pragma once #include "py/obj.h" typedef struct { mp_obj_base_t base; - uint32_t address; - uint16_t len; -} coproc_memory_obj_t; - -#endif // MICROPY_INCLUDED_ESPRESSIF_COMMON_HAL_COPROC_COPROCMEMORY_H + bool inited; +} espulp_ulp_obj_t; diff --git a/ports/espressif/common-hal/espulp/ULPAlarm.c b/ports/espressif/common-hal/espulp/ULPAlarm.c new file mode 100644 index 0000000000..ec1fb8bc45 --- /dev/null +++ b/ports/espressif/common-hal/espulp/ULPAlarm.c @@ -0,0 +1,110 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2022 microDev + * + * 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 "bindings/espulp/ULPAlarm.h" + +#include "common-hal/alarm/__init__.h" +#include "supervisor/port.h" + +#include "driver/rtc_cntl.h" +#include "soc/rtc_cntl_reg.h" + +#include "esp_sleep.h" + +static volatile bool woke_up = false; +static bool alarm_set = false; + +void common_hal_espulp_ulpalarm_construct(espulp_ulpalarm_obj_t *self) { + +} + +mp_obj_t espulp_ulpalarm_find_triggered_alarm(const size_t n_alarms, const mp_obj_t *alarms) { + for (size_t i = 0; i < n_alarms; i++) { + if (mp_obj_is_type(alarms[i], &espulp_ulpalarm_type)) { + return alarms[i]; + } + } + return mp_const_none; +} + +mp_obj_t espulp_ulpalarm_record_wake_alarm(void) { + espulp_ulpalarm_obj_t *const alarm = &alarm_wake_alarm.ulp_alarm; + + alarm->base.type = &espulp_ulpalarm_type; + return alarm; +} + +// This is used to wake the main CircuitPython task. +STATIC void ulp_interrupt(void *arg) { + (void)arg; + woke_up = true; + port_wake_main_task_from_isr(); +} + +void espulp_ulpalarm_set_alarm(const bool deep_sleep, const size_t n_alarms, const mp_obj_t *alarms) { + espulp_ulpalarm_obj_t *alarm = MP_OBJ_NULL; + + for (size_t i = 0; i < n_alarms; i++) { + if (mp_obj_is_type(alarms[i], &espulp_ulpalarm_type)) { + if (alarm != MP_OBJ_NULL) { + mp_raise_ValueError_varg(translate("Only one %q can be set."), MP_QSTR_ULPAlarm); + } + alarm = MP_OBJ_TO_PTR(alarms[i]); + } + } + + if (alarm == MP_OBJ_NULL) { + return; + } + + // enable ulp interrupt + rtc_isr_register(&ulp_interrupt, NULL, RTC_CNTL_COCPU_INT_ST); + REG_SET_BIT(RTC_CNTL_INT_ENA_REG, RTC_CNTL_COCPU_INT_ENA); + + alarm_set = true; +} + +void espulp_ulpalarm_prepare_for_deep_sleep(void) { + if (!alarm_set) { + return; + } + // disable ulp interrupt + rtc_isr_deregister(&ulp_interrupt, NULL); + REG_CLR_BIT(RTC_CNTL_INT_ENA_REG, RTC_CNTL_COCPU_INT_ENA); + + // enable ulp wakeup + esp_sleep_enable_ulp_wakeup(); + esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_SLOW_MEM, ESP_PD_OPTION_ON); +} + +bool espulp_ulpalarm_woke_this_cycle(void) { + return woke_up; +} + +void espulp_ulpalarm_reset(void) { + woke_up = false; + alarm_set = false; +} diff --git a/ports/espressif/common-hal/alarm/coproc/CoprocAlarm.h b/ports/espressif/common-hal/espulp/ULPAlarm.h similarity index 71% rename from ports/espressif/common-hal/alarm/coproc/CoprocAlarm.h rename to ports/espressif/common-hal/espulp/ULPAlarm.h index 57a9bcdbff..5d2610c6a3 100644 --- a/ports/espressif/common-hal/alarm/coproc/CoprocAlarm.h +++ b/ports/espressif/common-hal/espulp/ULPAlarm.h @@ -29,17 +29,14 @@ #include "py/obj.h" #include "py/runtime.h" -#include "common-hal/coproc/Coproc.h" - typedef struct { mp_obj_base_t base; - coproc_coproc_obj_t *coproc; -} alarm_coproc_coprocalarm_obj_t; +} espulp_ulpalarm_obj_t; -mp_obj_t alarm_coproc_coprocalarm_find_triggered_alarm(const size_t n_alarms, const mp_obj_t *alarms); -mp_obj_t alarm_coproc_coprocalarm_record_wake_alarm(void); +mp_obj_t espulp_ulpalarm_find_triggered_alarm(const size_t n_alarms, const mp_obj_t *alarms); +mp_obj_t espulp_ulpalarm_record_wake_alarm(void); -void alarm_coproc_coprocalarm_prepare_for_deep_sleep(void); -void alarm_coproc_coprocalarm_reset(void); -void alarm_coproc_coprocalarm_set_alarm(const bool deep_sleep, const size_t n_alarms, const mp_obj_t *alarms); -bool alarm_coproc_coprocalarm_woke_this_cycle(void); +void espulp_ulpalarm_prepare_for_deep_sleep(void); +void espulp_ulpalarm_reset(void); +void espulp_ulpalarm_set_alarm(const bool deep_sleep, const size_t n_alarms, const mp_obj_t *alarms); +bool espulp_ulpalarm_woke_this_cycle(void); diff --git a/ports/espressif/common-hal/espulp/__init__.c b/ports/espressif/common-hal/espulp/__init__.c new file mode 100644 index 0000000000..5d403129a6 --- /dev/null +++ b/ports/espressif/common-hal/espulp/__init__.c @@ -0,0 +1,34 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2022 Scott Shawcroft for Adafruit Industries LLC + * + * 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 "bindings/espulp/__init__.h" + +mp_int_t common_hal_espulp_get_rtc_gpio_number(const mcu_pin_obj_t *pin) { + if (pin->number <= 21) { + return pin->number; + } + return -1; +} diff --git a/ports/espressif/common-hal/memorymap/AddressRange.c b/ports/espressif/common-hal/memorymap/AddressRange.c new file mode 100644 index 0000000000..ed46c159bb --- /dev/null +++ b/ports/espressif/common-hal/memorymap/AddressRange.c @@ -0,0 +1,107 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020 microDev + * + * 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 + +#include "shared-bindings/memorymap/AddressRange.h" + +#include "py/runtime.h" + +#include "soc/soc.h" + +size_t allow_ranges[][2] = { + // ULP accessible RAM + {SOC_RTC_DATA_LOW, SOC_RTC_DATA_HIGH}, + // CPU accessible RAM that is preserved during sleep if the RTC power domain is left on. + {SOC_RTC_DRAM_LOW, SOC_RTC_DRAM_HIGH}, + // RTC peripheral registers + {0x60008000, 0x60009000} + +}; + +void common_hal_memorymap_addressrange_construct(memorymap_addressrange_obj_t *self, uint8_t *start_address, size_t length) { + bool allowed = false; + for (size_t i = 0; i < MP_ARRAY_SIZE(allow_ranges); i++) { + uint8_t *allowed_start = (uint8_t *)allow_ranges[i][0]; + uint8_t *allowed_end = (uint8_t *)allow_ranges[i][1]; + if (allowed_start <= start_address && + (start_address + length) <= allowed_end) { + allowed = true; + break; + } + } + + if (!allowed) { + mp_raise_ValueError(translate("Address range not allowed")); + } + + self->start_address = start_address; + self->len = length; +} + +size_t common_hal_memorymap_addressrange_get_length(const memorymap_addressrange_obj_t *self) { + return self->len; +} + +bool common_hal_memorymap_addressrange_set_bytes(const memorymap_addressrange_obj_t *self, + size_t start_index, uint8_t *values, size_t len) { + uint8_t *address = self->start_address + start_index; + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wcast-align" + if (len == 1) { + *((uint8_t *)address) = values[0]; + } else if (len == sizeof(uint16_t) && (((size_t)address) % sizeof(uint16_t)) == 0) { + *((uint16_t *)address) = ((uint16_t *)values)[0]; + } else if (len == sizeof(uint32_t) && (((size_t)address) % sizeof(uint32_t)) == 0) { + *((uint32_t *)address) = ((uint32_t *)values)[0]; + } else if (len == sizeof(uint64_t) && (((size_t)address) % sizeof(uint64_t)) == 0) { + *((uint64_t *)address) = ((uint64_t *)values)[0]; + } else { + memcpy(address, values, len); + } + #pragma GCC diagnostic pop + + return true; +} + +void common_hal_memorymap_addressrange_get_bytes(const memorymap_addressrange_obj_t *self, + size_t start_index, size_t len, uint8_t *values) { + uint8_t *address = self->start_address + start_index; + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wcast-align" + if (len == 1) { + values[0] = *((uint8_t *)address); + } else if (len == sizeof(uint16_t) && (((size_t)address) % sizeof(uint16_t)) == 0) { + ((uint16_t *)values)[0] = *((uint16_t *)address); + } else if (len == sizeof(uint32_t) && (((size_t)address) % sizeof(uint32_t)) == 0) { + ((uint32_t *)values)[0] = *((uint32_t *)address); + } else if (len == sizeof(uint64_t) && (((size_t)address) % sizeof(uint64_t)) == 0) { + ((uint64_t *)values)[0] = *((uint64_t *)address); + } else { + memcpy(values, address, len); + } + #pragma GCC diagnostic pop +} diff --git a/ports/espressif/common-hal/memorymap/AddressRange.h b/ports/espressif/common-hal/memorymap/AddressRange.h new file mode 100644 index 0000000000..e67cf32f5f --- /dev/null +++ b/ports/espressif/common-hal/memorymap/AddressRange.h @@ -0,0 +1,38 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020 microDev + * + * 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. + */ + +#ifndef MICROPY_INCLUDED_ESPRESSIF_COMMON_HAL_MEMORYMAP_ADDRESSRANGE_H +#define MICROPY_INCLUDED_ESPRESSIF_COMMON_HAL_MEMORYMAP_ADDRESSRANGE_H + +#include "py/obj.h" + +typedef struct { + mp_obj_base_t base; + uint8_t *start_address; + size_t len; +} memorymap_addressrange_obj_t; + +#endif // MICROPY_INCLUDED_ESPRESSIF_COMMON_HAL_MEMORYMAP_ADDRESSRANGE_H diff --git a/ports/espressif/common-hal/memorymap/__init__.c b/ports/espressif/common-hal/memorymap/__init__.c new file mode 100644 index 0000000000..c15b17f451 --- /dev/null +++ b/ports/espressif/common-hal/memorymap/__init__.c @@ -0,0 +1 @@ +// No memorymap module functions. diff --git a/ports/espressif/common-hal/microcontroller/Processor.c b/ports/espressif/common-hal/microcontroller/Processor.c index bacc48c07b..1f09742955 100644 --- a/ports/espressif/common-hal/microcontroller/Processor.c +++ b/ports/espressif/common-hal/microcontroller/Processor.c @@ -139,6 +139,7 @@ mcu_reset_reason_t common_hal_mcu_processor_get_reset_reason(void) { case ESP_SLEEP_WAKEUP_EXT0: case ESP_SLEEP_WAKEUP_EXT1: case ESP_SLEEP_WAKEUP_TOUCHPAD: + case ESP_SLEEP_WAKEUP_ULP: return RESET_REASON_DEEP_SLEEP_ALARM; case ESP_SLEEP_WAKEUP_UNDEFINED: diff --git a/ports/espressif/esp-idf b/ports/espressif/esp-idf index 20c6d4a623..8d0f1abce7 160000 --- a/ports/espressif/esp-idf +++ b/ports/espressif/esp-idf @@ -1 +1 @@ -Subproject commit 20c6d4a623a9391afd0e803b2bbebe020ed15ec8 +Subproject commit 8d0f1abce769ad4a212c1bb0337999cacd7ee83d diff --git a/ports/espressif/mpconfigport.mk b/ports/espressif/mpconfigport.mk index f1fa24a59b..c5c73c77bd 100644 --- a/ports/espressif/mpconfigport.mk +++ b/ports/espressif/mpconfigport.mk @@ -22,7 +22,6 @@ CIRCUITPY_AUDIOMP3 ?= 0 CIRCUITPY_BLEIO ?= 1 CIRCUITPY_BLEIO_HCI = 0 CIRCUITPY_CANIO ?= 1 -CIRCUITPY_COPROC ?= 1 CIRCUITPY_COUNTIO ?= 1 CIRCUITPY_DUALBANK ?= 1 CIRCUITPY_ESP32_CAMERA ?= 1 @@ -44,7 +43,6 @@ CIRCUITPY_WIFI ?= 1 ifeq ($(IDF_TARGET),esp32) # Modules CIRCUITPY_BLEIO = 0 -CIRCUITPY_COPROC = 0 CIRCUITPY_PARALLELDISPLAY = 0 CIRCUITPY_RGBMATRIX = 0 # Features @@ -54,7 +52,6 @@ else ifeq ($(IDF_TARGET),esp32c3) # Modules CIRCUITPY_ALARM = 0 CIRCUITPY_AUDIOBUSIO = 0 -CIRCUITPY_COPROC = 0 CIRCUITPY_COUNTIO = 0 CIRCUITPY_ESP32_CAMERA = 0 CIRCUITPY_FREQUENCYIO = 0 @@ -68,10 +65,14 @@ CIRCUITPY_USB = 0 else ifeq ($(IDF_TARGET),esp32s2) # Modules CIRCUITPY_BLEIO = 0 +CIRCUITPY_ESPULP = 1 +CIRCUITPY_MEMORYMAP = 1 else ifeq ($(IDF_TARGET),esp32s3) # Modules CIRCUITPY_PARALLELDISPLAY = 0 +CIRCUITPY_ESPULP = 1 +CIRCUITPY_MEMORYMAP = 1 endif # No room for dualbank on boards with 2MB flash diff --git a/ports/espressif/supervisor/port.c b/ports/espressif/supervisor/port.c index baeba5ce90..6dd09ed238 100644 --- a/ports/espressif/supervisor/port.c +++ b/ports/espressif/supervisor/port.c @@ -30,12 +30,14 @@ #include "supervisor/board.h" #include "supervisor/port.h" #include "supervisor/filesystem.h" +#include "supervisor/shared/reload.h" #include "py/runtime.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "bindings/espidf/__init__.h" +#include "bindings/espulp/__init__.h" #include "common-hal/microcontroller/Pin.h" #include "common-hal/analogio/AnalogOut.h" #include "common-hal/busio/I2C.h" @@ -367,6 +369,10 @@ void reset_port(void) { dualbank_reset(); #endif + #if CIRCUITPY_ESPULP + espulp_reset(); + #endif + #if CIRCUITPY_FREQUENCYIO peripherals_timer_reset(); #endif @@ -511,7 +517,7 @@ void port_interrupt_after_ticks(uint32_t ticks) { // On the ESP we use FreeRTOS notifications instead of interrupts so this is a // bit of a misnomer. void port_idle_until_interrupt(void) { - if (!background_callback_pending()) { + if (!background_callback_pending() && !autoreload_pending()) { xTaskNotifyWait(0x01, 0x01, NULL, portMAX_DELAY); } } diff --git a/py/circuitpy_defns.mk b/py/circuitpy_defns.mk index 22ea67d05e..be33d80a99 100644 --- a/py/circuitpy_defns.mk +++ b/py/circuitpy_defns.mk @@ -167,9 +167,6 @@ endif ifeq ($(CIRCUITPY_CANIO),1) SRC_PATTERNS += canio/% endif -ifeq ($(CIRCUITPY_COPROC),1) -SRC_PATTERNS += coproc/% -endif ifeq ($(CIRCUITPY_COUNTIO),1) SRC_PATTERNS += countio/% endif @@ -227,6 +224,9 @@ endif ifeq ($(CIRCUITPY_MATH),1) SRC_PATTERNS += math/% endif +ifeq ($(CIRCUITPY_MEMORYMAP),1) +SRC_PATTERNS += memorymap/% +endif ifeq ($(CIRCUITPY_MEMORYMONITOR),1) SRC_PATTERNS += memorymonitor/% endif @@ -400,7 +400,6 @@ SRC_COMMON_HAL_ALL = \ alarm/pin/PinAlarm.c \ alarm/time/TimeAlarm.c \ alarm/touch/TouchAlarm.c \ - alarm/coproc/CoprocAlarm.c \ analogbufio/BufferedIn.c \ analogbufio/__init__.c \ analogio/AnalogIn.c \ @@ -423,9 +422,6 @@ SRC_COMMON_HAL_ALL = \ canio/CAN.c \ canio/Listener.c \ canio/__init__.c \ - coproc/__init__.c \ - coproc/Coproc.c \ - coproc/CoprocMemory.c \ countio/Counter.c \ countio/__init__.c \ digitalio/DigitalInOut.c \ @@ -443,9 +439,11 @@ SRC_COMMON_HAL_ALL = \ hashlib/Hash.c \ i2ctarget/I2CTarget.c \ i2ctarget/__init__.c \ + memorymap/__init__.c \ + memorymap/AddressRange.c \ + microcontroller/__init__.c \ microcontroller/Pin.c \ microcontroller/Processor.c \ - microcontroller/__init__.c \ mdns/__init__.c \ mdns/Server.c \ mdns/RemoteService.c \ diff --git a/py/circuitpy_mpconfig.mk b/py/circuitpy_mpconfig.mk index f0e145998b..01b078c6e8 100644 --- a/py/circuitpy_mpconfig.mk +++ b/py/circuitpy_mpconfig.mk @@ -221,12 +221,15 @@ CFLAGS += -DCIRCUITPY_OS_GETENV=$(CIRCUITPY_OS_GETENV) CIRCUITPY_ERRNO ?= $(CIRCUITPY_FULL_BUILD) CFLAGS += -DCIRCUITPY_ERRNO=$(CIRCUITPY_ERRNO) -# CIRCUITPY_ESPIDF is handled in the espressif tree. +# CIRCUITPY_ESPIDF and CIRCUITPY_ESPULP is handled in the espressif tree. # Only for ESP32S chips. # Assume not a ESP build. CIRCUITPY_ESPIDF ?= 0 CFLAGS += -DCIRCUITPY_ESPIDF=$(CIRCUITPY_ESPIDF) +CIRCUITPY_ESPULP ?= 0 +CFLAGS += -DCIRCUITPY_ESPULP=$(CIRCUITPY_ESPULP) + CIRCUITPY_ESP32_CAMERA ?= 0 CFLAGS += -DCIRCUITPY_ESP32_CAMERA=$(CIRCUITPY_ESP32_CAMERA) @@ -283,6 +286,9 @@ CFLAGS += -DCIRCUITPY_KEYPAD=$(CIRCUITPY_KEYPAD) CIRCUITPY_MATH ?= 1 CFLAGS += -DCIRCUITPY_MATH=$(CIRCUITPY_MATH) +CIRCUITPY_MEMORYMAP ?= 0 +CFLAGS += -DCIRCUITPY_MEMORYMAP=$(CIRCUITPY_MEMORYMAP) + CIRCUITPY_MEMORYMONITOR ?= 0 CFLAGS += -DCIRCUITPY_MEMORYMONITOR=$(CIRCUITPY_MEMORYMONITOR) diff --git a/shared-bindings/alarm/__init__.c b/shared-bindings/alarm/__init__.c index bd11b16996..48dccff8df 100644 --- a/shared-bindings/alarm/__init__.c +++ b/shared-bindings/alarm/__init__.c @@ -27,12 +27,15 @@ #include "py/obj.h" #include "py/runtime.h" +#if CIRCUITPY_ESPULP +#include "bindings/espulp/ULPAlarm.h" +#endif + #include "shared-bindings/alarm/__init__.h" #include "shared-bindings/alarm/SleepMemory.h" #include "shared-bindings/alarm/pin/PinAlarm.h" #include "shared-bindings/alarm/time/TimeAlarm.h" #include "shared-bindings/alarm/touch/TouchAlarm.h" -#include "shared-bindings/alarm/coproc/CoprocAlarm.h" #include "shared-bindings/digitalio/DigitalInOut.h" #include "shared-bindings/supervisor/Runtime.h" #include "shared-bindings/time/__init__.h" @@ -77,8 +80,10 @@ STATIC void validate_objs_are_alarms(size_t n_args, const mp_obj_t *objs) { for (size_t i = 0; i < n_args; i++) { if (mp_obj_is_type(objs[i], &alarm_pin_pinalarm_type) || mp_obj_is_type(objs[i], &alarm_time_timealarm_type) || - mp_obj_is_type(objs[i], &alarm_touch_touchalarm_type) || - mp_obj_is_type(objs[i], &alarm_coproc_coprocalarm_type)) { + #if CIRCUITPY_ESPULP + mp_obj_is_type(objs[i], &espulp_ulpalarm_type) || + #endif + mp_obj_is_type(objs[i], &alarm_touch_touchalarm_type)) { continue; } mp_raise_TypeError_varg(translate("Expected an %q"), MP_QSTR_Alarm); @@ -256,18 +261,6 @@ STATIC const mp_obj_module_t alarm_touch_module = { .globals = (mp_obj_dict_t *)&alarm_touch_globals, }; -STATIC const mp_map_elem_t alarm_coproc_globals_table[] = { - { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_coproc) }, - { MP_ROM_QSTR(MP_QSTR_CoprocAlarm), MP_OBJ_FROM_PTR(&alarm_coproc_coprocalarm_type) }, -}; - -STATIC MP_DEFINE_CONST_DICT(alarm_coproc_globals, alarm_coproc_globals_table); - -STATIC const mp_obj_module_t alarm_coproc_module = { - .base = { &mp_type_module }, - .globals = (mp_obj_dict_t *)&alarm_coproc_globals, -}; - // The module table is mutable because .wake_alarm is a mutable attribute. STATIC mp_map_elem_t alarm_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_alarm) }, @@ -282,7 +275,6 @@ STATIC mp_map_elem_t alarm_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_pin), MP_OBJ_FROM_PTR(&alarm_pin_module) }, { MP_ROM_QSTR(MP_QSTR_time), MP_OBJ_FROM_PTR(&alarm_time_module) }, { MP_ROM_QSTR(MP_QSTR_touch), MP_OBJ_FROM_PTR(&alarm_touch_module) }, - { MP_ROM_QSTR(MP_QSTR_coproc), MP_OBJ_FROM_PTR(&alarm_coproc_module) }, { MP_ROM_QSTR(MP_QSTR_SleepMemory), MP_OBJ_FROM_PTR(&alarm_sleep_memory_type) }, { MP_ROM_QSTR(MP_QSTR_sleep_memory), MP_OBJ_FROM_PTR(&alarm_sleep_memory_obj) }, diff --git a/shared-bindings/alarm/coproc/CoprocAlarm.c b/shared-bindings/alarm/coproc/CoprocAlarm.c deleted file mode 100644 index 0b60282c2f..0000000000 --- a/shared-bindings/alarm/coproc/CoprocAlarm.c +++ /dev/null @@ -1,87 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2022 microDev - * - * 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 "py/runtime.h" - -#if CIRCUITPY_COPROC -#include "shared-bindings/util.h" -#include "shared-bindings/alarm/coproc/CoprocAlarm.h" -#include "shared-bindings/coproc/Coproc.h" - -STATIC coproc_coproc_obj_t *get_coproc_obj(mp_obj_t *self_in) { - if (!mp_obj_is_type(*self_in, &coproc_coproc_type)) { - mp_raise_TypeError_varg(translate("Expected a %q"), MP_QSTR_Coproc); - } - coproc_coproc_obj_t *self = MP_OBJ_TO_PTR(*self_in); - if (common_hal_coproc_coproc_deinited(self)) { - raise_deinited_error(); - } - return self; -} -#endif - -//| class CoprocAlarm: -//| """Trigger an alarm when another core or co-processor requests wake-up.""" -//| -//| def __init__(self, coproc: coproc.Coproc) -> None: -//| """Create an alarm that will be triggered when the co-processor requests wake-up. -//| -//| The alarm is not active until it is passed to an `alarm`-enabling function, such as -//| `alarm.light_sleep_until_alarms()` or `alarm.exit_and_deep_sleep_until_alarms()`. -//| -//| :param coproc.Coproc coproc: The coproc program to run. -//| -//| """ -//| ... -//| -STATIC mp_obj_t alarm_coproc_coprocalarm_make_new(const mp_obj_type_t *type, - size_t n_args, size_t n_kw, const mp_obj_t *all_args) { - enum { ARG_coproc }; - static const mp_arg_t allowed_args[] = { - { MP_QSTR_coproc, MP_ARG_REQUIRED | MP_ARG_OBJ }, - }; - - mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - - #if CIRCUITPY_COPROC - // initialize CoprocAlarm object - alarm_coproc_coprocalarm_obj_t *self = m_new_obj(alarm_coproc_coprocalarm_obj_t); - self->base.type = &alarm_coproc_coprocalarm_type; - self->coproc = get_coproc_obj(&args[ARG_coproc].u_obj); - // return CoprocAlarm object - return MP_OBJ_FROM_PTR(self); - #else - mp_raise_NotImplementedError(NULL); - return mp_const_none; - #endif -} - -const mp_obj_type_t alarm_coproc_coprocalarm_type = { - { &mp_type_type }, - .name = MP_QSTR_CoprocAlarm, - .make_new = alarm_coproc_coprocalarm_make_new, -}; diff --git a/shared-bindings/coproc/Coproc.c b/shared-bindings/coproc/Coproc.c deleted file mode 100644 index 85595578c8..0000000000 --- a/shared-bindings/coproc/Coproc.c +++ /dev/null @@ -1,110 +0,0 @@ -/* - * This file is part of the Micro Python project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2022 microDev - * - * 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 "shared/runtime/context_manager_helpers.h" -#include "py/objproperty.h" -#include "py/runtime.h" - -#include "shared-bindings/coproc/Coproc.h" -#include "shared-bindings/coproc/CoprocMemory.h" - -STATIC coproc_memory_obj_t *get_coproc_memory_obj(mp_obj_t *self_in) { - if (!mp_obj_is_type(*self_in, &coproc_memory_type)) { - mp_raise_TypeError_varg(translate("Expected a %q"), MP_QSTR_CoprocMemory); - } - return MP_OBJ_TO_PTR(*self_in); -} - -//| class Coproc: -//| def __init__(self, buffer: ReadableBuffer, memory: CoprocMemory) -> None: -//| """Loads the program binary into memory. -//| -//| :param buffer: The program binary to run on the core/co-processor -//| :param memory: The `CoprocMemory` object used to access shared memory""" -STATIC mp_obj_t coproc_coproc_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { - enum { ARG_buffer, ARG_memory }; - static const mp_arg_t allowed_args[] = { - { MP_QSTR_buffer, MP_ARG_REQUIRED | MP_ARG_OBJ }, - { MP_QSTR_memory, MP_ARG_OBJ, { .u_obj = mp_const_none } }, - }; - mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - - coproc_coproc_obj_t *self = m_new_obj(coproc_coproc_obj_t); - self->base.type = &coproc_coproc_type; - - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(args[ARG_buffer].u_obj, &bufinfo, MP_BUFFER_READ); - - coproc_memory_obj_t *coproc_memory = (args[ARG_memory].u_obj == mp_const_none) ? NULL : get_coproc_memory_obj(&args[ARG_memory].u_obj); - - common_hal_coproc_coproc_construct(self, bufinfo.buf, bufinfo.len, coproc_memory); - - return MP_OBJ_FROM_PTR(self); -} - -//| def deinit(self) -> None: -//| """Releases control of the underlying hardware so other classes can use it.""" -//| ... -STATIC mp_obj_t coproc_coproc_obj_deinit(mp_obj_t self_in) { - coproc_coproc_obj_t *self = MP_OBJ_TO_PTR(self_in); - common_hal_coproc_coproc_deinit(self); - return mp_const_none; -} -MP_DEFINE_CONST_FUN_OBJ_1(coproc_coproc_deinit_obj, coproc_coproc_obj_deinit); - -//| def __enter__(self) -> Coproc: -//| """No-op used in Context Managers.""" -//| ... -// Provided by context manager helper. - -//| def __exit__(self) -> None: -//| """Close the request.""" -//| ... -//| -STATIC mp_obj_t coproc_coproc_obj___exit__(size_t n_args, const mp_obj_t *args) { - (void)n_args; - mp_check_self(mp_obj_is_type(args[0], &coproc_coproc_type)); - return coproc_coproc_obj_deinit(args[0]); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(coproc_coproc___exit___obj, 4, 4, coproc_coproc_obj___exit__); - -STATIC const mp_rom_map_elem_t coproc_coproc_locals_dict_table[] = { - // context managers - { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) }, - { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&coproc_coproc___exit___obj) }, - - // functions - { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&coproc_coproc_deinit_obj) }, -}; -STATIC MP_DEFINE_CONST_DICT(coproc_coproc_locals_dict, coproc_coproc_locals_dict_table); - -const mp_obj_type_t coproc_coproc_type = { - { &mp_type_type }, - .name = MP_QSTR_Coproc, - .make_new = coproc_coproc_make_new, - .locals_dict = (mp_obj_dict_t *)&coproc_coproc_locals_dict, -}; diff --git a/shared-bindings/coproc/CoprocMemory.h b/shared-bindings/coproc/CoprocMemory.h deleted file mode 100644 index fdbb2fa0fa..0000000000 --- a/shared-bindings/coproc/CoprocMemory.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * This file is part of the Micro Python project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2022 microDev - * - * 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. - */ - -#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_COPROC_COPROCMEMORY_H -#define MICROPY_INCLUDED_SHARED_BINDINGS_COPROC_COPROCMEMORY_H - -#include "common-hal/coproc/CoprocMemory.h" - -extern const mp_obj_type_t coproc_memory_type; - -uint32_t common_hal_coproc_memory_get_length(coproc_memory_obj_t *self); - -bool common_hal_coproc_memory_set_bytes(coproc_memory_obj_t *self, uint32_t start_index, const uint8_t *values, uint32_t len); -void common_hal_coproc_memory_get_bytes(coproc_memory_obj_t *self, uint32_t start_index, uint8_t *values, uint32_t len); - -#endif // MICROPY_INCLUDED_SHARED_BINDINGS_COPROC_COPROCMEMORY_H diff --git a/shared-bindings/coproc/__init__.c b/shared-bindings/coproc/__init__.c deleted file mode 100644 index 06b196d8be..0000000000 --- a/shared-bindings/coproc/__init__.c +++ /dev/null @@ -1,115 +0,0 @@ -/* - * This file is part of the Micro Python project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2022 microDev - * - * 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 "shared-bindings/util.h" -#include "shared-bindings/coproc/__init__.h" -#include "shared-bindings/coproc/Coproc.h" -#include "shared-bindings/coproc/CoprocMemory.h" - -#include "py/runtime.h" - -//| """COPROC Module -//| -//| The `coproc` module adds ability to load and run -//| programs on a co-processor or a different cpu core. -//| -//| .. code-block:: python -//| -//| import coproc -//| -//| shared_mem = coproc.CoprocMemory(address=0x500007fc, length=1024) -//| -//| with open("program.bin", "rb") as f: -//| program = coproc.Coproc(buffer=f.read(), memory=shared_mem) -//| -//| coproc.run(program) -//| print(coproc.memory(program)[0]) -//| # coproc.halt(program) -//| """ -//| ... -//| - -STATIC coproc_coproc_obj_t *get_coproc_obj(mp_obj_t *self_in) { - if (!mp_obj_is_type(*self_in, &coproc_coproc_type)) { - mp_raise_TypeError_varg(translate("Expected a %q"), MP_QSTR_Coproc); - } - coproc_coproc_obj_t *self = MP_OBJ_TO_PTR(*self_in); - if (common_hal_coproc_coproc_deinited(self)) { - raise_deinited_error(); - } - return self; -} - -//| def run(*coproc: Coproc) -> None: -//| """Runs the loaded program.""" -//| ... -//| -STATIC mp_obj_t coproc_run(mp_obj_t self_in) { - common_hal_coproc_run(get_coproc_obj(&self_in)); - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(coproc_run_obj, coproc_run); - -//| def halt(*coproc: Coproc) -> None: -//| """Halts the loaded program.""" -//| ... -//| -STATIC mp_obj_t coproc_halt(mp_obj_t self_in) { - common_hal_coproc_halt(get_coproc_obj(&self_in)); - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(coproc_halt_obj, coproc_halt); - -//| def memory(*coproc: Coproc) -> CoprocMemory: -//| """Returns the shared memory as a bytearray.""" -//| ... -//| -STATIC mp_obj_t coproc_memory(mp_obj_t self_in) { - return common_hal_coproc_memory(get_coproc_obj(&self_in)); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(coproc_memory_obj, coproc_memory); - -STATIC const mp_rom_map_elem_t coproc_module_globals_table[] = { - // module name - { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_coproc) }, - - // module functions - { MP_ROM_QSTR(MP_QSTR_run), MP_ROM_PTR(&coproc_run_obj) }, - { MP_ROM_QSTR(MP_QSTR_halt), MP_ROM_PTR(&coproc_halt_obj) }, - { MP_ROM_QSTR(MP_QSTR_memory), MP_ROM_PTR(&coproc_memory_obj) }, - - // module classes - { MP_ROM_QSTR(MP_QSTR_Coproc), MP_OBJ_FROM_PTR(&coproc_coproc_type) }, - { MP_ROM_QSTR(MP_QSTR_CoprocMemory), MP_OBJ_FROM_PTR(&coproc_memory_type) }, -}; -STATIC MP_DEFINE_CONST_DICT(coproc_module_globals, coproc_module_globals_table); - -const mp_obj_module_t coproc_module = { - .base = { &mp_type_module }, - .globals = (mp_obj_dict_t *)&coproc_module_globals, -}; - -MP_REGISTER_MODULE(MP_QSTR_coproc, coproc_module, CIRCUITPY_COPROC); diff --git a/shared-bindings/coproc/CoprocMemory.c b/shared-bindings/memorymap/AddressRange.c similarity index 59% rename from shared-bindings/coproc/CoprocMemory.c rename to shared-bindings/memorymap/AddressRange.c index 0d49a2f008..511400d0af 100644 --- a/shared-bindings/coproc/CoprocMemory.c +++ b/shared-bindings/memorymap/AddressRange.c @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2022 microDev + * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -28,45 +28,62 @@ #include "py/objproperty.h" #include "py/runtime.h" #include "py/runtime0.h" - -#include "shared-bindings/coproc/CoprocMemory.h" +#include "shared-bindings/memorymap/AddressRange.h" #include "supervisor/shared/translate/translate.h" -//| class CoprocMemory: -//| def __init__(self, address: int, length: int) -> None: -//| """Initialize coproc shared memory. +//| class AddressRange: +//| r"""Presents a range of addresses as a bytearray. //| -//| :param address: address of shared memory -//| :param length: length of shared memory""" -STATIC mp_obj_t coproc_memory_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { - enum { ARG_address, ARG_length }; - static const mp_arg_t allowed_args[] = { - { MP_QSTR_address, MP_ARG_REQUIRED | MP_ARG_INT }, - { MP_QSTR_length, MP_ARG_REQUIRED | MP_ARG_INT }, - }; +//| The addresses may access memory or memory mapped peripherals. +//| +//| Some address ranges may be protected by CircuitPython to prevent errors. +//| An exception will be raised when constructing an AddressRange for an +//| invalid or protected address. +//| +//| Multiple AddressRanges may overlap. There is no "claiming" of addresses. +//| +//| Example usage on ESP32-S2:: +//| +//| import memorymap +//| rtc_slow_mem = memorymap.AddressRange(start=0x50000000, length=0x2000) +//| rtc_slow_mem[0:3] = b"\xcc\x10\x00" +//| """ +//| def __init__(self, *, start, length) -> None: +//| """Constructs an address range starting at ``start`` and ending at +//| ``start + length``. An exception will be raised if any of the +//| addresses are invalid or protected.""" +//| ... +STATIC mp_obj_t memorymap_addressrange_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { + enum { ARG_start, ARG_length }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_start, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_INT }, + { MP_QSTR_length, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_INT }, + }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - coproc_memory_obj_t *self = m_new_obj(coproc_memory_obj_t); - self->base.type = &coproc_memory_type; - self->address = args[ARG_address].u_int; - self->len = args[ARG_length].u_int; + size_t start = + mp_arg_validate_int_min(args[ARG_start].u_int, 0, MP_QSTR_start); + size_t length = + mp_arg_validate_int_min(args[ARG_length].u_int, 1, MP_QSTR_length); + + + memorymap_addressrange_obj_t *self = m_new_obj(memorymap_addressrange_obj_t); + self->base.type = &memorymap_addressrange_type; + + common_hal_memorymap_addressrange_construct(self, (uint8_t *)start, length); return MP_OBJ_FROM_PTR(self); } -//| def __bool__(self) -> bool: -//| """``coproc_memory`` is ``True`` if its length is greater than zero. -//| This is an easy way to check for its existence. -//| """ -//| ... +//| def __bool__(self) -> bool: ... //| def __len__(self) -> int: //| """Return the length. This is used by (`len`)""" //| ... -STATIC mp_obj_t coproc_memory_unary_op(mp_unary_op_t op, mp_obj_t self_in) { - coproc_memory_obj_t *self = MP_OBJ_TO_PTR(self_in); - uint16_t len = common_hal_coproc_memory_get_length(self); +STATIC mp_obj_t memorymap_addressrange_unary_op(mp_unary_op_t op, mp_obj_t self_in) { + memorymap_addressrange_obj_t *self = MP_OBJ_TO_PTR(self_in); + uint16_t len = common_hal_memorymap_addressrange_get_length(self); switch (op) { case MP_UNARY_OP_BOOL: return mp_obj_new_bool(len != 0); @@ -77,36 +94,42 @@ STATIC mp_obj_t coproc_memory_unary_op(mp_unary_op_t op, mp_obj_t self_in) { } } -STATIC const mp_rom_map_elem_t coproc_memory_locals_dict_table[] = { +STATIC const mp_rom_map_elem_t memorymap_addressrange_locals_dict_table[] = { }; -STATIC MP_DEFINE_CONST_DICT(coproc_memory_locals_dict, coproc_memory_locals_dict_table); +STATIC MP_DEFINE_CONST_DICT(memorymap_addressrange_locals_dict, memorymap_addressrange_locals_dict_table); //| @overload //| def __getitem__(self, index: slice) -> bytearray: ... //| @overload //| def __getitem__(self, index: int) -> int: -//| """Returns the value at the given index.""" +//| """Returns the value(s) at the given index. +//| +//| 1, 2, 4 and 8 byte reads will be done in one assignment. All others +//| will use memcpy.""" //| ... //| @overload //| def __setitem__(self, index: slice, value: ReadableBuffer) -> None: ... //| @overload //| def __setitem__(self, index: int, value: int) -> None: -//| """Set the value at the given index.""" +//| """Set the value(s) at the given index. +//| +//| 1, 2, 4 and 8 byte writes will be done in one assignment. All others +//| will use memcpy.""" //| ... //| -STATIC mp_obj_t coproc_memory_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value) { +STATIC mp_obj_t memorymap_addressrange_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value) { if (value == MP_OBJ_NULL) { // delete item // slice deletion return MP_OBJ_NULL; // op not supported } else { - coproc_memory_obj_t *self = MP_OBJ_TO_PTR(self_in); + memorymap_addressrange_obj_t *self = MP_OBJ_TO_PTR(self_in); if (0) { #if MICROPY_PY_BUILTINS_SLICE } else if (mp_obj_is_type(index_in, &mp_type_slice)) { mp_bound_slice_t slice; - if (!mp_seq_get_fast_slice_indexes(common_hal_coproc_memory_get_length(self), index_in, &slice)) { + if (!mp_seq_get_fast_slice_indexes(common_hal_memorymap_addressrange_get_length(self), index_in, &slice)) { mp_raise_NotImplementedError(translate("only slices with step=1 (aka None) are supported")); } if (value != MP_OBJ_SENTINEL) { @@ -132,8 +155,8 @@ STATIC mp_obj_t coproc_memory_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj mp_raise_NotImplementedError(translate("array/bytes required on right side")); } - if (!common_hal_coproc_memory_set_bytes(self, slice.start, src_items, src_len)) { - mp_raise_RuntimeError(translate("Unable to write")); + if (!common_hal_memorymap_addressrange_set_bytes(self, slice.start, src_items, src_len)) { + mp_raise_RuntimeError(translate("Unable to write to address.")); } return mp_const_none; #else @@ -143,18 +166,18 @@ STATIC mp_obj_t coproc_memory_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj // Read slice. size_t len = slice.stop - slice.start; uint8_t *items = m_new(uint8_t, len); - common_hal_coproc_memory_get_bytes(self, slice.start, items, len); + common_hal_memorymap_addressrange_get_bytes(self, slice.start, len, items); return mp_obj_new_bytearray_by_ref(len, items); } #endif } else { // Single index rather than slice. - size_t index = mp_get_index(self->base.type, common_hal_coproc_memory_get_length(self), + size_t index = mp_get_index(self->base.type, common_hal_memorymap_addressrange_get_length(self), index_in, false); if (value == MP_OBJ_SENTINEL) { // load uint8_t value_out; - common_hal_coproc_memory_get_bytes(self, index, &value_out, 1); + common_hal_memorymap_addressrange_get_bytes(self, index, 1, &value_out); return MP_OBJ_NEW_SMALL_INT(value_out); } else { // store @@ -162,8 +185,8 @@ STATIC mp_obj_t coproc_memory_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj mp_arg_validate_int_range(byte_value, 0, 255, MP_QSTR_bytes); uint8_t short_value = byte_value; - if (!common_hal_coproc_memory_set_bytes(self, index, &short_value, 1)) { - mp_raise_RuntimeError(translate("Unable to write")); + if (!common_hal_memorymap_addressrange_set_bytes(self, index, &short_value, 1)) { + mp_raise_RuntimeError(translate("Unable to write to address.")); } return mp_const_none; } @@ -171,14 +194,14 @@ STATIC mp_obj_t coproc_memory_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj } } -const mp_obj_type_t coproc_memory_type = { +const mp_obj_type_t memorymap_addressrange_type = { { &mp_type_type }, - .name = MP_QSTR_CoprocMemory, .flags = MP_TYPE_FLAG_EXTENDED, - .make_new = coproc_memory_make_new, - .locals_dict = (mp_obj_t)&coproc_memory_locals_dict, + .name = MP_QSTR_AddressRange, + .make_new = memorymap_addressrange_make_new, + .locals_dict = (mp_obj_t)&memorymap_addressrange_locals_dict, MP_TYPE_EXTENDED_FIELDS( - .subscr = coproc_memory_subscr, - .unary_op = coproc_memory_unary_op, + .subscr = memorymap_addressrange_subscr, + .unary_op = memorymap_addressrange_unary_op, ), }; diff --git a/ports/espressif/common-hal/coproc/CoprocMemory.c b/shared-bindings/memorymap/AddressRange.h similarity index 53% rename from ports/espressif/common-hal/coproc/CoprocMemory.c rename to shared-bindings/memorymap/AddressRange.h index ca9a82dbcf..74a214d949 100644 --- a/ports/espressif/common-hal/coproc/CoprocMemory.c +++ b/shared-bindings/memorymap/AddressRange.h @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2022 microDev + * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -24,29 +24,23 @@ * THE SOFTWARE. */ -#include "shared-bindings/coproc/CoprocMemory.h" +#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_MEMORYMAP_ADDRESSRANGE_H +#define MICROPY_INCLUDED_SHARED_BINDINGS_MEMORYMAP_ADDRESSRANGE_H -uint32_t common_hal_coproc_memory_get_length(coproc_memory_obj_t *self) { - return self->len; -} +#include "common-hal/memorymap/AddressRange.h" -bool common_hal_coproc_memory_set_bytes(coproc_memory_obj_t *self, - uint32_t start_index, const uint8_t *values, uint32_t len) { +extern const mp_obj_type_t memorymap_addressrange_type; - if (start_index + len > self->len) { - return false; - } +void common_hal_memorymap_addressrange_construct(memorymap_addressrange_obj_t *self, uint8_t *start_address, size_t length); - memcpy((uint8_t *)(self->address + start_index), values, len); - return true; -} +uint32_t common_hal_memorymap_addressrange_get_length(const memorymap_addressrange_obj_t *self); -void common_hal_coproc_memory_get_bytes(coproc_memory_obj_t *self, - uint32_t start_index, uint8_t *values, uint32_t len) { +bool common_hal_memorymap_addressrange_set_bytes(const memorymap_addressrange_obj_t *self, + uint32_t start_index, uint8_t *values, uint32_t len); - if (start_index + len > self->len) { - return; - } +// len and values are intentionally swapped to signify values is an output and +// also leverage the compiler to validate uses are expected. +void common_hal_memorymap_addressrange_get_bytes(const memorymap_addressrange_obj_t *self, + uint32_t start_index, uint32_t len, uint8_t *values); - memcpy(values, (uint8_t *)(self->address + start_index), len); -} +#endif // MICROPY_INCLUDED_SHARED_BINDINGS_MEMORYMAP_ADDRESSRANGE_H diff --git a/shared-bindings/memorymap/__init__.c b/shared-bindings/memorymap/__init__.c new file mode 100644 index 0000000000..576c7f1e1d --- /dev/null +++ b/shared-bindings/memorymap/__init__.c @@ -0,0 +1,52 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries + * + * 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 "py/obj.h" +#include "py/mphal.h" +#include "py/runtime.h" + +#include "shared-bindings/memorymap/__init__.h" +#include "shared-bindings/memorymap/AddressRange.h" + +//| """Raw memory map access +//| +//| The `memorymap` module allows you to read and write memory addresses in the +//| address space seen from the processor running CircuitPython. It is usually +//| the physical address space. +//| """ +STATIC const mp_rom_map_elem_t memorymap_module_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_memorymap) }, + { MP_ROM_QSTR(MP_QSTR_AddressRange), MP_ROM_PTR(&memorymap_addressrange_type) }, +}; + +STATIC MP_DEFINE_CONST_DICT(memorymap_module_globals, memorymap_module_globals_table); + +const mp_obj_module_t memorymap_module = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t *)&memorymap_module_globals, +}; + +MP_REGISTER_MODULE(MP_QSTR_memorymap, memorymap_module, CIRCUITPY_MEMORYMAP); diff --git a/shared-bindings/memorymap/__init__.h b/shared-bindings/memorymap/__init__.h new file mode 100644 index 0000000000..f4e6c51481 --- /dev/null +++ b/shared-bindings/memorymap/__init__.h @@ -0,0 +1,30 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2022 Scott Shawcroft for Adafruit Industries + * + * 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. + */ + +#ifndef SHARED_BINDINGS_MEMORYMAP_H +#define SHARED_BINDINGS_MEMORYMAP_H + +#endif // SHARED_BINDINGS_MEMORYMAP_H diff --git a/supervisor/shared/reload.c b/supervisor/shared/reload.c index e1ae2e6764..4e351704f8 100644 --- a/supervisor/shared/reload.c +++ b/supervisor/shared/reload.c @@ -28,6 +28,7 @@ #include "py/mphal.h" #include "py/mpstate.h" +#include "supervisor/port.h" #include "supervisor/shared/reload.h" #include "supervisor/shared/tick.h" @@ -52,6 +53,7 @@ void reload_initiate(supervisor_run_reason_t run_reason) { MP_STATE_VM(sched_state) = MP_SCHED_PENDING; } #endif + port_wake_main_task(); } void autoreload_reset() { diff --git a/supervisor/shared/web_workflow/web_workflow.c b/supervisor/shared/web_workflow/web_workflow.c index 35d5c46a94..c34c3b3c9f 100644 --- a/supervisor/shared/web_workflow/web_workflow.c +++ b/supervisor/shared/web_workflow/web_workflow.c @@ -246,6 +246,15 @@ void supervisor_web_workflow_status(void) { void supervisor_start_web_workflow(void) { #if CIRCUITPY_WEB_WORKFLOW && CIRCUITPY_WIFI && CIRCUITPY_OS_GETENV + // Skip starting the workflow if we're not starting from power on or reset. + const mcu_reset_reason_t reset_reason = common_hal_mcu_processor_get_reset_reason(); + if (reset_reason != RESET_REASON_POWER_ON && + reset_reason != RESET_REASON_RESET_PIN && + reset_reason != RESET_REASON_UNKNOWN && + reset_reason != RESET_REASON_SOFTWARE) { + return; + } + char ssid[33]; char password[64];