2021-09-27 00:46:51 -04:00
|
|
|
/*
|
|
|
|
* SPDX-FileCopyrightText: 2010-2021 Espressif Systems (Shanghai) CO LTD
|
|
|
|
*
|
|
|
|
* SPDX-License-Identifier: CC0-1.0
|
|
|
|
*/
|
2016-11-22 13:15:27 -05:00
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "freertos/FreeRTOS.h"
|
|
|
|
#include "freertos/task.h"
|
|
|
|
#include "freertos/queue.h"
|
|
|
|
#include "driver/timer.h"
|
2021-12-17 00:19:20 -05:00
|
|
|
#include "esp_log.h"
|
2016-11-22 13:15:27 -05:00
|
|
|
|
2021-12-17 00:19:20 -05:00
|
|
|
#define TIMER_RESOLUTION_HZ 1000000 // 1MHz resolution
|
|
|
|
#define TIMER_ALARM_PERIOD_S 0.5 // Alarm period 0.5s
|
2016-11-22 13:15:27 -05:00
|
|
|
|
2021-12-17 00:19:20 -05:00
|
|
|
static const char *TAG = "example";
|
2021-02-01 01:10:15 -05:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief A sample structure to pass events from the timer ISR to task
|
|
|
|
*/
|
|
|
|
typedef struct {
|
2021-12-17 00:19:20 -05:00
|
|
|
uint64_t timer_count_value;
|
2021-02-01 01:10:15 -05:00
|
|
|
} example_timer_event_t;
|
2016-11-22 13:15:27 -05:00
|
|
|
|
2021-12-17 00:19:20 -05:00
|
|
|
/**
|
|
|
|
* @brief Timer user data, will be pass to timer alarm callback
|
2016-11-22 13:15:27 -05:00
|
|
|
*/
|
2021-12-17 00:19:20 -05:00
|
|
|
typedef struct {
|
|
|
|
xQueueHandle user_queue;
|
|
|
|
int timer_group;
|
|
|
|
int timer_idx;
|
|
|
|
int alarm_value;
|
|
|
|
bool auto_reload;
|
|
|
|
} example_timer_user_data_t;
|
2016-11-22 13:15:27 -05:00
|
|
|
|
2021-02-01 01:10:15 -05:00
|
|
|
static bool IRAM_ATTR timer_group_isr_callback(void *args)
|
2016-11-22 13:15:27 -05:00
|
|
|
{
|
2021-02-01 01:10:15 -05:00
|
|
|
BaseType_t high_task_awoken = pdFALSE;
|
2021-12-17 00:19:20 -05:00
|
|
|
example_timer_user_data_t *user_data = (example_timer_user_data_t *) args;
|
|
|
|
// fetch current count value
|
|
|
|
uint64_t timer_count_value = timer_group_get_counter_value_in_isr(user_data->timer_group, user_data->timer_idx);
|
2021-02-01 01:10:15 -05:00
|
|
|
example_timer_event_t evt = {
|
2021-12-17 00:19:20 -05:00
|
|
|
.timer_count_value = timer_count_value,
|
2021-02-01 01:10:15 -05:00
|
|
|
};
|
|
|
|
|
2021-12-17 00:19:20 -05:00
|
|
|
// set new alarm value if necessary
|
|
|
|
if (!user_data->auto_reload) {
|
|
|
|
user_data->alarm_value += TIMER_ALARM_PERIOD_S * TIMER_RESOLUTION_HZ;
|
|
|
|
timer_group_set_alarm_value_in_isr(user_data->timer_group, user_data->timer_idx, user_data->alarm_value);
|
2016-11-22 13:15:27 -05:00
|
|
|
}
|
2017-09-25 00:20:12 -04:00
|
|
|
|
2021-12-17 00:19:20 -05:00
|
|
|
// Send the event data back to the main program task
|
|
|
|
xQueueSendFromISR(user_data->user_queue, &evt, &high_task_awoken);
|
2021-02-01 01:10:15 -05:00
|
|
|
|
2021-12-17 00:19:20 -05:00
|
|
|
return high_task_awoken == pdTRUE; // return whether a task switch is needed
|
2016-11-22 13:15:27 -05:00
|
|
|
}
|
|
|
|
|
2021-12-17 00:19:20 -05:00
|
|
|
static void example_tg_timer_init(example_timer_user_data_t *user_data)
|
2016-11-22 13:15:27 -05:00
|
|
|
{
|
2021-12-17 00:19:20 -05:00
|
|
|
int group = user_data->timer_group;
|
|
|
|
int timer = user_data->timer_idx;
|
|
|
|
|
2020-04-10 04:23:19 -04:00
|
|
|
timer_config_t config = {
|
2021-12-17 00:19:20 -05:00
|
|
|
.clk_src = TIMER_SRC_CLK_APB,
|
|
|
|
.divider = APB_CLK_FREQ / TIMER_RESOLUTION_HZ,
|
2020-04-10 04:23:19 -04:00
|
|
|
.counter_dir = TIMER_COUNT_UP,
|
|
|
|
.counter_en = TIMER_PAUSE,
|
|
|
|
.alarm_en = TIMER_ALARM_EN,
|
2021-12-17 00:19:20 -05:00
|
|
|
.auto_reload = user_data->auto_reload,
|
|
|
|
};
|
|
|
|
ESP_ERROR_CHECK(timer_init(group, timer, &config));
|
|
|
|
|
|
|
|
// For the timer counter to a initial value
|
|
|
|
ESP_ERROR_CHECK(timer_set_counter_value(group, timer, 0));
|
|
|
|
// Set alarm value and enable alarm interrupt
|
|
|
|
ESP_ERROR_CHECK(timer_set_alarm_value(group, timer, user_data->alarm_value));
|
|
|
|
ESP_ERROR_CHECK(timer_enable_intr(group, timer));
|
|
|
|
// Hook interrupt callback
|
|
|
|
ESP_ERROR_CHECK(timer_isr_callback_add(group, timer, timer_group_isr_callback, user_data, 0));
|
|
|
|
// Start timer
|
|
|
|
ESP_ERROR_CHECK(timer_start(group, timer));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void example_tg_timer_deinit(int group, int timer)
|
|
|
|
{
|
|
|
|
ESP_ERROR_CHECK(timer_isr_callback_remove(group, timer));
|
|
|
|
ESP_ERROR_CHECK(timer_deinit(group, timer));
|
2016-11-22 13:15:27 -05:00
|
|
|
}
|
|
|
|
|
2021-02-01 01:10:15 -05:00
|
|
|
void app_main(void)
|
2016-11-22 13:15:27 -05:00
|
|
|
{
|
2021-12-17 00:19:20 -05:00
|
|
|
example_timer_user_data_t *user_data = calloc(1, sizeof(example_timer_user_data_t));
|
|
|
|
assert(user_data);
|
|
|
|
user_data->user_queue = xQueueCreate(10, sizeof(example_timer_event_t));
|
|
|
|
assert(user_data->user_queue);
|
|
|
|
user_data->timer_group = 0;
|
|
|
|
user_data->timer_idx = 0;
|
|
|
|
user_data->alarm_value = TIMER_ALARM_PERIOD_S * TIMER_RESOLUTION_HZ;
|
|
|
|
|
|
|
|
|
|
|
|
ESP_LOGI(TAG, "Init timer with auto-reload");
|
|
|
|
user_data->auto_reload = true;
|
|
|
|
example_tg_timer_init(user_data);
|
|
|
|
|
|
|
|
example_timer_event_t evt;
|
|
|
|
uint32_t test_count = 4;
|
|
|
|
while (test_count--) {
|
|
|
|
xQueueReceive(user_data->user_queue, &evt, portMAX_DELAY);
|
|
|
|
ESP_LOGI(TAG, "Timer auto reloaded, count value in ISR: %llu", evt.timer_count_value);
|
2017-09-25 00:20:12 -04:00
|
|
|
}
|
2021-12-17 00:19:20 -05:00
|
|
|
example_tg_timer_deinit(user_data->timer_group, user_data->timer_idx);
|
|
|
|
|
|
|
|
ESP_LOGI(TAG, "Init timer without auto-reload");
|
|
|
|
user_data->auto_reload = false;
|
|
|
|
example_tg_timer_init(user_data);
|
|
|
|
|
|
|
|
test_count = 4;
|
|
|
|
while (test_count--) {
|
|
|
|
xQueueReceive(user_data->user_queue, &evt, portMAX_DELAY);
|
|
|
|
ESP_LOGI(TAG, "Timer alarmed at %llu", evt.timer_count_value);
|
|
|
|
}
|
|
|
|
example_tg_timer_deinit(user_data->timer_group, user_data->timer_idx);
|
|
|
|
|
|
|
|
vQueueDelete(user_data->user_queue);
|
|
|
|
free(user_data);
|
2016-11-22 13:15:27 -05:00
|
|
|
}
|