forked from espressif/esp-idf
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
gptimer: add example with various use cases
- Loading branch information
1 parent
5deb83b
commit 25490dd
Showing
11 changed files
with
255 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
idf_component_register(SRCS "gptimer_example_main.c" | ||
INCLUDE_DIRS ".") |
155 changes: 155 additions & 0 deletions
155
examples/peripherals/timer_group/gptimer/main/gptimer_example_main.c
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 changes: 39 additions & 0 deletions
39
examples/peripherals/timer_group/gptimer/pytest_gptimer.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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') |
File renamed without changes.
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion
2
...mer_group/main/timer_group_example_main.c → ...cy_driver/main/timer_group_example_main.c
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
4 changes: 4 additions & 0 deletions
4
examples/peripherals/timer_group/legacy_driver/sdkconfig.defaults
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |