mirror of
				https://github.com/espressif/esp-idf.git
				synced 2025-11-04 06:11:06 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			172 lines
		
	
	
		
			5.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			172 lines
		
	
	
		
			5.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
 * SPDX-FileCopyrightText: 2010-2022 Espressif Systems (Shanghai) CO LTD
 | 
						|
 *
 | 
						|
 * SPDX-License-Identifier: CC0-1.0
 | 
						|
 */
 | 
						|
 | 
						|
#include <stdio.h>
 | 
						|
#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);
 | 
						|
}
 |