Skip to content

Commit

Permalink
CLOCK_MONOTONIC_RAW
Browse files Browse the repository at this point in the history
  • Loading branch information
RainerZ committed Oct 27, 2024
1 parent c3c36be commit 6003e06
Show file tree
Hide file tree
Showing 8 changed files with 125 additions and 105 deletions.
4 changes: 2 additions & 2 deletions tests/xcp_test_executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@ pub const OPTION_XCP_LOG_LEVEL: xcp::XcpLogLevel = xcp::XcpLogLevel::Info;

// Test parameters
pub const MULTI_THREAD_TASK_COUNT: usize = 16; // Number of threads
pub const DAQ_TEST_TASK_SLEEP_TIME_US: u64 = 100; // Measurement thread task cycle time in us
pub const DAQ_TEST_TASK_SLEEP_TIME_US: u64 = 500; // Measurement thread task cycle time in us
const DAQ_TEST_DURATION_MS: u64 = 6000; // DAQ test duration, 6s to get a nano second 32 bit overflow while checking timestamp monotony
const CAL_TEST_MAX_ITER: u32 = 4000; // Number of calibrations
const CAL_TEST_TASK_SLEEP_TIME_US: u64 = 50; // Checking task cycle time in us
const CAL_TEST_TASK_SLEEP_TIME_US: u64 = 100; // Checking task cycle time in us

//------------------------------------------------------------------------
// Handle incomming SERV_TEXT data
Expand Down
51 changes: 22 additions & 29 deletions xcplib/main_cfg.h
Original file line number Diff line number Diff line change
@@ -1,46 +1,47 @@
#pragma once
#define __MAIN_CFG_H__

// main_cfg.h
// XCPlite

/* Copyright(c) Vector Informatik GmbH.All rights reserved.
Licensed under the MIT license.See LICENSE file in the project root for details. */
/* main.h */
/*
| Code released into public domain, no attribution required
*/


// When static library xcplib is used for Rust xcp-lite, consider the following options which are compiled into it
/*
Build options:
OPTION_ENABLE_DBG_PRINTS // Enable debug prints
OPTION_DEFAULT_DEBUG_LEVEL // Default debug level 1-5
OPTION_MTU // UDP MTU
Clock default is 1ns since 1970 epoch, free running timescale
OPTION_ARB_CLOCK // 1 us free running timescale and arbitrary epoch
OPTION_TAI_CLOCK // 1ns since 1970 clock, TAI syncronized by platform specific real time clock NTP, PTP4L, ...
PLATFORM_ENABLE_GET_LOCAL_ADDR
PLATFORM_ENABLE_KEYBOARD
main_cfg.h:
XCP_ENABLE_DBG_PRINTS // Enable debug prints
XCP_DEFAULT_DEBUG_LEVEL // Default debug level 1-5
OPTION_MTU // UDP MTU
XCPTL_ENABLE_TCP
XCPTL_ENABLE_UDP
CLOCK_USE_APP_TIME_US or CLOCK_USE_UTC_TIME_NS // Clock resolution, TAI or ARB epoch
xcptl_cfg.h:
XCPTL_QUEUE_SIZE // Allocate static memory for transmit queue, an entry has XCPTL_MAX_SEGMENT_SIZE bytes
XCPTL_MAX_SEGMENT_SIZE // Set to (OPTION_MTU-20-8) optimzed for the maximum possible UDP payload
xcp_cfg.h:
XCP_DAQ_MEM_SIZE // Allocate static meory for DAQ tables
XCP_DAQ_MEM_SIZE // Amount of memory used for DAQ setup
CLOCK_TICKS_PER_S // Resolution of the DAQ clock
*/

// Application configuration:
// XCP configuration is in xcp_cfg.h (Protocol Layer) and xcptl_cfg.h (Transport Layer)

#define ON 1
#define OFF 0

// Set clock resolution (for clock function in platform.c)
//#define CLOCK_USE_APP_TIME_US
#define CLOCK_USE_UTC_TIME_NS

// #define PLATFORM_ENABLE_GET_LOCAL_ADDR
// #define PLATFORM_ENABLE_KEYBOARD
// Debug prints
#define OPTION_ENABLE_DBG_PRINTS
#define OPTION_DEFAULT_DBG_LEVEL 4 /* Default log level: 1 - Error, 2 - Warn, 3 - Info, 4 - Trace, 5 - Debug */


// Ethernet Server
Expand All @@ -52,11 +53,3 @@
// Ethernet Transport Layer
#define OPTION_MTU 8000 // Ethernet MTU

