Rework the coproc API

It is now a generic `memorymap` API and an ESP specific `espulp` module.

Fixes #7218. Fixes #3234. Fixes #7300.
This commit is contained in:
Scott Shawcroft 2022-12-02 14:54:42 -08:00
parent 9629a0cc4e
commit f8ac1d9261
No known key found for this signature in database
GPG Key ID: 9349BC7E64B1921E
37 changed files with 922 additions and 741 deletions

View File

@ -100,6 +100,7 @@ msgstr ""
msgid "%q failure: %d" msgid "%q failure: %d"
msgstr "" msgstr ""
#: ports/espressif/common-hal/espulp/ULP.c
#: ports/raspberrypi/common-hal/rp2pio/StateMachine.c #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c
#: shared-bindings/digitalio/DigitalInOut.c #: shared-bindings/digitalio/DigitalInOut.c
#: shared-bindings/microcontroller/Pin.c #: shared-bindings/microcontroller/Pin.c
@ -180,7 +181,6 @@ msgstr ""
#: ports/atmel-samd/common-hal/pulseio/PulseIn.c #: ports/atmel-samd/common-hal/pulseio/PulseIn.c
#: ports/cxd56/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/nrf/common-hal/pulseio/PulseIn.c
#: ports/raspberrypi/common-hal/rp2pio/StateMachine.c #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c
#: ports/stm/common-hal/pulseio/PulseIn.c py/argcheck.c #: ports/stm/common-hal/pulseio/PulseIn.c py/argcheck.c
@ -393,6 +393,10 @@ msgstr ""
msgid "Address must be %d bytes long" msgid "Address must be %d bytes long"
msgstr "" msgstr ""
#: ports/espressif/common-hal/memorymap/AddressRange.c
msgid "Address range not allowed"
msgstr ""
#: ports/espressif/common-hal/canio/CAN.c #: ports/espressif/common-hal/canio/CAN.c
msgid "All CAN peripherals are in use" msgid "All CAN peripherals are in use"
msgstr "" msgstr ""
@ -473,7 +477,7 @@ msgstr ""
msgid "Already have all-matches listener" msgid "Already have all-matches listener"
msgstr "" msgstr ""
#: ports/espressif/common-hal/coproc/__init__.c #: ports/espressif/common-hal/espulp/ULP.c
#: shared-module/memorymonitor/AllocationAlarm.c #: shared-module/memorymonitor/AllocationAlarm.c
#: shared-module/memorymonitor/AllocationSize.c #: shared-module/memorymonitor/AllocationSize.c
msgid "Already running" msgid "Already running"
@ -497,7 +501,7 @@ msgstr ""
msgid "Array must contain halfwords (type 'H')" msgid "Array must contain halfwords (type 'H')"
msgstr "" 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 #: shared-bindings/nvm/ByteArray.c
msgid "Array values should be single bytes." msgid "Array values should be single bytes."
msgstr "" msgstr ""
@ -914,10 +918,10 @@ msgstr ""
msgid "Error: Failure to bind" msgid "Error: Failure to bind"
msgstr "" msgstr ""
#: py/enum.c shared-bindings/_bleio/__init__.c shared-bindings/aesio/aes.c #: ports/espressif/bindings/espulp/ULP.c py/enum.c
#: shared-bindings/alarm/__init__.c shared-bindings/alarm/coproc/CoprocAlarm.c #: shared-bindings/_bleio/__init__.c shared-bindings/aesio/aes.c
#: shared-bindings/busio/SPI.c shared-bindings/coproc/Coproc.c #: shared-bindings/alarm/__init__.c shared-bindings/busio/SPI.c
#: shared-bindings/coproc/__init__.c shared-bindings/microcontroller/Pin.c #: shared-bindings/microcontroller/Pin.c
#: shared-bindings/neopixel_write/__init__.c #: shared-bindings/neopixel_write/__init__.c
msgid "Expected a %q" msgid "Expected a %q"
msgstr "" msgstr ""
@ -1020,7 +1024,6 @@ msgstr ""
msgid "Firmware is invalid" msgid "Firmware is invalid"
msgstr "" msgstr ""
#: ports/espressif/common-hal/coproc/Coproc.c
#: ports/espressif/common-hal/dualbank/__init__.c #: ports/espressif/common-hal/dualbank/__init__.c
msgid "Firmware is too big" msgid "Firmware is too big"
msgstr "" msgstr ""
@ -1628,11 +1631,14 @@ msgid ""
"%d bpp given" "%d bpp given"
msgstr "" msgstr ""
#: ports/espressif/common-hal/alarm/coproc/CoprocAlarm.c
#: ports/espressif/common-hal/alarm/touch/TouchAlarm.c #: ports/espressif/common-hal/alarm/touch/TouchAlarm.c
msgid "Only one %q can be set in deep sleep." msgid "Only one %q can be set in deep sleep."
msgstr "" msgstr ""
#: ports/espressif/common-hal/espulp/ULPAlarm.c
msgid "Only one %q can be set."
msgstr ""
#: ports/espressif/common-hal/i2ctarget/I2CTarget.c #: ports/espressif/common-hal/i2ctarget/I2CTarget.c
#: ports/raspberrypi/common-hal/i2ctarget/I2CTarget.c #: ports/raspberrypi/common-hal/i2ctarget/I2CTarget.c
msgid "Only one address is allowed" msgid "Only one address is allowed"
@ -1748,6 +1754,10 @@ msgid ""
"constructor" "constructor"
msgstr "" msgstr ""
#: ports/espressif/common-hal/espulp/ULP.c
msgid "Pins 21+ not supported from ULP"
msgstr ""
#: ports/raspberrypi/common-hal/imagecapture/ParallelImageCapture.c #: ports/raspberrypi/common-hal/imagecapture/ParallelImageCapture.c
msgid "Pins must be sequential" msgid "Pins must be sequential"
msgstr "" msgstr ""
@ -1792,6 +1802,10 @@ msgstr ""
msgid "Program size invalid" msgid "Program size invalid"
msgstr "" msgstr ""
#: ports/espressif/common-hal/espulp/ULP.c
msgid "Program too long"
msgstr ""
#: shared-bindings/digitalio/DigitalInOut.c #: shared-bindings/digitalio/DigitalInOut.c
msgid "Pull not used when direction is output." msgid "Pull not used when direction is output."
msgstr "" msgstr ""
@ -1936,7 +1950,7 @@ msgstr ""
msgid "Sleep Memory not available" msgid "Sleep Memory not available"
msgstr "" 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 #: shared-bindings/nvm/ByteArray.c
msgid "Slice and value different lengths." msgid "Slice and value different lengths."
msgstr "" msgstr ""
@ -2210,8 +2224,8 @@ msgstr ""
msgid "Unable to start mDNS query" msgid "Unable to start mDNS query"
msgstr "" msgstr ""
#: shared-bindings/coproc/CoprocMemory.c #: shared-bindings/memorymap/AddressRange.c
msgid "Unable to write" msgid "Unable to write to address."
msgstr "" msgstr ""
#: shared-bindings/nvm/ByteArray.c #: shared-bindings/nvm/ByteArray.c
@ -2467,7 +2481,7 @@ msgid "array has too many dimensions"
msgstr "" msgstr ""
#: py/objarray.c shared-bindings/alarm/SleepMemory.c #: 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" msgid "array/bytes required on right side"
msgstr "" msgstr ""
@ -3725,7 +3739,7 @@ msgid "only sample_rate=16000 is supported"
msgstr "" msgstr ""
#: py/objarray.c py/objstr.c py/objstrunicode.c py/objtuple.c #: 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 #: shared-bindings/nvm/ByteArray.c
msgid "only slices with step=1 (aka None) are supported" msgid "only slices with step=1 (aka None) are supported"
msgstr "" msgstr ""

