mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
gptimer: add example with various use cases
This commit is contained in:
parent
5deb83b12d
commit
25490dd45f
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
|
||||
*/
|
@ -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
|
||||
|
||||
import pytest
|
||||
@ -10,7 +10,7 @@ from pytest_embedded.dut import Dut
|
||||
@pytest.mark.esp32s3
|
||||
@pytest.mark.esp32c3
|
||||
@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)
|
||||
res = dut.expect(r'Timer auto reloaded, count value in ISR: (\d+)', timeout=5)
|
||||
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
|
Loading…
Reference in New Issue
Block a user