1 /*
2  * SPDX-FileCopyrightText: 2010-2022 Espressif Systems (Shanghai) CO LTD
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 /*
8  * ets_timer module implements a set of legacy timer APIs which are
9  * used by the WiFi driver. This is done on top of the newer esp_timer APIs.
10  * Applications should not use ets_timer functions, as they may change without
11  * notice.
12  */
13 
14 #include <string.h>
15 #include "esp_types.h"
16 #include "esp_log.h"
17 #include "esp_attr.h"
18 #include "esp_intr_alloc.h"
19 #include "sdkconfig.h"
20 #include "esp_timer.h"
21 // for ETSTimer type
22 #if CONFIG_IDF_TARGET_ESP32
23 #include "esp32/rom/ets_sys.h"
24 #elif CONFIG_IDF_TARGET_ESP32S2
25 #include "esp32s2/rom/ets_sys.h"
26 #elif CONFIG_IDF_TARGET_ESP32S3
27 #include "esp32s3/rom/ets_sys.h"
28 #elif CONFIG_IDF_TARGET_ESP32C3
29 #include "esp32c3/rom/ets_sys.h"
30 #elif CONFIG_IDF_TARGET_ESP32C2
31 #include "esp32c2/rom/ets_sys.h"
32 #elif CONFIG_IDF_TARGET_ESP32C6
33 #include "esp32c6/rom/ets_sys.h"
34 #elif CONFIG_IDF_TARGET_ESP32H2
35 #include "esp32h2/rom/ets_sys.h"
36 #endif
37 
38 /* We abuse 'timer_arg' field of ETSTimer structure to hold a pointer to esp_timer */
39 #define ESP_TIMER(p_ets_timer) ((esp_timer_handle_t) (p_ets_timer)->timer_arg)
40 
41 /* We abuse 'timer_expire' field of ETSTimer structure to hold a magic value
42  * signifying that the contents of the timer was zeroed out.
43  */
44 #define TIMER_INITIALIZED_FIELD(p_ets_timer) ((p_ets_timer)->timer_expire)
45 #define TIMER_INITIALIZED_VAL 0x12121212
46 
timer_initialized(ETSTimer * ptimer)47 static IRAM_ATTR bool timer_initialized(ETSTimer *ptimer)
48 {
49     return TIMER_INITIALIZED_FIELD(ptimer) == TIMER_INITIALIZED_VAL;
50 }
51 
ets_timer_setfn(ETSTimer * ptimer,ETSTimerFunc * pfunction,void * parg)52 void ets_timer_setfn(ETSTimer *ptimer, ETSTimerFunc *pfunction, void *parg)
53 {
54     if (!timer_initialized(ptimer)) {
55         memset(ptimer, 0, sizeof(*ptimer));
56         TIMER_INITIALIZED_FIELD(ptimer) = TIMER_INITIALIZED_VAL;
57     }
58 
59     if (ESP_TIMER(ptimer) == NULL) {
60         const esp_timer_create_args_t create_args = {
61                 .callback = pfunction,
62                 .arg = parg,
63                 .name = "ETSTimer",
64                 .dispatch_method = ESP_TIMER_TASK
65         };
66 
67         ESP_ERROR_CHECK( esp_timer_create(&create_args, (esp_timer_handle_t*)&(ptimer->timer_arg)) );
68     }
69 }
70 
71 
ets_timer_arm_us(ETSTimer * ptimer,uint32_t time_us,bool repeat_flag)72 void IRAM_ATTR ets_timer_arm_us(ETSTimer *ptimer, uint32_t time_us, bool repeat_flag)
73 {
74     assert(timer_initialized(ptimer));
75     esp_timer_stop(ESP_TIMER(ptimer));  // no error check
76     if (!repeat_flag) {
77         ESP_ERROR_CHECK( esp_timer_start_once(ESP_TIMER(ptimer), time_us) );
78     } else {
79         ESP_ERROR_CHECK( esp_timer_start_periodic(ESP_TIMER(ptimer), time_us) );
80     }
81 }
82 
ets_timer_arm(ETSTimer * ptimer,uint32_t time_ms,bool repeat_flag)83 void IRAM_ATTR ets_timer_arm(ETSTimer *ptimer, uint32_t time_ms, bool repeat_flag)
84 {
85     uint64_t time_us = 1000LL * (uint64_t) time_ms;
86     assert(timer_initialized(ptimer));
87     esp_timer_stop(ESP_TIMER(ptimer));  // no error check
88     if (!repeat_flag) {
89         ESP_ERROR_CHECK( esp_timer_start_once(ESP_TIMER(ptimer), time_us) );
90     } else {
91         ESP_ERROR_CHECK( esp_timer_start_periodic(ESP_TIMER(ptimer), time_us) );
92     }
93 }
94 
ets_timer_done(ETSTimer * ptimer)95 void ets_timer_done(ETSTimer *ptimer)
96 {
97     if (timer_initialized(ptimer)) {
98         esp_timer_delete(ESP_TIMER(ptimer));
99         ptimer->timer_arg = NULL;
100         TIMER_INITIALIZED_FIELD(ptimer) = 0;
101     }
102 }
103 
ets_timer_disarm(ETSTimer * ptimer)104 void IRAM_ATTR ets_timer_disarm(ETSTimer *ptimer)
105 {
106     if (timer_initialized(ptimer)) {
107         esp_timer_stop(ESP_TIMER(ptimer));
108     }
109 }
110 
111 
ets_timer_init(void)112 void ets_timer_init(void)
113 {
114 
115 }
116 
ets_timer_deinit(void)117 void ets_timer_deinit(void)
118 {
119 
120 }
121 
122 void os_timer_setfn(ETSTimer *ptimer, ETSTimerFunc *pfunction, void *parg) __attribute__((alias("ets_timer_setfn")));
123 void os_timer_disarm(ETSTimer *ptimer) __attribute__((alias("ets_timer_disarm")));
124 void os_timer_arm_us(ETSTimer *ptimer,uint32_t u_seconds,bool repeat_flag) __attribute__((alias("ets_timer_arm_us")));
125 void os_timer_arm(ETSTimer *ptimer,uint32_t milliseconds,bool repeat_flag) __attribute__((alias("ets_timer_arm")));
126 void os_timer_done(ETSTimer *ptimer) __attribute__((alias("ets_timer_done")));
127