View File

@ -100,8 +100,6 @@ INC += \
-isystem esp-idf/components/soc/include \ -isystem esp-idf/components/soc/include \
-isystem esp-idf/components/soc/$(IDF_TARGET)/include \ -isystem esp-idf/components/soc/$(IDF_TARGET)/include \
-isystem esp-idf/components/spi_flash/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)/include \
-isystem esp-idf/components/$(IDF_TARGET_ARCH)/$(IDF_TARGET)/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 CFLAGS += -isystem esp32-camera/conversions/include
endif 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 = \ SRC_COMMON_HAL_EXPANDED = \
$(addprefix shared-bindings/, $(SRC_COMMON_HAL)) \ $(addprefix shared-bindings/, $(SRC_COMMON_HAL)) \
$(addprefix shared-bindings/, $(SRC_BINDINGS_ENUMS)) \ $(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 \ 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 esp-idf/components/bt/controller/lib_esp32c3_family/$(IDF_TARGET)/libbtdm_app.a
endif endif
ifneq ($(CIRCUITPY_COPROC),0) ifneq ($(CIRCUITPY_ESPULP),0)
ESP_IDF_COMPONENTS_LINK += ulp ESP_IDF_COMPONENTS_LINK += ulp
endif endif

View File

@ -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,
};

View File

@ -24,14 +24,17 @@
* THE SOFTWARE. * THE SOFTWARE.
*/ */
#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_COPROC___INIT___H #pragma once
#define MICROPY_INCLUDED_SHARED_BINDINGS_COPROC___INIT___H
#include "py/obj.h" #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);

View File

@ -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) * The MIT License (MIT)
* *
@ -24,17 +24,33 @@
* THE SOFTWARE. * THE SOFTWARE.
*/ */
#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_COPROC_COPROC_H #include "bindings/espulp/ULPAlarm.h"
#define MICROPY_INCLUDED_SHARED_BINDINGS_COPROC_COPROC_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, espulp_ulpalarm_obj_t *self = m_new_obj(espulp_ulpalarm_obj_t);
const uint8_t *buf, const size_t buf_len, coproc_memory_obj_t *coproc_memory); 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); const mp_obj_type_t espulp_ulpalarm_type = {
extern bool common_hal_coproc_coproc_deinited(coproc_coproc_obj_t *self); { &mp_type_type },
.name = MP_QSTR_ULPAlarm,
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_COPROC_COPROC_H .make_new = espulp_ulpalarm_make_new,
};

View File

@ -24,11 +24,10 @@
* THE SOFTWARE. * THE SOFTWARE.
*/ */
#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_ALARM_COPROC_COPROCALARM_H #pragma once
#define MICROPY_INCLUDED_SHARED_BINDINGS_ALARM_COPROC_COPROCALARM_H
#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);

View File

@ -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);

View File

