diff --git a/examples/peripherals/timer_group/gptimer/CMakeLists.txt b/examples/peripherals/timer_group/gptimer/CMakeLists.txt new file mode 100644 index 000000000000..d4076f376862 --- /dev/null +++ b/examples/peripherals/timer_group/gptimer/CMakeLists.txt @@ -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) diff --git a/examples/peripherals/timer_group/gptimer/README.md b/examples/peripherals/timer_group/gptimer/README.md new file mode 100644 index 000000000000..687c3881302a --- /dev/null +++ b/examples/peripherals/timer_group/gptimer/README.md @@ -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. diff --git a/examples/peripherals/timer_group/gptimer/main/CMakeLists.txt b/examples/peripherals/timer_group/gptimer/main/CMakeLists.txt new file mode 100644 index 000000000000..81e0fad7b26d --- /dev/null +++ b/examples/peripherals/timer_group/gptimer/main/CMakeLists.txt @@ -0,0 +1,2 @@ +idf_component_register(SRCS "gptimer_example_main.c" + INCLUDE_DIRS ".") diff --git a/examples/peripherals/timer_group/gptimer/main/gptimer_example_main.c b/examples/peripherals/timer_group/gptimer/main/gptimer_example_main.c new file mode 100644 index 000000000000..35fe5471c3ae --- /dev/null +++ b/examples/peripherals/timer_group/gptimer/main/gptimer_example_main.c @@ -0,0 +1,155 @@ +/* + * SPDX-FileCopyrightText: 2010-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: CC0-1.0 + */ + +#include +#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); +} diff --git a/examples/peripherals/timer_group/gptimer/pytest_gptimer.py b/examples/peripherals/timer_group/gptimer/pytest_gptimer.py new file mode 100644 index 000000000000..7d03f0e00f03 --- /dev/null +++ b/examples/peripherals/timer_group/gptimer/pytest_gptimer.py @@ -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') diff --git a/examples/peripherals/timer_group/CMakeLists.txt b/examples/peripherals/timer_group/legacy_driver/CMakeLists.txt similarity index 100% rename from examples/peripherals/timer_group/CMakeLists.txt rename to examples/peripherals/timer_group/legacy_driver/CMakeLists.txt diff --git a/examples/peripherals/timer_group/README.md b/examples/peripherals/timer_group/legacy_driver/README.md similarity index 100% rename from examples/peripherals/timer_group/README.md rename to examples/peripherals/timer_group/legacy_driver/README.md diff --git a/examples/peripherals/timer_group/main/CMakeLists.txt b/examples/peripherals/timer_group/legacy_driver/main/CMakeLists.txt similarity index 100% rename from examples/peripherals/timer_group/main/CMakeLists.txt rename to examples/peripherals/timer_group/legacy_driver/main/CMakeLists.txt diff --git a/examples/peripherals/timer_group/main/timer_group_example_main.c b/examples/peripherals/timer_group/legacy_driver/main/timer_group_example_main.c similarity index 98% rename from examples/peripherals/timer_group/main/timer_group_example_main.c rename to examples/peripherals/timer_group/legacy_driver/main/timer_group_example_main.c index 5b90ab190ef2..c5983ca65e23 100644 --- a/examples/peripherals/timer_group/main/timer_group_example_main.c +++ b/examples/peripherals/timer_group/legacy_driver/main/timer_group_example_main.c @@ -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 */ diff --git a/examples/peripherals/timer_group/pytest_timer_group.py b/examples/peripherals/timer_group/legacy_driver/pytest_timer_group.py similarity index 85% rename from examples/peripherals/timer_group/pytest_timer_group.py rename to examples/peripherals/timer_group/legacy_driver/pytest_timer_group.py index b715ec81ea04..f8924b14611e 100644 --- a/examples/peripherals/timer_group/pytest_timer_group.py +++ b/examples/peripherals/timer_group/legacy_driver/pytest_timer_group.py @@ -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 @@ @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') diff --git a/examples/peripherals/timer_group/legacy_driver/sdkconfig.defaults b/examples/peripherals/timer_group/legacy_driver/sdkconfig.defaults new file mode 100644 index 000000000000..57b9e914f0ec --- /dev/null +++ b/examples/peripherals/timer_group/legacy_driver/sdkconfig.defaults @@ -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