1 /*
2  * SPDX-FileCopyrightText: 2010-2021 Espressif Systems (Shanghai) CO LTD
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #pragma once
8 
9 #include "esp_err.h"
10 #include "esp_attr.h"
11 #include "soc/soc.h"
12 #include "soc/timer_periph.h"
13 #include "esp_intr_alloc.h"
14 #include "hal/timer_types.h"
15 
16 #ifdef __cplusplus
17 extern "C" {
18 #endif
19 
20 #define TIMER_BASE_CLK   (APB_CLK_FREQ)  /*!< Frequency of the clock on the input of the timer groups */
21 
22 /**
23  * @brief Interrupt handle callback function. User need to retrun a bool value
24  *        in callback.
25  *
26  * @return
27  *     - True Do task yield at the end of ISR
28  *     - False Not do task yield at the end of ISR
29  *
30  * @note If you called FreeRTOS functions in callback, you need to return true or false based on
31  *       the retrun value of argument `pxHigherPriorityTaskWoken`.
32  *       For example, `xQueueSendFromISR` is called in callback, if the return value `pxHigherPriorityTaskWoken`
33  *       of any FreeRTOS calls is pdTRUE, return true; otherwise return false.
34  */
35 typedef bool (*timer_isr_t)(void *);
36 
37 /**
38  * @brief Interrupt handle, used in order to free the isr after use.
39  * Aliases to an int handle for now.
40  */
41 typedef intr_handle_t timer_isr_handle_t;
42 
43 /**
44  * @brief Read the counter value of hardware timer.
45  *
46  * @param group_num Timer group, 0 for TIMERG0 or 1 for TIMERG1
47  * @param timer_num Timer index, 0 for hw_timer[0] & 1 for hw_timer[1]
48  * @param timer_val Pointer to accept timer counter value.
49  *
50  * @return
51  *     - ESP_OK Success
52  *     - ESP_ERR_INVALID_ARG Parameter error
53  */
54 esp_err_t timer_get_counter_value(timer_group_t group_num, timer_idx_t timer_num, uint64_t *timer_val);
55 
56 /**
57  * @brief Read the counter value of hardware timer, in unit of a given scale.
58  *
59  * @param group_num Timer group, 0 for TIMERG0 or 1 for TIMERG1
60  * @param timer_num Timer index, 0 for hw_timer[0] & 1 for hw_timer[1]
61  * @param time Pointer, type of double*, to accept timer counter value, in seconds.
62  *
63  * @return
64  *     - ESP_OK Success
65  *     - ESP_ERR_INVALID_ARG Parameter error
66  */
67 esp_err_t timer_get_counter_time_sec(timer_group_t group_num, timer_idx_t timer_num, double *time);
68 
69 /**
70  * @brief Set counter value to hardware timer.
71  *
72  * @param group_num Timer group, 0 for TIMERG0 or 1 for TIMERG1
73  * @param timer_num Timer index, 0 for hw_timer[0] & 1 for hw_timer[1]
74  * @param load_val Counter value to write to the hardware timer.
75  *
76  * @return
77  *     - ESP_OK Success
78  *     - ESP_ERR_INVALID_ARG Parameter error
79  */
80 esp_err_t timer_set_counter_value(timer_group_t group_num, timer_idx_t timer_num, uint64_t load_val);
81 
82 /**
83  * @brief Start the counter of hardware timer.
84  *
85  * @param group_num Timer group number, 0 for TIMERG0 or 1 for TIMERG1
86  * @param timer_num Timer index, 0 for hw_timer[0] & 1 for hw_timer[1]
87  *
88  * @return
89  *     - ESP_OK Success
90  *     - ESP_ERR_INVALID_ARG Parameter error
91  */
92 esp_err_t timer_start(timer_group_t group_num, timer_idx_t timer_num);
93 
94 /**
95  * @brief Pause the counter of hardware timer.
96  *
97  * @param group_num Timer group number, 0 for TIMERG0 or 1 for TIMERG1
98  * @param timer_num Timer index, 0 for hw_timer[0] & 1 for hw_timer[1]
99  *
100  * @return
101  *     - ESP_OK Success
102  *     - ESP_ERR_INVALID_ARG Parameter error
103  */
104 esp_err_t timer_pause(timer_group_t group_num, timer_idx_t timer_num);
105 
106 /**
107  * @brief Set counting mode for hardware timer.
108  *
109  * @param group_num Timer group number, 0 for TIMERG0 or 1 for TIMERG1
110  * @param timer_num Timer index, 0 for hw_timer[0] & 1 for hw_timer[1]
111  * @param counter_dir Counting direction of timer, count-up or count-down
112  *
113  * @return
114  *     - ESP_OK Success
115  *     - ESP_ERR_INVALID_ARG Parameter error
116  */
117 esp_err_t timer_set_counter_mode(timer_group_t group_num, timer_idx_t timer_num, timer_count_dir_t counter_dir);
118 
119 /**
120  * @brief Enable or disable counter reload function when alarm event occurs.
121  *
122  * @param group_num Timer group number, 0 for TIMERG0 or 1 for TIMERG1
123  * @param timer_num Timer index, 0 for hw_timer[0] & 1 for hw_timer[1]
124  * @param reload Counter reload mode.
125  *
126  * @return
127  *     - ESP_OK Success
128  *     - ESP_ERR_INVALID_ARG Parameter error
129  */
130 esp_err_t timer_set_auto_reload(timer_group_t group_num, timer_idx_t timer_num, timer_autoreload_t reload);
131 
132 /**
133  * @brief Set hardware divider of the source clock to the timer group.
134  * By default, the source clock is APB clock running at 80 MHz.
135  * For more information, please check Chapter Reset and Clock in Chip Technical Reference Manual.
136  * @param group_num Timer group number, 0 for TIMERG0 or 1 for TIMERG1
137  * @param timer_num Timer index, 0 for hw_timer[0] & 1 for hw_timer[1]
138  * @param divider Timer clock divider value. The divider's range is from from 2 to 65536.
139  *
140  * @return
141  *     - ESP_OK Success
142  *     - ESP_ERR_INVALID_ARG Parameter error
143  */
144 esp_err_t timer_set_divider(timer_group_t group_num, timer_idx_t timer_num, uint32_t divider);
145 
146 /**
147  * @brief Set timer alarm value.
148  *
149  * @param group_num Timer group, 0 for TIMERG0 or 1 for TIMERG1
150  * @param timer_num Timer index, 0 for hw_timer[0] & 1 for hw_timer[1]
151  * @param alarm_value A 64-bit value to set the alarm value.
152  *
153  * @return
154  *     - ESP_OK Success
155  *     - ESP_ERR_INVALID_ARG Parameter error
156  */
157 esp_err_t timer_set_alarm_value(timer_group_t group_num, timer_idx_t timer_num, uint64_t alarm_value);
158 
159 /**
160  * @brief Get timer alarm value.
161  *
162  * @param group_num Timer group, 0 for TIMERG0 or 1 for TIMERG1
163  * @param timer_num Timer index, 0 for hw_timer[0] & 1 for hw_timer[1]
164  * @param alarm_value Pointer of A 64-bit value to accept the alarm value.
165  *
166  * @return
167  *     - ESP_OK Success
168  *     - ESP_ERR_INVALID_ARG Parameter error
169  */
170 esp_err_t timer_get_alarm_value(timer_group_t group_num, timer_idx_t timer_num, uint64_t *alarm_value);
171 
172 /**
173  * @brief Enable or disable generation of timer alarm events.
174  *
175  * @param group_num Timer group, 0 for TIMERG0 or 1 for TIMERG1
176  * @param timer_num Timer index, 0 for hw_timer[0] & 1 for hw_timer[1]
177  * @param alarm_en To enable or disable timer alarm function.
178  *
179  * @return
180  *     - ESP_OK Success
181  *     - ESP_ERR_INVALID_ARG Parameter error
182  */
183 esp_err_t timer_set_alarm(timer_group_t group_num, timer_idx_t timer_num, timer_alarm_t alarm_en);
184 
185 /**
186  * @brief Add ISR handle callback for the corresponding timer.
187  *
188  * @param group_num Timer group number
189  * @param timer_num Timer index of timer group
190  * @param isr_handler Interrupt handler function, it is a callback function.
191  * @param arg Parameter for handler function
192  * @param intr_alloc_flags Flags used to allocate the interrupt. One or multiple (ORred)
193  *        ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info.
194  *
195  * @note This ISR handler will be called from an ISR.
196  *       This ISR handler do not need to handle interrupt status, and should be kept short.
197  *       If you want to realize some specific applications or write the whole ISR, you can
198  *       call timer_isr_register(...) to register ISR.
199  *
200  *       The callback should return a bool value to determine whether need to do YIELD at
201  *       the end of the ISR.
202  *
203  *       If the intr_alloc_flags value ESP_INTR_FLAG_IRAM is set,
204  *       the handler function must be declared with IRAM_ATTR attribute
205  *       and can only call functions in IRAM or ROM. It cannot call other timer APIs.
206  *
207  * @return
208  *     - ESP_OK Success
209  *     - ESP_ERR_INVALID_ARG Parameter error
210  */
211 esp_err_t timer_isr_callback_add(timer_group_t group_num, timer_idx_t timer_num, timer_isr_t isr_handler, void *arg, int intr_alloc_flags);
212 
213 /**
214  * @brief Remove ISR handle callback for the corresponding timer.
215  *
216  * @param group_num Timer group number
217  * @param timer_num Timer index of timer group
218  *
219  * @return
220  *     - ESP_OK Success
221  *     - ESP_ERR_INVALID_ARG Parameter error
222  */
223 esp_err_t timer_isr_callback_remove(timer_group_t group_num, timer_idx_t timer_num);
224 
225 /**
226  * @brief Register Timer interrupt handler, the handler is an ISR.
227  *        The handler will be attached to the same CPU core that this function is running on.
228  *
229  * @param group_num Timer group number
230  * @param timer_num Timer index of timer group
231  * @param fn Interrupt handler function.
232  * @param arg Parameter for handler function
233  * @param intr_alloc_flags Flags used to allocate the interrupt. One or multiple (ORred)
234  *        ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info.
235  * @param handle Pointer to return handle. If non-NULL, a handle for the interrupt will
236  *        be returned here.
237  *
238  * @note If use this function to reigster ISR, you need to write the whole ISR.
239  *       In the interrupt handler, you need to call timer_spinlock_take(..) before
240  *       your handling, and call timer_spinlock_give(...) after your handling.
241  *
242  *       If the intr_alloc_flags value ESP_INTR_FLAG_IRAM is set,
243  *       the handler function must be declared with IRAM_ATTR attribute
244  *       and can only call functions in IRAM or ROM. It cannot call other timer APIs.
245  *       Use direct register access to configure timers from inside the ISR in this case.
246  *
247  * @return
248  *     - ESP_OK Success
249  *     - ESP_ERR_INVALID_ARG Parameter error
250  */
251 esp_err_t timer_isr_register(timer_group_t group_num, timer_idx_t timer_num, void (*fn)(void *), void *arg, int intr_alloc_flags, timer_isr_handle_t *handle);
252 
253 /** @brief Initializes and configure the timer.
254  *
255  * @param group_num Timer group number, 0 for TIMERG0 or 1 for TIMERG1
256  * @param timer_num Timer index, 0 for hw_timer[0] & 1 for hw_timer[1]
257  * @param config Pointer to timer initialization parameters.
258  *
259  * @return
260  *     - ESP_OK Success
261  *     - ESP_ERR_INVALID_ARG Parameter error
262  */
263 esp_err_t timer_init(timer_group_t group_num, timer_idx_t timer_num, const timer_config_t *config);
264 
265 /** @brief Deinitializes the timer.
266  *
267  * @param group_num Timer group number, 0 for TIMERG0 or 1 for TIMERG1
268  * @param timer_num Timer index, 0 for hw_timer[0] & 1 for hw_timer[1]
269  *
270  * @return
271  *     - ESP_OK Success
272  *     - ESP_ERR_INVALID_ARG Parameter error
273  */
274 esp_err_t timer_deinit(timer_group_t group_num, timer_idx_t timer_num);
275 
276 /** @brief Get timer configure value.
277  *
278  * @param group_num Timer group number, 0 for TIMERG0 or 1 for TIMERG1
279  * @param timer_num Timer index, 0 for hw_timer[0] & 1 for hw_timer[1]
280  * @param config Pointer of struct to accept timer parameters.
281  *
282  * @return
283  *     - ESP_OK Success
284  *     - ESP_ERR_INVALID_ARG Parameter error
285  */
286 esp_err_t timer_get_config(timer_group_t group_num, timer_idx_t timer_num, timer_config_t *config);
287 
288 /** @brief Enable timer group interrupt, by enable mask
289  *
290  * @param group_num Timer group number, 0 for TIMERG0 or 1 for TIMERG1
291  * @param intr_mask Timer interrupt enable mask.
292  *          - TIMER_INTR_T0: t0 interrupt
293  *          - TIMER_INTR_T1: t1 interrupt
294  *          - TIMER_INTR_WDT: watchdog interrupt
295  *
296  * @return
297  *     - ESP_OK Success
298  *     - ESP_ERR_INVALID_ARG Parameter error
299  */
300 esp_err_t timer_group_intr_enable(timer_group_t group_num, timer_intr_t intr_mask);
301 
302 /** @brief Disable timer group interrupt, by disable mask
303  *
304  * @param group_num Timer group number, 0 for TIMERG0 or 1 for TIMERG1
305  * @param intr_mask Timer interrupt disable mask.
306  *          - TIMER_INTR_T0: t0 interrupt
307  *          - TIMER_INTR_T1: t1 interrupt
308  *          - TIMER_INTR_WDT: watchdog interrupt
309  *
310  * @return
311  *     - ESP_OK Success
312  *     - ESP_ERR_INVALID_ARG Parameter error
313  */
314 esp_err_t timer_group_intr_disable(timer_group_t group_num, timer_intr_t intr_mask);
315 
316 /** @brief Enable timer interrupt
317  *
318  * @param group_num Timer group number, 0 for TIMERG0 or 1 for TIMERG1
319  * @param timer_num Timer index.
320  *
321  * @return
322  *     - ESP_OK Success
323  *     - ESP_ERR_INVALID_ARG Parameter error
324  */
325 esp_err_t timer_enable_intr(timer_group_t group_num, timer_idx_t timer_num);
326 
327 /** @brief Disable timer interrupt
328  *
329  * @param group_num Timer group number, 0 for TIMERG0 or 1 for TIMERG1
330  * @param timer_num Timer index.
331  *
332  * @return
333  *     - ESP_OK Success
334  *     - ESP_ERR_INVALID_ARG Parameter error
335  */
336 esp_err_t timer_disable_intr(timer_group_t group_num, timer_idx_t timer_num);
337 
338 /** @brief Clear timer interrupt status, just used in ISR
339  *
340  * @param group_num Timer group number, 0 for TIMERG0 or 1 for TIMERG1
341  * @param timer_num Timer index.
342  *
343  */
344 void timer_group_intr_clr_in_isr(timer_group_t group_num, timer_idx_t timer_num) __attribute__((deprecated));
345 
346 /** @brief Clear timer interrupt status, just used in ISR
347  *
348  * @param group_num Timer group number, 0 for TIMERG0 or 1 for TIMERG1
349  * @param timer_num Timer index.
350  *
351  */
352 void timer_group_clr_intr_status_in_isr(timer_group_t group_num, timer_idx_t timer_num);
353 
354 /** @brief Enable alarm interrupt, just used in ISR
355  *
356  * @param group_num Timer group number, 0 for TIMERG0 or 1 for TIMERG1
357  * @param timer_num Timer index.
358  *
359  */
360 void timer_group_enable_alarm_in_isr(timer_group_t group_num, timer_idx_t timer_num);
361 
362 /** @brief Get the current counter value, just used in ISR
363  *
364  * @param group_num Timer group number, 0 for TIMERG0 or 1 for TIMERG1
365  * @param timer_num Timer index.
366  *
367  * @return
368  *     - Counter value
369  */
370 uint64_t timer_group_get_counter_value_in_isr(timer_group_t group_num, timer_idx_t timer_num);
371 
372 /** @brief Set the alarm threshold for the timer, just used in ISR
373  *
374  * @param group_num Timer group number, 0 for TIMERG0 or 1 for TIMERG1
375  * @param timer_num Timer index.
376  * @param alarm_val Alarm threshold.
377  *
378  */
379 void timer_group_set_alarm_value_in_isr(timer_group_t group_num, timer_idx_t timer_num, uint64_t alarm_val);
380 
381 /** @brief Enable/disable a counter, just used in ISR
382  *
383  * @param group_num Timer group number, 0 for TIMERG0 or 1 for TIMERG1
384  * @param timer_num Timer index.
385  * @param counter_en Enable/disable.
386  *
387  */
388 void timer_group_set_counter_enable_in_isr(timer_group_t group_num, timer_idx_t timer_num, timer_start_t counter_en);
389 
390 /** @brief Get the masked interrupt status, just used in ISR
391  *
392  * @param group_num Timer group number, 0 for TIMERG0 or 1 for TIMERG1
393  *
394  * @return
395  *     - Interrupt status
396  */
397 timer_intr_t timer_group_intr_get_in_isr(timer_group_t group_num) __attribute__((deprecated));
398 
399 /** @brief Get interrupt status, just used in ISR
400  *
401  * @param group_num Timer group number, 0 for TIMERG0 or 1 for TIMERG1
402  *
403  * @return
404  *     - Interrupt status
405  */
406 uint32_t timer_group_get_intr_status_in_isr(timer_group_t group_num);
407 
408 /** @brief Clear the masked interrupt status, just used in ISR
409  *
410  * @param group_num Timer group number, 0 for TIMERG0 or 1 for TIMERG1
411  * @param intr_mask Masked interrupt.
412  *
413  */
414 void timer_group_clr_intr_sta_in_isr(timer_group_t group_num, timer_intr_t intr_mask) __attribute__((deprecated));
415 
416 /** @brief Get auto reload enable status, just used in ISR
417  *
418  * @param group_num Timer group number, 0 for TIMERG0 or 1 for TIMERG1
419  * @param timer_num Timer index
420  *
421  * @return
422  *     - True Auto reload enabled
423  *     - False Auto reload disabled
424  */
425 bool timer_group_get_auto_reload_in_isr(timer_group_t group_num, timer_idx_t timer_num);
426 
427 /** @brief Take timer spinlock to enter critical protect
428  *
429  *  @note Deprecated, the recommended way is to use ISR callbacks instead, see timer_group_example_main
430  *
431  * @param group_num Timer group number, 0 for TIMERG0 or 1 for TIMERG1
432  *
433  * @return
434  *     - ESP_OK Success
435  *     - ESP_ERR_INVALID_ARG Parameter error
436  */
437 esp_err_t timer_spinlock_take(timer_group_t group_num) __attribute__ ((deprecated));
438 
439 /** @brief Give timer spinlock to exit critical protect
440  *
441  *  @note Deprecated, the recommended way is to use ISR callbacks instead, see timer_group_example_main
442  *
443  * @param group_num Timer group number, 0 for TIMERG0 or 1 for TIMERG1
444  *
445  * @return
446  *     - ESP_OK Success
447  *     - ESP_ERR_INVALID_ARG Parameter error
448  */
449 esp_err_t timer_spinlock_give(timer_group_t group_num) __attribute__ ((deprecated));
450 
451 #ifdef __cplusplus
452 }
453 #endif
454