@ -24,17 +24,10 @@
* THE SOFTWARE. * THE SOFTWARE.
*/ */
#ifndef MICROPY_INCLUDED_ESPRESSIF_COMMON_HAL_COPROC_COPROC_H #pragma once
#define MICROPY_INCLUDED_ESPRESSIF_COMMON_HAL_COPROC_COPROC_H
#include "py/obj.h" #include "shared-bindings/microcontroller/Pin.h"
#include "common-hal/coproc/CoprocMemory.h"
typedef struct { void espulp_reset(void);
mp_obj_base_t base;
uint8_t *buf;
size_t buf_len;
coproc_memory_obj_t *coproc_memory;
} coproc_coproc_obj_t;
#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);

View File

@ -35,11 +35,14 @@
#include "shared-bindings/alarm/pin/PinAlarm.h" #include "shared-bindings/alarm/pin/PinAlarm.h"
#include "shared-bindings/alarm/time/TimeAlarm.h" #include "shared-bindings/alarm/time/TimeAlarm.h"
#include "shared-bindings/alarm/touch/TouchAlarm.h" #include "shared-bindings/alarm/touch/TouchAlarm.h"
#include "shared-bindings/alarm/coproc/CoprocAlarm.h"
#include "shared-bindings/wifi/__init__.h" #include "shared-bindings/wifi/__init__.h"
#include "shared-bindings/microcontroller/__init__.h" #include "shared-bindings/microcontroller/__init__.h"
#if CIRCUITPY_ESPULP
#include "bindings/espulp/ULPAlarm.h"
#endif
#include "common-hal/digitalio/DigitalInOut.h" #include "common-hal/digitalio/DigitalInOut.h"
#include "supervisor/port.h" #include "supervisor/port.h"
@ -67,7 +70,9 @@ void alarm_reset(void) {
alarm_pin_pinalarm_reset(); alarm_pin_pinalarm_reset();
alarm_time_timealarm_reset(); alarm_time_timealarm_reset();
alarm_touch_touchalarm_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); 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()) { if (alarm_touch_touchalarm_woke_this_cycle()) {
return ESP_SLEEP_WAKEUP_TOUCHPAD; 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; return ESP_SLEEP_WAKEUP_ULP;
} }
#endif
// If waking from true deep sleep, modules will have lost their state, // If waking from true deep sleep, modules will have lost their state,
// so check the deep wakeup cause manually // so check the deep wakeup cause manually
return esp_sleep_get_wakeup_cause(); 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(); return alarm_touch_touchalarm_record_wake_alarm();
} }
#if CIRCUITPY_ESPULP
case ESP_SLEEP_WAKEUP_ULP: { case ESP_SLEEP_WAKEUP_ULP: {
return alarm_coproc_coprocalarm_record_wake_alarm(); return espulp_ulpalarm_record_wake_alarm();
} }
#endif
case ESP_SLEEP_WAKEUP_UNDEFINED: case ESP_SLEEP_WAKEUP_UNDEFINED:
default: 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_pin_pinalarm_set_alarms(deep_sleep, n_alarms, alarms);
alarm_time_timealarm_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_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) { 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); wake_alarm = alarm_touch_touchalarm_find_triggered_alarm(n_alarms,alarms);
break; break;
} }
#if CIRCUITPY_ESPULP
case ESP_SLEEP_WAKEUP_ULP: { 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; break;
} }
#endif
default: default:
// Should not reach this, if all light sleep types are covered correctly // Should not reach this, if all light sleep types are covered correctly
break; 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) { void NORETURN common_hal_alarm_enter_deep_sleep(void) {
alarm_pin_pinalarm_prepare_for_deep_sleep(); alarm_pin_pinalarm_prepare_for_deep_sleep();
alarm_touch_touchalarm_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. // We no longer need to remember the pin preservations, since any pin resets are all done.
clear_pin_preservations(); clear_pin_preservations();

View File

@ -27,13 +27,16 @@
#pragma once #pragma once
#include "common-hal/alarm/SleepMemory.h" #include "common-hal/alarm/SleepMemory.h"
#include "common-hal/alarm/coproc/CoprocAlarm.h"
#include "common-hal/alarm/pin/PinAlarm.h" #include "common-hal/alarm/pin/PinAlarm.h"
#include "common-hal/alarm/time/TimeAlarm.h" #include "common-hal/alarm/time/TimeAlarm.h"
#include "common-hal/alarm/touch/TouchAlarm.h" #include "common-hal/alarm/touch/TouchAlarm.h"
#if CIRCUITPY_ESPULP
#include "common-hal/espulp/ULPAlarm.h"
#endif
typedef union { typedef union {
alarm_coproc_coprocalarm_obj_t coproc_alarm; espulp_ulpalarm_obj_t ulp_alarm;
alarm_pin_pinalarm_obj_t pin_alarm; alarm_pin_pinalarm_obj_t pin_alarm;
alarm_time_timealarm_obj_t time_alarm; alarm_time_timealarm_obj_t time_alarm;
alarm_touch_touchalarm_obj_t touch_alarm; alarm_touch_touchalarm_obj_t touch_alarm;

View File

@ -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

View File

@ -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;
}

View File

@ -24,49 +24,104 @@
* THE SOFTWARE. * THE SOFTWARE.
*/ */
#include "shared-bindings/coproc/__init__.h" #include "bindings/espulp/__init__.h"
#include "bindings/espulp/ULP.h"
#include "py/runtime.h" #include "py/runtime.h"
#include "shared-bindings/microcontroller/Pin.h"
#if defined(CONFIG_IDF_TARGET_ESP32S2) #if defined(CONFIG_IDF_TARGET_ESP32S2)
#include "esp32s2/ulp.h" #include "esp32s2/ulp.h"
#include "esp32s2/ulp_riscv.h" #include "esp32s2/ulp_riscv.h"
#define ULP_COPROC_RESERVE_MEM (CONFIG_ESP32S2_ULP_COPROC_RESERVE_MEM)
#elif defined(CONFIG_IDF_TARGET_ESP32S3) #elif defined(CONFIG_IDF_TARGET_ESP32S3)
#include "esp32s3/ulp.h" #include "esp32s3/ulp.h"
#include "esp32s3/ulp_riscv.h" #include "esp32s3/ulp_riscv.h"
#define ULP_COPROC_RESERVE_MEM (CONFIG_ESP32S3_ULP_COPROC_RESERVE_MEM)
#endif #endif
// To-do idf v5.0: remove following include // To-do idf v5.0: remove following include
#include "soc/rtc_cntl_reg.h" #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)) { if (GET_PERI_REG_MASK(RTC_CNTL_ULP_CP_TIMER_REG, RTC_CNTL_ULP_CP_SLP_TIMER_EN)) {
mp_raise_RuntimeError(translate("Already running")); mp_raise_RuntimeError(translate("Already running"));
} }
ulp_riscv_load_binary(self->buf, self->buf_len); if (pin_mask >= (1 << 22)) {
m_free(self->buf); mp_raise_ValueError(translate("Pins 21+ not supported from ULP"));
self->buf = (uint8_t *)RTC_SLOW_MEM; }
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(); ulp_riscv_run();
} }
void common_hal_coproc_halt(coproc_coproc_obj_t *self) { void common_hal_espulp_ulp_halt(espulp_ulp_obj_t *self) {
self->buf = (uint8_t *)m_malloc(self->buf_len, false);
memcpy(self->buf, (uint8_t *)RTC_SLOW_MEM, self->buf_len);
// To-do idf v5.0: use following functions // To-do idf v5.0: use following functions
// ulp_riscv_timer_stop(); // ulp_riscv_timer_stop();
// ulp_riscv_halt(); // 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); CLEAR_PERI_REG_MASK(RTC_CNTL_ULP_CP_TIMER_REG, RTC_CNTL_ULP_CP_SLP_TIMER_EN);
// suspends the ulp operation // suspends the ulp operation
SET_PERI_REG_MASK(RTC_CNTL_COCPU_CTRL_REG, RTC_CNTL_COCPU_DONE); SET_PERI_REG_MASK(RTC_CNTL_COCPU_CTRL_REG, RTC_CNTL_COCPU_DONE);
// resets the processor // resets the processor
SET_PERI_REG_MASK(RTC_CNTL_COCPU_CTRL_REG, RTC_CNTL_COCPU_SHUT_RESET_EN); 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) { void common_hal_espulp_ulp_construct(espulp_ulp_obj_t *self) {
return (self->coproc_memory) ? MP_OBJ_FROM_PTR(self->coproc_memory) : mp_const_none; 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;
} }

View File

@ -24,15 +24,11 @@
* THE SOFTWARE. * THE SOFTWARE.
*/ */
#ifndef MICROPY_INCLUDED_ESPRESSIF_COMMON_HAL_COPROC_COPROCMEMORY_H #pragma once
#define MICROPY_INCLUDED_ESPRESSIF_COMMON_HAL_COPROC_COPROCMEMORY_H
#include "py/obj.h" #include "py/obj.h"
typedef struct { typedef struct {
mp_obj_base_t base; mp_obj_base_t base;
uint32_t address; bool inited;
uint16_t len; } espulp_ulp_obj_t;
} coproc_memory_obj_t;
#endif // MICROPY_INCLUDED_ESPRESSIF_COMMON_HAL_COPROC_COPROCMEMORY_H

View File

@ -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;
}

