Skip to content

Commit a7b12de

Browse files
authored
Merge pull request #7473 from MicroDev1/espulp
Add ULP FSM
2 parents 5fb0333 + bfb77d0 commit a7b12de

File tree

13 files changed

+228
-34
lines changed

13 files changed

+228
-34
lines changed
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/*
2+
* This file is part of the MicroPython project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2023 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 "py/enum.h"
28+
29+
#include "bindings/espulp/Architecture.h"
30+
31+
MAKE_ENUM_VALUE(espulp_architecture_type, architecture, FSM, FSM);
32+
MAKE_ENUM_VALUE(espulp_architecture_type, architecture, RISCV, RISCV);
33+
34+
//| class Architecture:
35+
//| """The ULP architectures available."""
36+
//|
37+
//| FSM: Architecture
38+
//| """The ULP Finite State Machine."""
39+
//|
40+
//| RISCV: Architecture
41+
//| """The ULP RISC-V Coprocessor."""
42+
//|
43+
MAKE_ENUM_MAP(espulp_architecture) {
44+
MAKE_ENUM_MAP_ENTRY(architecture, FSM),
45+
MAKE_ENUM_MAP_ENTRY(architecture, RISCV),
46+
};
47+
STATIC MP_DEFINE_CONST_DICT(espulp_architecture_locals_dict, espulp_architecture_locals_table);
48+
49+
MAKE_PRINTER(espulp, espulp_architecture);
50+
51+
MAKE_ENUM_TYPE(espulp, Architecture, espulp_architecture);
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*
2+
* This file is part of the MicroPython project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2023 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+
#ifndef MICROPY_INCLUDED_BINDINGS_ESPULP_ARCHITECTURE_H
28+
#define MICROPY_INCLUDED_BINDINGS_ESPULP_ARCHITECTURE_H
29+
30+
#include "py/enum.h"
31+
32+
typedef enum {
33+
FSM,
34+
RISCV
35+
} espulp_architecture_t;
36+
37+
extern const mp_obj_type_t espulp_architecture_type;
38+
extern const cp_enum_obj_t architecture_FSM_obj;
39+
40+
#endif // MICROPY_INCLUDED_BINDINGS_ESPULP_ARCHITECTURE_H

ports/espressif/bindings/espulp/ULP.c

Lines changed: 39 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,19 +28,35 @@
2828
#include "shared-bindings/util.h"
2929
#include "bindings/espulp/ULP.h"
3030

31+
#include "py/enum.h"
3132
#include "py/runtime.h"
33+
#include "py/objproperty.h"
3234

3335
//| class ULP:
34-
//| def __init__(self):
36+
//| def __init__(self, arch: Architecture = Architecture.FSM):
3537
//| """The ultra-low-power processor.
3638
//|
3739
//| 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."""
40+
//| ensures that is is only used by one piece of code at a time.
41+
//|
42+
//| :param Architecture arch: The ulp arch"""
3943
//| ...
4044
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) {
45+
enum { ARG_arch };
46+
static const mp_arg_t allowed_args[] = {
47+
{ MP_QSTR_arch, MP_ARG_OBJ, {.u_obj = (void *)&architecture_FSM_obj} },
48+
};
49+
50+
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
51+
mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
52+
53+
const espulp_architecture_t arch = cp_enum_value(&espulp_architecture_type, args[ARG_arch].u_obj, MP_QSTR_arch);
54+
4155
espulp_ulp_obj_t *self = m_new_obj(espulp_ulp_obj_t);
4256
self->base.type = &espulp_ulp_type;
43-
common_hal_espulp_ulp_construct(self);
57+
58+
common_hal_espulp_ulp_construct(self, arch);
59+
4460
return MP_OBJ_FROM_PTR(self);
4561
}
4662

@@ -124,7 +140,6 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(espulp_ulp_run_obj, 2, espulp_ulp_run);
124140
//| def halt(self) -> None:
125141
//| """Halts the running program and releases the pins given in `run()`."""
126142
//| ...
127-
//|
128143
STATIC mp_obj_t espulp_ulp_halt(mp_obj_t self_in) {
129144
espulp_ulp_obj_t *self = MP_OBJ_TO_PTR(self_in);
130145
check_for_deinit(self);
@@ -134,12 +149,27 @@ STATIC mp_obj_t espulp_ulp_halt(mp_obj_t self_in) {
134149
}
135150
STATIC MP_DEFINE_CONST_FUN_OBJ_1(espulp_ulp_halt_obj, espulp_ulp_halt);
136151

152+
//| arch: Architecture
153+
//| """The ulp architecture. (read-only)"""
154+
//|
155+
STATIC mp_obj_t espulp_ulp_get_arch(mp_obj_t self_in) {
156+
espulp_ulp_obj_t *self = MP_OBJ_TO_PTR(self_in);
157+
check_for_deinit(self);
158+
159+
return cp_enum_find(&espulp_architecture_type, self->arch);
160+
}
161+
MP_DEFINE_CONST_FUN_OBJ_1(espulp_ulp_get_arch_obj, espulp_ulp_get_arch);
162+
163+
MP_PROPERTY_GETTER(espulp_ulp_arch_obj,
164+
(mp_obj_t)&espulp_ulp_get_arch_obj);
165+
137166
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) },
167+
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&espulp_ulp_deinit_obj) },
168+
{ MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&mp_identity_obj) },
169+
{ MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&espulp_ulp___exit___obj) },
170+
{ MP_ROM_QSTR(MP_QSTR_run), MP_ROM_PTR(&espulp_ulp_run_obj) },
171+
{ MP_ROM_QSTR(MP_QSTR_halt), MP_ROM_PTR(&espulp_ulp_halt_obj) },
172+
{ MP_ROM_QSTR(MP_QSTR_arch), MP_ROM_PTR(&espulp_ulp_arch_obj) },
143173
};
144174
STATIC MP_DEFINE_CONST_DICT(espulp_ulp_locals_dict, espulp_ulp_locals_table);
145175

ports/espressif/bindings/espulp/ULP.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,9 @@
2929
#include "py/obj.h"
3030
#include "common-hal/espulp/ULP.h"
3131

32-
3332
extern const mp_obj_type_t espulp_ulp_type;
3433

35-
void common_hal_espulp_ulp_construct(espulp_ulp_obj_t *self);
34+
void common_hal_espulp_ulp_construct(espulp_ulp_obj_t *self, espulp_architecture_t arch);
3635
bool common_hal_espulp_ulp_deinited(espulp_ulp_obj_t *self);
3736
void common_hal_espulp_ulp_deinit(espulp_ulp_obj_t *self);
3837

ports/espressif/bindings/espulp/ULPAlarm.c

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,25 +27,36 @@
2727
#include "bindings/espulp/ULPAlarm.h"
2828

2929
#include "py/runtime.h"
30+
#include "py/objproperty.h"
3031

3132
//| class ULPAlarm:
3233
//| """Trigger an alarm when the ULP requests wake-up."""
3334
//|
34-
//| def __init__(self) -> None:
35+
//| def __init__(self, ulp: ULP) -> None:
3536
//| """Create an alarm that will be triggered when the ULP requests wake-up.
3637
//|
3738
//| The alarm is not active until it is passed to an `alarm`-enabling function, such as
3839
//| `alarm.light_sleep_until_alarms()` or `alarm.exit_and_deep_sleep_until_alarms()`.
3940
//|
40-
//| """
41+
//| :param ULP ulp: The ulp instance"""
4142
//| ...
4243
//|
43-
STATIC mp_obj_t espulp_ulpalarm_make_new(const mp_obj_type_t *type,
44-
size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
44+
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) {
45+
enum { ARG_ulp };
46+
static const mp_arg_t allowed_args[] = {
47+
{ MP_QSTR_ulp, MP_ARG_REQUIRED | MP_ARG_OBJ },
48+
};
49+
50+
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
51+
mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
4552

4653
espulp_ulpalarm_obj_t *self = m_new_obj(espulp_ulpalarm_obj_t);
4754
self->base.type = &espulp_ulpalarm_type;
48-
common_hal_espulp_ulpalarm_construct(self);
55+
56+
espulp_ulp_obj_t *ulp = mp_arg_validate_type(args[ARG_ulp].u_obj, &espulp_ulp_type, MP_QSTR_ulp);
57+
58+
common_hal_espulp_ulpalarm_construct(self, ulp);
59+
4960
return MP_OBJ_FROM_PTR(self);
5061
}
5162

ports/espressif/bindings/espulp/ULPAlarm.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,4 @@
3030

3131
extern const mp_obj_type_t espulp_ulpalarm_type;
3232

33-
void common_hal_espulp_ulpalarm_construct(espulp_ulpalarm_obj_t *self);
33+
void common_hal_espulp_ulpalarm_construct(espulp_ulpalarm_obj_t *self, espulp_ulp_obj_t *ulp);

ports/espressif/bindings/espulp/__init__.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,11 @@
2525
*/
2626

