/* * SPDX-FileCopyrightText: 2010-2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: CC0-1.0 */ #include #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/queue.h" #include "driver/gptimer.h" #include "esp_log.h" static const char *TAG = "example"; typedef struct { uint64_t event_count; } example_queue_element_t; static bool IRAM_ATTR example_timer_on_alarm_cb_v1(gptimer_handle_t timer, const gptimer_alarm_event_data_t *edata, void *user_data) { BaseType_t high_task_awoken = pdFALSE; QueueHandle_t queue = (QueueHandle_t)user_data; // stop timer immediately gptimer_stop(timer); // Retrieve count value and send to queue example_queue_element_t ele = { .event_count = edata->count_value }; xQueueSendFromISR(queue, &ele, &high_task_awoken); // return whether we need to yield at the end of ISR return (high_task_awoken == pdTRUE); } static bool IRAM_ATTR example_timer_on_alarm_cb_v2(gptimer_handle_t timer, const gptimer_alarm_event_data_t *edata, void *user_data) { BaseType_t high_task_awoken = pdFALSE; QueueHandle_t queue = (QueueHandle_t)user_data; // Retrieve count value and send to queue example_queue_element_t ele = { .event_count = edata->count_value }; xQueueSendFromISR(queue, &ele, &high_task_awoken); // return whether we need to yield at the end of ISR return (high_task_awoken == pdTRUE); } static bool IRAM_ATTR example_timer_on_alarm_cb_v3(gptimer_handle_t timer, const gptimer_alarm_event_data_t *edata, void *user_data) { BaseType_t high_task_awoken = pdFALSE; QueueHandle_t queue = (QueueHandle_t)user_data; // Retrieve count value and send to queue example_queue_element_t ele = { .event_count = edata->count_value }; xQueueSendFromISR(queue, &ele, &high_task_awoken); // reconfigure alarm value gptimer_alarm_config_t alarm_config = { .alarm_count = edata->alarm_value + 1000000, // alarm in next 1s }; gptimer_set_alarm_action(timer, &alarm_config); // return whether we need to yield at the end of ISR return (high_task_awoken == pdTRUE); } void app_main(void) { example_queue_element_t ele; QueueHandle_t queue = xQueueCreate(10, sizeof(example_queue_element_t)); if (!queue) { ESP_LOGE(TAG, "Creating queue failed"); return; } ESP_LOGI(TAG, "Create timer handle"); gptimer_handle_t gptimer = NULL; gptimer_config_t timer_config = { .clk_src = GPTIMER_CLK_SRC_DEFAULT, .direction = GPTIMER_COUNT_UP, .resolution_hz = 1000000, // 1MHz, 1 tick=1us }; ESP_ERROR_CHECK(gptimer_new_timer(&timer_config, &gptimer)); gptimer_event_callbacks_t cbs = { .on_alarm = example_timer_on_alarm_cb_v1, }; ESP_ERROR_CHECK(gptimer_register_event_callbacks(gptimer, &cbs, queue)); ESP_LOGI(TAG, "Enable timer"); ESP_ERROR_CHECK(gptimer_enable(gptimer)); ESP_LOGI(TAG, "Start timer, stop it at alarm event"); gptimer_alarm_config_t alarm_config1 = { .alarm_count = 1000000, // period = 1s }; ESP_ERROR_CHECK(gptimer_set_alarm_action(gptimer, &alarm_config1)); ESP_ERROR_CHECK(gptimer_start(gptimer)); if (xQueueReceive(queue, &ele, pdMS_TO_TICKS(2000))) { ESP_LOGI(TAG, "Timer stopped, count=%llu", ele.event_count); } else { ESP_LOGW(TAG, "Missed one count event"); } ESP_LOGI(TAG, "Set count value"); ESP_ERROR_CHECK(gptimer_set_raw_count(gptimer, 100)); ESP_LOGI(TAG, "Get count value"); uint64_t count; ESP_ERROR_CHECK(gptimer_get_raw_count(gptimer, &count)); ESP_LOGI(TAG, "Timer count value=%llu", count); // before updating the alarm callback, we should make sure the timer is not in the enable state ESP_LOGI(TAG, "Disable timer"); ESP_ERROR_CHECK(gptimer_disable(gptimer)); // set a new callback function cbs.on_alarm = example_timer_on_alarm_cb_v2; ESP_ERROR_CHECK(gptimer_register_event_callbacks(gptimer, &cbs, queue)); ESP_LOGI(TAG, "Enable timer"); ESP_ERROR_CHECK(gptimer_enable(gptimer)); ESP_LOGI(TAG, "Start timer, auto-reload at alarm event"); gptimer_alarm_config_t alarm_config2 = { .reload_count = 0, .alarm_count = 1000000, // period = 1s .flags.auto_reload_on_alarm = true, }; ESP_ERROR_CHECK(gptimer_set_alarm_action(gptimer, &alarm_config2)); ESP_ERROR_CHECK(gptimer_start(gptimer)); int record = 4; while (record) { if (xQueueReceive(queue, &ele, pdMS_TO_TICKS(2000))) { ESP_LOGI(TAG, "Timer reloaded, count=%llu", ele.event_count); record--; } else { ESP_LOGW(TAG, "Missed one count event"); } } ESP_LOGI(TAG, "Stop timer"); ESP_ERROR_CHECK(gptimer_stop(gptimer)); ESP_LOGI(TAG, "Disable timer"); ESP_ERROR_CHECK(gptimer_disable(gptimer)); cbs.on_alarm = example_timer_on_alarm_cb_v3; ESP_ERROR_CHECK(gptimer_register_event_callbacks(gptimer, &cbs, queue)); ESP_LOGI(TAG, "Enable timer"); ESP_ERROR_CHECK(gptimer_enable(gptimer)); ESP_LOGI(TAG, "Start timer, update alarm value dynamically"); gptimer_alarm_config_t alarm_config3 = { .alarm_count = 1000000, // period = 1s }; ESP_ERROR_CHECK(gptimer_set_alarm_action(gptimer, &alarm_config3)); ESP_ERROR_CHECK(gptimer_start(gptimer)); record = 4; while (record) { if (xQueueReceive(queue, &ele, pdMS_TO_TICKS(2000))) { ESP_LOGI(TAG, "Timer alarmed, count=%llu", ele.event_count); record--; } else { ESP_LOGW(TAG, "Missed one count event"); } } ESP_LOGI(TAG, "Stop timer"); ESP_ERROR_CHECK(gptimer_stop(gptimer)); ESP_LOGI(TAG, "Disable timer"); ESP_ERROR_CHECK(gptimer_disable(gptimer)); ESP_LOGI(TAG, "Delete timer"); ESP_ERROR_CHECK(gptimer_del_timer(gptimer)); vQueueDelete(queue); }