gptimer: add example with various use cases

This commit is contained in:
morris 2022-01-02 16:17:44 +08:00
parent 5deb83b12d
commit 25490dd45f
11 changed files with 255 additions and 3 deletions

View 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)

View 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.

View File

@ -0,0 +1,2 @@
idf_component_register(SRCS "gptimer_example_main.c"
INCLUDE_DIRS ".")

View File

@ -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);
}

View 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')

View File

@ -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
*/

View File

@ -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')

View File

@ -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