View File

@ -29,17 +29,14 @@
#include "py/obj.h" #include "py/obj.h"
#include "py/runtime.h" #include "py/runtime.h"
#include "common-hal/coproc/Coproc.h"
typedef struct { typedef struct {
mp_obj_base_t base; mp_obj_base_t base;
coproc_coproc_obj_t *coproc; } espulp_ulpalarm_obj_t;
} alarm_coproc_coprocalarm_obj_t;
mp_obj_t alarm_coproc_coprocalarm_find_triggered_alarm(const size_t n_alarms, const mp_obj_t *alarms); mp_obj_t espulp_ulpalarm_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_record_wake_alarm(void);
void alarm_coproc_coprocalarm_prepare_for_deep_sleep(void); void espulp_ulpalarm_prepare_for_deep_sleep(void);
void alarm_coproc_coprocalarm_reset(void); void espulp_ulpalarm_reset(void);
void alarm_coproc_coprocalarm_set_alarm(const bool deep_sleep, const size_t n_alarms, const mp_obj_t *alarms); void espulp_ulpalarm_set_alarm(const bool deep_sleep, const size_t n_alarms, const mp_obj_t *alarms);
bool alarm_coproc_coprocalarm_woke_this_cycle(void); bool espulp_ulpalarm_woke_this_cycle(void);

View File

@ -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;
}

View File

@ -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 <string.h>
#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
}

View File

@ -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

View File

@ -0,0 +1 @@
// No memorymap module functions.

View File

