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..4b014edc80b --- /dev/null +++ b/testing/ostest/hrtimer.c @@ -0,0 +1,217 @@ +/**************************************************************************** + * 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_500MS (500 * NSEC_PER_MSEC) +#define NSEC_MARGIN (5) + +/* 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 */ + uint64_t now; /* Current 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: + * test_hrtimer - 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 *test_hrtimer, + uint32_t period) +{ + test_hrtimer->previous = 0; + test_hrtimer->now = 0; + test_hrtimer->count = 0; + test_hrtimer->active = true; + test_hrtimer->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_500MS) + * + ****************************************************************************/ + +static uint32_t test_hrtimer_callback(FAR hrtimer_t *hrtimer) +{ + struct timespec ts; + uint32_t diff; + 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); + test->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)(test->now - test->previous); + + HRTIMER_TEST(NSEC_PER_500MS < diff + NSEC_MARGIN, true); + HRTIMER_TEST(NSEC_PER_500MS > diff - NSEC_MARGIN, true); + } + + test->previous = test->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 test_hrtimer_500ms; + + /* Initialize test structure */ + + hrtimer_test_init(&test_hrtimer_500ms, NSEC_PER_500MS); + + /* Initialize the high-resolution timer */ + + hrtimer_init(&test_hrtimer_500ms.timer, + test_hrtimer_callback, + NULL); + + /* Start the timer with 500ms relative timeout */ + + ret = hrtimer_start(&test_hrtimer_500ms.timer, + test_hrtimer_500ms.period, + HRTIMER_MODE_REL); + + HRTIMER_TEST(ret, OK); + + /* Wait until the test completes */ + + while (test_hrtimer_500ms.active) + { + usleep(500 * 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. */