1 /* 2 * SPDX-FileCopyrightText: 2017-2021 Espressif Systems (Shanghai) CO LTD 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 */ 6 7 #pragma once 8 9 /** 10 * @file esp_timer.h 11 * @brief microsecond-precision 64-bit timer API, replacement for ets_timer 12 * 13 * esp_timer APIs allow components to receive callbacks when a hardware timer 14 * reaches certain value. The timer provides microsecond accuracy and 15 * up to 64 bit range. Note that while the timer itself provides microsecond 16 * accuracy, callbacks are dispatched from an auxiliary task. Some time is 17 * needed to notify this task from timer ISR, and then to invoke the callback. 18 * If more than one callback needs to be dispatched at any particular time, 19 * each subsequent callback will be dispatched only when the previous callback 20 * returns. Therefore, callbacks should not do much work; instead, they should 21 * use RTOS notification mechanisms (queues, semaphores, event groups, etc.) to 22 * pass information to other tasks. 23 * 24 * To be implemented: it should be possible to request the callback to be called 25 * directly from the ISR. This reduces the latency, but has potential impact on 26 * all other callbacks which need to be dispatched. This option should only be 27 * used for simple callback functions, which do not take longer than a few 28 * microseconds to run. 29 * 30 * Implementation note: on the ESP32, esp_timer APIs use the "legacy" FRC2 31 * timer. Timer callbacks are called from a task running on the PRO CPU. 32 */ 33 34 #include <stdint.h> 35 #include <stdio.h> 36 #include <stdbool.h> 37 #include "esp_err.h" 38 #include "sdkconfig.h" 39 40 #ifdef __cplusplus 41 extern "C" { 42 #endif 43 44 /** 45 * @brief Opaque type representing a single esp_timer 46 */ 47 typedef struct esp_timer* esp_timer_handle_t; 48 49 /** 50 * @brief Timer callback function type 51 * @param arg pointer to opaque user-specific data 52 */ 53 typedef void (*esp_timer_cb_t)(void* arg); 54 55 56 /** 57 * @brief Method for dispatching timer callback 58 */ 59 typedef enum { 60 ESP_TIMER_TASK, //!< Callback is called from timer task 61 #ifdef CONFIG_ESP_TIMER_SUPPORTS_ISR_DISPATCH_METHOD 62 ESP_TIMER_ISR, //!< Callback is called from timer ISR 63 #endif 64 ESP_TIMER_MAX, //!< Count of the methods for dispatching timer callback 65 } esp_timer_dispatch_t; 66 67 /** 68 * @brief Timer configuration passed to esp_timer_create 69 */ 70 typedef struct { 71 esp_timer_cb_t callback; //!< Function to call when timer expires 72 void* arg; //!< Argument to pass to the callback 73 esp_timer_dispatch_t dispatch_method; //!< Call the callback from task or from ISR 74 const char* name; //!< Timer name, used in esp_timer_dump function 75 bool skip_unhandled_events; //!< Skip unhandled events for periodic timers 76 } esp_timer_create_args_t; 77 78 79 /** 80 * @brief Minimal initialization of esp_timer 81 * 82 * @note This function is called from startup code. Applications do not need 83 * to call this function before using other esp_timer APIs. 84 * 85 * This function can be called very early in startup process, after this call 86 * only esp_timer_get_time function can be used. 87 * 88 * @return 89 * - ESP_OK on success 90 */ 91 esp_err_t esp_timer_early_init(void); 92 93 /** 94 * @brief Initialize esp_timer library 95 * 96 * @note This function is called from startup code. Applications do not need 97 * to call this function before using other esp_timer APIs. 98 * Before calling this function, esp_timer_early_init must be called by the 99 * startup code. 100 * 101 * @return 102 * - ESP_OK on success 103 * - ESP_ERR_NO_MEM if allocation has failed 104 * - ESP_ERR_INVALID_STATE if already initialized 105 * - other errors from interrupt allocator 106 */ 107 esp_err_t esp_timer_init(void); 108 109 /** 110 * @brief De-initialize esp_timer library 111 * 112 * @note Normally this function should not be called from applications 113 * 114 * @return 115 * - ESP_OK on success 116 * - ESP_ERR_INVALID_STATE if not yet initialized 117 */ 118 esp_err_t esp_timer_deinit(void); 119 120 /** 121 * @brief Create an esp_timer instance 122 * 123 * @note When done using the timer, delete it with esp_timer_delete function. 124 * 125 * @param create_args Pointer to a structure with timer creation arguments. 126 * Not saved by the library, can be allocated on the stack. 127 * @param[out] out_handle Output, pointer to esp_timer_handle_t variable which 128 * will hold the created timer handle. 129 * 130 * @return 131 * - ESP_OK on success 132 * - ESP_ERR_INVALID_ARG if some of the create_args are not valid 133 * - ESP_ERR_INVALID_STATE if esp_timer library is not initialized yet 134 * - ESP_ERR_NO_MEM if memory allocation fails 135 */ 136 esp_err_t esp_timer_create(const esp_timer_create_args_t* create_args, 137 esp_timer_handle_t* out_handle); 138 139 /** 140 * @brief Start one-shot timer 141 * 142 * Timer should not be running when this function is called. 143 * 144 * @param timer timer handle created using esp_timer_create 145 * @param timeout_us timer timeout, in microseconds relative to the current moment 146 * @return 147 * - ESP_OK on success 148 * - ESP_ERR_INVALID_ARG if the handle is invalid 149 * - ESP_ERR_INVALID_STATE if the timer is already running 150 */ 151 esp_err_t esp_timer_start_once(esp_timer_handle_t timer, uint64_t timeout_us); 152 153 /** 154 * @brief Start a periodic timer 155 * 156 * Timer should not be running when this function is called. This function will 157 * start the timer which will trigger every 'period' microseconds. 158 * 159 * @param timer timer handle created using esp_timer_create 160 * @param period timer period, in microseconds 161 * @return 162 * - ESP_OK on success 163 * - ESP_ERR_INVALID_ARG if the handle is invalid 164 * - ESP_ERR_INVALID_STATE if the timer is already running 165 */ 166 esp_err_t esp_timer_start_periodic(esp_timer_handle_t timer, uint64_t period); 167 168 /** 169 * @brief Stop the timer 170 * 171 * This function stops the timer previously started using esp_timer_start_once 172 * or esp_timer_start_periodic. 173 * 174 * @param timer timer handle created using esp_timer_create 175 * @return 176 * - ESP_OK on success 177 * - ESP_ERR_INVALID_STATE if the timer is not running 178 */ 179 esp_err_t esp_timer_stop(esp_timer_handle_t timer); 180 181 /** 182 * @brief Delete an esp_timer instance 183 * 184 * The timer must be stopped before deleting. A one-shot timer which has expired 185 * does not need to be stopped. 186 * 187 * @param timer timer handle allocated using esp_timer_create 188 * @return 189 * - ESP_OK on success 190 * - ESP_ERR_INVALID_STATE if the timer is running 191 */ 192 esp_err_t esp_timer_delete(esp_timer_handle_t timer); 193 194 /** 195 * @brief Get time in microseconds since boot 196 * @return number of microseconds since underlying timer has been started 197 */ 198 int64_t esp_timer_get_time(void); 199 200 /** 201 * @brief Get the timestamp when the next timeout is expected to occur 202 * @return Timestamp of the nearest timer event, in microseconds. 203 * The timebase is the same as for the values returned by esp_timer_get_time. 204 */ 205 int64_t esp_timer_get_next_alarm(void); 206 207 /** 208 * @brief Get the timestamp when the next timeout is expected to occur skipping those which have skip_unhandled_events flag 209 * @return Timestamp of the nearest timer event, in microseconds. 210 * The timebase is the same as for the values returned by esp_timer_get_time. 211 */ 212 int64_t esp_timer_get_next_alarm_for_wake_up(void); 213 214 /** 215 * @brief Dump the list of timers to a stream 216 * 217 * If CONFIG_ESP_TIMER_PROFILING option is enabled, this prints the list of all 218 * the existing timers. Otherwise, only the list active timers is printed. 219 * 220 * The format is: 221 * 222 * name period alarm times_armed times_triggered total_callback_run_time 223 * 224 * where: 225 * 226 * name — timer name (if CONFIG_ESP_TIMER_PROFILING is defined), or timer pointer 227 * period — period of timer, in microseconds, or 0 for one-shot timer 228 * alarm - time of the next alarm, in microseconds since boot, or 0 if the timer 229 * is not started 230 * 231 * The following fields are printed if CONFIG_ESP_TIMER_PROFILING is defined: 232 * 233 * times_armed — number of times the timer was armed via esp_timer_start_X 234 * times_triggered - number of times the callback was called 235 * total_callback_run_time - total time taken by callback to execute, across all calls 236 * 237 * @param stream stream (such as stdout) to dump the information to 238 * @return 239 * - ESP_OK on success 240 * - ESP_ERR_NO_MEM if can not allocate temporary buffer for the output 241 */ 242 esp_err_t esp_timer_dump(FILE* stream); 243 244 #ifdef CONFIG_ESP_TIMER_SUPPORTS_ISR_DISPATCH_METHOD 245 /** 246 * @brief Requests a context switch from a timer callback function. 247 * 248 * This only works for a timer that has an ISR dispatch method. 249 * The context switch will be called after all ISR dispatch timers have been processed. 250 */ 251 void esp_timer_isr_dispatch_need_yield(void); 252 #endif // CONFIG_ESP_TIMER_SUPPORTS_ISR_DISPATCH_METHOD 253 254 /** 255 * @brief Returns status of a timer, active or not 256 * 257 * This function is used to identify if the timer is still active or not. 258 * 259 * @param timer timer handle created using esp_timer_create 260 * @return 261 * - 1 if timer is still active 262 * - 0 if timer is not active. 263 */ 264 bool esp_timer_is_active(esp_timer_handle_t timer); 265 266 #ifdef __cplusplus 267 } 268 #endif 269