SZSPTP ez430-RF2480 1.0

ZigBee Sensor Network with synchronized time and time-stamped measurements.
ptp.c
Go to the documentation of this file.
1 /*
2  * ptp.c
3  *
4  * Date: 19/06/2014
5  * Author: Fernando Biazi Nascimento
6  * Copyright © 2014 Fernando Biazi Nascimento. All rights reserved.
7  *
8  * License of use and copy on file license.txt
9  *
10  */
11 
21 /*
22  * ======== Standard MSP430 includes ========
23  */
24 #include <msp430.h>
25 
26 /*
27  * ======== Includes ========
28  */
29 
30 #include "ptp.h"
31 #include "ptp_util.h"
32 #include "ptp_messages.h"
33 #include "clock.h"
34 #include "uart.h"
35 
36 /*
37  * ======== Constants ========
38  */
39 
40 /*
41  * ======== Macros ========
42  */
43 
44 #define PTP_FLAGRUNNING 0x01
45 
46 /*
47  * ======== Types ========
48  */
49 
50 /*
51  * ======== Global Variables ========
52  */
53 
54 ptp_clock ptpClock;
55 ptp_uinteger64 ptp_meanPathDelay[PTP_NUMBERPORTS];
56 PTP_foreignMasterDS ptp_foreignMaster[PTP_NUMBERPORTS][1];
57 ptp_integer64 ptp_lastAdjust;
58 ptp_uinteger64 ptp_meanDelayAtLastAdjust;
59 PTP_TimeStamp ptp_lastAdjustTime;
60 
61 /*
62  * ======== Local Variables ========
63  */
64 
73 
74 /*
75  * ======== Local Functions ========
76  */
77 
78 
79 /*
80  * ================
81  */
82 
95 void ptp_init() {
96  ptp_uinteger8 portIndex;
97 
98  // ensure that ptp_process won't run before initialization end.
99  ptp_flags &= !PTP_FLAGRUNNING;
100  ptpClock.portDS[0].portState = PTP_PS_INITIALIZING;
101 
102  ptp_lastAdjust = 0;
103  ptp_meanDelayAtLastAdjust = 0;
104  ptp_lastAdjustTime.secondsField.secondsLow = 0;
105  ptp_lastAdjustTime.secondsField.secondsHigh = 0;
106  ptp_lastAdjustTime.nanoSecondsField = 0;
107 
108  ptp_tsTimeout = 255;
109 
110  ptpClock.defaultDS.numberPorts = 1;
111  portIndex = PTP_NUMBERPORTS;
112  while (portIndex) {
113  portIndex--;
114  ptp_meanPathDelay[portIndex] = 0;
115  }
117 }
118 
128 void ptp_initEnd() {
129  ptpClock.defaultDS.clockIdentity = ptp_getClockIdentity();
130  ptpClock.parentDS.parentPortIdentity.clockIdentity =
131  ptpClock.defaultDS.clockIdentity; // 8.2.3.2
132  ptpClock.parentDS.grandMasterIdentity = ptpClock.defaultDS.clockIdentity; // 8.2.3.6
134 }
135 
145 UInt16 ptp_process() {
146  static ptp_uinteger16 runCounter = 0;
147  static ptp_uinteger8 portNumber = 0;
148  ptp_uinteger8 portIndex;
149  clock_timeStamp ts;
150 
151  if ((ptpClock.defaultDS.clockQuality.clockClass == 13)
152  || (ptpClock.defaultDS.clockQuality.clockClass == 14))
153  if ((runCounter & ((1 << PTP_LOG2TSVERIFY) - 1)) == 0)
154  // if External time source, verify timeout
155  // verify timeout
156  if (ptp_tsTimeout == 0) {
157  // Set time source to internal oscillator
158  ptpClock.timePropertiesDS.timeSource =
159  PTP_TS_INTERNAL_OSCILLATOR;
160  } else {
161  // send time stamp message to source
162  if (uart_startFrame(14, 0xE1, 0x04)) {
163  clock_getTime(&ts);
164  uart_sndUInt32(&(ts.seconds.secondsLow));
165  uart_sndUInt16(ts.seconds.secondsHigh);
166  uart_sndUInt32(&(ts.nanoSeconds));
168  uart_endFrame();
169  } else {
170  // decrease timeout
171  ptp_tsTimeout--;
172  }
173  }
174 
175  // Check if protocol is running
176  if (!(ptp_flags & PTP_FLAGRUNNING)) {
177  // STATE_DECISION_EVENT only occur if no port is in the PTP_PS_INITIALIZING state
178  // no processing is made until no port is in this state.
179  portIndex = ptpClock.defaultDS.numberPorts;
180  while (portIndex) {
181  portIndex--;
182  if (ptpClock.portDS[portIndex].portState == PTP_PS_INITIALIZING){
183  runCounter++;
184  return 1000;}
185  }
186  ptp_flags |= PTP_FLAGRUNNING;
187  }
188 
189  // verify need to send messages
190  // timeouts are represented in log value, 0x0 means 2^0 = 1, 0x1 represents 2^1 = 2 and so on.
191  // This intervals must agree with configurations
192  // better prevent simultaneous execution of more than one code that sends messages, specially timed messages.
193  switch (runCounter & ((1 << PTP_LOG2ANNOUNCESYNCPDELEREQ) - 1)) {
194  case 1:
195  // run the STATE_DECISION_EVENT
196  // At least once per announce message transmission interval - 9.2.6.8
198  if (!ptp_MsgAnnounceSnd())
199  return 2;
200  break;
201  case 2:
202  // send PdelayReq to all known neighbors.
203  // 9.5.13.1, 8.2.5.4.4, 9.5.13.2
204  if (portNumber) {
205  portIndex = portNumber - 1;
206  if ((nwk_getNeighborAddress(portNumber) != 0xFFFF)
207  && (ptpClock.portDS[portIndex].delayMechanism == PTP_DM_P2P)) {
208  if (ptp_MsgPdelayReqSnd(portNumber))
209  portNumber = portIndex;
210  } else {
211  portNumber = portIndex;
212  }
213  }
214  if (portNumber)
215  return 50; // this time should be enough to free the cache from previous port message
216  else {
217  portNumber = ptpClock.defaultDS.numberPorts;
218  runCounter++;
219  if (ptpClock.defaultDS.numberPorts == 1) {
220  return 1000 - 50;
221  } else {
222  return 1000 - (50 * PTP_NUMBERPORTS);
223  }
224  }
225  default:
226  break;
227  }
228 
229  runCounter++;
230  return 1000;
231 }
232 
243  return 1;
244 }
245 
257 void ptp_rcvmessage(ptp_octet *pBuf, ptp_uinteger8 portNumber,
258  ptp_uinteger16 size) {
259  // processing semantics: 9.5
260  // formats: 13
261  PTP_TimeStamp ts;
262 
263  // time stamp for event messages
264  ptp_getCurrentTime(&ts);
265 
266  // check version
267  if ((pBuf[1] & 0x0F) != 2)
268  return;
269 
270  // check informed size
271  if (size != ptp_rcvUInt16(&(pBuf[2]))) {
272  return;
273  }
274 
275  // check for message from self. 9.5.2
276  if (ptp_clockIdentityCompare((&pBuf[20]),
277  *(ptpClock.defaultDS.clockIdentity)) == 0)
278  return;
279 
280  // message type
281  switch (pBuf[0] & 0x0F) {
282  case PTP_MSGTYPE_SYNC: // Event
283 
284  break;
285  case PTP_MSGTYPE_DELAY_REQ: // Event
286 
287  break;
288  case PTP_MSGTYPE_PDELAY_REQ: // Event
289  ptp_MsgPdelayReqRcv(pBuf, &ts, portNumber);
290  break;
291  case PTP_MSGTYPE_PDELAY_RESP: // Event
292  ptp_MsgPdelayRespRcv(pBuf, &ts, portNumber);
293  break;
294  case PTP_MSGTYPE_FOLLOW_UP: // General
295 
296  break;
297  case PTP_MSGTYPE_DELAY_RESP: // General
298 
299  break;
300  case PTP_MSGTYPE_PDELAY_RESP_FOLLOW_UP: // General
301 
302  break;
303  case PTP_MSGTYPE_ANNOUNCE: // General
304  ptp_MsgAnnounceRcv(pBuf, portNumber);
305  break;
306  case PTP_MSGTYPE_SIGNALING: // General
307 
308  break;
309  case PTP_MSGTYPE_MANAGEMENT: // General
310 
311  break;
312  default:
313  break;
314  }
315 }
316 
329  ptp_clockAccuracy clockAccuracy, ptp_timeSource timeSource) {
330  clock_setTime((void *) time);
331  ptpClock.defaultDS.clockQuality.clockClass = clockClass;
332  ptpClock.defaultDS.clockQuality.clockAccuracy = clockAccuracy;
333  ptpClock.timePropertiesDS.timeSource = timeSource;
335  if (ptp_flags & PTP_FLAGRUNNING) {
337  }
338 }
339 
340 
349 void ptp_setTickTime(ptp_uinteger32 *newTickSize) {
350  if (*newTickSize)
351  clock_tickSize = *newTickSize;
352 }
353 
354 
363 void ptp_adjNetTime(ptp_integer64 *timeAdjust) {
364  ptp_boolean flags = 0;
365 
366  clock_adjTime(timeAdjust);
367  if (*timeAdjust < 0) {
368  *timeAdjust = -*timeAdjust;
369  flags |= 1;
370  }
371  if (*timeAdjust < 1000000)
372  ptpClock.defaultDS.clockQuality.clockAccuracy = PTP_CA_001MS;
373  else if (*timeAdjust < 10000000)
374  ptpClock.defaultDS.clockQuality.clockAccuracy = PTP_CA_010MS;
375  else if (*timeAdjust < 100000000)
376  ptpClock.defaultDS.clockQuality.clockAccuracy = PTP_CA_100MS;
377  else if (*timeAdjust < 1000000000)
378  ptpClock.defaultDS.clockQuality.clockAccuracy = PTP_CA_001US;
379  else if (*timeAdjust < 10000000000)
380  ptpClock.defaultDS.clockQuality.clockAccuracy = PTP_CA_010S;
381 
382  if (flags & 1) {
383  *timeAdjust = -*timeAdjust;
384  }
386 }
PTP messages interface.
unsigned char ptp_boolean
Definition: ptp_types.h:68
UART interface.
void ptp_clock_initialize()
PTP clock initialization.
Definition: ptp_clock.c:64
ptp_uinteger8 ptp_MsgAnnounceSnd()
Send Announce message.
Definition: ptp_messages.c:469
PTP clock structure.
Definition: ptp_clock.h:65
UInt16 ptp_process()
PTP process.
Definition: ptp.c:145
unsigned long long ptp_uinteger64
Definition: ptp_types.h:125
void ptp_init()
PTP initialization.
Definition: ptp.c:95
ptp_integer8 ptp_clockIdentityCompare(ptp_clockIdentity A, ptp_clockIdentity B)
Clock identity compare.
Definition: ptp_util.c:201
void ptp_initEnd()
PTP initialization completion.
Definition: ptp.c:128
Pdelay_Req message.
Definition: ptp_messages.h:72
Signaling message.
Definition: ptp_messages.h:97
void ptp_MsgPdelayReqRcv(ptp_octet *pBuf, PTP_TimeStamp *t2, ptp_uinteger8 portNumber)
Receive PDelay_Req message.
Definition: ptp_messages.c:313
pear-to-pear
Definition: ptp_types.h:279
void ptp_MsgAnnounceRcv(ptp_octet *pBuf, ptp_uinteger8 portNumber)
Receive Announce message.
Definition: ptp_messages.c:519
UInt32 clock_tickSize
Tick size (ns)
Definition: clock.c:102
long long ptp_integer64
Definition: ptp_types.h:120
Follow_Up message.
Definition: ptp_messages.h:81
Time stamp.
Definition: clock.h:75
Delay_Resp message.
Definition: ptp_messages.h:85
Clock interface.
unsigned long ptp_uinteger32
Definition: ptp_types.h:110
ptp_timeSource
Definition: ptp_types.h:244
ptp_clockIdentity * ptp_getClockIdentity()
Get clock identity.
Definition: ptp_util.c:85
PTP interface.
UInt8 uart_startFrame(UInt8 len, UInt8 cmd0, UInt8 cmd1)
Start frame.
Definition: uart.c:141
Announce message.
Definition: ptp_messages.h:93
UInt8 uart_sndUInt16(UInt16 v)
Send UInt16.
Definition: uart.c:396
PTP functions specific to the implementation.
UInt8 uart_sndUInt32(UInt32 *p)
Send UInt32.
Definition: uart.c:381
UInt16 ptp_processPDelayReq()
Process PDelayReq.
Definition: ptp.c:241
Management message.
Definition: ptp_messages.h:101
Pdelay_Resp_Follow_Up message.
Definition: ptp_messages.h:89
void ptp_state_decision_event()
State decision event.
Definition: ptp_util.c:248
ptp_uinteger8 ptp_tsTimeout
Definition: ptp.c:72
Sync message.
Definition: ptp_messages.h:64
#define PTP_NUMBERPORTS
Definition: ptp_cfg.h:100
#define PTP_LOG2ANNOUNCESYNCPDELEREQ
Definition: ptp_cfg.h:67
unsigned char ptp_uinteger8
Definition: ptp_types.h:90
void ptp_portsSetListening()
Ports set listening.
Definition: ptp_util.c:224
ptp_clockAccuracy
Definition: ptp_types.h:170
void ptp_MsgPdelayReqCheck()
Check for PDelay_Req message.
Definition: ptp_messages.c:365
void ptp_adjNetTime(ptp_integer64 *timeAdjust)
Adjust net time.
Definition: ptp.c:363
void ptp_setNetTime(PTP_TimeStamp *time, ptp_uinteger8 clockClass, ptp_clockAccuracy clockAccuracy, ptp_timeSource timeSource)
Set net time.
Definition: ptp.c:328
void ptp_getCurrentTime(PTP_TimeStamp *dest)
Get cuttent time.
Definition: ptp_util.c:104
ptp_uinteger8 ptp_MsgPdelayReqSnd(ptp_uinteger8 portNumber)
Send PDelay_Req message.
Definition: ptp_messages.c:284
char ptp_octet
Definition: ptp_types.h:137
void ptp_rcvmessage(ptp_octet *pBuf, ptp_uinteger8 portNumber, ptp_uinteger16 size)
Receive message.
Definition: ptp.c:257
void uart_endFrame()
End frame.
Definition: uart.c:165
ptp_uinteger8 ptp_flags
Definition: ptp.c:68
Pdelay_Resp message.
Definition: ptp_messages.h:76
void ptp_setTickTime(ptp_uinteger32 *newTickSize)
Set tick time.
Definition: ptp.c:349
UInt16 nwk_getNeighborAddress(UInt8 portNumber)
Get neighbor address.
Definition: nwk.c:1578
#define PTP_TSTIMEOUT
Definition: ptp_cfg.h:62
#define PTP_LOG2TSVERIFY
Definition: ptp_cfg.h:57
void clock_setTime(clock_timeStamp *sourceTime)
Set time.
Definition: clock.c:237
Delay_Req message.
Definition: ptp_messages.h:68
void ptp_MsgPdelayRespRcv(ptp_octet *pBuf, PTP_TimeStamp *t4, ptp_uinteger8 portNumber)
Receive Pdelay_Resp message.
Definition: ptp_messages.c:425
ptp_uinteger16 ptp_rcvUInt16(ptp_octet *pBuf)
Receive unsigned 16 bits integer.
Definition: ptp_util.c:1043
void clock_adjTime(int64_t *adjValue)
Adjust time.
Definition: clock.c:256
unsigned short ptp_uinteger16
Definition: ptp_types.h:100
void clock_getTime(clock_timeStamp *destTime)
Get time.
Definition: clock.c:218