@ -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_EXT0:
case ESP_SLEEP_WAKEUP_EXT1: case ESP_SLEEP_WAKEUP_EXT1:
case ESP_SLEEP_WAKEUP_TOUCHPAD: case ESP_SLEEP_WAKEUP_TOUCHPAD:
case ESP_SLEEP_WAKEUP_ULP:
return RESET_REASON_DEEP_SLEEP_ALARM; return RESET_REASON_DEEP_SLEEP_ALARM;
case ESP_SLEEP_WAKEUP_UNDEFINED: case ESP_SLEEP_WAKEUP_UNDEFINED:

@ -1 +1 @@
Subproject commit 20c6d4a623a9391afd0e803b2bbebe020ed15ec8 Subproject commit 8d0f1abce769ad4a212c1bb0337999cacd7ee83d

View File

@ -22,7 +22,6 @@ CIRCUITPY_AUDIOMP3 ?= 0
CIRCUITPY_BLEIO ?= 1 CIRCUITPY_BLEIO ?= 1
CIRCUITPY_BLEIO_HCI = 0 CIRCUITPY_BLEIO_HCI = 0
CIRCUITPY_CANIO ?= 1 CIRCUITPY_CANIO ?= 1
CIRCUITPY_COPROC ?= 1
CIRCUITPY_COUNTIO ?= 1 CIRCUITPY_COUNTIO ?= 1
CIRCUITPY_DUALBANK ?= 1 CIRCUITPY_DUALBANK ?= 1
CIRCUITPY_ESP32_CAMERA ?= 1 CIRCUITPY_ESP32_CAMERA ?= 1
@ -44,7 +43,6 @@ CIRCUITPY_WIFI ?= 1
ifeq ($(IDF_TARGET),esp32) ifeq ($(IDF_TARGET),esp32)
# Modules # Modules
CIRCUITPY_BLEIO = 0 CIRCUITPY_BLEIO = 0
CIRCUITPY_COPROC = 0
CIRCUITPY_PARALLELDISPLAY = 0 CIRCUITPY_PARALLELDISPLAY = 0
CIRCUITPY_RGBMATRIX = 0 CIRCUITPY_RGBMATRIX = 0
# Features # Features
@ -54,7 +52,6 @@ else ifeq ($(IDF_TARGET),esp32c3)
# Modules # Modules
CIRCUITPY_ALARM = 0 CIRCUITPY_ALARM = 0
CIRCUITPY_AUDIOBUSIO = 0 CIRCUITPY_AUDIOBUSIO = 0
CIRCUITPY_COPROC = 0
CIRCUITPY_COUNTIO = 0 CIRCUITPY_COUNTIO = 0
CIRCUITPY_ESP32_CAMERA = 0 CIRCUITPY_ESP32_CAMERA = 0
CIRCUITPY_FREQUENCYIO = 0 CIRCUITPY_FREQUENCYIO = 0
@ -68,10 +65,14 @@ CIRCUITPY_USB = 0
else ifeq ($(IDF_TARGET),esp32s2) else ifeq ($(IDF_TARGET),esp32s2)
# Modules # Modules
CIRCUITPY_BLEIO = 0 CIRCUITPY_BLEIO = 0
CIRCUITPY_ESPULP = 1
CIRCUITPY_MEMORYMAP = 1
else ifeq ($(IDF_TARGET),esp32s3) else ifeq ($(IDF_TARGET),esp32s3)
# Modules # Modules
CIRCUITPY_PARALLELDISPLAY = 0 CIRCUITPY_PARALLELDISPLAY = 0
CIRCUITPY_ESPULP = 1
CIRCUITPY_MEMORYMAP = 1
endif endif
# No room for dualbank on boards with 2MB flash # No room for dualbank on boards with 2MB flash

View File

