o-du/phy
Intel O-RAN/X-RAN Generated Doxygen Documentation
xran_timer.c
Go to the documentation of this file.
1 /******************************************************************************
2 *
3 * Copyright (c) 2019 Intel.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 *******************************************************************************/
18 
28 #include <time.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <stdint.h>
32 
33 #include "xran_timer.h"
34 #include "xran_printf.h"
35 #include "xran_mlog_lnx.h"
36 #include "xran_lib_mlog_tasks_id.h"
37 #include "ethdi.h"
38 #include "xran_fh_o_du.h"
39 #include "xran_common.h"
40 
41 #define NSEC_PER_SEC 1000000000L
42 #define NSEC_PER_USEC 1000L
43 #define THRESHOLD 35
44 #define TIMECOMPENSATION 2
46 #define SEC_MOD_STOP (60)
47 
48 static struct timespec started_time;
49 static struct timespec last_time;
50 static struct timespec cur_time;
51 
52 static uint64_t curr_tick;
53 static uint64_t last_tick;
54 
55 static struct timespec* p_cur_time = &cur_time;
56 static struct timespec* p_last_time = &last_time;
57 
58 
59 static struct timespec* p_temp_time;
60 
61 static unsigned long current_second = 0;
62 static unsigned long started_second = 0;
63 static uint8_t numerlogy = 0;
64 extern uint32_t xran_lib_ota_sym;
65 extern uint32_t xran_lib_ota_tti;
66 extern uint32_t xran_lib_ota_sym_idx;
67 
68 static int debugStop = 0;
69 static int debugStopCount = 0;
70 
71 static long fine_tuning[5][2] =
72 {
73  {71428L, 71429L}, /* mu = 0 */
74  {35714L, 35715L}, /* mu = 1 */
75  {0, 0}, /* mu = 2 not supported */
76  {8928L, 8929L}, /* mu = 3 */
77  {0,0 } /* mu = 4 not supported */
78 };
79 
80 static uint8_t slots_per_subframe[4] =
81 {
82  1, /* mu = 0 */
83  2, /* mu = 1 */
84  4, /* mu = 2 */
85  8, /* mu = 3 */
86 };
87 
89 {
90  return current_second;
91 }
92 
93 int timing_set_numerology(uint8_t value)
94 {
95  numerlogy = value;
96  return numerlogy;
97 }
98 
99 int timing_set_debug_stop(int value, int count)
100 {
101  debugStop = value;
102  debugStopCount = count;
103 
104  if(debugStop){
105  clock_gettime(CLOCK_REALTIME, &started_time);
106  started_second =started_time.tv_sec;
107  }
108  return debugStop;
109 }
110 
112 {
113  return debugStop;
114 }
115 
116 void timing_adjust_gps_second(struct timespec* p_time)
117 {
118  struct xran_device_ctx * p_xran_dev_ctx = xran_dev_get_ctx();
119 
120  long nsec = p_time->tv_nsec + p_xran_dev_ctx->offset_nsec;
121  p_time->tv_sec += p_xran_dev_ctx->offset_sec;
122  if (nsec >= 1e9)
123  {
124  nsec -=1e9;
125  p_time->tv_sec += 1;
126  }
127  p_time->tv_nsec = nsec;
128 
129  return;
130 }
131 uint64_t xran_tick(void)
132 {
133  uint32_t hi, lo;
134  __asm volatile ("rdtsc" : "=a"(lo), "=d"(hi));
135  return ( (uint64_t)lo)|( ((uint64_t)hi)<<32 );
136 }
137 
138 unsigned long get_ticks_diff(unsigned long curr_tick, unsigned long last_tick)
139 {
140  if (curr_tick >= last_tick)
141  return (unsigned long)(curr_tick - last_tick);
142  else
143  return (unsigned long)(0xFFFFFFFFFFFFFFFF - last_tick + curr_tick);
144 }
145 
146 long poll_next_tick(long interval_ns, unsigned long *used_tick)
147 {
148  struct xran_device_ctx * p_xran_dev_ctx = xran_dev_get_ctx();
149  long target_time;
150  long delta;
151  static int counter = 0;
152  static long sym_acc = 0;
153  static long sym_cnt = 0;
154 
155  if(counter == 0) {
156  clock_gettime(CLOCK_REALTIME, p_last_time);
157  last_tick = MLogTick();
158  if(unlikely(p_xran_dev_ctx->offset_sec || p_xran_dev_ctx->offset_nsec))
159  timing_adjust_gps_second(p_last_time);
160  current_second = p_last_time->tv_sec;
161  counter = 1;
162  }
163 
164  target_time = (p_last_time->tv_sec * NSEC_PER_SEC + p_last_time->tv_nsec + interval_ns);
165 
166  while(1) {
167  clock_gettime(CLOCK_REALTIME, p_cur_time);
168  curr_tick = MLogTick();
169  if(unlikely(p_xran_dev_ctx->offset_sec || p_xran_dev_ctx->offset_nsec))
170  timing_adjust_gps_second(p_cur_time);
171  delta = (p_cur_time->tv_sec * NSEC_PER_SEC + p_cur_time->tv_nsec) - target_time;
172  if(delta > 0 || (delta < 0 && abs(delta) < THRESHOLD)) {
173  if (debugStop &&(debugStopCount > 0) && (tx_counter >= debugStopCount)){
174  uint64_t t1;
175  printf("STOP:[%ld.%09ld], debugStopCount %d, tx_counter %ld\n", p_cur_time->tv_sec, p_cur_time->tv_nsec, debugStopCount, tx_counter);
176  t1 = MLogTick();
177  rte_pause();
180  }
181  if(current_second != p_cur_time->tv_sec){
182  current_second = p_cur_time->tv_sec;
185  xran_lib_ota_tti = 0;
186  xran_lib_ota_sym = 0;
187  sym_cnt = 0;
188  sym_acc = 0;
189  print_dbg("ToS:C Sync timestamp: [%ld.%09ld]\n", p_cur_time->tv_sec, p_cur_time->tv_nsec);
190  if(debugStop){
191  if(p_cur_time->tv_sec > started_second && ((p_cur_time->tv_sec % SEC_MOD_STOP) == 0)){
192  uint64_t t1;
193  printf("STOP:[%ld.%09ld]\n", p_cur_time->tv_sec, p_cur_time->tv_nsec);
194  t1 = MLogTick();
195  rte_pause();
198  }
199  }
200  p_cur_time->tv_nsec = 0; // adjust to 1pps
201  } else {
203  /* adjust to sym boundary */
204  if(sym_cnt & 1)
205  sym_acc += fine_tuning[numerlogy][0];
206  else
207  sym_acc += fine_tuning[numerlogy][1];
208  /* fine tune to second boundary */
209  if(sym_cnt % 13 == 0)
210  sym_acc += 1;
211 
212  p_cur_time->tv_nsec = sym_acc;
213  sym_cnt++;
214  }
215 
216 #ifdef USE_PTP_TIME
217  if(debugStop && delta < interval_ns*10)
218  MLogTask(PID_TIME_SYSTIME_POLL, (p_last_time->tv_sec * NSEC_PER_SEC + p_last_time->tv_nsec), (p_cur_time->tv_sec * NSEC_PER_SEC + p_cur_time->tv_nsec));
219 #else
220  MLogTask(PID_TIME_SYSTIME_POLL, last_tick, curr_tick);
221  last_tick = curr_tick;
222 #endif
223 
224 
225  p_temp_time = p_last_time;
226  p_last_time = p_cur_time;
227  p_cur_time = p_temp_time;
228  break;
229  } else {
230  if( likely(xran_if_current_state == XRAN_RUNNING)){
231  uint64_t t1, t2;
232  t1 = xran_tick();
233 
235  process_dpdk_io();
236 
237  t2 = xran_tick();
238  *used_tick += get_ticks_diff(t2, t1);
239  }
240  }
241  }
242 
243  return delta;
244 }
245 
246 long sleep_next_tick(long interval)
247 {
248  struct timespec start_time;
249  struct timespec cur_time;
250  //struct timespec target_time_convert;
251  struct timespec sleep_target_time_convert;
252  long target_time;
253  long sleep_target_time;
254  long delta;
255 
256  clock_gettime(CLOCK_REALTIME, &start_time);
257  target_time = (start_time.tv_sec * NSEC_PER_SEC + start_time.tv_nsec + interval * NSEC_PER_USEC) / (interval * NSEC_PER_USEC) * interval;
258  //printf("target: %ld, current: %ld, %ld\n", target_time, start_time.tv_sec, start_time.tv_nsec);
259  sleep_target_time = target_time - TIMECOMPENSATION;
260  sleep_target_time_convert.tv_sec = sleep_target_time * NSEC_PER_USEC / NSEC_PER_SEC;
261  sleep_target_time_convert.tv_nsec = (sleep_target_time * NSEC_PER_USEC) % NSEC_PER_SEC;
262 
263  //target_time_convert.tv_sec = target_time * NSEC_PER_USEC / NSEC_PER_SEC;
264  //target_time_convert.tv_nsec = (target_time * NSEC_PER_USEC) % NSEC_PER_SEC;
265 
266  clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, &sleep_target_time_convert, NULL);
267 
268  clock_gettime(CLOCK_REALTIME, &cur_time);
269 
270  delta = (cur_time.tv_sec * NSEC_PER_SEC + cur_time.tv_nsec) - target_time * NSEC_PER_USEC;
271 
272  return delta;
273 }
274 
275 
276 
uint32_t xran_lib_ota_sym
Definition: xran_main.c:112
#define print_dbg(fmt, args...)
Definition: xran_printf.h:54
uint64_t xran_tick(void)
Definition: xran_timer.c:131
int timing_set_debug_stop(int value, int count)
Definition: xran_timer.c:99
enum xran_if_state xran_if_current_state
Definition: ethdi.c:75
int32_t ring_processing_func(void)
Definition: xran_common.c:700
#define PID_TIME_SYSTIME_STOP
long poll_next_tick(long interval_ns, unsigned long *used_tick)
Definition: xran_timer.c:146
#define SEC_MOD_STOP
Definition: xran_timer.c:46
long tx_counter
Definition: xran_common.c:118
uint32_t xran_lib_ota_sym_idx
Definition: xran_main.c:113
void timing_adjust_gps_second(struct timespec *p_time)
Definition: xran_timer.c:116
struct xran_device_ctx * xran_dev_get_ctx(void)
Definition: xran_main.c:223
int64_t offset_sec
Definition: xran_common.h:216
This file provides interface to Timing for XRAN.
int32_t process_dpdk_io(void)
Definition: ethdi.c:445
uint64_t timing_get_current_second(void)
Definition: xran_timer.c:88
#define TIMECOMPENSATION
Definition: xran_timer.c:44
int timing_get_debug_stop(void)
Definition: xran_timer.c:111
int timing_set_numerology(uint8_t value)
Definition: xran_timer.c:93
This file has all definitions for the Ethernet Data Interface Layer.
Modules provide debug prints and utility functions.
uint32_t xran_lib_ota_tti
Definition: xran_main.c:111
XRAN layer common functionality for both lls-CU and RU as well as C-plane and U-plane.
#define XranIncrementSymIdx(sym_idx, numSymPerMs)
Definition: xran_timer.h:42
#define XRAN_NUM_OF_SYMBOL_PER_SLOT
Definition: xran_fh_o_du.h:122
void xran_updateSfnSecStart(void)
Definition: xran_main.c:201
This file provides public interface to xRAN Front Haul layer implementation as defined in the ORAN-WG...
unsigned long get_ticks_diff(unsigned long curr_tick, unsigned long last_tick)
Definition: xran_timer.c:138
#define THRESHOLD
Definition: xran_timer.c:43
long sleep_next_tick(long interval)
Definition: xran_timer.c:246
#define MLogTask(w, x, y)
Definition: xran_mlog_lnx.h:44
#define NSEC_PER_USEC
Definition: xran_timer.c:42
#define PID_TIME_SYSTIME_POLL
int64_t offset_nsec
Definition: xran_common.h:217
#define MLogTick()
Definition: xran_mlog_lnx.h:42
#define NSEC_PER_SEC
Definition: xran_timer.c:41