677 lines
25 KiB
HTML
677 lines
25 KiB
HTML
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
|
|
"http://www.w3.org/TR/html4/loose.dtd">
|
|
<html><head>
|
|
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
|
|
<meta http-equiv="author" content="Babak Kalantari">
|
|
<style type="text/css">
|
|
<!--
|
|
body { font-family:Arial,sans-serif,espy;
|
|
background:white; margin:0; }
|
|
body,p,ul,ol,dl,div,table {font-size:12pt; }
|
|
p { line-height:120%; }
|
|
pre,code,tt { font-family:"Courier New",Courier,monospace; }
|
|
code,tt { font-size:13pt; }
|
|
h1 { font-size: 24pt; margin-top:1ex; margin-bottom:0; text-align:center; }
|
|
h2 { font-size: 18pt; margin-bottom:0.5ex; }
|
|
h3 { font-size: 14pt; margin-bottom:0.5ex; }
|
|
h4 { font-size: 13pt; margin-bottom:0.5ex; }
|
|
h5 { font-size: 12pt; margin-bottom:0.5ex; }
|
|
small { font-size: 9pt; }
|
|
code { color:#0000C0; }
|
|
li { margin-top: 2pt; margin-bottom: 2pt; }
|
|
pre { font-size: 13pt;
|
|
white-space:pre; }
|
|
.box { border:1px solid #000000;
|
|
background-color:#f4f4f4;
|
|
padding:1ex;
|
|
margin: 0 2ex 1ex 2ex; font-size:90%; }
|
|
th.PageTitle {
|
|
font-size : 14pt;
|
|
font-weight : bold; }
|
|
.menuf {
|
|
font-size:11pt;
|
|
color:#333333;
|
|
font-weight:600;
|
|
text-decoration:none;
|
|
}
|
|
.menuf:link {color:#333333;}
|
|
.menuf:visited {color:#666666;}
|
|
.menuf:hover {color:#FF0000;}
|
|
.menuf:active {color:#FF0000;}
|
|
.menus, .menus a {
|
|
font-size:10pt;
|
|
color:#333333;
|
|
text-decoration:none;
|
|
}
|
|
.menus:visited, .menus a:visited {color:#666666;}
|
|
.menus:hover, .menus a:hover {color:#FF0000;}
|
|
.menus:active, .menus a:active {color:#FF0000;}
|
|
a:hover {color:#FF0000;}
|
|
.red {color:#FF0000;}
|
|
.green {color:#008000;}
|
|
.blue {color:#0000C0;}
|
|
|
|
@media screen {
|
|
.printlayout {display:none;}
|
|
}
|
|
|
|
@media print {
|
|
.screenlayout {display:none;}
|
|
code { color:#000000; }
|
|
a:link {color:#000000;text-decoration:none}
|
|
a:visited {color:#000000;text-decoration:none}
|
|
a:hover {color:#000000;text-decoration:none}
|
|
a:active {color:#000000;text-decoration:none}
|
|
}
|
|
-->
|
|
</style>
|
|
<link rel="shortcut icon" href="http://epics.web.psi.ch/images/sls_icon.ico">
|
|
<title>generalTime</title>
|
|
</head>
|
|
<body bgcolor="#FFFFFF">
|
|
<table cellspacing="0" cellpadding="0" border="0" width="100%">
|
|
|
|
<tr class="screenlayout">
|
|
<td bgcolor="#267ab8" colspan="5" valign="bottom" height="10">
|
|
<img
|
|
src="../../images/black"
|
|
width="100%" height="1" alt=""></td>
|
|
</tr>
|
|
|
|
<tr class="screenlayout">
|
|
<td rowspan="2" colspan="2" align="center">
|
|
<a class="menuf" href="http://www.psi.ch"><img
|
|
src="../../images/psi_logo" border="0"
|
|
alt="PAUL SCHERRER INSTITUT"></a></td>
|
|
<td rowspan="2"><img
|
|
src="../../images/space"
|
|
width="1" height="65" alt=""></td>
|
|
<th class="PageTitle"><center>
|
|
<big>EPICS at PSI<big>
|
|
</center>
|
|
</th>
|
|
<td><img
|
|
src="../../images/space"
|
|
width="10" height="1" alt=""></td>
|
|
</tr>
|
|
|
|
<tr class="screenlayout">
|
|
<th width="100%" valign="bottom" align="left">
|
|
<table border="0" cellspacing="0" cellpadding="0"><tr><td><a
|
|
href="https://www.psi.ch"
|
|
class="menuf">PSI</a></td><td><img
|
|
src="../../images/space"
|
|
width="10" height="1" alt=""></td><td bgcolor="black"><img
|
|
src="../../images/space"
|
|
width="1" height="1" alt=""></td><td><img
|
|
src="../../images/space"
|
|
width="10" height="1" alt=""></td><td><a
|
|
href="https://www.aps.anl.gov/epics"
|
|
class="menuf">EPICS</a></td><td><img
|
|
src="../../images/space"
|
|
width="10" height="1" alt=""></td><td bgcolor="black"><img
|
|
src="../../images/space"
|
|
width="1" height="1" alt=""></td><td><img
|
|
src="../../images/space"
|
|
width="10" height="1" alt=""></td><td><a
|
|
href="https://www.psi.ch/en/sls"
|
|
class="menuf">SLS</a></td><td><img
|
|
src="../../images/space"
|
|
width="10" height="1" alt=""></td><td bgcolor="black"><img
|
|
src="../../images/space"
|
|
width="1" height="1" alt=""></td><td><img
|
|
src="../../images/space"
|
|
width="10" height="1" alt=""></td><td><a
|
|
href="https://www.psi.ch/en/swissfel"
|
|
class="menuf">SwissFEL</a></td><td><img
|
|
src="../../images/space"
|
|
width="10" height="1" alt=""></td><td bgcolor="black"><img
|
|
src="../../images/space"
|
|
width="1" height="1" alt=""></td><td><img
|
|
src="../../images/space"
|
|
width="10" height="1" alt=""></td><td><a
|
|
href="https://www.psi.ch/en/protontherapy"
|
|
class="menuf">Proscan</a></td></tr></table>
|
|
</th>
|
|
</tr>
|
|
|
|
<tr class="screenlayout">
|
|
<td height="5" bgcolor="#267ab8" colspan="6" valign="bottom">
|
|
<img
|
|
src="../../images/black"
|
|
width="100%" height="1" alt=""></td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td class="screenlayout" bgcolor="#e3eaf6" valign="top" align="center" width="179">
|
|
<br><a href="http://www.aps.anl.gov/epics"><img
|
|
src="../../images/EPICS_small"
|
|
alt="EPICS" border=0></a><br><br>
|
|
<table cellspacing="0" cellpadding="0" border="0" width="100%"><tr><td><img
|
|
src="../../images/space"
|
|
width="20" height="29" alt=""></td><th width="100%" align="left"><a
|
|
href="../../index.html"
|
|
class="menuf">EPICS at PSI</a>
|
|
<img
|
|
src="../../images/black"
|
|
height="1" width="100%" alt=""></th></tr></table>
|
|
<table cellspacing="0" cellpadding="0" border="0" width="100%"><tr><td><img
|
|
src="../../images/space"
|
|
width="20" height="29" alt=""></td><th width="100%" align="left"><a
|
|
href="../../software.html"
|
|
class="menuf">Software</a>
|
|
<ul style="margin:0 0 0 0; padding-left:1em;">
|
|
<li class="menus"><a href="../s7plc.html"
|
|
>PLC Communication</a></li>
|
|
<li class="menus"><a href="../streamdevice.html"
|
|
>StreamDevice</a></li>
|
|
<li class="menus"><a href="../regDev.html"
|
|
>regDev</a></li>
|
|
<li class="menus"><a href="../iocmon.html"
|
|
>IOC Monitoring</a></li>
|
|
<li class="menus"><a href="../pcmon.html"
|
|
>PC Monitoring</a></li>
|
|
<li class="menus"><a href="../firewire.html"
|
|
>Firewire Camera</a></li>
|
|
<li class="menus"><a href="http://dps.web.psi.ch/template.html?/psc/"
|
|
>Digital PS Control</a></li>
|
|
<li class="menus"><a href="../tclioc.html"
|
|
>Tcl-IOC</a></li>
|
|
<li class="menus"><a href="../iocLogBrowser.html"
|
|
>iocLogBrowser</a></li>
|
|
<li class="menus"><a href="../ioc-octave.html"
|
|
>IOC-Octave</a></li>
|
|
<li class="menus"><a href="http://gfa-it.web.psi.ch/epicsSharp/"
|
|
>C# EPICS</a></li>
|
|
<li class="menus"><a href="../generalTime.html"
|
|
>generalTime</a></li>
|
|
<li class="menus"><a href="../GPMM.html"
|
|
>GPMM</a></li>
|
|
<li class="menus"><a href="../sequencer.html"
|
|
>SNC/SEQ</a></li>
|
|
<li class="menus"><a href="../caqtdm.html"
|
|
>caQtDM</a></li>
|
|
<li class="menus"><a href="../CSDataQuick.html"
|
|
>CSDataQuick</a></li>
|
|
</ul>
|
|
<img
|
|
src="../../images/black"
|
|
height="1" width="100%" alt=""></th></tr></table>
|
|
<table cellspacing="0" cellpadding="0" border="0" width="100%"><tr><td><img
|
|
src="../../images/space"
|
|
width="20" height="29" alt=""></td><th width="100%" align="left"><a
|
|
href="../../training.html"
|
|
class="menuf">Training</a>
|
|
<ul style="margin:0 0 0 0; padding-left:1em;">
|
|
<li class="menus"><a href="../../training/PSI-training.html"
|
|
>Courses at PSI</a></li>
|
|
<li class="menus"><a href="../../training/caClientLessons.html"
|
|
>CA client lessons</a></li>
|
|
<li class="menus"><a href="../../training/downloads.html"
|
|
>Downloads</a></li>
|
|
</ul>
|
|
<img
|
|
src="../../images/black"
|
|
height="1" width="100%" alt=""></th></tr></table>
|
|
<form method="get" action="http://www.google.com/search">
|
|
<table border="0" cellpadding="0" cellspacing="0">
|
|
<tr><td align="center" nowrap>
|
|
<input type="search" placeholder="search" name="q" size="13" maxlength="255" value=""><br>
|
|
<input type="hidden" name="domains" value="epics.web.psi.ch">
|
|
<small>
|
|
<input type="radio" name="sitesearch" value=""> web
|
|
<input type="radio" name="sitesearch" value="epics.web.psi.ch"
|
|
checked="checked"> epics.web.psi.ch<br>
|
|
</small>
|
|
</td></tr></table>
|
|
</form><p></p><small>
|
|
Author: <a href="mailto:Babak Kalantari <babak.kalantari@psi.ch>?subject=http://epics.web.psi.ch%2Fsoftware%2FgeneralTime%2FEVENT_README.php">Babak Kalantari</a><br>
|
|
Phone: +41 56 310 5122<br>
|
|
Updated: 11.09.2007<br>
|
|
<br><a
|
|
href="http://epics.web.psi.ch/software/generalTime/%2Fsoftware%2FgeneralTime%2FEVENT_README.php?forprint"><img
|
|
src="../../images/printer"
|
|
border="0" alt=""></a>
|
|
<br><a
|
|
href="http://epics.web.psi.ch/software/generalTime/%2Fsoftware%2FgeneralTime%2FEVENT_README.php?forprint">Printer friendly version</a>
|
|
<br> </small><img
|
|
src="../../images/space"
|
|
width="179" height="1" alt=""></td>
|
|
<td width="1" bgcolor="#000000"><img
|
|
src="../../images/space"
|
|
width="1" height="1" alt=""></td>
|
|
<td><img
|
|
src="../../images/space"
|
|
width="10" height="1" alt=""></td>
|
|
<td valign="top" width="100%" colspan="2">
|
|
<a name="top"></a><center><h1>generalTime</h1></center>
|
|
<body>
|
|
<p>
|
|
<br>#####################################################################
|
|
<br>
|
|
<br> <b>Author:</b> Babak Kalantari at PSI dot CH
|
|
<br> <b>Institution:</b> Paul Scherrer Institute / SLS controls
|
|
<br> <b>Initial Version:</b> 17.11.2006
|
|
<br> <b>Purpose:</b> Description of usage and functionality of EventTime driver support for generalTime
|
|
<br> <b>Acknowledgment:</b>
|
|
The code was developed through interactive technical discussions with Timo Korhonen.
|
|
Some parts of the code has been inspired by the earlier work of Jim Kowalkowsky.
|
|
<br>
|
|
<br>#####################################################################
|
|
</p>
|
|
|
|
<p>
|
|
<br>#########################################################################
|
|
<br>###### modifictaion log #######
|
|
<br>version 1.1
|
|
<br>- initial version
|
|
<br>
|
|
<br>version 1.2
|
|
<br>- master PLL/validation relies only generalTime
|
|
<br>- clock validation changed to aoRecord
|
|
<br>
|
|
<br>The event time driver 'drvDevEventTime' has been developed to support
|
|
hardware synchronized timestamps for generalTime driver. It provides
|
|
tight clock synchronization among IOC's equipped with required hardware.
|
|
<br>
|
|
Great care has been taken into account to keep the code as OS-independent
|
|
as possible, however, at present we can only gaurantee its proper operation
|
|
under vxWorks. Where it was possible, we have used standard EPICS routines
|
|
supported by libCom.
|
|
|
|
</p>
|
|
<p>
|
|
<br>#########################################################################
|
|
<br>##
|
|
<br>### Organization of this document
|
|
<br>##
|
|
<ul>
|
|
<li>System requirements & configurations</li>
|
|
<li>Relation to generalTime</li>
|
|
<li>Initialization</li>
|
|
<li>EPICS threads</li>
|
|
<li>Hardware interface</li>
|
|
<li>Clock monitoring & controls</li>
|
|
<li>Data types</li>
|
|
</ul>
|
|
|
|
</p>
|
|
|
|
|
|
<p>
|
|
<br>#########################################################################
|
|
<br>##
|
|
<br>### System requirements & configurations
|
|
<br>##
|
|
|
|
<br>- Epics 3.14.8 or higher.
|
|
<br>- generalTime driver
|
|
<br>- EventTime driver (drvDevEventTime.c)
|
|
<br>
|
|
<br>For Event Master IOC:
|
|
<br>- EVG
|
|
<br>- EVR
|
|
<br>
|
|
<br>For Event Slave IOC:
|
|
<br>- EVR
|
|
<br>
|
|
<br>There is no rule or limitation on the card number of EVG-EVR.
|
|
The EventTime driver recognizes the first card (EVG/EVR) which is
|
|
found, to be configured in the linked list of the EVG/EVR drivers as
|
|
we have implemented this for EVG/EVR-100 series in the corresponding
|
|
device drivers. This first card can have any card number for example 5.
|
|
|
|
<br>To use the EventTime, the following configuration
|
|
function should be called in the IOC startup script:
|
|
<br>
|
|
<br>EvtTimeConfigure(
|
|
<br> master, ## 0=slave, 1=master
|
|
<br> sync_rate_sec, ## sync rate in seconds
|
|
<br> clock_rate_hz, ## clock rate in Herz
|
|
<br> master_port, ## master listens here (UDP port 18323)
|
|
<br> slave_port, ## slave talks here (UDP port 18322)
|
|
<br> time_out ## reply timout in ms
|
|
<br> )
|
|
<br>
|
|
<br>
|
|
The event Master IOC is responsible for generation and distribution of the
|
|
clock tick event (0x7c) and tick-counter-reset event (0x7d).
|
|
The user has to make sure that the parameter "clock_rate_hz" is consistent
|
|
with the physical tick frequncy which goes on the event stream.
|
|
If the interface functions to control the tick rate (set/get_ClkFreq,
|
|
see "Hardware Interface" section below) are present, the tick frequecny
|
|
will be regulated to follow reference (global) time provided by
|
|
generalTime otherwise tick rate stays constant and the EventTime still
|
|
works but drifts from the global time during a long run (typically few weeks).
|
|
</p>
|
|
|
|
<p>
|
|
<br>#########################################################################
|
|
<br>##
|
|
<br>### Relation to generalTime
|
|
<br>##
|
|
<br>
|
|
<br>The concept of generalTime introduced by Scheng Peng (SNS) provides a
|
|
priority-based clock mechanism. To keep it simple, generalTime maintains
|
|
a list of the time providers (clocks) each with a certain priority.
|
|
Whenever asked for the current time the generalTime gets the time from the
|
|
highest priority avaiable clock. Each time-provider has to register itself
|
|
to generalTime at init using the registeration functions provided by
|
|
generalTime driver. Each time provider is responsible for consistency of
|
|
its own time and as soon as it finds out that it is not valid anymore should
|
|
anounce itself as faulty. generalTime gets to know this by ckecking the return
|
|
value of the call to time provider (epicsTimeERROR or notepicsTimeERROR).
|
|
The EvenTime driver relation to generalTime also satisfies what was described.
|
|
At its init routine EventTime driver checks all the requirements (see -
|
|
initialization section below) and when everything turned out to be fine
|
|
it registres itself with generalTime and declares itself as a time provider.
|
|
There are some critical points where EventTime driver relies on generalTime:
|
|
<br>
|
|
<br>1) when EventTime wants to setup its clock it has to set its time to an
|
|
estimation of the current time (actual global time). It relies only on generalTime
|
|
to provide a consitent time. At init EventTime asks generalTime by calling
|
|
"epicsTimeGetCurrent()".
|
|
<br>
|
|
<br>2) When the EventTime is invalid and the user (via aoRecord) tries to validate
|
|
it, then a call to "epicsTimeGetCurrent()" gets the EPICS current time and the
|
|
result is compared with the time read from a direct call to EventTime in order
|
|
to judge if EventTime is ready to become valid.
|
|
</p>
|
|
|
|
<p>
|
|
|
|
<br>#########################################################################
|
|
<br>##
|
|
<br>### Initialization
|
|
<br>##
|
|
<br>
|
|
<br>The initialization of EventTime is done via "EventTime_Init()" which is called
|
|
at "initHookAtEnd" (timing hardware has to be initialized before EventTime).
|
|
<br>The following sequence is done by the init routine:
|
|
<ol>
|
|
<li> checks if EventTime device private (pEventTimePvt) exists </li>
|
|
<li> EventTime is set to FALSE state (invalid) </li>
|
|
<li> checks if timing receiver HW (EVR) is installed </li>
|
|
<li> checks if the "get_ticks()" is installed (by the HW driver e.g. EVR driver) </li>
|
|
<li> checks if "ts_sync_signal()" is installed and uses it to get sync event
|
|
number, if this function is not installed the "ER_EVENT_RESET_TICK" is used </li>
|
|
<li> checks if "force_sync()" is installed by HW driver and if not uses
|
|
the "EVTforceSoftSync()" instead. </li>
|
|
<li> checks if there is a "direct_time()" provided </li>
|
|
<li> sets up the "event_table" buffer to maintain individual event timestamps </li>
|
|
<li> determines if it can have the role of Master/Slave according to the user
|
|
request in configuration function and the info it has got in previous steps </li>
|
|
<li> EventTime registers its "EVTeventHandler()" to the receiver (EVR) driver </li>
|
|
<li> EventTime registers its "EVTerrorHandler()" to the receiver (EVR) driver</li>
|
|
<li> for the Master:
|
|
<br>- calls EVTstartStampServer()
|
|
<br>- calls EVTstartSyncServer()
|
|
<br>- calls EVTstartPLL() if "set_ClkFreq()" and "get_ClkFreq()" are present</li>
|
|
<li> for the Slave:
|
|
<br>- calls EVTsetClockFromMaster()
|
|
<br>- calls EVTstartSyncClient()</li>
|
|
<li> calls "EVTstartClkWatch()" </li>
|
|
<li> calls any HW specific initialization provided by HW driver (ts_drv_init)</li>
|
|
<li> registers itself to generalTime by a call to "generalTimeTpRegister()" with
|
|
time provider priority set to 70 </li>
|
|
</ol>
|
|
</p>
|
|
|
|
|
|
<p>
|
|
|
|
<br>#########################################################################
|
|
<br>##
|
|
<br>### EPICS threads
|
|
<br>##
|
|
<ul>
|
|
<li> epicsThreadId <b>EVTstartSyncServer()</b>;
|
|
<br>creates the server thread only on event Master IOC that
|
|
broadcasts the sync time stamp every time a sync event
|
|
(default 0x7d) is receive by the event system. The event
|
|
time is not valid until the first sync event ocuuers.
|
|
When the event time becomes invalid due to a reason the
|
|
sync messages are not broadcast except if the detected fault
|
|
is "EVT_ntpLock_lost". This is to inform slaves quickly to
|
|
give up the master and invalidate their event time.</li>
|
|
|
|
|
|
<li> epicsThreadId <b>EVTstartStampServer()</b>;
|
|
<br>creates the Server thread only on event Master IOC that
|
|
listens for time stamp and sync requests from slaves. If
|
|
the event time is not valid the thread does not reply the
|
|
request (to force slaves to give up the master).</li>
|
|
|
|
<li> epicsThreadId <b>EVTstartPLL()</b>;
|
|
<br>creates the server thread only on event Master IOC to keep
|
|
event time in sync with a reference time provided by generalTime.
|
|
It invalidates the event time when it cannot lock to refernce time
|
|
and tells the slaves that it is faulty, but it tries endlessly to
|
|
lock the refernce by restoring the initial frequency of the clock
|
|
tick. When it succeeds to track reference time it validates the
|
|
event time again. When EventTime is valid it gets the reference time
|
|
by a calling generalTimeGetExceptPriority() which returns the best
|
|
available time excluding a time provider (in this case EventTime).</li>
|
|
|
|
<li> epicsThreadId <b>EVTstartSyncClient()</b>;
|
|
<br>creates the client thread that listens for sync time stamp
|
|
message (from Master) on a port and verifies with this, its
|
|
sync time stamp. If it does not receive the sync message after
|
|
three sync interval it invalidates the event time and sets
|
|
the fault state to "EVT_sync_timeout". Furthermore if it
|
|
receives a sync message where it says master has the state of
|
|
"EVT_ntpLock_lost" then it also sets its fault state the same.</li>
|
|
|
|
|
|
<li> epicsThreadId <b>EVTstartClkWatch()</b>;
|
|
<br>creates a thread that periodically (2 seconds) checks if the
|
|
current event time is in progress and if not, it invalidates
|
|
the event time and sets the fault state to "EVT_tick_fail".</li>
|
|
|
|
</ul>
|
|
|
|
|
|
</p>
|
|
<p>
|
|
|
|
<br>#########################################################################
|
|
<br>##
|
|
<br>### Hardware interface
|
|
<br>##
|
|
<br>
|
|
<br>Event time is only usable if adequate hardware (HW) is present
|
|
in the system and the minimal requirements are supported and
|
|
plugged (installed) in the following HW-interface structure.
|
|
The event time driver checks this in its initialization routine.
|
|
|
|
<br>/**
|
|
<br> receiver
|
|
<br>**/
|
|
<br>An IOC which uses Event Time and is configured to be Slave, must
|
|
set at least some members of the global variable 'TSrxHW' in dev/drv
|
|
support of its timing hardware (e.g. event system) as following:
|
|
<br>
|
|
<br>- <b>card</b> A non-negative integer corresponding
|
|
to the reciver.
|
|
<br>- <b>have_rx</b> A pointer to a function which recognizes
|
|
the card (No specific functionality is required).
|
|
<br>- <b>get_ticks</b> A pointer to a funtion which can give the actual
|
|
value of the clock tick counter whenever is called.
|
|
<br>- <b>register_signal_handler</b> A pointer to a registration function to provide
|
|
event system indication to event time driver for
|
|
event timestamp handling.
|
|
<br>- <b>register_error_handler</b> A pointer to a registration function to provide
|
|
event system indication to event time driver for
|
|
error handling (e.g. borken link, lost heartbeat, etc.)
|
|
|
|
<br>struct devTSrxHWStruct {
|
|
<br> int numFuncs;
|
|
<br> int card;
|
|
<br> long (*have_rx)(int Card);
|
|
<br> long (*get_ticks)(int Card, unsigned long *Ticks);
|
|
<br> long (*register_signal_handler)(int Card, void(*func)());
|
|
<br> long (*register_error_handler)(int Card, void(*func)());
|
|
<br> long (*direct_time)();
|
|
<br> long (*ts_drv_init)();
|
|
<br> long (*ts_get_time)(struct timespec*);
|
|
<br> long (*ts_user_get)(int event_number,struct timespec* sp);
|
|
<br> long (*ts_sync_signal)(); /* gives sync event (default 0x7d) */
|
|
<br>};
|
|
<br>typedef struct devTSrxHWStruct devTSrxHW;
|
|
|
|
|
|
<br>/**
|
|
<br> transmitter
|
|
<br>**/
|
|
<br>An IOC which uses Event Time and is configured to be Master, in addition
|
|
to set all the required members of TSrxHW (receiver), must also set the
|
|
required members of global variable 'TStxHW' in dev/drv support of its
|
|
timing hardware (e.g. event system) as following:
|
|
<br>
|
|
<br>- card A non-negative integer corresponding
|
|
to the transmitter (e.g. event generator).
|
|
<br>- have_tx A pointer to a function which recognizes
|
|
the card (No specific functionality is required).
|
|
|
|
<br>- set_ClkFreq Pointers to functions which could set / get
|
|
<br>- get_ClkFreq the freuqncy of the clock tick generator. This
|
|
is used to provide the synchronization with
|
|
external time refernce namely NTP server and
|
|
compensatefor the drift rate.
|
|
The clock tick generator can be a tick rate
|
|
generator which is integrated in the event generator
|
|
or a totally stand-alone device external to event
|
|
generator (e.g. a pulse generator).
|
|
|
|
<br>
|
|
<br>struct devTStxHWStruct {
|
|
<br> int numFuncs;
|
|
<br> int card;
|
|
<br> long (*have_tx)(int Card);
|
|
<br> long (*force_sync)(int Card);
|
|
<br> long (*set_ClkFreq)(int Card, unsigned long freq);
|
|
<br> long (*get_ClkFreq)(int Card, unsigned long *freq);
|
|
<br>};
|
|
<br>typedef struct devTStxHWStruct devTStxHW;
|
|
|
|
</p>
|
|
<p>
|
|
|
|
<br>#########################################################################
|
|
<br>##
|
|
<br>### Clock monitoring & controls
|
|
<br>##
|
|
<br>
|
|
<br>- aoRecord support to validate the event time.
|
|
When the EventTime has been invalidated for
|
|
whatever reason (e.g. broken event stream), it
|
|
should be validated after the problem has been
|
|
solved.
|
|
How this is handled is as the following:
|
|
When the EventTime is invalid and the ao record is
|
|
processed to validate it, record processing routine
|
|
first asks generalTime (calling epicsTimeGetCurrent)
|
|
for the current time; it immediately asks EventTime
|
|
directly (calling EVTgetTimeStamp) too. Then it
|
|
compares the difference of theses two with the VAL
|
|
field and allows a validation of EventTime only when
|
|
the differnce of the two time values is less than VAL
|
|
seconds. Otherwise it rejects the validation operation
|
|
and returns a WRITE alarm.
|
|
|
|
<br>- mbbiRecord support to find out the reason of
|
|
the event time invalidity (fauilor detection).
|
|
The following are the possible states:
|
|
<br>
|
|
EVT_time_OK: event time is not faulty (it is valid)
|
|
<br>
|
|
<br> EVT_stream_lost: occures when event system harware (receiver)
|
|
detects that event stream is lost and sends
|
|
an interrupt if enabled
|
|
<br>
|
|
<br> EVT_sync_timeout: occures when the sysnchronization message broadcast
|
|
from master does not arrive after 3*sync_rate_sec
|
|
<br>
|
|
<br> EVT_ntpLock_lost: occures when Master is not able anymore to keep track
|
|
of external time reference (e.g. NTP server)
|
|
<br>
|
|
<br> EVT_tick_fail: occures when clock tick counter is not increasing
|
|
|
|
|
|
</p>
|
|
<p>
|
|
|
|
<br>#########################################################################
|
|
<br>##
|
|
<br>### Data types
|
|
<br>##
|
|
<br>
|
|
<br>
|
|
<br>typedef enum { EVT_sync_master,
|
|
<br> EVT_sync_slave,
|
|
<br> EVT_direct_master,
|
|
<br> EVT_direct_slave
|
|
<br> } TStime_type;
|
|
<br>
|
|
<br>
|
|
<br>typedef enum { EVT_time_OK,
|
|
<br> EVT_stream_lost,
|
|
<br> EVT_sync_timeout,
|
|
<br> EVT_ntpLock_lost,
|
|
<br> EVT_tick_fail} TSfault_type;
|
|
<br>
|
|
|
|
</p>
|
|
<p>
|
|
|
|
<br>##############################################
|
|
<br>#### fixes in iocClockRegister.c ####
|
|
<br>##############################################
|
|
<br>## located in
|
|
<br>## "base-3.14.x/src/libCom/osi/os/vxWorks"
|
|
<br>##
|
|
<br>## The main point here is to allow generalTime to install the time
|
|
<br>## providers by calling iocClockRegister() in drvGeneralTime.c
|
|
<br>## Therefore the iocClockRegister() was modified as the following.
|
|
<br>##
|
|
<br>void iocClockRegister(pepicsTimeGetCurrent getCurrent,
|
|
<br> pepicsTimeGetEvent getEvent)
|
|
<br>{
|
|
<br> if(!piocClockPvt) {
|
|
<br> printf("iocClockRegister: iocClock NOT yet initialized\n");
|
|
<br> iocClockInit();
|
|
<br> }
|
|
<br> piocClockPvt->getCurrent = getCurrent;
|
|
<br> piocClockPvt->getEvent = getEvent;
|
|
<br> if(piocClockPvt->getEvent==NULL)
|
|
<br> printf("iocClockRegister: getEvent Not found! ...\n");
|
|
<br> return;
|
|
<br>}
|
|
<br>
|
|
<br>##
|
|
<br>## I added 'else' part to iocClockGetEvent() which is necessary
|
|
<br>## when a record requests the event time upon processing; that
|
|
<br>## means when the TSE field is set to a non-zero event number.
|
|
<br>##
|
|
<br>int iocClockGetEvent(epicsTimeStamp *pDest, int eventNumber)
|
|
<br>{
|
|
<br> if (eventNumber==epicsTimeEventCurrentTime) {
|
|
<br> *pDest = piocClockPvt->clock;
|
|
<br> return(0);
|
|
<br> }
|
|
<br> else {
|
|
<br> epicsTimeGetEvent(pDest,eventNumber);
|
|
<br> return(0);
|
|
<br> }
|
|
<br> return(epicsTimeERROR);
|
|
<br>}
|
|
<br>##############################################
|
|
</p>
|
|
</body>
|
|
<hr noshade size=1><small>
|
|
<span class="printlayout">Author: Babak Kalantari Phone: +41 56 310 5122 Email: babak.kalantari@psi.ch Updated: 11.09.2007 </span>
|
|
Source: /afs/psi.ch/project/epics/webhosting/software/generalTime/EVENT_README.php
|
|
</small>
|
|
</td></tr></table>
|
|
</body></html>
|