52 #define MBG_FIRST_COPYRIGHT_YEAR 2013 53 #define MBG_LAST_COPYRIGHT_YEAR 0 // use default 55 static const char *
pname =
"mbgcmptime";
85 FILE *fp = fopen(
log_fn, mode );
89 fprintf( stderr,
"Failed to open log file %s: %s. Giving up logging.\n",
log_fn, strerror( errno ) );
109 double prv_delta_t = 0.0;
110 int prv_delta_t_avail = 0;
111 int this_loops =
loops;
147 delta_t =
get_htc_delta( &htc1, &htc2, &delta_ts, &delta_cyc );
151 static double initial_offset;
152 static int initial_offset_set;
154 if ( !initial_offset_set )
156 initial_offset = delta_t;
157 initial_offset_set = 1;
158 printf(
"Initial offset: %.1f us\n", initial_offset * 1e6 );
161 delta_t -= initial_offset;
174 snprintf_safe( ws3,
sizeof( ws3 ),
"%+.1f us", delta_t * 1e6 );
178 n +=
snprintf_safe( &ws[n],
sizeof( ws ) - n,
"%s, %s", ws1, ws2 );
180 n +=
snprintf_safe( &ws[n],
sizeof( ws ) - n,
" ts: %.1f us, cyc: %.1f us, delta: %s",
181 delta_ts * 1e6, delta_cyc * 1e6, ws3 );
191 if ( prv_delta_t_avail )
193 double ddelta_t = delta_t - prv_delta_t;
228 printf(
"\r%s%s%s", ws,
term_clreol, ( add_marker ) ?
"\n" :
"" );
231 printf(
"%s\n", ws );
239 fprintf( fp,
"%s\n", ws );
244 if ( this_loops > 0 )
247 if ( this_loops == 0 )
252 prv_delta_t = delta_t;
253 prv_delta_t_avail = 1;
276 "Compare the time on two devices by reading the time stamps plus cycles from\n" 277 "both devices immediately after each other, and compensate the execution delay\n" 278 "based on the returned cycles counts.\n" 279 "The device to be used as reference has to be specified by parameter -i (see\n" 280 "below), whereas the device under test is specified as last parameter on the\n" 284 mbg_print_opt_info(
"-i dev",
"reference device the test card's time shall be compared to" );
285 mbg_print_opt_info(
"-l limit",
"append a marker '*' to the output if delta exceeds limit [us]" );
286 mbg_print_opt_info(
"-L limit",
"append a marker '<<' to the output if delta changes [us]" );
295 mbg_print_opt_info(
"-q",
"quiet, only log errors to console (use -o to specify file for full log)" );
300 printf(
"\nExamples:\n\n" );
302 "Run once and compare the time from the 2 devices with indexes 1 and 2\n" 303 "to the time from reference device with index 0:\n\n" 304 " %s -i 0 1 2\n\n",
pname 307 "Run continuously in 1 s intervals and compare the time from %s\n" 308 "to the time from reference device %s:\n\n" 317 int main(
int argc,
char *argv[] )
326 while ( ( c = getopt( argc, argv,
"acCfi:l:L:n:o:qrs:u:h?" ) ) != -1 )
347 chk_limit = (double) atoi( optarg ) / 1e6;
359 loops = atoi( optarg );
394 fprintf( stderr,
"A reference device has to be specified using the -i parameter.\n\n" );
404 #if !MBG_TGT_SUPP_MEM_ACC 405 fprintf( stderr,
"** Memory mapped access not supported on this target platform.\n\n" );
409 #if !MBG_PC_CYCLES_SUPPORTED 410 fprintf( stderr,
"** Warning: No cycles support to compute real latencies on this platform!\n" );
415 setvbuf( stdout, NULL, _IONBF, 0 );
429 ref_dev_fn,
sizeof( ref_dev_fn ) );
433 fprintf( stderr,
"** Failed to open ref device %s: %s.\n",
439 fprintf( stderr,
"Ref device %s (%s) opened successfully.\n",
447 fprintf( stderr,
"** Failed to get device info for ref device %s: %s.\n",
static const char term_clreol[]
Requested action completed successfully.
MBG_PC_CYCLES_FREQUENCY cyc_freq
Must be set up tby the application.
bool mbg_cond_err_msg(int rc, const char *what)
Check if a value is an error code and print an associated error message.
PCPS_SECONDS sec
seconds since 1970, usually UTC scale
Unable to handle requested action, usage printed.
int sn_cpy_str_safe(char *dst, size_t max_len, const char *src)
A function to copy a string safely, returning the number of characters copied.
#define mbg_rc_is_success(_rc)
static const char * pname
int get_htc_timestamps(MBG_DEV_HANDLE dh1, PCPS_HR_TIME_CYCLES *p_htc1, MBG_DEV_HANDLE dh2, PCPS_HR_TIME_CYCLES *p_htc2, int read_fast)
Read timestamps and cycles from both devices.
PCPS_TIME_STATUS_X status
status bits, see PCPS_TIME_STATUS_FLAGS
_MBG_API_ATTR int _MBG_API mbg_get_default_cycles_frequency_from_dev(MBG_DEV_HANDLE dh, MBG_PC_CYCLES_FREQUENCY *p)
Retrieve the system's default cycles counter frequency from the kernel driver.
_MBG_API_ATTR int _MBG_API mbg_get_device_info(MBG_DEV_HANDLE dh, PCPS_DEV *p)
Read detailed device information.
static MBG_DEV_HANDLE dh_ref
static const char * log_fn
PCPS_TIME_STAMP tstamp
High resolution time stamp (UTC)
int mbg_snprint_hr_tstamp_ext(char *s, int max_len, const PCPS_TIME_STAMP *p, int print_raw)
Print UTC date and time from a PCPS_TIME_STAMP structure to a string.
static const char * ref_dev_param
#define MBG_SUCCESS
Error codes used with Meinberg devices and drivers.
Requested action not supported on the running OS.
_MBG_API_ATTR void _MBG_API mbg_close_device(MBG_DEV_HANDLE *dev_handle)
Close a device handle and set the handle value to MBG_INVALID_DEV_HANDLE.
#define MBG_LAST_COPYRIGHT_YEAR
Action failed for specified device.
#define MBG_FIRST_COPYRIGHT_YEAR
uint64_t MBG_PC_CYCLES_FREQUENCY
double get_htc_delta(const PCPS_HR_TIME_CYCLES *p_htc, const PCPS_HR_TIME_CYCLES *p_htc_ref, double *p_delta_ts, double *p_delta_cyc)
Compute the delta cycles and time difference.
static int do_mbgcmptime(MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev)
static FILE * fopen_log(const char *mode)
High resolution time plus associated system cycles count.
int snprintf_safe(char *s, size_t max_len, const char *fmt,...)
A portable, safe implementation of snprintf()
int main(int argc, char *argv[])
#define MBG_ERR_NOT_SUPP_BY_DEV
Command or feature not supported by device.
#define mbg_rc_is_error(_rc)
const char * mbg_strerror(int mbg_errno)
Return an error string associated with the MBG_ERROR_CODES.
static PCPS_DEV dev_info_ref
char MBG_DEV_FN[260]
A string that can take a device file name.
int chk_fast_tstamp_supp(MBG_DEV_HANDLE dh1, const PCPS_DEV *p_dev_1, MBG_DEV_HANDLE dh2, const PCPS_DEV *p_dev_2, MBG_ERR_MSG_FNC err_msg_fnc)
Check if both devices support fast HR timestamps.