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