1 /* 2 * SPDX-FileCopyrightText: 2017-2022 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 * Timer callbacks are called from a task running on the PRO CPU. 31 */ 32 33 #include <stdint.h> 34 #include <stdio.h> 35 #include <stdbool.h> 36 #include "esp_err.h" 37 #include "esp_etm.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 * This function will be called from startup code on every core 102 * if CONFIG_ESP_TIMER_ISR_AFFINITY_NO_AFFINITY is enabled, 103 * It allocates the timer ISR on MULTIPLE cores and 104 * creates the timer task which can be run on any core. 105 * 106 * @return 107 * - ESP_OK on success 108 * - ESP_ERR_NO_MEM if allocation has failed 109 * - ESP_ERR_INVALID_STATE if already initialized 110 * - other errors from interrupt allocator 111 */ 112 esp_err_t esp_timer_init(void); 113 114 /** 115 * @brief De-initialize esp_timer library 116 * 117 * @note Normally this function should not be called from applications 118 * 119 * @return 120 * - ESP_OK on success 121 * - ESP_ERR_INVALID_STATE if not yet initialized 122 */ 123 esp_err_t esp_timer_deinit(void); 124 125 /** 126 * @brief Create an esp_timer instance 127 * 128 * @note When done using the timer, delete it with esp_timer_delete function. 129 * 130 * @param create_args Pointer to a structure with timer creation arguments. 131 * Not saved by the library, can be allocated on the stack. 132 * @param[out] out_handle Output, pointer to esp_timer_handle_t variable which 133 * will hold the created timer handle. 134 * 135 * @return 136 * - ESP_OK on success 137 * - ESP_ERR_INVALID_ARG if some of the create_args are not valid 138 * - ESP_ERR_INVALID_STATE if esp_timer library is not initialized yet 139 * - ESP_ERR_NO_MEM if memory allocation fails 140 */ 141 esp_err_t esp_timer_create(const esp_timer_create_args_t* create_args, 142 esp_timer_handle_t* out_handle); 143 144 /** 145 * @brief Start one-shot timer 146 * 147 * Timer should not be running when this function is called. 148 * 149 * @param timer timer handle created using esp_timer_create 150 * @param timeout_us timer timeout, in microseconds relative to the current moment 151 * @return 152 * - ESP_OK on success 153 * - ESP_ERR_INVALID_ARG if the handle is invalid 154 * - ESP_ERR_INVALID_STATE if the timer is already running 155 */ 156 esp_err_t esp_timer_start_once(esp_timer_handle_t timer, uint64_t timeout_us); 157 158 /** 159 * @brief Start a periodic timer 160 * 161 * Timer should not be running when this function is called. This function will 162 * start the timer which will trigger every 'period' microseconds. 163 * 164 * @param timer timer handle created using esp_timer_create 165 * @param period timer period, in microseconds 166 * @return 167 * - ESP_OK on success 168 * - ESP_ERR_INVALID_ARG if the handle is invalid 169 * - ESP_ERR_INVALID_STATE if the timer is already running 170 */ 171 esp_err_t esp_timer_start_periodic(esp_timer_handle_t timer, uint64_t period); 172 173 /** 174 * @brief Restart a currently running timer 175 * 176 * If the given timer is a one-shot timer, the timer is restarted immediately and will timeout once in `timeout_us` microseconds. 177 * If the given timer is a periodic timer, the timer is restarted immediately with a new period of `timeout_us` microseconds. 178 * 179 * @param timer timer Handle created using esp_timer_create 180 * @param timeout_us Timeout, in microseconds relative to the current time. 181 * In case of a periodic timer, also represents the new period. 182 * @return 183 * - ESP_OK on success 184 * - ESP_ERR_INVALID_ARG if the handle is invalid 185 * - ESP_ERR_INVALID_STATE if the timer is not running 186 */ 187 esp_err_t esp_timer_restart(esp_timer_handle_t timer, uint64_t timeout_us); 188 189 /** 190 * @brief Stop the timer 191 * 192 * This function stops the timer previously started using esp_timer_start_once 193 * or esp_timer_start_periodic. 194 * 195 * @param timer timer handle created using esp_timer_create 196 * @return 197 * - ESP_OK on success 198 * - ESP_ERR_INVALID_STATE if the timer is not running 199 */ 200 esp_err_t esp_timer_stop(esp_timer_handle_t timer); 201 202 /** 203 * @brief Delete an esp_timer instance 204 * 205 * The timer must be stopped before deleting. A one-shot timer which has expired 206 * does not need to be stopped. 207 * 208 * @param timer timer handle allocated using esp_timer_create 209 * @return 210 * - ESP_OK on success 211 * - ESP_ERR_INVALID_STATE if the timer is running 212 */ 213 esp_err_t esp_timer_delete(esp_timer_handle_t timer); 214 215 /** 216 * @brief Get time in microseconds since boot 217 * @return number of microseconds since underlying timer has been started 218 */ 219 int64_t esp_timer_get_time(void); 220 221 /** 222 * @brief Get the timestamp when the next timeout is expected to occur 223 * @return Timestamp of the nearest timer event, in microseconds. 224 * The timebase is the same as for the values returned by esp_timer_get_time. 225 */ 226 int64_t esp_timer_get_next_alarm(void); 227 228 /** 229 * @brief Get the timestamp when the next timeout is expected to occur skipping those which have skip_unhandled_events flag 230 * @return Timestamp of the nearest timer event, in microseconds. 231 * The timebase is the same as for the values returned by esp_timer_get_time. 232 */ 233 int64_t esp_timer_get_next_alarm_for_wake_up(void); 234 235 /** 236 * @brief Get the period of a timer 237 * 238 * This function fetches the timeout period of a timer. 239 * 240 * @note The timeout period is the time interval with which a timer restarts after expiry. For one-shot timers, the 241 * period is 0 as there is no periodicity associated with such timers. 242 * 243 * @param timer timer handle allocated using esp_timer_create 244 * @param period memory to store the timer period value in microseconds 245 * @return 246 * - ESP_OK on success 247 * - ESP_ERR_INVALID_ARG if the arguments are invalid 248 */ 249 esp_err_t esp_timer_get_period(esp_timer_handle_t timer, uint64_t *period); 250 251 /** 252 * @brief Get the expiry time of a one-shot timer 253 * 254 * This function fetches the expiry time of a one-shot timer. 255 * 256 * @note This API returns a valid expiry time only for a one-shot timer. It returns an error if the timer handle passed 257 * to the function is for a periodic timer. 258 * 259 * @param timer timer handle allocated using esp_timer_create 260 * @param expiry memory to store the timeout value in microseconds 261 * @return 262 * - ESP_OK on success 263 * - ESP_ERR_INVALID_ARG if the arguments are invalid 264 * - ESP_ERR_NOT_SUPPORTED if the timer type is periodic 265 */ 266 esp_err_t esp_timer_get_expiry_time(esp_timer_handle_t timer, uint64_t *expiry); 267 268 /** 269 * @brief Dump the list of timers to a stream 270 * 271 * If CONFIG_ESP_TIMER_PROFILING option is enabled, this prints the list of all 272 * the existing timers. Otherwise, only the list active timers is printed. 273 * 274 * The format is: 275 * 276 * name period alarm times_armed times_triggered total_callback_run_time 277 * 278 * where: 279 * 280 * name — timer name (if CONFIG_ESP_TIMER_PROFILING is defined), or timer pointer 281 * period — period of timer, in microseconds, or 0 for one-shot timer 282 * alarm - time of the next alarm, in microseconds since boot, or 0 if the timer 283 * is not started 284 * 285 * The following fields are printed if CONFIG_ESP_TIMER_PROFILING is defined: 286 * 287 * times_armed — number of times the timer was armed via esp_timer_start_X 288 * times_triggered - number of times the callback was called 289 * total_callback_run_time - total time taken by callback to execute, across all calls 290 * 291 * @param stream stream (such as stdout) to dump the information to 292 * @return 293 * - ESP_OK on success 294 * - ESP_ERR_NO_MEM if can not allocate temporary buffer for the output 295 */ 296 esp_err_t esp_timer_dump(FILE* stream); 297 298 #if CONFIG_ESP_TIMER_SUPPORTS_ISR_DISPATCH_METHOD || defined __DOXYGEN__ 299 /** 300 * @brief Requests a context switch from a timer callback function. 301 * 302 * This only works for a timer that has an ISR dispatch method. 303 * The context switch will be called after all ISR dispatch timers have been processed. 304 */ 305 void esp_timer_isr_dispatch_need_yield(void); 306 #endif // CONFIG_ESP_TIMER_SUPPORTS_ISR_DISPATCH_METHOD || defined __DOXYGEN__ 307 308 /** 309 * @brief Returns status of a timer, active or not 310 * 311 * This function is used to identify if the timer is still active or not. 312 * 313 * @param timer timer handle created using esp_timer_create 314 * @return 315 * - 1 if timer is still active 316 * - 0 if timer is not active. 317 */ 318 bool esp_timer_is_active(esp_timer_handle_t timer); 319 320 /** 321 * @brief Get the ETM event handle of esp_timer underlying alarm event 322 * 323 * @note The created ETM event object can be deleted later by calling `esp_etm_del_event` 324 * 325 * @note The ETM event is generated by the underlying hardware -- systimer, 326 * therefore, if the esp_timer is not clocked by systimer, then no ETM event will be generated. 327 * 328 * @param[out] out_event Returned ETM event handle 329 * @return 330 * - ESP_OK Success 331 * - ESP_ERR_INVALID_ARG Parameter error 332 */ 333 esp_err_t esp_timer_new_etm_alarm_event(esp_etm_event_handle_t *out_event); 334 335 #ifdef __cplusplus 336 } 337 #endif 338