1 /*
2  * Copyright (c) 2018 Intel Corporation
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 /*
8  * @file
9  * @brief Test early sleep functionality
10  *
11  * @defgroup kernel_earlysleep_tests Early Sleep Tests
12  *
13  * @ingroup all_tests
14  *
15  * This test verifies that k_sleep() can be used to put the calling thread to
16  * sleep for a specified number of ticks during system initialization.  In this
17  * test we are calling k_sleep() at POST_KERNEL and APPLICATION level
18  * initialization sequence.
19  *
20  * Note: We can not call k_sleep() during PRE_KERNEL1 or PRE_KERNEL2 level
21  * because the core kernel objects and devices initialization happens at these
22  * levels.
23  * @{
24  * @}
25  */
26 
27 #include <zephyr/init.h>
28 #include <zephyr/arch/cpu.h>
29 #include <zephyr/sys_clock.h>
30 #include <stdbool.h>
31 #include <zephyr/tc_util.h>
32 #include <zephyr/ztest.h>
33 
34 #define THREAD_STACK		(384 + CONFIG_TEST_EXTRA_STACK_SIZE)
35 
36 #define TEST_TICKS_TO_SLEEP	(CONFIG_SYS_CLOCK_TICKS_PER_SEC / 2)
37 
38 /* Helper thread data */
39 static K_THREAD_STACK_DEFINE(helper_tstack, THREAD_STACK);
40 static struct k_thread helper_tdata;
41 static k_tid_t  helper_ttid;
42 
43 /* time that the thread was actually sleeping */
44 static int actual_sleep_ticks;
45 static int actual_post_kernel_sleep_ticks;
46 static int actual_app_sleep_ticks;
47 
48 static bool test_failure = true;
49 
helper_thread(void * p1,void * p2,void * p3)50 static void helper_thread(void *p1, void *p2, void *p3)
51 {
52 	test_failure = false;
53 }
54 
ticks_to_sleep(int ticks)55 static int ticks_to_sleep(int ticks)
56 {
57 	uint32_t start_time;
58 	uint32_t stop_time;
59 
60 	start_time = k_cycle_get_32();
61 	k_sleep(K_MSEC(k_ticks_to_ms_floor64(ticks)));
62 	stop_time = k_cycle_get_32();
63 
64 	return (stop_time - start_time) / k_ticks_to_cyc_floor32(1);
65 }
66 
67 
test_early_sleep_post_kernel(void)68 static int test_early_sleep_post_kernel(void)
69 {
70 	actual_post_kernel_sleep_ticks = ticks_to_sleep(TEST_TICKS_TO_SLEEP);
71 	return 0;
72 }
73 
74 SYS_INIT(test_early_sleep_post_kernel,
75 		POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE);
76 
test_early_sleep_app(void)77 static int test_early_sleep_app(void)
78 {
79 	actual_app_sleep_ticks = ticks_to_sleep(TEST_TICKS_TO_SLEEP);
80 	return 0;
81 }
82 
83 SYS_INIT(test_early_sleep_app, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEVICE);
84 
85 /**
86  * @brief Test early sleep
87  *
88  * @ingroup kernel_earlysleep_tests
89  *
90  * @see k_sleep()
91  */
ZTEST(earlysleep,test_early_sleep)92 ZTEST(earlysleep, test_early_sleep)
93 {
94 	TC_PRINT("Testing early sleeping\n");
95 
96 	/*
97 	 * Main thread(test_main) priority is 0 but ztest thread runs at
98 	 * priority -1. To run the test smoothly make both main and ztest
99 	 * threads run at same priority level.
100 	 */
101 	k_thread_priority_set(k_current_get(), 0);
102 
103 	TC_PRINT("msec per tick: %" PRId64 ".%03" PRId64 ", ticks to sleep: %d\n",
104 			k_ticks_to_ms_floor64(1000) / 1000U,
105 			k_ticks_to_ms_floor64(1000) % 1000,
106 			TEST_TICKS_TO_SLEEP);
107 
108 	/* Create a lower priority thread */
109 	helper_ttid = k_thread_create(&helper_tdata,
110 				   helper_tstack, THREAD_STACK,
111 				   helper_thread, NULL, NULL, NULL,
112 				   k_thread_priority_get(k_current_get()) + 1,
113 				   K_INHERIT_PERMS, K_NO_WAIT);
114 
115 	TC_PRINT("k_sleep() ticks at POST_KERNEL level: %d\n",
116 					actual_post_kernel_sleep_ticks);
117 	zassert_true((actual_post_kernel_sleep_ticks + 1) >
118 					TEST_TICKS_TO_SLEEP, NULL);
119 
120 	TC_PRINT("k_sleep() ticks at APPLICATION level: %d\n",
121 					actual_app_sleep_ticks);
122 	zassert_true((actual_app_sleep_ticks + 1) >
123 					TEST_TICKS_TO_SLEEP, NULL);
124 
125 	actual_sleep_ticks = ticks_to_sleep(TEST_TICKS_TO_SLEEP);
126 	TC_PRINT("k_sleep() ticks on running system: %d\n",
127 					actual_sleep_ticks);
128 	zassert_true((actual_sleep_ticks + 1) >
129 					TEST_TICKS_TO_SLEEP, NULL);
130 
131 	zassert_false(test_failure, "Lower priority thread not ran!!");
132 }
133 
134 ZTEST_SUITE(earlysleep, NULL, NULL,
135 		ztest_simple_1cpu_before, ztest_simple_1cpu_after, NULL);
136