Skip to content

Commit 2a1bb72

Browse files
authored
Merge pull request #7359 from tannewt/rework_coproc_api
Rework the coproc API
2 parents e9f032f + c16b42e commit 2a1bb72

38 files changed

+993
-800
lines changed

locale/circuitpython.pot

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ msgstr ""
100100
msgid "%q failure: %d"
101101
msgstr ""
102102

103+
#: ports/espressif/common-hal/espulp/ULP.c
103104
#: ports/raspberrypi/common-hal/rp2pio/StateMachine.c
104105
#: shared-bindings/digitalio/DigitalInOut.c
105106
#: shared-bindings/microcontroller/Pin.c
@@ -180,7 +181,6 @@ msgstr ""
180181

181182
#: ports/atmel-samd/common-hal/pulseio/PulseIn.c
182183
#: ports/cxd56/common-hal/pulseio/PulseIn.c
183-
#: ports/espressif/common-hal/coproc/Coproc.c
184184
#: ports/nrf/common-hal/pulseio/PulseIn.c
185185
#: ports/raspberrypi/common-hal/rp2pio/StateMachine.c
186186
#: ports/stm/common-hal/pulseio/PulseIn.c py/argcheck.c
@@ -393,6 +393,10 @@ msgstr ""
393393
msgid "Address must be %d bytes long"
394394
msgstr ""
395395

396+
#: ports/espressif/common-hal/memorymap/AddressRange.c
397+
msgid "Address range not allowed"
398+
msgstr ""
399+
396400
#: ports/espressif/common-hal/canio/CAN.c
397401
msgid "All CAN peripherals are in use"
398402
msgstr ""
@@ -473,7 +477,7 @@ msgstr ""
473477
msgid "Already have all-matches listener"
474478
msgstr ""
475479

476-
#: ports/espressif/common-hal/coproc/__init__.c
480+
#: ports/espressif/common-hal/espulp/ULP.c
477481
#: shared-module/memorymonitor/AllocationAlarm.c
478482
#: shared-module/memorymonitor/AllocationSize.c
479483
msgid "Already running"
@@ -497,7 +501,7 @@ msgstr ""
497501
msgid "Array must contain halfwords (type 'H')"
498502
msgstr ""
499503

500-
#: shared-bindings/alarm/SleepMemory.c shared-bindings/coproc/CoprocMemory.c
504+
#: shared-bindings/alarm/SleepMemory.c shared-bindings/memorymap/AddressRange.c
501505
#: shared-bindings/nvm/ByteArray.c
502506
msgid "Array values should be single bytes."
503507
msgstr ""
@@ -914,10 +918,10 @@ msgstr ""
914918
msgid "Error: Failure to bind"
915919
msgstr ""
916920

917-
#: py/enum.c shared-bindings/_bleio/__init__.c shared-bindings/aesio/aes.c
918-
#: shared-bindings/alarm/__init__.c shared-bindings/alarm/coproc/CoprocAlarm.c
919-
#: shared-bindings/busio/SPI.c shared-bindings/coproc/Coproc.c
920-
#: shared-bindings/coproc/__init__.c shared-bindings/microcontroller/Pin.c
921+
#: ports/espressif/bindings/espulp/ULP.c py/enum.c
922+
#: shared-bindings/_bleio/__init__.c shared-bindings/aesio/aes.c
923+
#: shared-bindings/alarm/__init__.c shared-bindings/busio/SPI.c
924+
#: shared-bindings/microcontroller/Pin.c
921925
#: shared-bindings/neopixel_write/__init__.c
922926
msgid "Expected a %q"
923927
msgstr ""
@@ -1020,7 +1024,6 @@ msgstr ""
10201024
msgid "Firmware is invalid"
10211025
msgstr ""
10221026

1023-
#: ports/espressif/common-hal/coproc/Coproc.c
10241027
#: ports/espressif/common-hal/dualbank/__init__.c
10251028
msgid "Firmware is too big"
10261029
msgstr ""
@@ -1628,11 +1631,14 @@ msgid ""
16281631
"%d bpp given"
16291632
msgstr ""
16301633

1631-
#: ports/espressif/common-hal/alarm/coproc/CoprocAlarm.c
16321634
#: ports/espressif/common-hal/alarm/touch/TouchAlarm.c
16331635
msgid "Only one %q can be set in deep sleep."
16341636
msgstr ""
16351637

