3030#include <stdint.h>
3131#include <stdio.h>
3232
33+ #include "py/mphal.h"
3334#include "py/obj.h"
3435#include "py/runtime.h"
3536#include "modmachine.h"
36- #include "mphalport.h"
3737
3838#include "hal/timer_hal.h"
3939#include "hal/timer_ll.h"
4040#include "soc/timer_periph.h"
41+ #include "esp_private/esp_clk_tree_common.h"
42+ #include "esp_private/periph_ctrl.h"
43+ #include "machine_timer.h"
4144
45+ #define TIMER_CLK_SRC GPTIMER_CLK_SRC_DEFAULT
4246#define TIMER_DIVIDER 8
4347
44- // TIMER_BASE_CLK is normally 80MHz. TIMER_DIVIDER ought to divide this exactly
45- #define TIMER_SCALE (APB_CLK_FREQ / TIMER_DIVIDER)
46-
4748#define TIMER_FLAGS 0
4849
49- typedef struct _machine_timer_obj_t {
50- mp_obj_base_t base ;
51-
52- timer_hal_context_t hal_context ;
53- mp_uint_t group ;
54- mp_uint_t index ;
55-
56- mp_uint_t repeat ;
57- // ESP32 timers are 64-bit
58- uint64_t period ;
59-
60- mp_obj_t callback ;
61-
62- intr_handle_t handle ;
63-
64- struct _machine_timer_obj_t * next ;
65- } machine_timer_obj_t ;
66-
6750const mp_obj_type_t machine_timer_type ;
6851
69- STATIC void machine_timer_disable (machine_timer_obj_t * self );
70- STATIC mp_obj_t machine_timer_init_helper (machine_timer_obj_t * self , mp_uint_t n_args , const mp_obj_t * pos_args , mp_map_t * kw_args );
52+ static mp_obj_t machine_timer_init_helper (machine_timer_obj_t * self , mp_uint_t n_args , const mp_obj_t * pos_args , mp_map_t * kw_args );
53+ static mp_obj_t machine_timer_deinit (mp_obj_t self_in );
54+
55+ uint32_t machine_timer_freq_hz (void ) {
56+ // The timer source clock is APB or a fixed PLL (depending on chip), both constant frequency.
57+ uint32_t freq ;
58+ check_esp_err (esp_clk_tree_src_get_freq_hz (TIMER_CLK_SRC , ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED , & freq ));
59+ assert (freq % TIMER_DIVIDER == 0 ); // Source clock should divide evenly into TIMER_DIVIDER
60+ return freq / TIMER_DIVIDER ;
61+ }
7162
7263void machine_timer_deinit_all (void ) {
7364 // Disable, deallocate and remove all timers from list
7465 machine_timer_obj_t * * t = & MP_STATE_PORT (machine_timer_obj_head );
7566 while (* t != NULL ) {
76- machine_timer_disable (* t );
67+ machine_timer_deinit (* t );
7768 machine_timer_obj_t * next = (* t )-> next ;
7869 m_del_obj (machine_timer_obj_t , * t );
7970 * t = next ;
8071 }
8172}
8273
83- STATIC void machine_timer_print (const mp_print_t * print , mp_obj_t self_in , mp_print_kind_t kind ) {
74+ static void machine_timer_print (const mp_print_t * print , mp_obj_t self_in , mp_print_kind_t kind ) {
8475 machine_timer_obj_t * self = self_in ;
8576 qstr mode = self -> repeat ? MP_QSTR_PERIODIC : MP_QSTR_ONE_SHOT ;
86- uint64_t period = self -> period / (TIMER_SCALE / 1000 ); // convert to ms
77+ uint64_t period = self -> period / (machine_timer_freq_hz () / 1000 ); // convert to ms
78+ #if SOC_TIMER_GROUP_TIMERS_PER_GROUP == 1
79+ mp_printf (print , "Timer(%u, mode=%q, period=%lu)" , self -> group , mode , period );
80+ #else
8781 mp_printf (print , "Timer(%u, mode=%q, period=%lu)" , (self -> group << 1 ) | self -> index , mode , period );
82+ #endif
8883}
8984
90- STATIC mp_obj_t machine_timer_make_new (const mp_obj_type_t * type , size_t n_args , size_t n_kw , const mp_obj_t * args ) {
91- mp_arg_check_num (n_args , n_kw , 1 , MP_OBJ_FUN_ARGS_MAX , true);
92- mp_uint_t group = (mp_obj_get_int (args [0 ]) >> 1 ) & 1 ;
93- mp_uint_t index = mp_obj_get_int (args [0 ]) & 1 ;
85+ static bool find_free_timer (mp_int_t * group , mp_int_t * index ) {
86+ // from highest to lowest id
87+ for (* group = SOC_TIMER_GROUPS - 1 ; * group >= 0 ; -- (* group )) {
88+ for (* index = SOC_TIMER_GROUP_TIMERS_PER_GROUP - 1 ; * index >= 0 ; -- (* index )) {
89+ bool free = true;
90+ // Check whether the timer is already initialized, if so skip it
91+ for (machine_timer_obj_t * t = MP_STATE_PORT (machine_timer_obj_head ); t ; t = t -> next ) {
92+ if (t -> group == * group && t -> index == * index ) {
93+ free = false;
94+ break ;
95+ }
96+ }
97+ if (free ) {
98+ return true;
99+ }
100+ }
101+ }
102+ return false;
103+ }
104+
105+ machine_timer_obj_t * machine_timer_create (mp_int_t timer ) {
94106
95107 machine_timer_obj_t * self = NULL ;
108+ mp_int_t group ;
109+ mp_int_t index ;
110+ if (timer == -2 ) {
111+ if (!find_free_timer (& group , & index )) {
112+ mp_raise_msg_varg (& mp_type_RuntimeError , MP_ERROR_TEXT ("out of Timers:%d" ), SOC_TIMER_GROUP_TOTAL_TIMERS );
113+ }
114+ } else {
115+ #if SOC_TIMER_GROUP_TIMERS_PER_GROUP == 1
116+ group = timer & 1 ;
117+ index = 0 ;
118+ #else
119+ group = (timer >> 1 ) & 1 ;
120+ index = timer & 1 ;
121+ #endif
122+ }
96123
97124 // Check whether the timer is already initialized, if so use it
98125 for (machine_timer_obj_t * t = MP_STATE_PORT (machine_timer_obj_head ); t ; t = t -> next ) {
@@ -106,11 +133,24 @@ STATIC mp_obj_t machine_timer_make_new(const mp_obj_type_t *type, size_t n_args,
106133 self = mp_obj_malloc (machine_timer_obj_t , & machine_timer_type );
107134 self -> group = group ;
108135 self -> index = index ;
136+ self -> handle = NULL ;
109137
110138 // Add the timer to the linked-list of timers
111139 self -> next = MP_STATE_PORT (machine_timer_obj_head );
112140 MP_STATE_PORT (machine_timer_obj_head ) = self ;
113141 }
142+ return self ;
143+ }
144+
145+ static mp_obj_t machine_timer_make_new (const mp_obj_type_t * type , size_t n_args , size_t n_kw , const mp_obj_t * args ) {
146+ mp_arg_check_num (n_args , n_kw , 1 , MP_OBJ_FUN_ARGS_MAX , true);
147+
148+ // Create the new timer.
149+ mp_int_t timer_number = mp_obj_get_int (args [0 ]);
150+ if (timer_number >= SOC_TIMER_GROUP_TOTAL_TIMERS ) {
151+ mp_raise_ValueError (MP_ERROR_TEXT ("invalid Timer number" ));
152+ }
153+ machine_timer_obj_t * self = machine_timer_create (timer_number );
114154
115155 if (n_args > 1 || n_kw > 0 ) {
116156 mp_map_t kw_args ;
@@ -121,24 +161,23 @@ STATIC mp_obj_t machine_timer_make_new(const mp_obj_type_t *type, size_t n_args,
121161 return self ;
122162}
123163
124- STATIC void machine_timer_disable (machine_timer_obj_t * self ) {
164+ void machine_timer_disable (machine_timer_obj_t * self ) {
125165 if (self -> hal_context .dev != NULL ) {
126166 // Disable the counter and alarm.
127167 timer_ll_enable_counter (self -> hal_context .dev , self -> index , false);
128168 timer_ll_enable_alarm (self -> hal_context .dev , self -> index , false);
129169 }
130170
131171 if (self -> handle ) {
132- // Free the interrupt handler.
133- esp_intr_free (self -> handle );
134- self -> handle = NULL ;
172+ // Disable the interrupt
173+ ESP_ERROR_CHECK (esp_intr_disable (self -> handle ));
135174 }
136175
137176 // We let the disabled timer stay in the list, as it might be
138177 // referenced elsewhere
139178}
140179
141- STATIC void machine_timer_isr (void * self_in ) {
180+ static void machine_timer_isr (void * self_in ) {
142181 machine_timer_obj_t * self = self_in ;
143182
144183 uint32_t intr_status = timer_ll_get_intr_status (self -> hal_context .dev );
@@ -148,27 +187,53 @@ STATIC void machine_timer_isr(void *self_in) {
148187 if (self -> repeat ) {
149188 timer_ll_enable_alarm (self -> hal_context .dev , self -> index , true);
150189 }
151- mp_sched_schedule (self -> callback , self );
152- mp_hal_wake_main_task_from_isr ();
190+ self -> handler (self );
153191 }
154192}
155193
156- STATIC void machine_timer_enable (machine_timer_obj_t * self ) {
194+ static void machine_timer_isr_handler (machine_timer_obj_t * self ) {
195+ mp_sched_schedule (self -> callback , self );
196+ mp_hal_wake_main_task_from_isr ();
197+ }
198+
199+ void machine_timer_enable (machine_timer_obj_t * self ) {
157200 // Initialise the timer.
158201 timer_hal_init (& self -> hal_context , self -> group , self -> index );
202+
203+ PERIPH_RCC_ACQUIRE_ATOMIC (timer_group_periph_signals .groups [self -> index ].module , ref_count ) {
204+ if (ref_count == 0 ) {
205+ timer_ll_enable_bus_clock (self -> index , true);
206+ timer_ll_reset_register (self -> index );
207+ }
208+ }
209+
159210 timer_ll_enable_counter (self -> hal_context .dev , self -> index , false);
160- timer_ll_set_clock_source (self -> hal_context .dev , self -> index , GPTIMER_CLK_SRC_APB );
211+ esp_clk_tree_enable_src (TIMER_CLK_SRC , true);
212+ #if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL (5 , 5 , 0 )
213+ timer_ll_set_clock_source (self -> hal_context .dev , self -> index , TIMER_CLK_SRC );
214+ timer_ll_enable_clock (self -> hal_context .dev , self -> index , true);
215+ #else
216+ timer_ll_set_clock_source (self -> group , self -> index , TIMER_CLK_SRC );
217+ timer_ll_enable_clock (self -> group , self -> index , true);
218+ #endif
161219 timer_ll_set_clock_prescale (self -> hal_context .dev , self -> index , TIMER_DIVIDER );
162220 timer_hal_set_counter_value (& self -> hal_context , 0 );
163221 timer_ll_set_count_direction (self -> hal_context .dev , self -> index , GPTIMER_COUNT_UP );
164222
165223 // Allocate and enable the alarm interrupt.
166224 timer_ll_enable_intr (self -> hal_context .dev , TIMER_LL_EVENT_ALARM (self -> index ), false);
167225 timer_ll_clear_intr_status (self -> hal_context .dev , TIMER_LL_EVENT_ALARM (self -> index ));
168- ESP_ERROR_CHECK (
169- esp_intr_alloc (timer_group_periph_signals .groups [self -> group ].timer_irq_id [self -> index ],
170- TIMER_FLAGS , machine_timer_isr , self , & self -> handle )
171- );
226+ if (self -> handle ) {
227+ ESP_ERROR_CHECK (esp_intr_enable (self -> handle ));
228+ } else {
229+ ESP_ERROR_CHECK (esp_intr_alloc (
230+ timer_group_periph_signals .groups [self -> group ].timer_irq_id [self -> index ],
231+ TIMER_FLAGS ,
232+ machine_timer_isr ,
233+ self ,
234+ & self -> handle
235+ ));
236+ }
172237 timer_ll_enable_intr (self -> hal_context .dev , TIMER_LL_EVENT_ALARM (self -> index ), true);
173238
174239 // Enable the alarm to trigger at the given period.
@@ -183,13 +248,14 @@ STATIC void machine_timer_enable(machine_timer_obj_t *self) {
183248 timer_ll_enable_counter (self -> hal_context .dev , self -> index , true);
184249}
185250
186- STATIC mp_obj_t machine_timer_init_helper (machine_timer_obj_t * self , mp_uint_t n_args , const mp_obj_t * pos_args , mp_map_t * kw_args ) {
251+ static mp_obj_t machine_timer_init_helper (machine_timer_obj_t * self , mp_uint_t n_args , const mp_obj_t * pos_args , mp_map_t * kw_args ) {
187252 enum {
188253 ARG_mode ,
189254 ARG_callback ,
190255 ARG_period ,
191256 ARG_tick_hz ,
192257 ARG_freq ,
258+ ARG_hard ,
193259 };
194260 static const mp_arg_t allowed_args [] = {
195261 { MP_QSTR_mode , MP_ARG_KW_ONLY | MP_ARG_INT , {.u_int = 1 } },
@@ -201,63 +267,77 @@ STATIC mp_obj_t machine_timer_init_helper(machine_timer_obj_t *self, mp_uint_t n
201267 #else
202268 { MP_QSTR_freq , MP_ARG_KW_ONLY | MP_ARG_INT , {.u_int = 0xffffffff } },
203269 #endif
270+ { MP_QSTR_hard , MP_ARG_KW_ONLY | MP_ARG_BOOL , {.u_bool = false} },
204271 };
205272
206273 machine_timer_disable (self );
207274
208275 mp_arg_val_t args [MP_ARRAY_SIZE (allowed_args )];
209276 mp_arg_parse_all (n_args , pos_args , kw_args , MP_ARRAY_SIZE (allowed_args ), allowed_args , args );
210277
278+ if (args [ARG_hard ].u_bool ) {
279+ mp_raise_ValueError (MP_ERROR_TEXT ("hard Timers are not implemented" ));
280+ }
281+
211282 #if MICROPY_PY_BUILTINS_FLOAT
212283 if (args [ARG_freq ].u_obj != mp_const_none ) {
213- self -> period = (uint64_t )(TIMER_SCALE / mp_obj_get_float (args [ARG_freq ].u_obj ));
284+ self -> period = (uint64_t )(machine_timer_freq_hz () / mp_obj_get_float (args [ARG_freq ].u_obj ));
214285 }
215286 #else
216287 if (args [ARG_freq ].u_int != 0xffffffff ) {
217288 self -> period = TIMER_SCALE / ((uint64_t )args [ARG_freq ].u_int );
218289 }
219290 #endif
220291 else {
221- self -> period = (((uint64_t )args [ARG_period ].u_int ) * TIMER_SCALE ) / args [ARG_tick_hz ].u_int ;
292+ self -> period = (((uint64_t )args [ARG_period ].u_int ) * machine_timer_freq_hz () ) / args [ARG_tick_hz ].u_int ;
222293 }
223294
224295 self -> repeat = args [ARG_mode ].u_int ;
296+ self -> handler = machine_timer_isr_handler ;
225297 self -> callback = args [ARG_callback ].u_obj ;
226- self -> handle = NULL ;
227298
228299 machine_timer_enable (self );
229300
230301 return mp_const_none ;
231302}
232303
233- STATIC mp_obj_t machine_timer_deinit (mp_obj_t self_in ) {
234- machine_timer_disable (self_in );
304+ static mp_obj_t machine_timer_deinit (mp_obj_t self_in ) {
305+ machine_timer_obj_t * self = self_in ;
306+
307+ machine_timer_disable (self );
308+ if (self -> handle ) {
309+ ESP_ERROR_CHECK (esp_intr_free (self -> handle ));
310+ self -> handle = NULL ;
311+ }
235312
236313 return mp_const_none ;
237314}
238- STATIC MP_DEFINE_CONST_FUN_OBJ_1 (machine_timer_deinit_obj , machine_timer_deinit );
315+ static MP_DEFINE_CONST_FUN_OBJ_1 (machine_timer_deinit_obj , machine_timer_deinit ) ;
239316
240- STATIC mp_obj_t machine_timer_init (size_t n_args , const mp_obj_t * args , mp_map_t * kw_args ) {
317+ static mp_obj_t machine_timer_init (size_t n_args , const mp_obj_t * args , mp_map_t * kw_args ) {
241318 return machine_timer_init_helper (args [0 ], n_args - 1 , args + 1 , kw_args );
242319}
243- STATIC MP_DEFINE_CONST_FUN_OBJ_KW (machine_timer_init_obj , 1 , machine_timer_init );
320+ static MP_DEFINE_CONST_FUN_OBJ_KW (machine_timer_init_obj , 1 , machine_timer_init ) ;
244321
245- STATIC mp_obj_t machine_timer_value (mp_obj_t self_in ) {
322+ static mp_obj_t machine_timer_value (mp_obj_t self_in ) {
246323 machine_timer_obj_t * self = self_in ;
324+ if (self -> handle == NULL ) {
325+ mp_raise_ValueError (MP_ERROR_TEXT ("timer not set" ));
326+ }
247327 uint64_t result = timer_ll_get_counter_value (self -> hal_context .dev , self -> index );
248- return MP_OBJ_NEW_SMALL_INT ((mp_uint_t )(result / (TIMER_SCALE / 1000 ))); // value in ms
328+ return MP_OBJ_NEW_SMALL_INT ((mp_uint_t )(result / (machine_timer_freq_hz () / 1000 ))); // value in ms
249329}
250- STATIC MP_DEFINE_CONST_FUN_OBJ_1 (machine_timer_value_obj , machine_timer_value );
330+ static MP_DEFINE_CONST_FUN_OBJ_1 (machine_timer_value_obj , machine_timer_value ) ;
251331
252- STATIC const mp_rom_map_elem_t machine_timer_locals_dict_table [] = {
332+ static const mp_rom_map_elem_t machine_timer_locals_dict_table [] = {
253333 { MP_ROM_QSTR (MP_QSTR___del__ ), MP_ROM_PTR (& machine_timer_deinit_obj ) },
254334 { MP_ROM_QSTR (MP_QSTR_deinit ), MP_ROM_PTR (& machine_timer_deinit_obj ) },
255335 { MP_ROM_QSTR (MP_QSTR_init ), MP_ROM_PTR (& machine_timer_init_obj ) },
256336 { MP_ROM_QSTR (MP_QSTR_value ), MP_ROM_PTR (& machine_timer_value_obj ) },
257337 { MP_ROM_QSTR (MP_QSTR_ONE_SHOT ), MP_ROM_INT (false) },
258338 { MP_ROM_QSTR (MP_QSTR_PERIODIC ), MP_ROM_INT (true) },
259339};
260- STATIC MP_DEFINE_CONST_DICT (machine_timer_locals_dict , machine_timer_locals_dict_table );
340+ static MP_DEFINE_CONST_DICT (machine_timer_locals_dict , machine_timer_locals_dict_table ) ;
261341
262342MP_DEFINE_CONST_OBJ_TYPE (
263343 machine_timer_type ,
0 commit comments