2727
#include "shared-bindings/util.h"
28+
2829
#include "bindings/espulp/__init__.h"
2930
#include "bindings/espulp/ULP.h"
3031
#include "bindings/espulp/ULPAlarm.h"
32+
#include "bindings/espulp/Architecture.h"
3133

3234
#include "py/runtime.h"
3335

@@ -80,6 +82,7 @@ STATIC const mp_rom_map_elem_t espulp_module_globals_table[] = {
8082
// module classes
8183
{ MP_ROM_QSTR(MP_QSTR_ULP), MP_OBJ_FROM_PTR(&espulp_ulp_type) },
8284
{ MP_ROM_QSTR(MP_QSTR_ULPAlarm), MP_OBJ_FROM_PTR(&espulp_ulpalarm_type) },
85+
{ MP_ROM_QSTR(MP_QSTR_Architecture), MP_ROM_PTR(&espulp_architecture_type) },
8386
};
8487
STATIC MP_DEFINE_CONST_DICT(espulp_module_globals, espulp_module_globals_table);
8588

ports/espressif/common-hal/espulp/ULP.c

Lines changed: 41 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,10 @@
3131

3232
#include "shared-bindings/microcontroller/Pin.h"
3333

34-
#if defined(CONFIG_IDF_TARGET_ESP32S2)
34+
#if defined(CONFIG_IDF_TARGET_ESP32)
35+
#include "esp32/ulp.h"
36+
#define ULP_COPROC_RESERVE_MEM (CONFIG_ESP32_ULP_COPROC_RESERVE_MEM)
37+
#elif defined(CONFIG_IDF_TARGET_ESP32S2)
3538
#include "esp32s2/ulp.h"
3639
#include "esp32s2/ulp_riscv.h"
3740
#define ULP_COPROC_RESERVE_MEM (CONFIG_ESP32S2_ULP_COPROC_RESERVE_MEM)
@@ -56,7 +59,14 @@ void common_hal_espulp_ulp_run(espulp_ulp_obj_t *self, uint32_t *program, size_t
5659
if (length > ULP_COPROC_RESERVE_MEM) {
5760
mp_raise_ValueError(translate("Program too long"));
5861
}
59-
if (GET_PERI_REG_MASK(RTC_CNTL_ULP_CP_TIMER_REG, RTC_CNTL_ULP_CP_SLP_TIMER_EN)) {
62+
63+
if (
64+
#ifdef CONFIG_IDF_TARGET_ESP32
65+
GET_PERI_REG_MASK(RTC_CNTL_STATE0_REG, RTC_CNTL_ULP_CP_SLP_TIMER_EN)
66+
#else
67+
GET_PERI_REG_MASK(RTC_CNTL_ULP_CP_TIMER_REG, RTC_CNTL_ULP_CP_SLP_TIMER_EN)
68+
#endif
69+
) {
6070
mp_raise_RuntimeError(translate("Already running"));
6171
}
6272

@@ -78,13 +88,29 @@ void common_hal_espulp_ulp_run(espulp_ulp_obj_t *self, uint32_t *program, size_t
7888
}
7989
pins_used = pin_mask;
8090

81-
82-
ulp_riscv_load_binary((const uint8_t *)program, length);
8391
ulp_set_wakeup_period(0, 20000);
84-
ulp_riscv_run();
92+
93+
switch (self->arch) {
94+
case FSM:
95+
ulp_load_binary(0, (const uint8_t *)program, length);
96+
ulp_run(0);
97+
break;
98+
case RISCV:
99+
#ifndef CONFIG_IDF_TARGET_ESP32
100+
ulp_riscv_load_binary((const uint8_t *)program, length);
101+
ulp_riscv_run();
102+
break;
103+
#endif
104+
default:
105+
mp_raise_NotImplementedError(NULL);
106+
break;
107+
}
85108
}
86109

87110
void common_hal_espulp_ulp_halt(espulp_ulp_obj_t *self) {
111+
#ifdef CONFIG_IDF_TARGET_ESP32
112+
mp_raise_NotImplementedError(NULL);
113+
#else
88114
// To-do idf v5.0: use following functions
89115
// ulp_riscv_timer_stop();
90116
// ulp_riscv_halt();
@@ -97,6 +123,7 @@ void common_hal_espulp_ulp_halt(espulp_ulp_obj_t *self) {
97123

98124
// resets the processor
99125
SET_PERI_REG_MASK(RTC_CNTL_COCPU_CTRL_REG, RTC_CNTL_COCPU_SHUT_RESET_EN);
126+
#endif
100127

101128
// Release pins we were using.
102129
for (uint8_t i = 0; i < 32; i++) {
@@ -106,13 +133,21 @@ void common_hal_espulp_ulp_halt(espulp_ulp_obj_t *self) {
106133
}
107134
}
108135

109-
void common_hal_espulp_ulp_construct(espulp_ulp_obj_t *self) {
136+
void common_hal_espulp_ulp_construct(espulp_ulp_obj_t *self, espulp_architecture_t arch) {
110137
// Use a static variable to track ULP in use so that subsequent code runs can
111138
// use a running ULP. This is only to prevent multiple portions of user code
112139
// from using the ULP concurrently.
113140
if (ulp_used) {
114141
mp_raise_ValueError_varg(translate("%q in use"), MP_QSTR_ULP);
115142
}
143+
144+
#ifdef CONFIG_IDF_TARGET_ESP32
145+
if (self->arch == RISCV) {
146+
mp_raise_NotImplementedError(NULL);
147+
}
148+
#endif
149+
150+
self->arch = arch;
116151
self->inited = true;
117152
}
118153

ports/espressif/common-hal/espulp/ULP.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,10 @@
2727
#pragma once
2828

2929
#include "py/obj.h"
30+
#include "bindings/espulp/Architecture.h"
3031

3132
typedef struct {
3233
mp_obj_base_t base;
34+
espulp_architecture_t arch;
3335
bool inited;
3436
} espulp_ulp_obj_t;

0 commit comments

Comments
 (0)