/* * Copyright (c) 2017 Intel Corporation * * SPDX-License-Identifier: Apache-2.0 */ #include #if defined(CONFIG_ARCH_POSIX) #define ALIGN_MS_BOUNDARY \ do { \ uint32_t t = k_uptime_get_32(); \ while (t == k_uptime_get_32()) \ k_busy_wait(50); \ } while (0) #else #define ALIGN_MS_BOUNDARY \ do { \ uint32_t t = k_uptime_get_32(); \ while (t == k_uptime_get_32()) \ ; \ } while (0) #endif struct timer_data { int duration_count; int stop_count; }; static void duration_expire(struct k_timer *timer); static void stop_expire(struct k_timer *timer); /** TESTPOINT: init timer via K_TIMER_DEFINE */ K_TIMER_DEFINE(ktimer, duration_expire, stop_expire); static ZTEST_BMEM struct timer_data tdata; #define DURATION 100 #define LESS_DURATION 80 /** * @addtogroup kernel_common_tests * @{ */ /** * @brief Test clock uptime APIs functionality * * @see k_uptime_get(), k_uptime_get_32(), k_uptime_delta() */ void test_clock_uptime(void) { uint64_t t64, t32; int64_t d64 = 0; /**TESTPOINT: uptime elapse*/ t64 = k_uptime_get(); while (k_uptime_get() < (t64 + 5)) { #if defined(CONFIG_ARCH_POSIX) k_busy_wait(50); #endif } /**TESTPOINT: uptime elapse lower 32-bit*/ t32 = k_uptime_get_32(); while (k_uptime_get_32() < (t32 + 5)) { #if defined(CONFIG_ARCH_POSIX) k_busy_wait(50); #endif } /**TESTPOINT: uptime straddled ms boundary*/ t32 = k_uptime_get_32(); ALIGN_MS_BOUNDARY; zassert_true(k_uptime_get_32() > t32, NULL); /**TESTPOINT: uptime delta*/ d64 = k_uptime_delta(&d64); while (k_uptime_delta(&d64) == 0) { #if defined(CONFIG_ARCH_POSIX) k_busy_wait(50); #endif } } /** * @brief Test clock cycle functionality * * @details * Test Objectve: * - The kernel architecture provide a 32bit monotonically increasing * cycle counter * - This routine tests the k_cycle_get_32() and k_uptime_get_32() * k_cycle_get_32() get cycles by accessing hardware clock. * k_uptime_get_32() return cycles by transforming ticks into cycles. * * Testing techniques * - Functional and black box testing * * Prerequisite Condition: * - N/A * * Input Specifications: * - N/A * * Expected Test Result: * - The timer increases monotonically * * Pass/Fail criteria: * - Success if cycles increase monotonically, failure otherwise. * * Test Procedure: * -# At mili-second boundary, get cycles repeatedly by k_cycle_get_32() * till cycles increased * -# At mili-second boundary, get cycles repeatedly by k_uptime_get_32() * till cycles increased * -# Cross check cycles gotten by k_cycle_get_32() and k_uptime_get_32(), * the delta cycle should be greater than 1 milli-second. * * Assumptions and Constraints * - N/A * * @see k_cycle_get_32(), k_uptime_get_32() */ void test_clock_cycle(void) { uint32_t c32, c0, c1, t32; /**TESTPOINT: cycle elapse*/ ALIGN_MS_BOUNDARY; c32 = k_cycle_get_32(); /*break if cycle counter wrap around*/ while (k_cycle_get_32() > c32 && k_cycle_get_32() < (c32 + k_ticks_to_cyc_floor32(1))) { #if defined(CONFIG_ARCH_POSIX) k_busy_wait(50); #endif } /**TESTPOINT: cycle/uptime cross check*/ c0 = k_cycle_get_32(); ALIGN_MS_BOUNDARY; t32 = k_uptime_get_32(); while (t32 == k_uptime_get_32()) { #if defined(CONFIG_ARCH_POSIX) k_busy_wait(50); #endif } c1 = k_uptime_get_32(); /*avoid cycle counter wrap around*/ if (c1 > c0) { /* delta cycle should be greater than 1 milli-second*/ zassert_true((c1 - c0) > (sys_clock_hw_cycles_per_sec() / MSEC_PER_SEC), NULL); /* delta NS should be greater than 1 milli-second */ zassert_true((uint32_t)k_cyc_to_ns_floor64(c1 - c0) > (NSEC_PER_SEC / MSEC_PER_SEC), NULL); } } /* *help function */ static void duration_expire(struct k_timer *timer) { tdata.duration_count++; } static void stop_expire(struct k_timer *timer) { tdata.stop_count++; } static void init_data_count(void) { tdata.duration_count = 0; tdata.stop_count = 0; } /** * @brief Test millisecond time duration * * @details initialize a timer, then providing time duration in * millisecond, and check the duration time whether correct. * * @see k_timer_init(), k_timer_start(), k_timer_stop(), * k_busy_wait() * * */ void test_ms_time_duration(void) { init_data_count(); k_timer_start(&ktimer, K_MSEC(DURATION), K_NO_WAIT); /** TESTPOINT: waiting time less than duration and check the count*/ k_busy_wait(LESS_DURATION * 1000); zassert_true(tdata.duration_count == 0, NULL); zassert_true(tdata.stop_count == 0, NULL); /** TESTPOINT: proving duration in millisecond */ init_data_count(); k_timer_start(&ktimer, K_MSEC(100), K_MSEC(50)); /** TESTPOINT: waiting time more than duration and check the count */ k_usleep(1); /* align to tick */ k_busy_wait((DURATION + 1) * 1000); zassert_true(tdata.duration_count == 1, "duration %u not 1", tdata.duration_count); zassert_true(tdata.stop_count == 0, "stop %u not 0", tdata.stop_count); /** cleanup environemtn */ k_timer_stop(&ktimer); } /** * @} */