1 /*
2 * Copyright (c) 2018 Oticon A/S
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/ztest.h>
8 #include <zephyr/kernel.h>
9 #include <zephyr/sys/printk.h>
10
11 #include <stdlib.h>
12 #include <stdio.h>
13 #include <time.h>
14
15 #include <nsi_hw_scheduler.h>
16 #include <nsi_timer_model.h>
17 #include "native_rtc.h"
18
19 #include <stdio.h>
20
us_time_to_str(char * dest,uint64_t time)21 static char *us_time_to_str(char *dest, uint64_t time)
22 {
23 if (time != NSI_NEVER) {
24 unsigned int hour;
25 unsigned int minute;
26 unsigned int second;
27 unsigned int us;
28
29 hour = (time / 3600U / 1000000U) % 24;
30 minute = (time / 60U / 1000000U) % 60;
31 second = (time / 1000000U) % 60;
32 us = time % 1000000;
33
34 sprintf(dest, "%02u:%02u:%02u.%06u", hour, minute, second, us);
35 } else {
36 sprintf(dest, " NEVER/UNKNOWN ");
37
38 }
39 return dest;
40 }
41
42 #define WAIT_TIME 250 /* ms */
43 #define TOLERANCE 20 /* ms Tolerance in native_sim time after WAIT_TIME */
44 #define TICK_MS (1000ul / CONFIG_SYS_CLOCK_TICKS_PER_SEC)
45
46 /**
47 * @brief Test native_sim real time control
48 */
ZTEST(native_realtime,test_realtime)49 ZTEST(native_realtime, test_realtime)
50 {
51 extern uint64_t get_host_us_time(void);
52 uint64_t time;
53 char time_s[60];
54 uint64_t end_time, start_time;
55 int64_t diff, error;
56 uint64_t start_rtc_time[3];
57 double acc_ratio = 1;
58 double time_ratios[5] = {0.25, 2, 2, 2, 2};
59 /* This ratio adjustments lead to test speeds 0.25x, 0.5x, 1x, 2x & 4x*/
60
61 time = native_rtc_gettime_us(RTC_CLOCK_REALTIME);
62
63 us_time_to_str(time_s, time);
64 printk("Booted @%s\n", time_s);
65
66 /*
67 * We override the real time speed in case it was set from command
68 * line
69 */
70 hwtimer_set_rt_ratio(1.0);
71
72 /*Let's wait >=1 tick to ensure everything is settled*/
73 k_msleep(TICK_MS);
74
75 start_time = get_host_us_time();
76 start_rtc_time[2] = native_rtc_gettime_us(RTC_CLOCK_PSEUDOHOSTREALTIME);
77 start_rtc_time[0] = native_rtc_gettime_us(RTC_CLOCK_BOOT);
78 start_rtc_time[1] = native_rtc_gettime_us(RTC_CLOCK_REALTIME);
79
80 for (int i = 0; i < 5; i++) {
81 native_rtc_adjust_clock(time_ratios[i]);
82 acc_ratio *= time_ratios[i];
83
84 /* k_sleep waits 1 tick more than asked */
85 k_msleep(WAIT_TIME - TICK_MS);
86
87 /*
88 * Check that during the sleep, the correct amount of real time
89 * passed
90 */
91 end_time = get_host_us_time();
92 diff = end_time - start_time;
93 error = diff / 1000 - WAIT_TIME / acc_ratio;
94
95 posix_print_trace("%i/5: Speed ratio %.2f. Took %.3fms. "
96 "Should take %.3fms +- %ims\n",
97 i+1,
98 acc_ratio,
99 diff / 1000.0,
100 WAIT_TIME / acc_ratio,
101 TOLERANCE);
102
103 zassert_true(llabs(error) < TOLERANCE,
104 "Real time error over TOLERANCE");
105
106 /*
107 * Check that the RTC clocks advanced WAIT_TIME
108 * independently of the real timeness ratio
109 */
110 diff = native_rtc_gettime_us(RTC_CLOCK_PSEUDOHOSTREALTIME) -
111 start_rtc_time[2];
112 error = diff - WAIT_TIME * 1000;
113
114 posix_print_trace("%i/5: PSEUDOHOSTREALTIME reports %.3fms "
115 "(error %.3fms)\n",
116 i+1,
117 diff / 1000.0,
118 error / 1000.0);
119
120 error /= 1000;
121 zassert_true(llabs(error) < TOLERANCE,
122 "PSEUDOHOSTREALTIME time error over TOLERANCE");
123
124 diff = native_rtc_gettime_us(RTC_CLOCK_BOOT) -
125 start_rtc_time[0];
126
127 zassert_true(diff == WAIT_TIME * 1000,
128 "Error in RTC_CLOCK_BOOT");
129
130 diff = native_rtc_gettime_us(RTC_CLOCK_REALTIME) -
131 start_rtc_time[1];
132
133 zassert_true(diff == WAIT_TIME * 1000,
134 "Error in RTC_CLOCK_REALTIME");
135
136 start_time += WAIT_TIME * 1000 / acc_ratio;
137 start_rtc_time[0] += WAIT_TIME * 1000;
138 start_rtc_time[1] += WAIT_TIME * 1000;
139 start_rtc_time[2] += WAIT_TIME * 1000;
140 }
141
142 }
143
144 /**
145 * @brief Test native_sim RTC offset functionality
146 */
ZTEST(native_realtime,test_rtc_offset)147 ZTEST(native_realtime, test_rtc_offset)
148 {
149 int offset = 567;
150 uint64_t start_rtc_time[2];
151 int64_t diff, error;
152
153 start_rtc_time[0] = native_rtc_gettime_us(RTC_CLOCK_REALTIME);
154 start_rtc_time[1] = native_rtc_gettime_us(RTC_CLOCK_PSEUDOHOSTREALTIME);
155 native_rtc_offset(offset);
156 diff = native_rtc_gettime_us(RTC_CLOCK_PSEUDOHOSTREALTIME)
157 - start_rtc_time[1];
158
159 error = diff - offset;
160 zassert_true(llabs(error) < TOLERANCE,
161 "PSEUDOHOSTREALTIME offset error over TOLERANCE");
162
163 diff = native_rtc_gettime_us(RTC_CLOCK_REALTIME) - start_rtc_time[0];
164
165 zassert_true(diff == offset, "Offsetting RTC failed\n");
166 }
167
168 ZTEST_SUITE(native_realtime, NULL, NULL, NULL, NULL, NULL);
169