1638+
#: ports/espressif/common-hal/espulp/ULPAlarm.c
1639+
msgid "Only one %q can be set."
1640+
msgstr ""
1641+
16361642
#: ports/espressif/common-hal/i2ctarget/I2CTarget.c
16371643
#: ports/raspberrypi/common-hal/i2ctarget/I2CTarget.c
16381644
msgid "Only one address is allowed"
@@ -1748,6 +1754,10 @@ msgid ""
17481754
"constructor"
17491755
msgstr ""
17501756

1757+
#: ports/espressif/common-hal/espulp/ULP.c
1758+
msgid "Pins 21+ not supported from ULP"
1759+
msgstr ""
1760+
17511761
#: ports/raspberrypi/common-hal/imagecapture/ParallelImageCapture.c
17521762
msgid "Pins must be sequential"
17531763
msgstr ""
@@ -1792,6 +1802,10 @@ msgstr ""
17921802
msgid "Program size invalid"
17931803
msgstr ""
17941804

1805+
#: ports/espressif/common-hal/espulp/ULP.c
1806+
msgid "Program too long"
1807+
msgstr ""
1808+
17951809
#: shared-bindings/digitalio/DigitalInOut.c
17961810
msgid "Pull not used when direction is output."
17971811
msgstr ""
@@ -1936,7 +1950,7 @@ msgstr ""
19361950
msgid "Sleep Memory not available"
19371951
msgstr ""
19381952

1939-
#: shared-bindings/alarm/SleepMemory.c shared-bindings/coproc/CoprocMemory.c
1953+
#: shared-bindings/alarm/SleepMemory.c shared-bindings/memorymap/AddressRange.c
19401954
#: shared-bindings/nvm/ByteArray.c
19411955
msgid "Slice and value different lengths."
19421956
msgstr ""
@@ -2210,8 +2224,8 @@ msgstr ""
22102224
msgid "Unable to start mDNS query"
22112225
msgstr ""
22122226

2213-
#: shared-bindings/coproc/CoprocMemory.c
2214-
msgid "Unable to write"
2227+
#: shared-bindings/memorymap/AddressRange.c
2228+
msgid "Unable to write to address."
22152229
msgstr ""
22162230

22172231
#: shared-bindings/nvm/ByteArray.c
@@ -2467,7 +2481,7 @@ msgid "array has too many dimensions"
24672481
msgstr ""
24682482

24692483
#: py/objarray.c shared-bindings/alarm/SleepMemory.c
2470-
#: shared-bindings/coproc/CoprocMemory.c shared-bindings/nvm/ByteArray.c
2484+
#: shared-bindings/memorymap/AddressRange.c shared-bindings/nvm/ByteArray.c
24712485
msgid "array/bytes required on right side"
24722486
msgstr ""
24732487

@@ -3725,7 +3739,7 @@ msgid "only sample_rate=16000 is supported"
37253739
msgstr ""
37263740

37273741
#: py/objarray.c py/objstr.c py/objstrunicode.c py/objtuple.c
3728-
#: shared-bindings/alarm/SleepMemory.c shared-bindings/coproc/CoprocMemory.c
3742+
#: shared-bindings/alarm/SleepMemory.c shared-bindings/memorymap/AddressRange.c
37293743
#: shared-bindings/nvm/ByteArray.c
37303744
msgid "only slices with step=1 (aka None) are supported"
37313745
msgstr ""

ports/espressif/Makefile

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -100,8 +100,6 @@ INC += \
100100
-isystem esp-idf/components/soc/include \
101101
-isystem esp-idf/components/soc/$(IDF_TARGET)/include \
102102
-isystem esp-idf/components/spi_flash/include \
103-
-isystem esp-idf/components/ulp/include \
104-
-isystem esp-idf/components/ulp/ulp_riscv/include \
105103
-isystem esp-idf/components/$(IDF_TARGET_ARCH)/include \
106104
-isystem esp-idf/components/$(IDF_TARGET_ARCH)/$(IDF_TARGET)/include
107105

@@ -261,6 +259,15 @@ CFLAGS += -isystem esp32-camera/driver/include
261259
CFLAGS += -isystem esp32-camera/conversions/include
262260
endif
263261

