Skip to content

Commit

Permalink
Rework the coproc API
Browse files Browse the repository at this point in the history
It is now a generic `memorymap` API and an ESP specific `espulp` module.

Fixes #7218. Fixes #3234. Fixes #7300.
  • Loading branch information
tannewt committed Dec 19, 2022
1 parent 9629a0c commit f8ac1d9
Show file tree
Hide file tree
Showing 37 changed files with 921 additions and 740 deletions.
42 changes: 28 additions & 14 deletions locale/circuitpython.pot
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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 ""
Expand Down Expand Up @@ -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"
Expand All @@ -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 ""
Expand Down Expand Up @@ -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 ""
Expand Down Expand Up @@ -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 ""
Expand Down Expand Up @@ -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"
Expand Down Expand Up @@ -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 ""
Expand Down Expand Up @@ -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 ""
Expand Down Expand Up @@ -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 ""
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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 ""

Expand Down Expand Up @@ -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 ""
Expand Down
13 changes: 10 additions & 3 deletions ports/espressif/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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)) \
Expand Down Expand Up @@ -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

Expand Down
144 changes: 144 additions & 0 deletions ports/espressif/bindings/espulp/ULP.c
Original file line number Diff line number Diff line change
@@ -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,
};
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Original file line number Diff line number Diff line change
@@ -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)
*
Expand All @@ -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,
};
Loading

0 comments on commit f8ac1d9

Please sign in to comment.