@ -30,12 +30,14 @@
#include "supervisor/board.h" #include "supervisor/board.h"
#include "supervisor/port.h" #include "supervisor/port.h"
#include "supervisor/filesystem.h" #include "supervisor/filesystem.h"
#include "supervisor/shared/reload.h"
#include "py/runtime.h" #include "py/runtime.h"
#include "freertos/FreeRTOS.h" #include "freertos/FreeRTOS.h"
#include "freertos/task.h" #include "freertos/task.h"
#include "bindings/espidf/__init__.h" #include "bindings/espidf/__init__.h"
#include "bindings/espulp/__init__.h"
#include "common-hal/microcontroller/Pin.h" #include "common-hal/microcontroller/Pin.h"
#include "common-hal/analogio/AnalogOut.h" #include "common-hal/analogio/AnalogOut.h"
#include "common-hal/busio/I2C.h" #include "common-hal/busio/I2C.h"
@ -367,6 +369,10 @@ void reset_port(void) {
dualbank_reset(); dualbank_reset();
#endif #endif
#if CIRCUITPY_ESPULP
espulp_reset();
#endif
#if CIRCUITPY_FREQUENCYIO #if CIRCUITPY_FREQUENCYIO
peripherals_timer_reset(); peripherals_timer_reset();
#endif #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 // On the ESP we use FreeRTOS notifications instead of interrupts so this is a
// bit of a misnomer. // bit of a misnomer.
void port_idle_until_interrupt(void) { void port_idle_until_interrupt(void) {
if (!background_callback_pending()) { if (!background_callback_pending() && !autoreload_pending()) {
xTaskNotifyWait(0x01, 0x01, NULL, portMAX_DELAY); xTaskNotifyWait(0x01, 0x01, NULL, portMAX_DELAY);
} }
} }

View File

@ -167,9 +167,6 @@ endif
ifeq ($(CIRCUITPY_CANIO),1) ifeq ($(CIRCUITPY_CANIO),1)
SRC_PATTERNS += canio/% SRC_PATTERNS += canio/%
endif endif
ifeq ($(CIRCUITPY_COPROC),1)
SRC_PATTERNS += coproc/%
endif
ifeq ($(CIRCUITPY_COUNTIO),1) ifeq ($(CIRCUITPY_COUNTIO),1)
SRC_PATTERNS += countio/% SRC_PATTERNS += countio/%
endif endif
@ -227,6 +224,9 @@ endif
ifeq ($(CIRCUITPY_MATH),1) ifeq ($(CIRCUITPY_MATH),1)
SRC_PATTERNS += math/% SRC_PATTERNS += math/%
endif endif
ifeq ($(CIRCUITPY_MEMORYMAP),1)
SRC_PATTERNS += memorymap/%
endif
ifeq ($(CIRCUITPY_MEMORYMONITOR),1) ifeq ($(CIRCUITPY_MEMORYMONITOR),1)
SRC_PATTERNS += memorymonitor/% SRC_PATTERNS += memorymonitor/%
endif endif
@ -400,7 +400,6 @@ SRC_COMMON_HAL_ALL = \
alarm/pin/PinAlarm.c \ alarm/pin/PinAlarm.c \
alarm/time/TimeAlarm.c \ alarm/time/TimeAlarm.c \
alarm/touch/TouchAlarm.c \ alarm/touch/TouchAlarm.c \
alarm/coproc/CoprocAlarm.c \
analogbufio/BufferedIn.c \ analogbufio/BufferedIn.c \
analogbufio/__init__.c \ analogbufio/__init__.c \
analogio/AnalogIn.c \ analogio/AnalogIn.c \
@ -423,9 +422,6 @@ SRC_COMMON_HAL_ALL = \
canio/CAN.c \ canio/CAN.c \
canio/Listener.c \ canio/Listener.c \
canio/__init__.c \ canio/__init__.c \
coproc/__init__.c \
coproc/Coproc.c \
coproc/CoprocMemory.c \
countio/Counter.c \ countio/Counter.c \
countio/__init__.c \ countio/__init__.c \
digitalio/DigitalInOut.c \ digitalio/DigitalInOut.c \
@ -443,9 +439,11 @@ SRC_COMMON_HAL_ALL = \
hashlib/Hash.c \ hashlib/Hash.c \
i2ctarget/I2CTarget.c \ i2ctarget/I2CTarget.c \
i2ctarget/__init__.c \ i2ctarget/__init__.c \
memorymap/__init__.c \
memorymap/AddressRange.c \
microcontroller/__init__.c \
microcontroller/Pin.c \ microcontroller/Pin.c \
microcontroller/Processor.c \ microcontroller/Processor.c \
microcontroller/__init__.c \
mdns/__init__.c \ mdns/__init__.c \
mdns/Server.c \ mdns/Server.c \
mdns/RemoteService.c \ mdns/RemoteService.c \

View File

@ -221,12 +221,15 @@ CFLAGS += -DCIRCUITPY_OS_GETENV=$(CIRCUITPY_OS_GETENV)
CIRCUITPY_ERRNO ?= $(CIRCUITPY_FULL_BUILD) CIRCUITPY_ERRNO ?= $(CIRCUITPY_FULL_BUILD)
CFLAGS += -DCIRCUITPY_ERRNO=$(CIRCUITPY_ERRNO) 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. # Only for ESP32S chips.
# Assume not a ESP build. # Assume not a ESP build.
CIRCUITPY_ESPIDF ?= 0 CIRCUITPY_ESPIDF ?= 0
CFLAGS += -DCIRCUITPY_ESPIDF=$(CIRCUITPY_ESPIDF) CFLAGS += -DCIRCUITPY_ESPIDF=$(CIRCUITPY_ESPIDF)
CIRCUITPY_ESPULP ?= 0
CFLAGS += -DCIRCUITPY_ESPULP=$(CIRCUITPY_ESPULP)
CIRCUITPY_ESP32_CAMERA ?= 0 CIRCUITPY_ESP32_CAMERA ?= 0
CFLAGS += -DCIRCUITPY_ESP32_CAMERA=$(CIRCUITPY_ESP32_CAMERA) CFLAGS += -DCIRCUITPY_ESP32_CAMERA=$(CIRCUITPY_ESP32_CAMERA)
@ -283,6 +286,9 @@ CFLAGS += -DCIRCUITPY_KEYPAD=$(CIRCUITPY_KEYPAD)
CIRCUITPY_MATH ?= 1 CIRCUITPY_MATH ?= 1
CFLAGS += -DCIRCUITPY_MATH=$(CIRCUITPY_MATH) CFLAGS += -DCIRCUITPY_MATH=$(CIRCUITPY_MATH)
CIRCUITPY_MEMORYMAP ?= 0
CFLAGS += -DCIRCUITPY_MEMORYMAP=$(CIRCUITPY_MEMORYMAP)
CIRCUITPY_MEMORYMONITOR ?= 0 CIRCUITPY_MEMORYMONITOR ?= 0
CFLAGS += -DCIRCUITPY_MEMORYMONITOR=$(CIRCUITPY_MEMORYMONITOR) CFLAGS += -DCIRCUITPY_MEMORYMONITOR=$(CIRCUITPY_MEMORYMONITOR)

View File

@ -27,12 +27,15 @@
#include "py/obj.h" #include "py/obj.h"
#include "py/runtime.h" #include "py/runtime.h"
#if CIRCUITPY_ESPULP
#include "bindings/espulp/ULPAlarm.h"
#endif
#include "shared-bindings/alarm/__init__.h" #include "shared-bindings/alarm/__init__.h"
#include "shared-bindings/alarm/SleepMemory.h" #include "shared-bindings/alarm/SleepMemory.h"
#include "shared-bindings/alarm/pin/PinAlarm.h" #include "shared-bindings/alarm/pin/PinAlarm.h"
#include "shared-bindings/alarm/time/TimeAlarm.h" #include "shared-bindings/alarm/time/TimeAlarm.h"
#include "shared-bindings/alarm/touch/TouchAlarm.h" #include "shared-bindings/alarm/touch/TouchAlarm.h"
#include "shared-bindings/alarm/coproc/CoprocAlarm.h"
#include "shared-bindings/digitalio/DigitalInOut.h" #include "shared-bindings/digitalio/DigitalInOut.h"
#include "shared-bindings/supervisor/Runtime.h" #include "shared-bindings/supervisor/Runtime.h"
#include "shared-bindings/time/__init__.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++) { for (size_t i = 0; i < n_args; i++) {
if (mp_obj_is_type(objs[i], &alarm_pin_pinalarm_type) || 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_time_timealarm_type) ||
mp_obj_is_type(objs[i], &alarm_touch_touchalarm_type) || #if CIRCUITPY_ESPULP
mp_obj_is_type(objs[i], &alarm_coproc_coprocalarm_type)) { mp_obj_is_type(objs[i], &espulp_ulpalarm_type) ||
#endif
mp_obj_is_type(objs[i], &alarm_touch_touchalarm_type)) {
continue; continue;
} }
mp_raise_TypeError_varg(translate("Expected an %q"), MP_QSTR_Alarm); 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, .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. // The module table is mutable because .wake_alarm is a mutable attribute.
STATIC mp_map_elem_t alarm_module_globals_table[] = { STATIC mp_map_elem_t alarm_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_alarm) }, { 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_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_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_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_SleepMemory), MP_OBJ_FROM_PTR(&alarm_sleep_memory_type) },
{ MP_ROM_QSTR(MP_QSTR_sleep_memory), MP_OBJ_FROM_PTR(&alarm_sleep_memory_obj) }, { MP_ROM_QSTR(MP_QSTR_sleep_memory), MP_OBJ_FROM_PTR(&alarm_sleep_memory_obj) },

