1919//| Raises an exception if another ULP has been instantiated. This
2020//| ensures that is is only used by one piece of code at a time.
2121//|
22- //| :param Architecture arch: The ulp arch"""
22+ //| :param Architecture arch: The ulp arch.
23+ //| """
2324//| ...
2425static 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 ) {
2526 enum { ARG_arch };
@@ -70,21 +71,50 @@ static mp_obj_t espulp_ulp_obj___exit__(size_t n_args, const mp_obj_t *args) {
7071}
7172static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN (espulp_ulp___exit___obj , 4 , 4 , espulp_ulp_obj___exit__ ) ;
7273
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+
7393//| 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] = ()
7599//| ) -> 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.
78101//|
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."""
80109//| ...
81110static mp_obj_t espulp_ulp_run (size_t n_args , const mp_obj_t * pos_args , mp_map_t * kw_args ) {
82111 espulp_ulp_obj_t * self = MP_OBJ_TO_PTR (pos_args [0 ]);
83112 check_for_deinit (self );
84113
85- enum { ARG_program , ARG_pins };
114+ enum { ARG_program , ARG_entrypoint , ARG_pins };
86115 static const mp_arg_t allowed_args [] = {
87116 { MP_QSTR_program , MP_ARG_REQUIRED | MP_ARG_OBJ },
117+ { MP_QSTR_entrypoint , MP_ARG_KW_ONLY | MP_ARG_INT , {.u_int = 0 }},
88118 { MP_QSTR_pins , MP_ARG_KW_ONLY | MP_ARG_OBJ , {.u_obj = mp_const_empty_tuple } },
89119 };
90120
@@ -94,6 +124,8 @@ static mp_obj_t espulp_ulp_run(size_t n_args, const mp_obj_t *pos_args, mp_map_t
94124 mp_buffer_info_t bufinfo ;
95125 mp_get_buffer_raise (args [ARG_program ].u_obj , & bufinfo , MP_BUFFER_READ );
96126
127+ mp_uint_t entrypoint = args [ARG_entrypoint ].u_int ;
128+
97129 mp_obj_t pins_in = args [ARG_pins ].u_obj ;
98130 const size_t num_pins = (size_t )MP_OBJ_SMALL_INT_VALUE (mp_obj_len (pins_in ));
99131
@@ -103,21 +135,25 @@ static mp_obj_t espulp_ulp_run(size_t n_args, const mp_obj_t *pos_args, mp_map_t
103135
104136 for (mp_uint_t i = 0 ; i < num_pins ; i ++ ) {
105137 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 );
107141 const mcu_pin_obj_t * pin = ((const mcu_pin_obj_t * )pin_obj );
108142 if (pin -> number >= 32 ) {
109143 raise_ValueError_invalid_pin ();
110144 }
111145 pin_mask |= 1 << pin -> number ;
112146 }
113147
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 );
115149 return mp_const_none ;
116150}
117151static MP_DEFINE_CONST_FUN_OBJ_KW (espulp_ulp_run_obj , 2 , espulp_ulp_run ) ;
118152
119153//| 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."""
121157//| ...
122158static mp_obj_t espulp_ulp_halt (mp_obj_t self_in ) {
123159 espulp_ulp_obj_t * self = MP_OBJ_TO_PTR (self_in );
@@ -143,12 +179,13 @@ MP_PROPERTY_GETTER(espulp_ulp_arch_obj,
143179 (mp_obj_t )& espulp_ulp_get_arch_obj );
144180
145181static 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 ) },
152189};
153190static MP_DEFINE_CONST_DICT (espulp_ulp_locals_dict , espulp_ulp_locals_table ) ;
154191
0 commit comments