Files
2026-07-30 11:19:44 +05:30

661 lines
14 KiB
C

/* tsnclock_dkm.c - Wind River tsn clock demo */
/*
* Copyright (c) 2017 Wind River Systems, Inc.
*
* The right to copy, distribute, modify or otherwise make use
* of this software may be licensed only pursuant to the terms
* of an applicable Wind River license agreement.
*/
/*
modification history
--------------------
03Jan17 xxy Init version.
*/
#include <vxWorks.h>
#include <vxbTimerLib.h>
#include <edrLib.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <endLib.h>
#include <tsnClkLib.h>
#define INCLUDE_USR_TSN_CLOCK_DEMO
#ifdef INCLUDE_USR_TSN_CLOCK_DEMO
#define tsnClockRecordMax 60
UINT64 usrTsnClock1TickCounts = 0;
UINT64 usrTsnClock2TickCounts = 0;
UINT32 tsnClock1RecordCount=0;
UINT32 tsnClock2RecordCount=0;
UINT64 usrTsnClockReadDelay = 0;
typedef struct tsnclockrec
{
struct timespec ts;
}TSNCLOCKREC;
TSNCLOCKREC tsnClock1Record[tsnClockRecordMax];
TSNCLOCKREC tsnClock2Record[tsnClockRecordMax];
clockid_t gTsnClock1Id=0;
clockid_t gTsnClock2Id=0;
LOCAL void usrTsnClockIsr
(
void
)
{
if( (gTsnClock1Id!= 0) && (tsnClock1RecordCount < tsnClockRecordMax))
{
(void)tsnClockTimeGet(gTsnClock1Id, &tsnClock1Record[tsnClock1RecordCount].ts);
tsnClock1RecordCount++;
}
usrTsnClock1TickCounts++;
return;
}
LOCAL void usrTsnClock2Isr
(
void
)
{
if( (gTsnClock2Id!= 0) && (tsnClock2RecordCount < tsnClockRecordMax))
{
(void)tsnClockTimeGet(gTsnClock2Id, &tsnClock2Record[tsnClock2RecordCount].ts);
tsnClock2RecordCount++;
}
usrTsnClock2TickCounts++;
return;
}
/*******************************************************************************
*
* usrTsnClockTimeInit - init TSN 1588 timer demo.
*
*
*
* Parameters:
* \is
* \i <pName>
* A pointer to the ethernet device name.
* \i <unit>
* Ethernet device index.
* \ie
*
* RETURNS:
* 0 (OK), or -1 (ERROR)
*
* ERRNO:
*
*
* SYNOPSIS
* STATUS usrTsnClockTimeInit
* (
* char *pName,
* int unit
* )
*
*
*/
STATUS usrTsnClockTimeInit
(
char *pName, /*eth device name */
int unit /*eth device index */
)
{
clockid_t cid ; /* ptr to return 1588 time clock ID */
struct timespec ts1;
struct timespec ts2;
UINT64 diff = 0;
UINT64 tryCounts = 0;
UINT64 usrTsnClock1ReadDelay = 0;
UINT64 usrTsnClock2ReadDelay = 0;
if(gTsnClock1Id ==0 )
{
cid=tsnClockIdGet(pName,unit,0);
if (cid == 0)
{
return (ERROR);
}
gTsnClock1Id=cid;
}
if(gTsnClock2Id ==0 )
{
cid=tsnClockIdGet(pName,unit,1);
if (cid == 0)
{
return (ERROR);
}
gTsnClock2Id=cid;
}
/* calculate the clock time getting delay*/
do{
(void)tsnClockTimeGet(gTsnClock1Id,&ts1);
(void)tsnClockTimeGet(gTsnClock1Id,&ts1);
(void)tsnClockTimeGet(gTsnClock1Id,&ts2);
usrTsnClock1ReadDelay= (UINT64)((((UINT64)ts2.tv_sec) * BILLION) +
(UINT64)ts2.tv_nsec) - (UINT64)((((UINT64)ts1.tv_sec) * BILLION)
+ (UINT64)ts1.tv_nsec);
(void)tsnClockTimeGet(gTsnClock2Id,&ts1);
(void)tsnClockTimeGet(gTsnClock2Id,&ts1);
(void)tsnClockTimeGet(gTsnClock2Id,&ts2);
usrTsnClock2ReadDelay= (UINT64)((((UINT64)ts2.tv_sec) * BILLION) +
(UINT64)ts2.tv_nsec) - (UINT64)((((UINT64)ts1.tv_sec) * BILLION)
+ (UINT64)ts1.tv_nsec);
if(usrTsnClock2ReadDelay > usrTsnClock1ReadDelay)
{
diff = usrTsnClock2ReadDelay - usrTsnClock1ReadDelay;
}
else
{
diff = usrTsnClock1ReadDelay - usrTsnClock2ReadDelay;
}
tryCounts++;
}while((diff > 100) && ( tryCounts < 10 ));
if(tryCounts >=10)
{
printf("calculate the clock time getting delay failed\n");
return (ERROR);
}
usrTsnClockReadDelay = (usrTsnClock1ReadDelay + usrTsnClock2ReadDelay)/2;
printf("delay1: %llu, delay2:%llu, diff:%llu , mean: %llu\n",
usrTsnClock1ReadDelay,
usrTsnClock2ReadDelay,
diff,
usrTsnClockReadDelay);
return (OK);
}
/*******************************************************************************
*
* usrTsnClockTimeGet - get a TSN 1588 timer time.
*
* This routine get a TSN 1588 timer time.
*
* The <timerNo> argument, refer to the 1588 timer unit,0 or 1
*
* Parameters:
* \is
* \i <pName>
* A pointer to the ethernet device name.
* \i <unit>
* Ethernet device index.
* \i <timerNo>
* 1588 clock timer number .
* \ie
*
* RETURNS:
* 0 (OK), or -1 (ERROR)
*
* ERRNO:
*
*
* SYNOPSIS
* STATUS usrTsnClockTimeGet
* (
* char *pName,
* int unit,
* int timerNo,
* )
*
*
*/
STATUS usrTsnClockTimeGet
(
char *pName, /*eth device name */
int unit, /*eth device index */
int timerNo /* 1588 clock timer nuber */
)
{
clockid_t cid ; /* ptr to return 1588 time clock ID */
struct timespec ts; /* current time */
STATUS ret ;
cid=tsnClockIdGet(pName,unit,timerNo);
if (cid == 0)
{
(void)printf("usrTsnClockTimeGetDemo %s%d-%d failed.\n",pName,unit,timerNo);
return (ERROR);
}
ret= tsnClockTimeGet (cid,& ts);
if( ret == ERROR )
return ERROR;
(void)printf("usrTsnClockTimeGetDemo %d: %09ld \n",ts.tv_sec,ts.tv_nsec);
return (OK);
}
/*******************************************************************************
*
* usrTsnClockRateGet - get a TSN 1588 timer ticks per second.
*
* This routine get get a TSN 1588 timer ticks per second.
*
* The <timerNo> argument, refer to the 1588 timer unit,0 or 1
*
* Parameters:
* \is
* \i <pName>
* A pointer to the ethernet device name.
* \i <unit>
* Ethernet device index.
* \i <timerNo>
* 1588 clock timer number .
* \ie
*
* RETURNS:
* 0 (OK), or -1 (ERROR)
*
* ERRNO:
*
*
* SYNOPSIS
* STATUS usrTsnClockRateGet
* (
* char *pName,
* int unit,
* int timerNo,
* )
*
*
*/
STATUS usrTsnClockRateGet
(
char *pName, /*eth device name */
int unit, /*eth device index */
int timerNo /* 1588 clock timer nuber */
)
{
clockid_t cid ; /* ptr to return 1588 time clock ID */
STATUS ret ;
cid=tsnClockIdGet(pName,unit,timerNo);
if (cid == 0)
{
(void)printf("usrTsnClockTimeGetDemo %s%d-%d failed.\n",pName,unit,timerNo);
return (ERROR);
}
ret= tsnClockRateGet (cid);
if( ret == ERROR )
return ERROR;
(void)printf("usrTsnClockRateGetDemo %d \n",ret);
return (OK);
}
/*******************************************************************************
*
* usrTsnClockAlloc - Allocate a timer for ticks or one shot interrupt.
*
* This routine enable a TSN 1588 timer.
*
* The <timerNo> argument, refer to the 1588 timer unit,0 or 1
*
* Parameters:
* \is
* \i <pName>
* A pointer to the ethernet device name.
* \i <unit>
* Ethernet device index.
* \i <timerNo>
* 1588 clock timer number .
* \i <ticksPerSecond>
* Number of ticks per second,to use one shot interrupt set to be zeros
* \ie
*
* RETURNS:
* 0 (OK), or -1 (ERROR)
*
* ERRNO:
*
*
* SYNOPSIS
* STATUS usrTsnClockAlloc
* (
* char *pName,
* int unit,
* int timerNo,
* UINT32 ticksPerSecond
* )
*
*
*/
STATUS usrTsnClockAlloc
(
char *pName, /*eth device name */
int unit , /*eth device index */
int timerNo, /* 1588 clock timer nuber */
UINT32 ticksPerSecond /* number of clock interrupts per second */
)
{
clockid_t cid =0 ;
STATUS ret ;
cid=tsnClockIdGet(pName,unit,timerNo);
if (cid == 0)
{
(void)printf("tsnClockIdGet %s%d-%d failed.\n",pName,unit,timerNo);
return (ERROR);
}
ret = tsnTimerAllocate(cid);
if (ret == ERROR)
{
(void)printf("tsnClockOpen cid: 0x%x failed.\n",cid);
return (ERROR);
}
if(timerNo == 1)
{
ret = tsnClockConnect(cid, (FUNCPTR)usrTsnClock2Isr, 0);
}
else
{
ret = tsnClockConnect(cid, (FUNCPTR)usrTsnClockIsr, 0);
}
if (ret == ERROR)
{
(void)printf("tsnClockConnect cid: 0x%x failed.\n",cid);
(void)tsnTimerRelease(cid);
return (ERROR);
}
ret=tsnClockRateSet(cid,ticksPerSecond);
if( ret == ERROR )
{
(void)printf("tsnClockRateSet cid: 0x%x failed.\n",cid);
(void)tsnTimerRelease(cid);
return ERROR;
}
return (OK);
}
/*******************************************************************************
*
* usrTsnClockEnable - enable a TSN 1588 timer .
*
* This routine enable a TSN 1588 timer.
*
* The <timerNo> argument, refer to the 1588 timer unit,0 or 1
*
* Parameters:
* \is
* \i <pName>
* A pointer to the ethernet device name.
* \i <unit>
* Ethernet device index.
* \i <timerNo>
* 1588 clock timer number .
* \i <seconds>
* offset to current second (second)
* \i <nanoseconds>
* absolute start nanosecond (nanosecond)
* \ie
*
* RETURNS:
* 0 (OK), or -1 (ERROR)
*
* ERRNO:
*
*
* SYNOPSIS
* STATUS usrTsnClockEnable
* (
* char *pName,
* int unit,
* int timerNo,
* UINT32 seconds,
* UINT32 nanoseconds
* )
*
*
*/
STATUS usrTsnClockEnable
(
char *pName, /*eth device name */
int unit , /*eth device index */
int timerNo, /* 1588 clock timer nuber */
UINT32 seconds, /* offset to current time (s) */
UINT32 nanoseconds /* absolute start time (ns) */
)
{
clockid_t cid =0 ;
STATUS ret ;
struct timespec ts;
cid=tsnClockIdGet(pName,unit,timerNo);
if (cid == 0)
{
(void)printf("tsnClockIdGet %s%d-%d failed.\n",pName,unit,timerNo);
return (ERROR);
}
ret= tsnClockTimeGet (cid,& ts);
if( ret == ERROR )
return ERROR;
ts.tv_sec += seconds;
ts.tv_nsec = nanoseconds;
ret = tsnClockEnable(cid,&ts);
(void)printf("usrTsnClockEnable launch time %d: %09ld \n",ts.tv_sec,ts.tv_nsec);
if (ret == ERROR)
{
(void)printf("tsnClockEnable cid: 0x%x failed.\n",cid);
return (ERROR);
}
return (OK);
}
/*******************************************************************************
*
* usrTsnClockDisable - disable a TSN 1588 timer .
*
* This routine disable a TSN 1588 timer.
*
* The <timerNo> argument, refer to the 1588 timer unit,0 or 1
*
* Parameters:
* \is
* \i <pName>
* A pointer to the ethernet device name.
* \i <unit>
* Ethernet device index.
* \i <timerNo>
* 1588 clock timer number .
* \ie
*
* RETURNS:
* 0 (OK), or -1 (ERROR)
*
* ERRNO:
*
*
* SYNOPSIS
* STATUS usrTsnClockDisable
* (
* char *pName,
* int unit,
* int timerNo,
* )
*
*
*/
STATUS usrTsnClockDisable
(
char *pName, /*eth device name */
int unit , /*eth device index */
int timerNo /* 1588 clock timer nuber */
)
{
clockid_t cid =0 ;
STATUS ret ;
cid=tsnClockIdGet(pName,unit,timerNo);
if (cid == 0)
{
(void)printf("tsnClockIdGet %s%d-%d failed.\n",pName,unit,timerNo);
return (ERROR);
}
ret = tsnClockDisable(cid);
return (ret);
}
/*******************************************************************************
*
* usrTsnClockRelease - release a TSN 1588 timer.
*
* This routine release a TSN 1588 timer.
*
* The <timerNo> argument, refer to the 1588 timer unit,0 or 1
*
* Parameters:
* \is
* \i <pName>
* A pointer to the ethernet device name.
* \i <unit>
* Ethernet device index.
* \i <timerNo>
* 1588 clock timer number .
* \ie
*
* RETURNS:
* 0 (OK), or -1 (ERROR)
*
* ERRNO:
*
*
* SYNOPSIS
* STATUS usrTsnClockDisable
* (
* char *pName,
* int unit,
* int timerNo,
* )
*
*
*/
STATUS usrTsnClockRelease
(
char *pName, /*eth device name */
int unit , /*eth device index */
int timerNo /* 1588 clock timer nuber */
)
{
clockid_t cid =0 ;
STATUS ret ;
cid=tsnClockIdGet(pName,unit,timerNo);
if (cid == 0)
{
(void)printf("tsnClockIdGet %s%d-%d failed.\n",pName,unit,timerNo);
return (ERROR);
}
ret = tsnTimerRelease(cid);
return (ret);
}
/******************************************************************************
*
* usrTsnClockshow - the routine of Tsn clock show
* RETURNS: N/A
*
* ERRNO: N/A
*/
void usrTsnClockshow( int unit)
{
int ix =0;
UINT64 timeCounts = 0;
if(unit ==0)
{
printf("\nclock1 interrrupt time sample:\n");
for (ix = 0; ix < tsnClock1RecordCount; ix++ )
{
timeCounts= ((UINT64)(tsnClock1Record[ix].ts.tv_sec) *BILLION)
+ tsnClock1Record[ix].ts.tv_nsec - usrTsnClockReadDelay;
printf(" %llu:%llu\n",
(timeCounts/BILLION),
(timeCounts%BILLION));
}
tsnClock1RecordCount=0;
}
else
{
printf("\n\n\nclock2 interrrupt time sample:\n");
for (ix = 0; ix < tsnClock2RecordCount; ix++ )
{
timeCounts= ((UINT64)(tsnClock2Record[ix].ts.tv_sec) *BILLION)
+ tsnClock2Record[ix].ts.tv_nsec - usrTsnClockReadDelay;
printf(" %llu:%llu\n",
(timeCounts/BILLION),
(timeCounts%BILLION));
}
tsnClock2RecordCount=0;
}
}
#endif