262+
ifneq ($(CIRCUITPY_ESPULP),0)
263+
SRC_ULP := \
264+
$(wildcard common-hal/espulp/*.c) \
265+
$(wildcard bindings/espulp/*.c)
266+
SRC_C += $(SRC_ULP)
267+
CFLAGS += -isystem esp-idf/components/ulp/include
268+
CFLAGS += -isystem esp-idf/components/ulp/ulp_riscv/include
269+
endif
270+
264271
SRC_COMMON_HAL_EXPANDED = \
265272
$(addprefix shared-bindings/, $(SRC_COMMON_HAL)) \
266273
$(addprefix shared-bindings/, $(SRC_BINDINGS_ENUMS)) \
@@ -364,7 +371,7 @@ ifneq ($(CIRCUITPY_BLEIO),0)
364371
BINARY_BLOBS += esp-idf/components/esp_phy/lib/$(IDF_TARGET)/libbtbb.a \
365372
esp-idf/components/bt/controller/lib_esp32c3_family/$(IDF_TARGET)/libbtdm_app.a
366373
endif
367-
ifneq ($(CIRCUITPY_COPROC),0)
374+
ifneq ($(CIRCUITPY_ESPULP),0)
368375
ESP_IDF_COMPONENTS_LINK += ulp
369376
endif
370377

ports/espressif/bindings/espulp/ULP.c

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
/*
2+
* This file is part of the Micro Python project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2022 microDev
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the "Software"), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in
16+
* all copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
* THE SOFTWARE.
25+
*/
26+
27+
#include "shared-bindings/microcontroller/Pin.h"
28+
#include "shared-bindings/util.h"
29+
#include "bindings/espulp/ULP.h"
30+
31+
#include "py/runtime.h"
32+
33+
//| class ULP:
34+
//| def __init__(self):
35+
//| """The ultra-low-power processor.
36+
//|
37+
//| Raises an exception if another ULP has been instantiated. This
38+
//| ensures that is is only used by one piece of code at a time."""
39+
//| ...
40+
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) {
41+
espulp_ulp_obj_t *self = m_new_obj(espulp_ulp_obj_t);
42+
self->base.type = &espulp_ulp_type;
43+
common_hal_espulp_ulp_construct(self);
44+
return MP_OBJ_FROM_PTR(self);
45+
}
46+
47+
STATIC espulp_ulp_obj_t *get_ulp_obj(mp_obj_t self_in) {
48+
if (!mp_obj_is_type(self_in, &espulp_ulp_type)) {
49+
mp_raise_TypeError_varg(translate("Expected a %q"), MP_QSTR_ULP);
50+
}
51+
espulp_ulp_obj_t *self = MP_OBJ_TO_PTR(self_in);
52+
if (common_hal_espulp_ulp_deinited(self)) {
53+
raise_deinited_error();
54+
}
55+
return self;
56+
}
57+
58+
//| def deinit(self) -> None:
59+
//| """Deinitialises the ULP and releases it for another program."""
60+
//| ...
61+
STATIC mp_obj_t espulp_ulp_deinit(mp_obj_t self_in) {
62+
espulp_ulp_obj_t *self = get_ulp_obj(self_in);
63+
common_hal_espulp_ulp_deinit(self);
64+
return mp_const_none;
65+
}
66+
STATIC MP_DEFINE_CONST_FUN_OBJ_1(espulp_ulp_deinit_obj, espulp_ulp_deinit);
67+
68+
//| def __enter__(self) -> ULP:
69+
//| """No-op used by Context Managers."""
70+
//| ...
71+
// Provided by context manager helper.
72+
73+
//| def __exit__(self) -> None:
74+
//| """Automatically deinitializes the hardware when exiting a context. See
75+
//| :ref:`lifetime-and-contextmanagers` for more info."""
76+
//| ...
77+
STATIC mp_obj_t espulp_ulp_obj___exit__(size_t n_args, const mp_obj_t *args) {
78+
(void)n_args;
79+
return espulp_ulp_deinit(args[0]);
80+
}
81+
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(espulp_ulp___exit___obj, 4, 4, espulp_ulp_obj___exit__);
82+
83+
//| def run(
84+
//| self, program: ReadableBuffer, *, pins: Sequence[microcontroller.Pin] = ()
85+
//| ) -> None:
86+
//| """Loads the program into ULP memory and then runs the program. The given pins are
87+
//| claimed and not reset until `halt()` is called.
88+
//|
89+
//| The program will continue to run even when the running Python is halted."""
90+
//| ...
91+
STATIC mp_obj_t espulp_ulp_run(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
92+
enum { ARG_program, ARG_pins };
93+
static const mp_arg_t allowed_args[] = {
94+
{ MP_QSTR_program, MP_ARG_REQUIRED | MP_ARG_OBJ},
95+
{ MP_QSTR_pins, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_empty_tuple} },
96+
};
97+
98+
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
99+
espulp_ulp_obj_t *self = get_ulp_obj(pos_args[0]);
100+
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
101+
102+
mp_buffer_info_t bufinfo;
103+
mp_get_buffer_raise(args[ARG_program].u_obj, &bufinfo, MP_BUFFER_READ);
104+
105+
mp_obj_t pins_in = args[ARG_pins].u_obj;
106+
const size_t num_pins = (size_t)MP_OBJ_SMALL_INT_VALUE(mp_obj_len(pins_in));
107+
108+
// The ULP only supports 21 pins on the ESP32-S2 and S3. So we can store it
109+
// as a bitmask in a 32 bit number. The common-hal code does further checks.
110+
uint32_t pin_mask = 0;
111+
112+
for (mp_uint_t i = 0; i < num_pins; i++) {
113+
mp_obj_t pin_obj = mp_obj_subscr(pins_in, MP_OBJ_NEW_SMALL_INT(i), MP_OBJ_SENTINEL);
114+
validate_obj_is_free_pin(pin_obj);
115+
const mcu_pin_obj_t *pin = ((const mcu_pin_obj_t *)pin_obj);
116+
if (pin->number >= 32) {
117+
raise_ValueError_invalid_pin();
118+
}
119+
pin_mask |= 1 << pin->number;
120+
}
121+
122+
common_hal_espulp_ulp_run(self, bufinfo.buf, bufinfo.len, pin_mask);
123+
return mp_const_none;
124+
}
125+
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(espulp_ulp_run_obj, 2, espulp_ulp_run);
126+
127+
//| def halt(self) -> None:
128+
//| """Halts the running program and releases the pins given in `run()`."""
129+
//| ...
130+
//|
131+
STATIC mp_obj_t espulp_ulp_halt(mp_obj_t self_in) {
132+
common_hal_espulp_ulp_halt(get_ulp_obj(self_in));
133+
return mp_const_none;
134+
}
135+
STATIC MP_DEFINE_CONST_FUN_OBJ_1(espulp_ulp_halt_obj, espulp_ulp_halt);
136+
137+
STATIC const mp_rom_map_elem_t espulp_ulp_locals_table[] = {
138+
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&espulp_ulp_deinit_obj) },
139+
{ MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&mp_identity_obj) },
140+
{ MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&espulp_ulp___exit___obj) },
141+
{ MP_ROM_QSTR(MP_QSTR_run), MP_ROM_PTR(&espulp_ulp_run_obj) },
142+
{ MP_ROM_QSTR(MP_QSTR_halt), MP_ROM_PTR(&espulp_ulp_halt_obj) },
143+
};
144+
STATIC MP_DEFINE_CONST_DICT(espulp_ulp_locals_dict, espulp_ulp_locals_table);
145+
146+
const mp_obj_type_t espulp_ulp_type = {
147+
{ &mp_type_type },
148+
.name = MP_QSTR_ULP,
149+
.make_new = espulp_ulp_make_new,
150+
.locals_dict = (mp_obj_t)&espulp_ulp_locals_dict,
151+
};

