From a0a736b24b2237406c0a523e4d450fa332e35e00 Mon Sep 17 00:00:00 2001 From: wangchengdong Date: Mon, 15 Dec 2025 21:49:17 +0800 Subject: [PATCH] testing/ostest: add hrtimer API functional tests Add functional tests for the newly added hrtimer APIs, including hrtimer_init(), hrtimer_start(), and hrtimer_cancel(). Signed-off-by: Chengdong Wang --- testing/ostest/CMakeLists.txt | 4 + testing/ostest/Makefile | 6 + testing/ostest/hrtimer.c | 228 ++++++++++++++++++++++++++++++++++ testing/ostest/ostest.h | 4 + testing/ostest/ostest_main.c | 10 +- 5 files changed, 251 insertions(+), 1 deletion(-) create mode 100644 testing/ostest/hrtimer.c diff --git a/testing/ostest/CMakeLists.txt b/testing/ostest/CMakeLists.txt index 2bbe6a730a3..6e971373dd1 100644 --- a/testing/ostest/CMakeLists.txt +++ b/testing/ostest/CMakeLists.txt @@ -153,6 +153,10 @@ if(CONFIG_TESTING_OSTEST) list(APPEND SRCS nxevent.c) endif() + if(CONFIG_HRTIMER AND CONFIG_BUILD_FLAT) + list(APPEND SRCS hrtimer.c) + endif() + if(CONFIG_BUILD_FLAT) list(APPEND SRCS wdog.c) endif() diff --git a/testing/ostest/Makefile b/testing/ostest/Makefile index c631fb3b878..5f7d5d4f823 100644 --- a/testing/ostest/Makefile +++ b/testing/ostest/Makefile @@ -150,6 +150,12 @@ CSRCS += nxevent.c endif endif +ifeq ($(CONFIG_HRTIMER),y) +ifeq ($(CONFIG_BUILD_FLAT),y) +CSRCS += hrtimer.c +endif +endif + ifeq ($(CONFIG_BUILD_FLAT),y) CSRCS += wdog.c endif diff --git a/testing/ostest/hrtimer.c b/testing/ostest/hrtimer.c new file mode 100644 index 00000000000..9b2d61430b2 --- /dev/null +++ b/testing/ostest/hrtimer.c @@ -0,0 +1,228 @@ +/**************************************************************************** + * apps/testing/ostest/hrtimer.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include +#include + +#include "ostest.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define NSEC_PER_50MS (50 * NSEC_PER_MSEC) + +/* Set a 1ms margin to allow hrtimertest to pass in QEMU. + * + * QEMU is a virtual platform, and its timer resolution and scheduling + * latency may be less precise than on real hardware. Using a larger + * margin ensures that tests do not fail due to timing inaccuracies. + * + * On real hardware (verified on the a2g-tc397-5v-tft board), this + * margin can be reduced to less than 5 ns because timers are precise + * and deterministic. + */ + +#define HRTIMER_TEST_MARGIN (NSEC_PER_MSEC) + +/* Simple assertion macro for HRTimer test cases */ +#define HRTIMER_TEST(expr, value) \ + do \ + { \ + ret = (expr); \ + if (ret != (value)) \ + { \ + printf("ERROR: HRTimer test failed, line=%d ret=%d\n", \ + __LINE__, ret); \ + ASSERT(false); \ + } \ + } \ + while (0) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* Structure for HRTimer test tracking */ + +struct hrtimer_test_s +{ + hrtimer_t timer; /* HRTimer instance */ + uint64_t previous; /* Previous timestamp in nanoseconds */ + uint32_t count; /* Number of timer expirations */ + uint32_t period; /* Expected period between expirations */ + bool active; /* True while the test is still running */ +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: hrtimer_test_init + * + * Description: + * Initialize a hrtimer_test_s structure for a new test. + * + * Input Parameters: + * hrtimer_test - Pointer to the test structure to initialize + * period - Expected timer period in nanoseconds + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void hrtimer_test_init(FAR struct hrtimer_test_s *hrtimer_test, + uint32_t period) +{ + hrtimer_test->previous = 0; + hrtimer_test->count = 0; + hrtimer_test->active = true; + hrtimer_test->period = period; +} + +/**************************************************************************** + * Name: test_hrtimer_callback + * + * Description: + * HRTimer callback function for test. + * + * - Verifies the timer interval is exactly 500ms (nanosecond precision) + * - Stops the test after 15 expirations + * - Re-arms the timer in absolute mode + * + * Input Parameters: + * hrtimer - Pointer to the expired HRTimer instance + * + * Returned Value: + * Timer period in nanoseconds (NSEC_PER_50MS) + * + ****************************************************************************/ + +static uint32_t test_hrtimer_callback(FAR hrtimer_t *hrtimer) +{ + struct timespec ts; + uint32_t diff; + uint64_t now; + int ret; + + FAR struct hrtimer_test_s *test = + (FAR struct hrtimer_test_s *)hrtimer; + + /* Increment expiration count */ + + test->count++; + + /* Get current system time */ + + clock_systime_timespec(&ts); + now = clock_time2nsec(&ts); + + /* Skip comparison for first two invocations */ + + if (test->count > 2) + { + /* Verify the timer interval is exactly + * 500ms with nsec resolution + */ + + diff = (uint32_t)(now - test->previous); + + HRTIMER_TEST(NSEC_PER_50MS < diff + HRTIMER_TEST_MARGIN, true); + HRTIMER_TEST(NSEC_PER_50MS > diff - HRTIMER_TEST_MARGIN, true); + } + + test->previous = now; + + /* Stop the test after 15 expirations */ + + if (test->count >= 15) + { + ret = hrtimer_cancel(hrtimer); + HRTIMER_TEST(ret, 0); + + test->active = false; + } + + return test->period; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: hrtimer_test + * + * Description: + * Entry point for high-resolution timer functional test. + * + * - Initializes a HRTimer + * - Starts it with a 500ms relative timeout + * - Verifies subsequent expirations occur at 500ms intervals + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +void hrtimer_test(void) +{ + int ret; + struct hrtimer_test_s hrtimer_test; + + /* Initialize test structure */ + + hrtimer_test_init(&hrtimer_test, NSEC_PER_50MS); + + /* Initialize the high-resolution timer */ + + hrtimer_init(&hrtimer_test.timer, + test_hrtimer_callback, + NULL); + + /* Start the timer with 500ms relative timeout */ + + ret = hrtimer_start(&hrtimer_test.timer, + hrtimer_test.period, + HRTIMER_MODE_REL); + + HRTIMER_TEST(ret, OK); + + /* Wait until the test completes */ + + while (hrtimer_test.active) + { + usleep(USEC_PER_MSEC); + } +} diff --git a/testing/ostest/ostest.h b/testing/ostest/ostest.h index fec7f81c282..30f16da5d91 100644 --- a/testing/ostest/ostest.h +++ b/testing/ostest/ostest.h @@ -304,4 +304,8 @@ int sem_nfreeholders(void); void nxevent_test(void); #endif +#if defined(CONFIG_SCHED_EVENTS) && defined(CONFIG_BUILD_FLAT) +void hrtimer_test(void); +#endif + #endif /* __APPS_TESTING_OSTEST_OSTEST_H */ diff --git a/testing/ostest/ostest_main.c b/testing/ostest/ostest_main.c index 201d52e389f..48dc94da79d 100644 --- a/testing/ostest/ostest_main.c +++ b/testing/ostest/ostest_main.c @@ -625,6 +625,14 @@ static int user_main(int argc, char *argv[]) check_test_memory_usage(); #endif +#if defined(CONFIG_HRTIMER) && defined(CONFIG_BUILD_FLAT) + /* Verify hrtimer */ + + printf("\nuser_main: hrtimer test\n"); + hrtimer_test(); + check_test_memory_usage(); +#endif + /* Compare memory usage at time ostest_main started until * user_main exits. These should not be identical, but should * be similar enough that we can detect any serious OS memory @@ -705,7 +713,7 @@ int main(int argc, FAR char **argv) stdio_test(); #ifdef SDCC - /* I am not yet certain why SDCC does not like the following initilizers. + /* I am not yet certain why SDCC does not like the following initializers. * It involves some issues with 2- vs 3-byte pointer types. */