// Debug prints
#define OPTION_ENABLE_DBG_PRINTS ON
#define OPTION_DEBUG_LEVEL 2 /*1 - Error, 2 - Warn, 3 - Info, 4 - Trace, 5 - Debug */
#if OPTION_ENABLE_DBG_PRINTS
#define XCP_ENABLE_DBG_PRINTS
#define XCP_DEFAULT_DEBUG_LEVEL OPTION_DEBUG_LEVEL
#endif

6 changes: 3 additions & 3 deletions xcplib/src/dbg_print.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@
//-------------------------------------------------------------------------------
// Debug print

#if !defined(OPTION_ENABLE_DBG_PRINTS) || !defined(OPTION_DEBUG_LEVEL)
#error "Please define OPTION_ENABLE_DBG_PRINTS and OPTION_DEBUG_LEVEL in main_cfg.h to ON or OFF"
#if defined(OPTION_ENABLE_DBG_PRINTS) && !defined(OPTION_DEFAULT_DBG_LEVEL)
#error "Please define OPTION_DEFAULT_DBG_LEVEL"
#endif


#if OPTION_ENABLE_DBG_PRINTS
#ifdef OPTION_ENABLE_DBG_PRINTS

/*
1 - Error
Expand Down
1 change: 0 additions & 1 deletion xcplib/src/main.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
#pragma once
#define __MAIN_CFG_H__


/* main.h */
/*
| Code released into public domain, no attribution required
Expand Down
108 changes: 70 additions & 38 deletions xcplib/src/platform.c
Original file line number Diff line number Diff line change
Expand Up @@ -674,25 +674,61 @@ uint64_t clockGetLast() {
return sClock;
}


/*
#include <mach/mach_time.h>
#include <iostream>
int main() {
uint64_t start = mach_absolute_time();
// Perform some actions here
uint64_t end = mach_absolute_time();
// Get the conversion factor to convert ticks to nanoseconds
mach_timebase_info_data_t timebase;
mach_timebase_info(&timebase);
uint64_t duration = (end - start) * timebase.numer / timebase.denom;
std::cout << "Duration in nanoseconds: " << duration << std::endl;
return 0;
}
*/



#if defined(_LINUX) // Linux

/*
Option OPTION_ARB_CLOCK provides a clock with 1us resolution since program start
Linux clock type
CLOCK_REALTIME This clock is affected by incremental adjustments performed by NTP
CLOCK_TAI This clock does not experience discontinuities and backwards jumps caused by NTP inserting leap seconds as CLOCK_REALTIME does.
Not available on WSL
CLOCK_REALTIME This clock is affected by incremental adjustments performed by NTP
1ns resolution on MacOS
CLOCK_TAI This clock does not experience discontinuities and backwards jumps caused by NTP or inserting leap seconds as CLOCK_REALTIME does.
Not available on Linux and MacOS
CLOCK_MONOTONIC_RAW Provides a monotonic clock without time drift adjustments by NTP, giving higher stability and resolution
1ns resolution also on MACOS
*/
#define CLOCK_TYPE CLOCK_REALTIME
// #define CLOCK_TYPE CLOCK_TAI


#define CLOCK_TYPE CLOCK_MONOTONIC_RAW
//#define CLOCK_TYPE CLOCK_REALTIME
//#define CLOCK_TYPE CLOCK_TAI


static struct timespec gtr;
#ifndef CLOCK_USE_UTC_TIME_NS
#ifdef OPTION_ARB_CLOCK
static struct timespec gts0;
#endif


