19
19
//| Raises an exception if another ULP has been instantiated. This
20
20
//| ensures that is is only used by one piece of code at a time.
21
21
//|
22
- //| :param Architecture arch: The ulp arch"""
22
+ //| :param Architecture arch: The ulp arch.
23
+ //| """
23
24
//| ...
24
25
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 ) {
25
26
enum { ARG_arch };
@@ -70,21 +71,50 @@ static mp_obj_t espulp_ulp_obj___exit__(size_t n_args, const mp_obj_t *args) {
70
71
}
71
72
static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN (espulp_ulp___exit___obj , 4 , 4 , espulp_ulp_obj___exit__ ) ;
72
73
74
+ //| def set_wakeup_period(self, period_index: int, period_us: int) -> None:
75
+ //| """Sets the wakeup period for the ULP.
76
+ //|
77
+ //| :param int period_index: = 0..4. Up to 5 different wakeup periods can be stored
78
+ //| and used by the wakeup timer.
79
+ //| By default, the value stored in period index 0 is used.
80
+ //| :param int period_us: The wakeup period given in microseconds."""
81
+ //| ...
82
+ static mp_obj_t espulp_ulp_set_wakeup_period (mp_obj_t self_in , mp_obj_t period_index , mp_obj_t period_us ) {
83
+ espulp_ulp_obj_t * self = MP_OBJ_TO_PTR (self_in );
84
+ check_for_deinit (self );
85
+
86
+ // period_index should be between 0 and 4 but bounds checking happens in esp-idf, so no need to do that here
87
+ common_hal_espulp_ulp_set_wakeup_period (self , mp_obj_get_int (period_index ), mp_obj_get_int (period_us ));
88
+
89
+ return mp_const_none ;
90
+ }
91
+ static MP_DEFINE_CONST_FUN_OBJ_3 (espulp_ulp_set_wakeup_period_obj , espulp_ulp_set_wakeup_period ) ;
92
+
73
93
//| def run(
74
- //| self, program: ReadableBuffer, *, pins: Sequence[microcontroller.Pin] = ()
94
+ //| self,
95
+ //| program: ReadableBuffer,
96
+ //| *,
97
+ //| entrypoint: int = 0,
98
+ //| pins: Sequence[microcontroller.Pin] = ()
75
99
//| ) -> None:
76
- //| """Loads the program into ULP memory and then runs the program. The given pins are
77
- //| claimed and not reset until `halt()` is called.
100
+ //| """Loads the program into ULP memory and then runs the program.
78
101
//|
79
- //| The program will continue to run even when the running Python is halted."""
102
+ //| The program will continue to run even Python is halted or in deep-sleep.
103
+ //|
104
+ //| :param ReadableBuffer program: the ULP binary.
105
+ //| :param int entrypoint: Specifies the offset (in bytes) of the first instruction
106
+ //| from the start of the program (Only used by FSM ULP).
107
+ //| :param Sequence[microcontroller.Pin] pins: Pins made available to the ULP.
108
+ //| The pins are claimed and not reset until `halt()` is called."""
80
109
//| ...
81
110
static mp_obj_t espulp_ulp_run (size_t n_args , const mp_obj_t * pos_args , mp_map_t * kw_args ) {
82
111
espulp_ulp_obj_t * self = MP_OBJ_TO_PTR (pos_args [0 ]);
83
112
check_for_deinit (self );
84
113
85
- enum { ARG_program , ARG_pins };
114
+ enum { ARG_program , ARG_entrypoint , ARG_pins };
86
115
static const mp_arg_t allowed_args [] = {
87
116
{ MP_QSTR_program , MP_ARG_REQUIRED | MP_ARG_OBJ },
117
+ { MP_QSTR_entrypoint , MP_ARG_KW_ONLY | MP_ARG_INT , {.u_int = 0 }},
88
118
{ MP_QSTR_pins , MP_ARG_KW_ONLY | MP_ARG_OBJ , {.u_obj = mp_const_empty_tuple } },
89
119
};
90
120
@@ -94,6 +124,8 @@ static mp_obj_t espulp_ulp_run(size_t n_args, const mp_obj_t *pos_args, mp_map_t
94
124
mp_buffer_info_t bufinfo ;
95
125
mp_get_buffer_raise (args [ARG_program ].u_obj , & bufinfo , MP_BUFFER_READ );
96
126
127
+ mp_uint_t entrypoint = args [ARG_entrypoint ].u_int ;
128
+
97
129
mp_obj_t pins_in = args [ARG_pins ].u_obj ;
98
130
const size_t num_pins = (size_t )MP_OBJ_SMALL_INT_VALUE (mp_obj_len (pins_in ));
99
131
@@ -103,21 +135,25 @@ static mp_obj_t espulp_ulp_run(size_t n_args, const mp_obj_t *pos_args, mp_map_t
103
135
104
136
for (mp_uint_t i = 0 ; i < num_pins ; i ++ ) {
105
137
mp_obj_t pin_obj = mp_obj_subscr (pins_in , MP_OBJ_NEW_SMALL_INT (i ), MP_OBJ_SENTINEL );
106
- validate_obj_is_free_pin (pin_obj , MP_QSTR_pin );
138
+ // common-hal checks that pin is free (that way a possible "ULP already running" error
139
+ // is triggered before a possible "Pin in use" error, if ulp.run is called twice with the same pins).
140
+ validate_obj_is_pin (pin_obj , MP_QSTR_pin );
107
141
const mcu_pin_obj_t * pin = ((const mcu_pin_obj_t * )pin_obj );
108
142
if (pin -> number >= 32 ) {
109
143
raise_ValueError_invalid_pin ();
110
144
}
111
145
pin_mask |= 1 << pin -> number ;
112
146
}
113
147
114
- common_hal_espulp_ulp_run (self , bufinfo .buf , bufinfo .len , pin_mask );
148
+ common_hal_espulp_ulp_run (self , bufinfo .buf , bufinfo .len , entrypoint , pin_mask );
115
149
return mp_const_none ;
116
150
}
117
151
static MP_DEFINE_CONST_FUN_OBJ_KW (espulp_ulp_run_obj , 2 , espulp_ulp_run ) ;
118
152
119
153
//| def halt(self) -> None:
120
- //| """Halts the running program and releases the pins given in `run()`."""
154
+ //| """Halts the running program and releases the pins given in `run()`.
155
+ //| Note: for the FSM ULP, a running ULP program is not actually interrupted.
156
+ //| Instead, only the wakeup timer is stopped."""
121
157
//| ...
122
158
static mp_obj_t espulp_ulp_halt (mp_obj_t self_in ) {
123
159
espulp_ulp_obj_t * self = MP_OBJ_TO_PTR (self_in );
@@ -143,12 +179,13 @@ MP_PROPERTY_GETTER(espulp_ulp_arch_obj,
143
179
(mp_obj_t )& espulp_ulp_get_arch_obj );
144
180
145
181
static const mp_rom_map_elem_t espulp_ulp_locals_table [] = {
146
- { MP_ROM_QSTR (MP_QSTR_deinit ), MP_ROM_PTR (& espulp_ulp_deinit_obj ) },
147
- { MP_ROM_QSTR (MP_QSTR___enter__ ), MP_ROM_PTR (& mp_identity_obj ) },
148
- { MP_ROM_QSTR (MP_QSTR___exit__ ), MP_ROM_PTR (& espulp_ulp___exit___obj ) },
149
- { MP_ROM_QSTR (MP_QSTR_run ), MP_ROM_PTR (& espulp_ulp_run_obj ) },
150
- { MP_ROM_QSTR (MP_QSTR_halt ), MP_ROM_PTR (& espulp_ulp_halt_obj ) },
151
- { MP_ROM_QSTR (MP_QSTR_arch ), MP_ROM_PTR (& espulp_ulp_arch_obj ) },
182
+ { MP_ROM_QSTR (MP_QSTR_deinit ), MP_ROM_PTR (& espulp_ulp_deinit_obj ) },
183
+ { MP_ROM_QSTR (MP_QSTR___enter__ ), MP_ROM_PTR (& mp_identity_obj ) },
184
+ { MP_ROM_QSTR (MP_QSTR___exit__ ), MP_ROM_PTR (& espulp_ulp___exit___obj ) },
185
+ { MP_ROM_QSTR (MP_QSTR_set_wakeup_period ), MP_ROM_PTR (& espulp_ulp_set_wakeup_period_obj ) },
186
+ { MP_ROM_QSTR (MP_QSTR_run ), MP_ROM_PTR (& espulp_ulp_run_obj ) },
187
+ { MP_ROM_QSTR (MP_QSTR_halt ), MP_ROM_PTR (& espulp_ulp_halt_obj ) },
188
+ { MP_ROM_QSTR (MP_QSTR_arch ), MP_ROM_PTR (& espulp_ulp_arch_obj ) },
152
189
};
153
190
static MP_DEFINE_CONST_DICT (espulp_ulp_locals_dict , espulp_ulp_locals_table ) ;
154
191
0 commit comments