View File

@ -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,
};

View File

@ -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,
};

View File

@ -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

View File

@ -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);

View File

@ -3,7 +3,7 @@
* *
* The MIT License (MIT) * 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 * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
@ -28,45 +28,62 @@
#include "py/objproperty.h" #include "py/objproperty.h"
#include "py/runtime.h" #include "py/runtime.h"
#include "py/runtime0.h" #include "py/runtime0.h"
#include "shared-bindings/memorymap/AddressRange.h"
#include "shared-bindings/coproc/CoprocMemory.h"
#include "supervisor/shared/translate/translate.h" #include "supervisor/shared/translate/translate.h"
//| class CoprocMemory: //| class AddressRange:
//| def __init__(self, address: int, length: int) -> None: //| r"""Presents a range of addresses as a bytearray.
//| """Initialize coproc shared memory.
//| //|
//| :param address: address of shared memory //| The addresses may access memory or memory mapped peripherals.
//| :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) { //| Some address ranges may be protected by CircuitPython to prevent errors.
enum { ARG_address, ARG_length }; //| An exception will be raised when constructing an AddressRange for an
static const mp_arg_t allowed_args[] = { //| invalid or protected address.
{ MP_QSTR_address, MP_ARG_REQUIRED | MP_ARG_INT }, //|
{ MP_QSTR_length, MP_ARG_REQUIRED | MP_ARG_INT }, //| 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_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); 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); size_t start =
self->base.type = &coproc_memory_type; mp_arg_validate_int_min(args[ARG_start].u_int, 0, MP_QSTR_start);
self->address = args[ARG_address].u_int; size_t length =
self->len = args[ARG_length].u_int; 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); return MP_OBJ_FROM_PTR(self);
} }
//| def __bool__(self) -> bool: //| 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 __len__(self) -> int: //| def __len__(self) -> int:
//| """Return the length. This is used by (`len`)""" //| """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) { STATIC mp_obj_t memorymap_addressrange_unary_op(mp_unary_op_t op, mp_obj_t self_in) {
coproc_memory_obj_t *self = MP_OBJ_TO_PTR(self_in); memorymap_addressrange_obj_t *self = MP_OBJ_TO_PTR(self_in);
uint16_t len = common_hal_coproc_memory_get_length(self); uint16_t len = common_hal_memorymap_addressrange_get_length(self);
switch (op) { switch (op) {
case MP_UNARY_OP_BOOL: case MP_UNARY_OP_BOOL:
return mp_obj_new_bool(len != 0); 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 //| @overload
//| def __getitem__(self, index: slice) -> bytearray: ... //| def __getitem__(self, index: slice) -> bytearray: ...
//| @overload //| @overload
//| def __getitem__(self, index: int) -> int: //| 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 //| @overload
//| def __setitem__(self, index: slice, value: ReadableBuffer) -> None: ... //| def __setitem__(self, index: slice, value: ReadableBuffer) -> None: ...
//| @overload //| @overload
//| def __setitem__(self, index: int, value: int) -> None: //| 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) { if (value == MP_OBJ_NULL) {
// delete item // delete item
// slice deletion // slice deletion
return MP_OBJ_NULL; // op not supported return MP_OBJ_NULL; // op not supported
} else { } 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 (0) {
#if MICROPY_PY_BUILTINS_SLICE #if MICROPY_PY_BUILTINS_SLICE
} else if (mp_obj_is_type(index_in, &mp_type_slice)) { } else if (mp_obj_is_type(index_in, &mp_type_slice)) {
mp_bound_slice_t 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")); mp_raise_NotImplementedError(translate("only slices with step=1 (aka None) are supported"));
} }
if (value != MP_OBJ_SENTINEL) { 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")); mp_raise_NotImplementedError(translate("array/bytes required on right side"));
} }
if (!common_hal_coproc_memory_set_bytes(self, slice.start, src_items, src_len)) { if (!common_hal_memorymap_addressrange_set_bytes(self, slice.start, src_items, src_len)) {
mp_raise_RuntimeError(translate("Unable to write")); mp_raise_RuntimeError(translate("Unable to write to address."));
} }
return mp_const_none; return mp_const_none;
#else #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. // Read slice.
size_t len = slice.stop - slice.start; size_t len = slice.stop - slice.start;
uint8_t *items = m_new(uint8_t, len); 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); return mp_obj_new_bytearray_by_ref(len, items);
} }
#endif #endif
} else { } else {
// Single index rather than slice. // 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); index_in, false);
if (value == MP_OBJ_SENTINEL) { if (value == MP_OBJ_SENTINEL) {
// load // load
uint8_t value_out; 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); return MP_OBJ_NEW_SMALL_INT(value_out);
} else { } else {
// store // 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); mp_arg_validate_int_range(byte_value, 0, 255, MP_QSTR_bytes);
uint8_t short_value = byte_value; uint8_t short_value = byte_value;
if (!common_hal_coproc_memory_set_bytes(self, index, &short_value, 1)) { if (!common_hal_memorymap_addressrange_set_bytes(self, index, &short_value, 1)) {
mp_raise_RuntimeError(translate("Unable to write")); mp_raise_RuntimeError(translate("Unable to write to address."));
} }
return mp_const_none; 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 }, { &mp_type_type },
.name = MP_QSTR_CoprocMemory,
.flags = MP_TYPE_FLAG_EXTENDED, .flags = MP_TYPE_FLAG_EXTENDED,
.make_new = coproc_memory_make_new, .name = MP_QSTR_AddressRange,
.locals_dict = (mp_obj_t)&coproc_memory_locals_dict, .make_new = memorymap_addressrange_make_new,
.locals_dict = (mp_obj_t)&memorymap_addressrange_locals_dict,
MP_TYPE_EXTENDED_FIELDS( MP_TYPE_EXTENDED_FIELDS(
.subscr = coproc_memory_subscr, .subscr = memorymap_addressrange_subscr,
.unary_op = coproc_memory_unary_op, .unary_op = memorymap_addressrange_unary_op,
), ),
}; };

