mirror of
https://github.com/espressif/esp-idf.git
synced 2025-09-30 19:19:21 +00:00
gptimer: add example with various use cases
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
# The following lines of boilerplate have to be in your project's CMakeLists
|
||||
# in this exact order for cmake to work correctly
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(timer_group)
|
46
examples/peripherals/timer_group/legacy_driver/README.md
Normal file
46
examples/peripherals/timer_group/legacy_driver/README.md
Normal file
@@ -0,0 +1,46 @@
|
||||
# Example: General Purpose Timer
|
||||
|
||||
This example uses the timer group driver to generate timer interrupts at two specified alarm intervals.
|
||||
|
||||
## How to Use Example
|
||||
|
||||
### Hardware Required
|
||||
|
||||
* A development board with ESP SoC (e.g., ESP32-DevKitC, ESP-WROVER-KIT, etc.)
|
||||
* A USB cable for Power supply and programming
|
||||
|
||||
### Build and Flash
|
||||
|
||||
Run `idf.py -p PORT flash monitor` to build, flash and monitor the project.
|
||||
|
||||
(To exit the serial monitor, type ``Ctrl-]``.)
|
||||
|
||||
See the [ESP-IDF Getting Started Guide](https://idf.espressif.com/) for all the steps to configure and use the ESP-IDF to build projects.
|
||||
## Example Output
|
||||
|
||||
```
|
||||
I (0) cpu_start: Starting scheduler on APP CPU.
|
||||
I (325) example: Init timer with auto-reload
|
||||
I (835) example: Timer auto reloaded, count value in ISR: 3
|
||||
I (1335) example: Timer auto reloaded, count value in ISR: 3
|
||||
I (1835) example: Timer auto reloaded, count value in ISR: 3
|
||||
I (2335) example: Timer auto reloaded, count value in ISR: 3
|
||||
I (2335) example: Init timer without auto-reload
|
||||
I (2835) example: Timer alarmed at 500003
|
||||
I (3335) example: Timer alarmed at 1000003
|
||||
I (3835) example: Timer alarmed at 1500003
|
||||
I (4335) example: Timer alarmed at 2000003
|
||||
```
|
||||
|
||||
## Functionality Overview
|
||||
|
||||
* Configure one timer with auto-reload enabled, alarm period set to 0.5s
|
||||
* On reaching the interval value the timer will generate an alarm
|
||||
* The timer will reload with initial count value on alarm, by hardware
|
||||
* Reconfigure the timer with auto-reload disabled, initial alarm value set to 0.5s
|
||||
* The timer keeps incrementing and in the alarm callback, the software reconfigures its alarm value by increasing 0.5s
|
||||
* The main task will print the count value that captured in the alarm callback
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
For any technical queries, please open an [issue](https://github.com/espressif/esp-idf/issues) on GitHub. We will get back to you soon.
|
@@ -0,0 +1,2 @@
|
||||
idf_component_register(SRCS "timer_group_example_main.c"
|
||||
INCLUDE_DIRS ".")
|
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* 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/timer.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
#define TIMER_RESOLUTION_HZ 1000000 // 1MHz resolution
|
||||
#define TIMER_ALARM_PERIOD_S 0.5 // Alarm period 0.5s
|
||||
|
||||
static const char *TAG = "example";
|
||||
|
||||
/**
|
||||
* @brief A sample structure to pass events from the timer ISR to task
|
||||
*/
|
||||
typedef struct {
|
||||
uint64_t timer_count_value;
|
||||
} example_timer_event_t;
|
||||
|
||||
/**
|
||||
* @brief Timer user data, will be pass to timer alarm callback
|
||||
*/
|
||||
typedef struct {
|
||||
xQueueHandle user_queue;
|
||||
int timer_group;
|
||||
int timer_idx;
|
||||
int alarm_value;
|
||||
bool auto_reload;
|
||||
} example_timer_user_data_t;
|
||||
|
||||
static bool IRAM_ATTR timer_group_isr_callback(void *args)
|
||||
{
|
||||
BaseType_t high_task_awoken = pdFALSE;
|
||||
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);
|
||||
example_timer_event_t evt = {
|
||||
.timer_count_value = timer_count_value,
|
||||
};
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
// Send the event data back to the main program task
|
||||
xQueueSendFromISR(user_data->user_queue, &evt, &high_task_awoken);
|
||||
|
||||
return high_task_awoken == pdTRUE; // return whether a task switch is needed
|
||||
}
|
||||
|
||||
static void example_tg_timer_init(example_timer_user_data_t *user_data)
|
||||
{
|
||||
int group = user_data->timer_group;
|
||||
int timer = user_data->timer_idx;
|
||||
|
||||
timer_config_t config = {
|
||||
.clk_src = TIMER_SRC_CLK_APB,
|
||||
.divider = APB_CLK_FREQ / TIMER_RESOLUTION_HZ,
|
||||
.counter_dir = TIMER_COUNT_UP,
|
||||
.counter_en = TIMER_PAUSE,
|
||||
.alarm_en = TIMER_ALARM_EN,
|
||||
.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));
|
||||
}
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
@@ -0,0 +1,24 @@
|
||||
# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
import pytest
|
||||
from pytest_embedded.dut import Dut
|
||||
|
||||
|
||||
@pytest.mark.esp32
|
||||
@pytest.mark.esp32s2
|
||||
@pytest.mark.esp32s3
|
||||
@pytest.mark.esp32c3
|
||||
@pytest.mark.generic
|
||||
def test_timer_group_example(dut: Dut) -> None:
|
||||
dut.expect(r'Init timer with auto-reload', timeout=5)
|
||||
res = dut.expect(r'Timer auto reloaded, count value in ISR: (\d+)', timeout=5)
|
||||
reloaded_count = res.group(1).decode('utf8')
|
||||
assert 0 <= int(reloaded_count) < 10
|
||||
|
||||
alarm_increase_step = 500000
|
||||
dut.expect(r'Init timer without auto-reload')
|
||||
for i in range(1, 5):
|
||||
res = dut.expect(r'Timer alarmed at (\d+)', timeout=3)
|
||||
alarm_count = res.group(1).decode('utf8')
|
||||
assert (i * alarm_increase_step - 10) < int(alarm_count) < (i * alarm_increase_step + 10)
|
@@ -0,0 +1,4 @@
|
||||
# This file was generated using idf.py save-defconfig. It can be edited manually.
|
||||
# Espressif IoT Development Framework (ESP-IDF) Project Minimal Configuration
|
||||
#
|
||||
CONFIG_GPTIMER_SUPPRESS_DEPRECATE_WARN=y
|
Reference in New Issue
Block a user