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