| /* | 
 |  * Copyright (c) 2017 Intel Corporation | 
 |  * | 
 |  * SPDX-License-Identifier: Apache-2.0 | 
 |  */ | 
 |  | 
 | #include <ztest.h> | 
 |  | 
 | #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); | 
 | } | 
 | /** | 
 |  * @} | 
 |  */ |