shared-bindings/coproc/__init__.h renamed to ports/espressif/bindings/espulp/ULP.h

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,17 @@
2424
* THE SOFTWARE.
2525
*/
2626

27-
#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_COPROC___INIT___H
28-
#define MICROPY_INCLUDED_SHARED_BINDINGS_COPROC___INIT___H
27+
#pragma once
2928

3029
#include "py/obj.h"
31-
#include "common-hal/coproc/Coproc.h"
30+
#include "common-hal/espulp/ULP.h"
3231

33-
extern void common_hal_coproc_run(coproc_coproc_obj_t *self);
34-
extern void common_hal_coproc_halt(coproc_coproc_obj_t *self);
35-
extern mp_obj_t common_hal_coproc_memory(coproc_coproc_obj_t *self);
3632

37-
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_COPROC___INIT___H
33+
extern const mp_obj_type_t espulp_ulp_type;
34+
35+
void common_hal_espulp_ulp_construct(espulp_ulp_obj_t *self);
36+
bool common_hal_espulp_ulp_deinited(espulp_ulp_obj_t *self);
37+
void common_hal_espulp_ulp_deinit(espulp_ulp_obj_t *self);
38+
39+
void common_hal_espulp_ulp_run(espulp_ulp_obj_t *self, uint32_t *program, size_t length, uint32_t pin_mask);
40+
void common_hal_espulp_ulp_halt(espulp_ulp_obj_t *self);

0 commit comments

Comments
 (0)