5#include "freertos/FreeRTOS.h"
8#include "driver/gptimer.h"
9#include "esp_clk_tree.h"
10#include "soc/clk_tree_defs.h"
12static const char *
const TAG =
"hw_timer_esp_idf";
17static constexpr uint32_t GPTIMER_DIVIDER_MIN = 2;
18static constexpr uint32_t GPTIMER_DIVIDER_MAX = 65536;
23struct InterruptConfigT {
29 gptimer_handle_t timer_handle{
nullptr};
30 InterruptConfigT interrupt_handle{};
31 bool timer_started{
false};
35 esp_err_t err = ESP_OK;
36 uint32_t counter_src_hz = 0;
39 for (
auto clk_candidate : SOC_GPTIMER_CLKS) {
41 esp_clk_tree_src_get_freq_hz(clk, ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, &counter_src_hz);
43 if ((divider >= GPTIMER_DIVIDER_MIN) && (divider <= GPTIMER_DIVIDER_MAX)) {
51 ESP_LOGE(TAG,
"Resolution not possible; aborting");
55 gptimer_config_t config = {
56 .clk_src =
static_cast<gptimer_clock_source_t
>(clk),
59 .
flags = {.intr_shared =
true},
62 HWTimer *timer =
new HWTimer();
64 err = gptimer_new_timer(&config, &timer->timer_handle);
66 ESP_LOGE(TAG,
"GPTimer creation failed; error %d", err);
71 err = gptimer_enable(timer->timer_handle);
73 ESP_LOGE(TAG,
"GPTimer enable failed; error %d", err);
74 gptimer_del_timer(timer->timer_handle);
79 err = gptimer_start(timer->timer_handle);
81 ESP_LOGE(TAG,
"GPTimer start failed; error %d", err);
82 gptimer_disable(timer->timer_handle);
83 gptimer_del_timer(timer->timer_handle);
88 timer->timer_started =
true;
92bool IRAM_ATTR
timer_fn_wrapper(gptimer_handle_t timer,
const gptimer_alarm_event_data_t *edata,
void *args) {
93 auto *isr =
static_cast<InterruptConfigT *
>(args);
105static void timer_attach_interrupt_functional_arg(HWTimer *timer,
void (*user_func)(
void *),
void *arg) {
106 if (timer ==
nullptr) {
107 ESP_LOGE(TAG,
"Timer handle is nullptr");
110 gptimer_event_callbacks_t cbs = {
114 timer->interrupt_handle.fn =
reinterpret_cast<voidFuncPtr>(user_func);
115 timer->interrupt_handle.arg = arg;
117 if (timer->timer_started) {
118 gptimer_stop(timer->timer_handle);
120 gptimer_disable(timer->timer_handle);
121 esp_err_t err = gptimer_register_event_callbacks(timer->timer_handle, &cbs, &timer->interrupt_handle);
123 ESP_LOGE(TAG,
"Timer Attach Interrupt failed; error %d", err);
125 gptimer_enable(timer->timer_handle);
126 if (timer->timer_started) {
127 gptimer_start(timer->timer_handle);
132 timer_attach_interrupt_functional_arg(timer,
reinterpret_cast<voidFuncPtrArg>(user_func),
nullptr);
135void timer_alarm(HWTimer *timer, uint64_t alarm_value,
bool autoreload, uint64_t reload_count) {
136 if (timer ==
nullptr) {
137 ESP_LOGE(TAG,
"Timer handle is nullptr");
140 gptimer_alarm_config_t alarm_cfg = {
141 .alarm_count = alarm_value,
142 .reload_count = reload_count,
143 .flags = {.auto_reload_on_alarm = autoreload},
145 esp_err_t err = gptimer_set_alarm_action(timer->timer_handle, &alarm_cfg);
147 ESP_LOGE(TAG,
"Timer Alarm Write failed; error %d", err);
void timer_attach_interrupt(HWTimer *timer, voidFuncPtr user_func)
void(*)(void *) voidFuncPtrArg
void timer_alarm(HWTimer *timer, uint64_t alarm_value, bool autoreload, uint64_t reload_count)
HWTimer * timer_begin(uint32_t frequency)
bool IRAM_ATTR timer_fn_wrapper(gptimer_handle_t timer, const gptimer_alarm_event_data_t *edata, void *args)