mirror of
https://github.com/espressif/esp-idf.git
synced 2025-08-03 20:54:32 +02:00
gptimer: add example with various use cases
This commit is contained in:
6
examples/peripherals/timer_group/gptimer/CMakeLists.txt
Normal file
6
examples/peripherals/timer_group/gptimer/CMakeLists.txt
Normal file
@@ -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(gptimer)
|
46
examples/peripherals/timer_group/gptimer/README.md
Normal file
46
examples/peripherals/timer_group/gptimer/README.md
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
# Example: General Purpose Timer
|
||||||
|
|
||||||
|
This example illustrates how to use gptimer APIs to generate periodic alarm events and how different alarm actions behave on events.
|
||||||
|
|
||||||
|
## How to Use Example
|
||||||
|
|
||||||
|
### Hardware Required
|
||||||
|
|
||||||
|
* A development board with ESP SOC chip
|
||||||
|
* 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 (323) example: Create timer handle
|
||||||
|
I (323) example: Start timer, stop it at alarm event
|
||||||
|
I (1333) example: Timer stopped, count=1000002
|
||||||
|
I (1333) example: Set count value
|
||||||
|
I (1333) example: Get count value
|
||||||
|
I (1333) example: Timer count value=100
|
||||||
|
I (1343) example: Start timer, auto-reload at alarm event
|
||||||
|
I (2343) example: Timer reloaded, count=2
|
||||||
|
I (3343) example: Timer reloaded, count=2
|
||||||
|
I (4343) example: Timer reloaded, count=2
|
||||||
|
I (5343) example: Timer reloaded, count=2
|
||||||
|
I (5343) example: Stop timer
|
||||||
|
I (5343) example: Update alarm value dynamically
|
||||||
|
I (6353) example: Timer alarmed, count=1000002
|
||||||
|
I (7353) example: Timer alarmed, count=2000002
|
||||||
|
I (8353) example: Timer alarmed, count=3000002
|
||||||
|
I (9353) example: Timer alarmed, count=4000002
|
||||||
|
I (9353) example: Stop timer
|
||||||
|
I (9353) example: Delete timer
|
||||||
|
```
|
||||||
|
|
||||||
|
## 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 "gptimer_example_main.c"
|
||||||
|
INCLUDE_DIRS ".")
|
@@ -0,0 +1,155 @@
|
|||||||
|
/*
|
||||||
|
* 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_APB,
|
||||||
|
.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, "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);
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "Start timer, auto-reload at alarm event");
|
||||||
|
cbs.on_alarm = example_timer_on_alarm_cb_v2;
|
||||||
|
ESP_ERROR_CHECK(gptimer_register_event_callbacks(gptimer, &cbs, queue));
|
||||||
|
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, "Update alarm value dynamically");
|
||||||
|
cbs.on_alarm = example_timer_on_alarm_cb_v3;
|
||||||
|
ESP_ERROR_CHECK(gptimer_register_event_callbacks(gptimer, &cbs, queue));
|
||||||
|
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, "Delete timer");
|
||||||
|
ESP_ERROR_CHECK(gptimer_del_timer(gptimer));
|
||||||
|
|
||||||
|
vQueueDelete(queue);
|
||||||
|
}
|
39
examples/peripherals/timer_group/gptimer/pytest_gptimer.py
Normal file
39
examples/peripherals/timer_group/gptimer/pytest_gptimer.py
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
# 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_gptimer_example(dut: Dut) -> None:
|
||||||
|
dut.expect(r'Create timer handle', timeout=5)
|
||||||
|
dut.expect(r'Start timer, stop it at alarm event', timeout=5)
|
||||||
|
res = dut.expect(r'Timer stopped, count=(\d+)', timeout=30)
|
||||||
|
stopped_count = res.group(1).decode('utf8')
|
||||||
|
assert (1000000 - 10) < int(stopped_count) < (1000000 + 10)
|
||||||
|
|
||||||
|
dut.expect(r'Set count value')
|
||||||
|
dut.expect(r'Get count value')
|
||||||
|
res = dut.expect(r'Timer count value=(\d+)', timeout=5)
|
||||||
|
count_val = res.group(1).decode('utf8')
|
||||||
|
assert int(count_val) == 100
|
||||||
|
|
||||||
|
dut.expect(r'Start timer, auto-reload at alarm event', timeout=5)
|
||||||
|
res = dut.expect(r'Timer reloaded, count=(\d+)', timeout=5)
|
||||||
|
reloaded_count = res.group(1).decode('utf8')
|
||||||
|
assert 0 <= int(reloaded_count) < 10
|
||||||
|
|
||||||
|
dut.expect(r'Stop timer')
|
||||||
|
dut.expect(r'Update alarm value dynamically')
|
||||||
|
for i in range(1,5):
|
||||||
|
res = dut.expect(r'Timer alarmed, count=(\d+)', timeout=5)
|
||||||
|
alarm_count = res.group(1).decode('utf8')
|
||||||
|
assert (i * 1000000 - 10) < int(alarm_count) < (i * 1000000 + 10)
|
||||||
|
|
||||||
|
dut.expect(r'Stop timer')
|
||||||
|
dut.expect(r'Delete timer')
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2010-2021 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2010-2022 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: CC0-1.0
|
* SPDX-License-Identifier: CC0-1.0
|
||||||
*/
|
*/
|
@@ -1,4 +1,4 @@
|
|||||||
# SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
|
# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
||||||
# SPDX-License-Identifier: CC0-1.0
|
# SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
@@ -10,7 +10,7 @@ from pytest_embedded.dut import Dut
|
|||||||
@pytest.mark.esp32s3
|
@pytest.mark.esp32s3
|
||||||
@pytest.mark.esp32c3
|
@pytest.mark.esp32c3
|
||||||
@pytest.mark.generic
|
@pytest.mark.generic
|
||||||
def test_timer_group_example(dut: Dut): # type: ignore
|
def test_timer_group_example(dut: Dut) -> None:
|
||||||
dut.expect(r'Init timer with auto-reload', timeout=5)
|
dut.expect(r'Init timer with auto-reload', timeout=5)
|
||||||
res = dut.expect(r'Timer auto reloaded, count value in ISR: (\d+)', timeout=5)
|
res = dut.expect(r'Timer auto reloaded, count value in ISR: (\d+)', timeout=5)
|
||||||
reloaded_count = res.group(1).decode('utf8')
|
reloaded_count = res.group(1).decode('utf8')
|
@@ -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