mirror of
https://github.com/espressif/esp-idf.git
synced 2026-05-28 16:46:31 +03:00
test(rtc_timer): add rtc-timer test-app
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
components/esp_hal_rtc_timer/test_apps:
|
||||
enable:
|
||||
- if: SOC_RTC_TIMER_SUPPORTED == 1
|
||||
depends_components:
|
||||
- esp_hal_rtc_timer
|
||||
- soc
|
||||
6
components/esp_hal_rtc_timer/test_apps/CMakeLists.txt
Normal file
6
components/esp_hal_rtc_timer/test_apps/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.22)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(test_rtc_timer)
|
||||
12
components/esp_hal_rtc_timer/test_apps/README.md
Normal file
12
components/esp_hal_rtc_timer/test_apps/README.md
Normal file
@@ -0,0 +1,12 @@
|
||||
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H21 | ESP32-H4 | ESP32-P4 | ESP32-S2 | ESP32-S3 | ESP32-S31 |
|
||||
| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | --------- | -------- | -------- | -------- | -------- | --------- |
|
||||
|
||||
# RTC timer HAL tests
|
||||
|
||||
This test app validates the `esp_hal_rtc_timer` component directly.
|
||||
|
||||
It focuses on:
|
||||
|
||||
1. Reading RTC timer counters.
|
||||
2. Converting RTC slow-clock ticks into elapsed time and checking the result against a measured delay.
|
||||
3. Exercising alarm interrupt raise/clear behavior on targets with the newer multi-target RTC timer hardware.
|
||||
@@ -0,0 +1,8 @@
|
||||
set(srcs "test_app_main.c"
|
||||
"test_rtc_timer.c")
|
||||
|
||||
# In order for the cases defined by `TEST_CASE` to be linked into the final elf,
|
||||
# the component can be registered as WHOLE_ARCHIVE
|
||||
idf_component_register(SRCS ${srcs}
|
||||
INCLUDE_DIRS "."
|
||||
WHOLE_ARCHIVE)
|
||||
29
components/esp_hal_rtc_timer/test_apps/main/test_app_main.c
Normal file
29
components/esp_hal_rtc_timer/test_apps/main/test_app_main.c
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "unity.h"
|
||||
#include "unity_test_runner.h"
|
||||
#include "esp_heap_caps.h"
|
||||
#include "esp_newlib.h"
|
||||
#include "unity_test_utils.h"
|
||||
|
||||
#define TEST_MEMORY_LEAK_THRESHOLD (0)
|
||||
|
||||
void setUp(void)
|
||||
{
|
||||
unity_utils_record_free_mem();
|
||||
}
|
||||
|
||||
void tearDown(void)
|
||||
{
|
||||
esp_reent_cleanup();
|
||||
unity_utils_evaluate_leaks_direct(TEST_MEMORY_LEAK_THRESHOLD);
|
||||
}
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
unity_run_menu();
|
||||
}
|
||||
141
components/esp_hal_rtc_timer/test_apps/main/test_rtc_timer.c
Normal file
141
components/esp_hal_rtc_timer/test_apps/main/test_rtc_timer.c
Normal file
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "unity.h"
|
||||
#include "esp_rom_sys.h"
|
||||
#include "esp_timer.h"
|
||||
#include "esp_private/esp_clk.h"
|
||||
#include "hal/rtc_timer_hal.h"
|
||||
#include "hal/rtc_timer_ll.h"
|
||||
#include "soc/rtc.h"
|
||||
#include "soc/soc_caps.h"
|
||||
#include "soc/rtc_cntl_periph.h"
|
||||
|
||||
#if SOC_RTC_TIMER_SUPPORTED
|
||||
|
||||
#define RTC_TIMER_SAMPLE_DELAY_US 50000
|
||||
#define RTC_TIMER_CONVERSION_MIN_TOLERANCE_US 5000
|
||||
#define RTC_TIMER_ALARM_DELAY_US 4000
|
||||
#define RTC_TIMER_ALARM_TIMEOUT_US 100000
|
||||
|
||||
static uint64_t max_u64(uint64_t lhs, uint64_t rhs)
|
||||
{
|
||||
return (lhs > rhs) ? lhs : rhs;
|
||||
}
|
||||
|
||||
static uint64_t abs_diff_u64(uint64_t lhs, uint64_t rhs)
|
||||
{
|
||||
return (lhs > rhs) ? (lhs - rhs) : (rhs - lhs);
|
||||
}
|
||||
|
||||
static uint32_t get_rtc_timer_period(void)
|
||||
{
|
||||
uint32_t period = esp_clk_slowclk_cal_get();
|
||||
|
||||
TEST_ASSERT_NOT_EQUAL_UINT32(0, period);
|
||||
return period;
|
||||
}
|
||||
|
||||
static void assert_counter_elapsed_matches_time(uint8_t timer_id)
|
||||
{
|
||||
const uint32_t period = get_rtc_timer_period();
|
||||
const int64_t start_host_us = esp_timer_get_time();
|
||||
const uint64_t start_cycles = rtc_timer_hal_get_cycle_count(timer_id);
|
||||
|
||||
esp_rom_delay_us(RTC_TIMER_SAMPLE_DELAY_US);
|
||||
|
||||
const uint64_t end_cycles = rtc_timer_hal_get_cycle_count(timer_id);
|
||||
const int64_t end_host_us = esp_timer_get_time();
|
||||
const uint64_t host_elapsed_us = end_host_us - start_host_us;
|
||||
const uint64_t timer_elapsed_us = rtc_time_slowclk_to_us(end_cycles - start_cycles, period);
|
||||
const uint64_t tolerance_us = max_u64(host_elapsed_us / 4, RTC_TIMER_CONVERSION_MIN_TOLERANCE_US);
|
||||
const uint64_t delta_us = abs_diff_u64(timer_elapsed_us, host_elapsed_us);
|
||||
char message[160];
|
||||
|
||||
printf("timer%" PRIu8 " counter %" PRIu64 " -> %" PRIu64 " cycles, host=%" PRIu64 "us timer=%" PRIu64 "us tol=%" PRIu64 "us\n",
|
||||
timer_id, start_cycles, end_cycles, host_elapsed_us, timer_elapsed_us, tolerance_us);
|
||||
|
||||
snprintf(message, sizeof(message), "timer%" PRIu8 " counter did not increase: %" PRIu64 " -> %" PRIu64,
|
||||
timer_id, start_cycles, end_cycles);
|
||||
TEST_ASSERT_TRUE_MESSAGE(end_cycles > start_cycles, message);
|
||||
|
||||
snprintf(message, sizeof(message), "timer%" PRIu8 " elapsed mismatch: host=%" PRIu64 "us timer=%" PRIu64 "us delta=%" PRIu64 "us tol=%" PRIu64 "us",
|
||||
timer_id, host_elapsed_us, timer_elapsed_us, delta_us, tolerance_us);
|
||||
TEST_ASSERT_TRUE_MESSAGE(delta_us <= tolerance_us, message);
|
||||
}
|
||||
|
||||
TEST_CASE("rtc timer counter can be read and converted to elapsed time", "[rtc_timer]")
|
||||
{
|
||||
assert_counter_elapsed_matches_time(0);
|
||||
}
|
||||
|
||||
#if SOC_RTC_TIMER_V2 || SOC_RTC_TIMER_V3
|
||||
static uint32_t get_alarm_intr_mask(uint8_t timer_id)
|
||||
{
|
||||
if (timer_id == 0) {
|
||||
#if SOC_RTC_TIMER_V3
|
||||
return RTC_TIMER_SOC_WAKEUP_INT_RAW;
|
||||
#else
|
||||
return LP_TIMER_SOC_WAKEUP_INT_RAW;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(RTC_TIMER_MAIN_TIMER_LP_INT_RAW)
|
||||
return RTC_TIMER_MAIN_TIMER_LP_INT_RAW;
|
||||
#elif defined(LP_TIMER_MAIN_TIMER_LP_INT_RAW)
|
||||
return LP_TIMER_MAIN_TIMER_LP_INT_RAW;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void assert_alarm_interrupt_round_trip(uint8_t timer_id)
|
||||
{
|
||||
const uint32_t period = get_rtc_timer_period();
|
||||
uint64_t delay_ticks = rtc_time_us_to_slowclk(RTC_TIMER_ALARM_DELAY_US, period);
|
||||
const uint32_t raw_mask = get_alarm_intr_mask(timer_id);
|
||||
|
||||
rtc_timer_ll_set_target_enable(&LP_TIMER, timer_id, false);
|
||||
rtc_timer_ll_alarm_intr_enable(&LP_TIMER, timer_id, false);
|
||||
rtc_timer_ll_clear_alarm_intr_status(&LP_TIMER, timer_id);
|
||||
TEST_ASSERT_EQUAL_HEX32(0, rtc_timer_ll_get_intr_raw(&LP_TIMER, timer_id) & raw_mask);
|
||||
|
||||
const uint64_t start_cycles = rtc_timer_hal_get_cycle_count(timer_id);
|
||||
rtc_timer_hal_set_wakeup_time(timer_id, start_cycles + delay_ticks);
|
||||
|
||||
bool fired = false;
|
||||
const int64_t deadline = esp_timer_get_time() + RTC_TIMER_ALARM_TIMEOUT_US;
|
||||
while (esp_timer_get_time() < deadline) {
|
||||
if (rtc_timer_ll_get_intr_raw(&LP_TIMER, timer_id) & raw_mask) {
|
||||
fired = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
printf("timer%" PRIu8 " alarm raw=0x%" PRIx32 " mask=0x%" PRIx32 "\n",
|
||||
timer_id, rtc_timer_ll_get_intr_raw(&LP_TIMER, timer_id), raw_mask);
|
||||
TEST_ASSERT_TRUE_MESSAGE(fired, "RTC timer alarm did not raise its raw interrupt status");
|
||||
|
||||
rtc_timer_ll_set_target_enable(&LP_TIMER, timer_id, false);
|
||||
rtc_timer_ll_alarm_intr_enable(&LP_TIMER, timer_id, false);
|
||||
rtc_timer_ll_clear_alarm_intr_status(&LP_TIMER, timer_id);
|
||||
TEST_ASSERT_EQUAL_HEX32(0, rtc_timer_ll_get_intr_raw(&LP_TIMER, timer_id) & raw_mask);
|
||||
}
|
||||
|
||||
TEST_CASE("rtc timer alarm interrupts can be raised and cleared", "[rtc_timer]")
|
||||
{
|
||||
assert_alarm_interrupt_round_trip(0);
|
||||
if (get_alarm_intr_mask(1) != 0) {
|
||||
assert_alarm_interrupt_round_trip(1);
|
||||
}
|
||||
}
|
||||
#endif // SOC_RTC_TIMER_V2 || SOC_RTC_TIMER_V3
|
||||
|
||||
#endif // SOC_RTC_TIMER_SUPPORTED
|
||||
13
components/esp_hal_rtc_timer/test_apps/pytest_rtc_timer.py
Normal file
13
components/esp_hal_rtc_timer/test_apps/pytest_rtc_timer.py
Normal file
@@ -0,0 +1,13 @@
|
||||
# SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import pytest
|
||||
from pytest_embedded import Dut
|
||||
from pytest_embedded_idf.utils import idf_parametrize
|
||||
|
||||
|
||||
@pytest.mark.generic
|
||||
@pytest.mark.parametrize('config', ['default'], indirect=True)
|
||||
@idf_parametrize('target', ['supported_targets'], indirect=['target'])
|
||||
def test_rtc_timer(dut: Dut) -> None:
|
||||
dut.run_all_single_board_cases()
|
||||
@@ -0,0 +1 @@
|
||||
CONFIG_ESP_TASK_WDT_EN=n
|
||||
Reference in New Issue
Block a user