char* clockGetString(char* s, uint32_t l, uint64_t c) {

#ifndef CLOCK_USE_UTC_TIME_NS
#ifdef OPTION_ARB_CLOCK
SNPRINTF(s,l, "%gs", (double)c / CLOCK_TICKS_PER_S);
#else
time_t t = (time_t)(c / CLOCK_TICKS_PER_S); // s since 1.1.1970
Expand All @@ -711,43 +747,41 @@ char* clockGetString(char* s, uint32_t l, uint64_t c) {
BOOL clockInit()
{
DBG_PRINT3("\nInit clock\n (");
#ifdef CLOCK_USE_UTC_TIME_NS
DBG_PRINT3("CLOCK_USE_UTC_TIME_NS,");
#endif
#ifdef CLOCK_USE_APP_TIME_US
DBG_PRINT3("CLOCK_USE_APP_TIME_US,");
#endif
#if CLOCK_TYPE == CLOCK_TAI
DBG_PRINT3("CLOCK_TYPE_TAI,");
#ifdef OPTION_TAI_CLOCK
DBG_PRINT3("OPTION_TAI_CLOCK\n");
#endif
#if CLOCK_TYPE == CLOCK_REALTIME
DBG_PRINT3("CLOCK_TYPE_REALTIME,");
#ifdef OPTION_ARB_CLOCK
DBG_PRINT3("OPTION_TAI_CLOCK\n");
#endif
DBG_PRINT3(")\n");


sClock = 0;

clock_getres(CLOCK_TYPE, &gtr);
DBG_PRINTF4("Clock resolution is %lds,%ldns!\n", gtr.tv_sec, gtr.tv_nsec);
DBG_PRINTF3("Clock resolution is %lds,%ldns!\n", gtr.tv_sec, gtr.tv_nsec);

#ifndef CLOCK_USE_UTC_TIME_NS
#ifdef OPTION_ARB_CLOCK
clock_gettime(CLOCK_TYPE, &gts0);
#endif
clockGet();

#ifdef DBG_LEVEL
if (DBG_LEVEL >= 4) {
if (DBG_LEVEL >= 4) { // Test
uint64_t t1, t2;
char s[128];
/*
struct timespec gts;
struct timeval ptm;
time_t now = time(NULL);
gettimeofday(&ptm, NULL);
clock_gettime(CLOCK_TYPE, &gts);
DBG_PRINTF4(" CLOCK_REALTIME=%lus time=%lu timeofday=%lu\n", gts.tv_sec, now, ptm.tv_sec);
t1 = clockGet(); sleepNs(100000); t2 = clockGet();
DBG_PRINTF5(" CLOCK_REALTIME=%lus time=%lu timeofday=%lu\n", gts.tv_sec, now, ptm.tv_sec);
*/
t1 = clockGet(); sleepMs(1); t2 = clockGet();
DBG_PRINTF4(" +0us: %llu %s\n", t1, clockGetString(s, sizeof(s), t1));
DBG_PRINTF4(" +1ms: %llu %s (dt=%u)\n", t2, clockGetString(s, sizeof(s), t2), (uint32_t)(t2 - t1));
t1 = clockGet(); sleepMs(100); t2 = clockGet();
DBG_PRINTF4(" +0us: %llu %s\n", t1, clockGetString(s, sizeof(s), t1));
DBG_PRINTF4(" +100us: %llu %s (dt=%u)\n", t2, clockGetString(s, sizeof(s), t2), (uint32_t)(t2 - t1));
DBG_PRINTF4(" +100ms: %llu %s (dt=%u)\n", t2, clockGetString(s, sizeof(s), t2), (uint32_t)(t2 - t1));
DBG_PRINT4("\n");
}
#endif
Expand All @@ -761,7 +795,7 @@ uint64_t clockGet() {

struct timespec ts;
clock_gettime(CLOCK_TYPE, &ts);
#ifdef CLOCK_USE_UTC_TIME_NS // ns since 1.1.1970
#ifndef OPTION_ARB_CLOCK // ns since 1.1.1970
return sClock = (((uint64_t)(ts.tv_sec) * 1000000000ULL) + (uint64_t)(ts.tv_nsec)); // ns
#else // us since init
return sClock = (((uint64_t)(ts.tv_sec - gts0.tv_sec) * 1000000ULL) + (uint64_t)(ts.tv_nsec / 1000)); // us
Expand All @@ -772,14 +806,14 @@ uint64_t clockGet() {

// Performance counter to clock conversion
static uint64_t sFactor = 0; // ticks per us
#ifdef CLOCK_USE_UTC_TIME_NS
#ifndef OPTION_ARB_CLOCK
static uint8_t sDivide = 0; // divide or multiply
#endif
static uint64_t sOffset = 0; // offset

char* clockGetString(char* str, uint32_t l, uint64_t c) {

#ifndef CLOCK_USE_UTC_TIME_NS
#ifdef OPTION_ARB_CLOCK
SNPRINTF(str, l, "%gs", (double)c / CLOCK_TICKS_PER_S);
#else
uint64_t s = c / CLOCK_TICKS_PER_S;
Expand All @@ -799,7 +833,7 @@ char* clockGetString(char* str, uint32_t l, uint64_t c) {

char* clockGetTimeString(char* str, uint32_t l, int64_t t) {

#ifndef CLOCK_USE_UTC_TIME_NS
#ifdef OPTION_ARB_CLOCK
SNPRINTF(str, l, "%gs", (double)t/CLOCK_TICKS_PER_S);
#else
char sign = '+'; if (t < 0) { sign = '-'; t = -t; }
Expand All @@ -815,10 +849,8 @@ char* clockGetTimeString(char* str, uint32_t l, int64_t t) {
BOOL clockInit() {

DBG_PRINT3("\nInit clock\n");
#ifdef CLOCK_USE_UTC_TIME_NS
DBG_PRINT3(" CLOCK_USE_UTC_TIME_NS\n");
#else
DBG_PRINT3(" CLOCK_USE_APP_TIME_US\n");
#ifndef OPTION_ARB_CLOCK
DBG_PRINT3(" OPTION_TAI_CLOCK\n");
#endif

sClock = 0;
Expand All @@ -835,7 +867,7 @@ BOOL clockInit() {
DBG_PRINT_ERROR("ERROR: Unexpected performance counter frequency!\n");
return FALSE;
}
#ifdef CLOCK_USE_UTC_TIME_NS
#ifndef OPTION_ARB_CLOCK
if (CLOCK_TICKS_PER_S > tF.u.LowPart) {
sFactor = CLOCK_TICKS_PER_S / tF.u.LowPart;
sDivide = 0;
Expand All @@ -849,7 +881,7 @@ BOOL clockInit() {
#endif

// Get current performance counter to absolute time relation
#ifdef CLOCK_USE_UTC_TIME_NS
#ifndef OPTION_ARB_CLOCK

// Set time zone from TZ environment variable. If TZ is not set, the operating system is queried
_tzset();
Expand All @@ -867,7 +899,7 @@ BOOL clockInit() {
// Calculate factor and offset
QueryPerformanceCounter(&tC);
tp = (((int64_t)tC.u.HighPart) << 32) | (int64_t)tC.u.LowPart;
#ifdef CLOCK_USE_UTC_TIME_NS
#ifndef OPTION_ARB_CLOCK
// set offset from local clock UTC value t
// this is inaccurate up to 1 s, but irrelevant because system clock UTC offset is also not accurate
sOffset = time_s * CLOCK_TICKS_PER_S + (uint64_t)time_ms * CLOCK_TICKS_PER_MS - tp * sFactor;
Expand All @@ -880,7 +912,7 @@ BOOL clockInit() {

#ifdef DBG_LEVEL
if (DBG_LEVEL >= 5) {
#ifdef CLOCK_USE_UTC_TIME_NS
#ifndef OPTION_ARB_CLOCK
if (DBG_LEVEL >= 6) {
struct tm tm;
_gmtime64_s(&tm, (const __time64_t*)&time_s);
Expand Down Expand Up @@ -915,7 +947,7 @@ uint64_t clockGet() {

QueryPerformanceCounter(&tp);
t = (((uint64_t)tp.u.HighPart) << 32) | (uint64_t)tp.u.LowPart;
#ifdef CLOCK_USE_UTC_TIME_NS
#ifndef OPTION_ARB_CLOCK
if (sDivide) {
t = t / sFactor + sOffset;
}
Expand Down
29 changes: 11 additions & 18 deletions xcplib/src/platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
*/

#ifndef __MAIN_CFG_H__
#error "Include dependency error!"
#error "Include dependency error! options not set"
#endif

//-------------------------------------------------------------------------------
Expand Down Expand Up @@ -159,28 +159,21 @@ extern BOOL socketGetLocalAddr(uint8_t* mac, uint8_t* addr);
#endif

//-------------------------------------------------------------------------------
// Clock

// Clock resolution and epoch
#if !defined(CLOCK_USE_UTC_TIME_NS) && !defined(CLOCK_USE_APP_TIME_US)
// Default
#define CLOCK_USE_UTC_TIME_NS // Use ns timestamps relative to 1.1.1970 (TAI monotonic - no backward jumps)
//#define CLOCK_USE_APP_TIME_US // Use arbitrary us timestamps relative to application start
#endif
// High resolution clock

#ifdef CLOCK_USE_UTC_TIME_NS
#ifndef OPTION_ARB_CLOCK

#define CLOCK_TICKS_PER_M (1000000000ULL*60)
#define CLOCK_TICKS_PER_S 1000000000
#define CLOCK_TICKS_PER_MS 1000000
#define CLOCK_TICKS_PER_US 1000
#define CLOCK_TICKS_PER_NS 1
#define CLOCK_TICKS_PER_M (1000000000ULL*60)
#define CLOCK_TICKS_PER_S 1000000000
#define CLOCK_TICKS_PER_MS 1000000
#define CLOCK_TICKS_PER_US 1000
#define CLOCK_TICKS_PER_NS 1

#else

#define CLOCK_TICKS_PER_S 1000000
#define CLOCK_TICKS_PER_MS 1000
#define CLOCK_TICKS_PER_US 1
#define CLOCK_TICKS_PER_S 1000000
#define CLOCK_TICKS_PER_MS 1000
#define CLOCK_TICKS_PER_US 1

#endif

Expand Down
Loading

0 comments on commit 6003e06

Please sign in to comment.