View File

@ -3,7 +3,7 @@
* *
* The MIT License (MIT) * 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 * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
@ -24,29 +24,23 @@
* THE SOFTWARE. * 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) { #include "common-hal/memorymap/AddressRange.h"
return self->len;
}
bool common_hal_coproc_memory_set_bytes(coproc_memory_obj_t *self, extern const mp_obj_type_t memorymap_addressrange_type;
uint32_t start_index, const uint8_t *values, uint32_t len) {
if (start_index + len > self->len) { void common_hal_memorymap_addressrange_construct(memorymap_addressrange_obj_t *self, uint8_t *start_address, size_t length);
return false;
}
memcpy((uint8_t *)(self->address + start_index), values, len); uint32_t common_hal_memorymap_addressrange_get_length(const memorymap_addressrange_obj_t *self);
return true;
}
void common_hal_coproc_memory_get_bytes(coproc_memory_obj_t *self, bool common_hal_memorymap_addressrange_set_bytes(const memorymap_addressrange_obj_t *self,
uint32_t start_index, uint8_t *values, uint32_t len) { uint32_t start_index, uint8_t *values, uint32_t len);
if (start_index + len > self->len) { // len and values are intentionally swapped to signify values is an output and
return; // 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
}

View File

@ -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);

View File

@ -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

View File

@ -28,6 +28,7 @@
#include "py/mphal.h" #include "py/mphal.h"
#include "py/mpstate.h" #include "py/mpstate.h"
#include "supervisor/port.h"
#include "supervisor/shared/reload.h" #include "supervisor/shared/reload.h"
#include "supervisor/shared/tick.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; MP_STATE_VM(sched_state) = MP_SCHED_PENDING;
} }
#endif #endif
port_wake_main_task();
} }
void autoreload_reset() { void autoreload_reset() {

View File

@ -246,6 +246,15 @@ void supervisor_web_workflow_status(void) {
void supervisor_start_web_workflow(void) { void supervisor_start_web_workflow(void) {
#if CIRCUITPY_WEB_WORKFLOW && CIRCUITPY_WIFI && CIRCUITPY_OS_GETENV #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 ssid[33];
char password[64]; char password[64];