Commit c81db09e authored by baujc's avatar baujc

Big update ...

- New L1Sync and PTP servo calculation (delayAsym,...)
- Make function calls more uniforms between extensions
- refactoring
- Add a new state machine to enable/disable an extension and provide
only PTP support: New timer, new hooks, ...
- Fix bug in time format conversion
- Code removed when an extension is not required (#ifdef XXX )
- Align the PTP and L1Sync servo calculation (shared fct, same
calculation,...)
- Force only one servo running at a given time for a given instance
- New servo reset hook : called by main loop
- Add function to converte a time into a string
- Force to stay in FAULTY state during 60s
- Optimise function wrs_enable_timing_output()
parent d456d2fd
...@@ -69,7 +69,8 @@ static int run_all_state_machines(struct pp_globals *ppg) ...@@ -69,7 +69,8 @@ static int run_all_state_machines(struct pp_globals *ppg)
ppi->frgn_rec_num = 0; ppi->frgn_rec_num = 0;
ppi->frgn_rec_best = -1; ppi->frgn_rec_best = -1;
if (ppg->ebest_idx == ppi->port_idx) if (ppg->ebest_idx == ppi->port_idx)
wr_servo_reset(ppi); if( ppi->ext_hooks->servo_reset)
(*ppi->ext_hooks->servo_reset)(ppi);
} }
} }
......
...@@ -35,9 +35,13 @@ int wrs_read_calibration_data(struct pp_instance *ppi, ...@@ -35,9 +35,13 @@ int wrs_read_calibration_data(struct pp_instance *ppi,
* way as the HAL itself was doing to fill the RPC structure. * way as the HAL itself was doing to fill the RPC structure.
* Formulas copied from libwr/hal_shmem.c (get_exported_state). * Formulas copied from libwr/hal_shmem.c (get_exported_state).
*/ */
#if CONFIG_PROFILE_WR == 1
port_fix_alpha = FIX_ALPHA_TWO_POW_FRACBITS * port_fix_alpha = FIX_ALPHA_TWO_POW_FRACBITS *
((p->calib.sfp.alpha + 1.0) / (p->calib.sfp.alpha + 2.0) ((p->calib.sfp.alpha + 1.0) / (p->calib.sfp.alpha + 2.0)
- 0.5); - 0.5);
#else
port_fix_alpha =0;
#endif
if ( delta_tx || delta_rx) { if ( delta_tx || delta_rx) {
port_delta_tx = p->calib.delta_tx_phy port_delta_tx = p->calib.delta_tx_phy
...@@ -64,15 +68,20 @@ int wrs_read_calibration_data(struct pp_instance *ppi, ...@@ -64,15 +68,20 @@ int wrs_read_calibration_data(struct pp_instance *ppi,
int wrs_read_correction_data(struct pp_instance *ppi, int64_t *fiber_fix_alpha, int wrs_read_correction_data(struct pp_instance *ppi, int64_t *fiber_fix_alpha,
int32_t *clock_period_ps, uint32_t *bit_slide_ps) { int32_t *clock_period_ps, uint32_t *bit_slide_ps) {
double alpha;
int32_t port_cP; int32_t port_cP;
wrs_read_calibration_data(ppi, NULL, NULL,NULL, &port_cP, bit_slide_ps); wrs_read_calibration_data(ppi, NULL, NULL,NULL, &port_cP, bit_slide_ps);
if(fiber_fix_alpha) { if(fiber_fix_alpha) {
#if CONFIG_PROFILE_WR == 1
double alpha;
alpha = ((double) ppi->asymmetryCorrectionPortDS.scaledDelayCoefficient)/REL_DIFF_TWO_POW_FRACBITS; alpha = ((double) ppi->asymmetryCorrectionPortDS.scaledDelayCoefficient)/REL_DIFF_TWO_POW_FRACBITS;
*fiber_fix_alpha = FIX_ALPHA_TWO_POW_FRACBITS * ((alpha + 1.0) / (alpha + 2.0) - 0.5); *fiber_fix_alpha = FIX_ALPHA_TWO_POW_FRACBITS * ((alpha + 1.0) / (alpha + 2.0) - 0.5);
#else
*fiber_fix_alpha=0;
#endif
} }
if(clock_period_ps) if(clock_period_ps)
*clock_period_ps = port_cP; /* REF_CLOCK_PERIOD_PS */ *clock_period_ps = port_cP; /* REF_CLOCK_PERIOD_PS */
return WRH_HW_CALIB_OK; return WRH_HW_CALIB_OK;
......
...@@ -102,15 +102,18 @@ static __inline__ double calculateDelayAsymCoefficient(double delayCoefficient ...@@ -102,15 +102,18 @@ static __inline__ double calculateDelayAsymCoefficient(double delayCoefficient
static void enable_asymmetryCorrection(struct pp_instance *ppi, Boolean enable ) { static void enable_asymmetryCorrection(struct pp_instance *ppi, Boolean enable ) {
if ( (ppi->asymmetryCorrectionPortDS.enable=enable)==TRUE ) { if ( (ppi->asymmetryCorrectionPortDS.enable=enable)==TRUE ) {
/* Enabled: The delay asymmetry will be calculated */ /* Enabled: The delay asymmetry will be calculated */
ppi->asymmetryCorrectionPortDS.scaledDelayCoefficient= double delayCoefficient;
ppi->cfg.scaledDelayCoefficient != 0 ?
ppi->cfg.scaledDelayCoefficient : if ( ppi->cfg.scaledDelayCoefficient != 0) {
(RelativeDifference)(ppi->cfg.delayCoefficient * REL_DIFF_TWO_POW_FRACBITS); ppi->asymmetryCorrectionPortDS.scaledDelayCoefficient=ppi->cfg.scaledDelayCoefficient;
ppi->portDS->delayAsymCoeff=(RelativeDifference)(calculateDelayAsymCoefficient(ppi->cfg.delayCoefficient) * REL_DIFF_TWO_POW_FRACBITS); delayCoefficient=ppi->cfg.scaledDelayCoefficient/REL_DIFF_TWO_POW_FRACBITS;
} else { } else {
/* Disabled: The delay asymmetry will be provided by the config (constantAsymmetry) */ ppi->asymmetryCorrectionPortDS.scaledDelayCoefficient=(RelativeDifference)(ppi->cfg.delayCoefficient * REL_DIFF_TWO_POW_FRACBITS);
ppi->asymmetryCorrectionPortDS.constantAsymmetry=picos_to_interval(ppi->cfg.constantAsymmetry_ps); delayCoefficient=ppi->cfg.delayCoefficient;
}
ppi->portDS->delayAsymCoeff=(RelativeDifference)(calculateDelayAsymCoefficient(delayCoefficient) * REL_DIFF_TWO_POW_FRACBITS);
} }
ppi->asymmetryCorrectionPortDS.constantAsymmetry=picos_to_interval(ppi->cfg.constantAsymmetry_ps);
} }
int main(int argc, char **argv) int main(int argc, char **argv)
...@@ -266,9 +269,9 @@ int main(int argc, char **argv) ...@@ -266,9 +269,9 @@ int main(int argc, char **argv)
Boolean configured=FALSE; Boolean configured=FALSE;
#if CONFIG_PROFILE_HA == 1 #if CONFIG_PROFILE_HA == 1
sprintf(s, "port %i; iface wri%i; proto raw; profile ha", i + 1, i + 1); sprintf(s, "port %i; iface wri%i; proto raw; profile ha", i + 1, i + 1);
configured=TRUE;
#endif #endif
#if CONFIG_PROFILE_WR == 1 #if CONFIG_PROFILE_WR == 1
configured=TRUE;
if ( ! configured ) if ( ! configured )
sprintf(s, "port %i; iface wri%i; proto raw; profile wr", i + 1, i + 1); sprintf(s, "port %i; iface wri%i; proto raw; profile wr", i + 1, i + 1);
#endif #endif
...@@ -288,6 +291,7 @@ int main(int argc, char **argv) ...@@ -288,6 +291,7 @@ int main(int argc, char **argv)
ppi->portDS = wrs_shm_alloc(ppsi_head, sizeof(*ppi->portDS)); ppi->portDS = wrs_shm_alloc(ppsi_head, sizeof(*ppi->portDS));
ppi->servo = wrs_shm_alloc(ppsi_head, sizeof(*ppi->servo)); ppi->servo = wrs_shm_alloc(ppsi_head, sizeof(*ppi->servo));
ppi->ext_hooks=&pp_hooks; /* Default value. Can be overwritten by an extension */ ppi->ext_hooks=&pp_hooks; /* Default value. Can be overwritten by an extension */
ppi->ptp_support=FALSE;
if (ppi->portDS) { if (ppi->portDS) {
switch (ppi->cfg.profile) { switch (ppi->cfg.profile) {
#if CONFIG_PROFILE_WR == 1 #if CONFIG_PROFILE_WR == 1
...@@ -324,9 +328,11 @@ int main(int argc, char **argv) ...@@ -324,9 +328,11 @@ int main(int argc, char **argv)
case PPSI_PROFILE_PTP : case PPSI_PROFILE_PTP :
/* Do not take care of L1SYNC */ /* Do not take care of L1SYNC */
enable_asymmetryCorrection(ppi,ppi->cfg.asymmetryCorrectionEnable); enable_asymmetryCorrection(ppi,ppi->cfg.asymmetryCorrectionEnable);
ppi->protocol_extension=PPSI_EXT_NONE;
break; break;
#if CONFIG_PROFILE_CUSTOM == 1 #if CONFIG_PROFILE_CUSTOM == 1
case PPSI_PROFILE_CUSTOM : case PPSI_PROFILE_CUSTOM :
ppi->protocol_extension=PPSI_EXT_NONE; /* can be changed ...*/
#if CONFIG_EXT_L1SYNC #if CONFIG_EXT_L1SYNC
if (ppi->cfg.l1SyncEnabled ) { if (ppi->cfg.l1SyncEnabled ) {
if ( !enable_l1Sync(ppi,TRUE) ) if ( !enable_l1Sync(ppi,TRUE) )
......
...@@ -276,7 +276,25 @@ int pp_state_machine(struct pp_instance *ppi, void *buf, int len) ...@@ -276,7 +276,25 @@ int pp_state_machine(struct pp_instance *ppi, void *buf, int len)
if (ppi->state != ppi->next_state) if (ppi->state != ppi->next_state)
return pp_leave_current_state(ppi); return pp_leave_current_state(ppi);
if (!len) if (len) {
if ( ppi->link_state == PP_LSTATE_PROTOCOL_DETECTION ) {
if ( ppi->ptp_msg_received==FALSE ) {
/* First frame received since instance initialization */
int tmo;
ppi->ptp_msg_received=TRUE;
if ( ppi->ext_hooks->get_tmo_lstate_detection!=NULL)
tmo=(*ppi->ext_hooks->get_tmo_lstate_detection)(ppi);
else
tmo= ppi->timeouts[PP_TO_ANN_RECEIPT].initValueMs;
__pp_timeout_set(ppi,PP_TO_PROT_STATE, tmo);
}
}
if ( !ppi->ext_enabled && ppi->link_state==PP_LSTATE_PROTOCOL_DETECTION) {
/* Ptp protocol only */
ppi->link_state= PP_LSTATE_IN_PROGRESS;
}
} else
ppi->received_ptp_header.messageType = PPM_NO_MESSAGE; ppi->received_ptp_header.messageType = PPM_NO_MESSAGE;
err = ip->f1(ppi, buf, len); err = ip->f1(ppi, buf, len);
...@@ -288,6 +306,19 @@ int pp_state_machine(struct pp_instance *ppi, void *buf, int len) ...@@ -288,6 +306,19 @@ int pp_state_machine(struct pp_instance *ppi, void *buf, int len)
if (ppi->state != ppi->next_state) if (ppi->state != ppi->next_state)
return pp_leave_current_state(ppi); return pp_leave_current_state(ppi);
/* Check protocol state */
if ( ppi->link_state==PP_LSTATE_PROTOCOL_DETECTION ) {
if ( ppi->ptp_msg_received && pp_timeout(ppi, PP_TO_PROT_STATE) ) {
if ( ppi->ptp_support && ppi->ext_enabled ) {
ppi->ext_enabled=FALSE;
ppi->ptp_msg_received=FALSE;
} else
ppi->link_state=PP_LSTATE_FAILURE;
}
}
if (ppi->link_state==PP_LSTATE_FAILURE ) {
}
/* run bmc independent of state, and since not message driven do this /* run bmc independent of state, and since not message driven do this
* here 9.2.6.8 */ * here 9.2.6.8 */
if (pp_timeout(ppi, PP_TO_BMC)) { if (pp_timeout(ppi, PP_TO_BMC)) {
...@@ -307,6 +338,11 @@ int pp_state_machine(struct pp_instance *ppi, void *buf, int len) ...@@ -307,6 +338,11 @@ int pp_state_machine(struct pp_instance *ppi, void *buf, int len)
/* Run the extension state machine. The extension can provide its own time-out */ /* Run the extension state machine. The extension can provide its own time-out */
if ( ppi->ext_hooks->run_ext_state_machine) { if ( ppi->ext_hooks->run_ext_state_machine) {
int delay = ppi->ext_hooks->run_ext_state_machine(ppi); int delay = ppi->ext_hooks->run_ext_state_machine(ppi);
if ( ppi->link_state==PP_LSTATE_FAILURE && ppi->ptp_support && ppi->ext_enabled ) {
ppi->ext_enabled=FALSE;
ppi->link_state=PP_LSTATE_PROTOCOL_DETECTION;
}
ppi->next_delay= (delay < ppi->next_delay) ? delay : ppi->next_delay; ppi->next_delay= (delay < ppi->next_delay) ? delay : ppi->next_delay;
} }
......
...@@ -29,12 +29,6 @@ ...@@ -29,12 +29,6 @@
#define WRH_HW_CALIB_ERROR -1 #define WRH_HW_CALIB_ERROR -1
#define WRH_HW_CALIB_NOT_FOUND -3 #define WRH_HW_CALIB_NOT_FOUND -3
enum {
WRH_SERVO_ENTER, WRH_SERVO_LEAVE
};
#define FIX_ALPHA_FRACBITS 40 #define FIX_ALPHA_FRACBITS 40
#define FIX_ALPHA_FRACBITS_AS_FLOAT 40.0 #define FIX_ALPHA_FRACBITS_AS_FLOAT 40.0
...@@ -70,7 +64,6 @@ struct wrh_operations { ...@@ -70,7 +64,6 @@ struct wrh_operations {
unsigned int calibrationPatternLen); unsigned int calibrationPatternLen);
int (*calib_pattern_disable)(struct pp_instance *ppi); int (*calib_pattern_disable)(struct pp_instance *ppi);
int (*enable_timing_output)(struct pp_instance *ppi, int enable); int (*enable_timing_output)(struct pp_instance *ppi, int enable);
int (*servo_hook)(struct pp_instance *ppi, int action);
int (*read_corr_data)(struct pp_instance *ppi, int64_t *fixAlpha, int (*read_corr_data)(struct pp_instance *ppi, int64_t *fixAlpha,
int32_t *clock_period, uint32_t *bit_slide_ps); int32_t *clock_period, uint32_t *bit_slide_ps);
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
/* general purpose constants */ /* general purpose constants */
#define PP_NSEC_PER_SEC (1000*1000*1000) #define PP_NSEC_PER_SEC (1000*1000*1000)
#define PP_PSEC_PER_SEC ((int64_t)1000*(int64_t)PP_NSEC_PER_SEC)
/* implementation specific constants */ /* implementation specific constants */
#define PP_MAX_LINKS 64 #define PP_MAX_LINKS 64
...@@ -112,6 +113,7 @@ enum pp_timeouts { ...@@ -112,6 +113,7 @@ enum pp_timeouts {
PP_TO_ANN_SEND, PP_TO_ANN_SEND,
PP_TO_FAULT, PP_TO_FAULT,
PP_TO_QUALIFICATION, PP_TO_QUALIFICATION,
PP_TO_PROT_STATE,
/* Two timeouts for the protocol extension */ /* Two timeouts for the protocol extension */
PP_TO_EXT_0, PP_TO_EXT_0,
PP_TO_EXT_1, PP_TO_EXT_1,
......
...@@ -52,7 +52,9 @@ typedef struct _UInteger64 { /*/* TODO : Should be replaced by UInteger64 */ ...@@ -52,7 +52,9 @@ typedef struct _UInteger64 { /*/* TODO : Should be replaced by UInteger64 */
/* Page 19 :the time interval is expressed in units of nanoseconds and multiplied by 2 +16 */ /* Page 19 :the time interval is expressed in units of nanoseconds and multiplied by 2 +16 */
#define TIME_INTERVAL_FRACBITS 16 #define TIME_INTERVAL_FRACBITS 16
#define TIME_INTERVAL_FRACMASK 0xFFFF
#define TIME_INTERVAL_FRACBITS_AS_FLOAT 16.0 #define TIME_INTERVAL_FRACBITS_AS_FLOAT 16.0
#define TIME_INTERVAL_ROUNDING_VALUE (1<<(TIME_INTERVAL_FRACBITS-1))
/* Min/max value expressed in picos (int64_t) which can be stored in a TimeInterval type */ /* Min/max value expressed in picos (int64_t) which can be stored in a TimeInterval type */
#define TIME_INTERVAL_MIN_PICOS_VALUE_AS_INT64 ((int64_t) 0xFE0C000000000000) #define TIME_INTERVAL_MIN_PICOS_VALUE_AS_INT64 ((int64_t) 0xFE0C000000000000)
...@@ -74,6 +76,7 @@ typedef struct Timestamp { /* page 13 (33) -- no typedef expected */ ...@@ -74,6 +76,7 @@ typedef struct Timestamp { /* page 13 (33) -- no typedef expected */
#define REL_DIFF_FRACBITS 62 #define REL_DIFF_FRACBITS 62
#define REL_DIFF_FRACBITS_AS_FLOAT 62.0 #define REL_DIFF_FRACBITS_AS_FLOAT 62.0
#define REL_DIFF_TWO_POW_FRACBITS ((double)4.611686018427388E18) /* double value returned by pow(2.0,62.0) */ #define REL_DIFF_TWO_POW_FRACBITS ((double)4.611686018427388E18) /* double value returned by pow(2.0,62.0) */
#define REL_DIFF_FRACMASK 0x3fffffffffffffff
/* Min/max values for RelativeDifference type */ /* Min/max values for RelativeDifference type */
#define RELATIVE_DIFFERENCE_MIN_VALUE INT64_MIN #define RELATIVE_DIFFERENCE_MIN_VALUE INT64_MIN
......
...@@ -105,21 +105,38 @@ struct pp_avg_fltr { ...@@ -105,21 +105,38 @@ struct pp_avg_fltr {
#define PP_SERVO_FLAG_VALID (1<<0) #define PP_SERVO_FLAG_VALID (1<<0)
#define PP_SERVO_FLAG_WAIT_HW (1<<1) #define PP_SERVO_FLAG_WAIT_HW (1<<1)
struct pp_servo { #define PP_SERVO_RESET_DATA_SIZE (sizeof(struct pp_servo)-offsetof(struct pp_servo,reset_address))
int state; #define PP_SERVO_RESET_DATA(servo) memset(&servo->reset_address,0,PP_SERVO_RESET_DATA_SIZE);
struct pp_time delayMS; struct pp_servo {
struct pp_time delaySM; /* ptp servo specific data */
long long obs_drift; long long obs_drift;
struct pp_avg_fltr mpd_fltr; struct pp_avg_fltr mpd_fltr;
struct pp_time meanDelay;
struct pp_time offsetFromMaster;
/* diagnostic data */ /* Data shared with extension servo */
struct pp_time delayMM; /* Shared with extension servo */
struct pp_time delayMS; /* Shared with extension servo */
struct pp_time meanDelay; /* Shared with extension servo */
struct pp_time offsetFromMaster; /* Shared with extension servo */
unsigned long flags; /* PP_SERVO_FLAG_INVALID, PP_SERVO_FLAG_VALID, ...*/ unsigned long flags; /* PP_SERVO_FLAG_INVALID, PP_SERVO_FLAG_VALID, ...*/
uint32_t update_count; /* incremented each time the servo is running */
/* Data used only by extensions */
int state;
char servo_state_name[32]; /* Updated by the servo itself */ char servo_state_name[32]; /* Updated by the servo itself */
/*
* ----- All data after this line will be cleared during by a servo initialization
*/
int reset_address;
/* Data shared with extension servo */
uint32_t update_count; /* incremented each time the servo is running */
struct pp_time update_time; /* Last updated time of the servo */
struct pp_time t1, t2, t3, t4, t5, t6;
/* ptp servo specific data */
int servo_locked; /* TRUE when servo is locked. This info can be used by HAL */ int servo_locked; /* TRUE when servo is locked. This info can be used by HAL */
int got_sync; /* True when T1/T2 are available */
}; };
enum { /* The two sockets. They are called "net path" for historical reasons */ enum { /* The two sockets. They are called "net path" for historical reasons */
...@@ -177,6 +194,17 @@ typedef struct { ...@@ -177,6 +194,17 @@ typedef struct {
unsigned long tmo; unsigned long tmo;
} t_timeOutConfig; } t_timeOutConfig;
/*
* This enumeration correspond to the protocol state of a pp_instance.
* It is used to decide which instance must be active on a given port.
*/
typedef enum {
PP_LSTATE_PROTOCOL_DETECTION, /* Checking if the peer instance is using the same protocol */
PP_LSTATE_IN_PROGRESS, /* Right protocol detected. Try to establish the link with peer instance */
PP_LSTATE_LINKED, /* Link with peer well established */
PP_LSTATE_FAILURE /* Impossible to connect correctly to a peer instance */
} pp_link_state;
/* /*
* Structure for the individual ppsi link * Structure for the individual ppsi link
*/ */
...@@ -258,7 +286,10 @@ struct pp_instance { ...@@ -258,7 +286,10 @@ struct pp_instance {
Boolean received_dresp; /* Count the number of delay response messages received for a given delay request */ Boolean received_dresp; /* Count the number of delay response messages received for a given delay request */
Boolean received_dresp_fup; /* Count the number of delay response follow up messages received for a given delay request */ Boolean received_dresp_fup; /* Count the number of delay response follow up messages received for a given delay request */
#endif #endif
Boolean ptp_msg_received; /* Use to detect reception of a ptp message after an ppsi instance initialization */
Boolean ptp_support; /* True if allow pure PTP support */
Boolean ext_enabled; /* True if the extension is enabled */
pp_link_state link_state;
}; };
/* The following things used to be bit fields. Other flags are now enums */ /* The following things used to be bit fields. Other flags are now enums */
......
#ifndef __PPSI_PP_TIME_H__ #ifndef __PPSI_PP_TIME_H__
#define __PPSI_PP_TIME_H__ #define __PPSI_PP_TIME_H__
#define TIME_FRACBITS 16
#define TIME_FRACMASK 0xFFFF
#define TIME_FRACBITS_AS_FLOAT 16.0
#define TIME_ROUNDING_VALUE (1<<(TIME_FRACBITS-1))
/* Everything internally uses this time format, *signed* */ /* Everything internally uses this time format, *signed* */
struct pp_time { struct pp_time {
int64_t secs; int64_t secs;
......
...@@ -213,8 +213,8 @@ struct pp_ext_hooks { ...@@ -213,8 +213,8 @@ struct pp_ext_hooks {
void (*s1)(struct pp_instance *ppi, struct pp_frgn_master *frgn_master); void (*s1)(struct pp_instance *ppi, struct pp_frgn_master *frgn_master);
int (*execute_slave)(struct pp_instance *ppi); int (*execute_slave)(struct pp_instance *ppi);
int (*handle_announce)(struct pp_instance *ppi); int (*handle_announce)(struct pp_instance *ppi);
int (*handle_sync)(struct pp_instance *ppi, struct pp_time *orig); int (*handle_sync)(struct pp_instance *ppi);
int (*handle_followup)(struct pp_instance *ppi, struct pp_time *orig); int (*handle_followup)(struct pp_instance *ppi);
int (*handle_preq) (struct pp_instance * ppi); int (*handle_preq) (struct pp_instance * ppi);
int (*handle_presp) (struct pp_instance * ppi); int (*handle_presp) (struct pp_instance * ppi);
int (*handle_signaling) (struct pp_instance * ppi, void *buf, int len); int (*handle_signaling) (struct pp_instance * ppi, void *buf, int len);
...@@ -224,8 +224,14 @@ struct pp_ext_hooks { ...@@ -224,8 +224,14 @@ struct pp_ext_hooks {
int (*state_decision)(struct pp_instance *ppi, int next_state); int (*state_decision)(struct pp_instance *ppi, int next_state);
void (*state_change)(struct pp_instance *ppi); void (*state_change)(struct pp_instance *ppi);
int (*run_ext_state_machine) (struct pp_instance *ppi); int (*run_ext_state_machine) (struct pp_instance *ppi);
void (*servo_reset)(struct pp_instance *ppi);
/* If the extension requires hardware support for precise time stamp, returns 1 */
int (*require_precise_timestamp)(struct pp_instance *ppi);
int (*get_tmo_lstate_detection) (struct pp_instance *ppi);
}; };
#define is_ext_hook_available(p, c) ( /*p->ext_enabled && */ p->ext_hooks->c)
/* /*
* Network methods are encapsulated in a structure, so each arch only needs * Network methods are encapsulated in a structure, so each arch only needs
* to provide that structure. This simplifies management overall. * to provide that structure. This simplifies management overall.
...@@ -508,9 +514,12 @@ extern int f_simple_int(struct pp_argline *l, int lineno, ...@@ -508,9 +514,12 @@ extern int f_simple_int(struct pp_argline *l, int lineno,
/* Servo */ /* Servo */
extern void pp_servo_init(struct pp_instance *ppi); extern void pp_servo_init(struct pp_instance *ppi);
extern void pp_servo_got_sync(struct pp_instance *ppi); /* got t1 and t2 */ extern void pp_servo_got_sync(struct pp_instance *ppi); /* got t1 and t2 */
extern void pp_servo_got_resp(struct pp_instance *ppi); /* got all t1..t4 */ extern int pp_servo_got_resp(struct pp_instance *ppi); /* got all t1..t4 */
extern void pp_servo_got_psync(struct pp_instance *ppi); /* got t1 and t2 */ extern void pp_servo_got_psync(struct pp_instance *ppi); /* got t1 and t2 */
extern void pp_servo_got_presp(struct pp_instance *ppi); /* got all t3..t6 */ extern int pp_servo_got_presp(struct pp_instance *ppi); /* got all t3..t6 */
extern int pp_servo_calculate_delays(struct pp_instance *ppi);
extern void pp_servo_apply_faulty_stamp(struct pp_servo *s, struct pp_time *faulty_stamps, int index);
/* bmc.c */ /* bmc.c */
extern void bmc_m1(struct pp_instance *ppi); extern void bmc_m1(struct pp_instance *ppi);
...@@ -554,11 +563,13 @@ extern void msg_unpack_pdelay_resp(void *buf, MsgPDelayResp * presp); ...@@ -554,11 +563,13 @@ extern void msg_unpack_pdelay_resp(void *buf, MsgPDelayResp * presp);
extern void msg_unpack_pdelay_req(void *buf, MsgPDelayReq * pdelay_req); extern void msg_unpack_pdelay_req(void *buf, MsgPDelayReq * pdelay_req);
/* each of them returns 0 if ok, -1 in case of error in send, 1 if stamp err */ /* each of them returns 0 if ok, -1 in case of error in send, 1 if stamp err */
#define PP_SEND_OK 0 typedef enum {
#define PP_SEND_ERROR -1 PP_SEND_OK=0,
#define PP_SEND_NO_STAMP 1 PP_SEND_ERROR=-1,
#define PP_SEND_DROP -2 PP_SEND_NO_STAMP=1,
#define PP_RECV_DROP PP_SEND_DROP PP_SEND_DROP=-2,
PP_RECV_DROP=PP_SEND_DROP
}pp_send_status;
extern void *msg_copy_header(MsgHeader *dest, MsgHeader *src); /* REMOVE ME!! */ extern void *msg_copy_header(MsgHeader *dest, MsgHeader *src); /* REMOVE ME!! */
extern int msg_issue_announce(struct pp_instance *ppi); extern int msg_issue_announce(struct pp_instance *ppi);
...@@ -587,7 +598,9 @@ extern void picos_to_pp_time(int64_t picos, struct pp_time *ts); ...@@ -587,7 +598,9 @@ extern void picos_to_pp_time(int64_t picos, struct pp_time *ts);
extern void pp_time_hardwarize(struct pp_time *time, int clock_period_ps,int32_t *ticks, int32_t *picos); extern void pp_time_hardwarize(struct pp_time *time, int clock_period_ps,int32_t *ticks, int32_t *picos);
extern int64_t interval_to_picos(TimeInterval interval); extern int64_t interval_to_picos(TimeInterval interval);
extern int is_timestamps_incorrect(struct pp_instance *ppsi, int *err_count, int ts_mask); extern int is_timestamps_incorrect(struct pp_instance *ppsi, int *err_count, int ts_mask);
extern char *time_to_string(struct pp_time *t);
extern char *interval_to_string(TimeInterval time);
extern char *relative_interval_to_string(TimeInterval time);
/* /*
* The state machine itself is an array of these structures. * The state machine itself is an array of these structures.
......
...@@ -6,6 +6,9 @@ ...@@ -6,6 +6,9 @@
*/ */
#include <limits.h> #include <limits.h>
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#include <ppsi/ppsi.h> #include <ppsi/ppsi.h>
void normalize_pp_time(struct pp_time *t) void normalize_pp_time(struct pp_time *t)
...@@ -38,17 +41,30 @@ void normalize_pp_time(struct pp_time *t) ...@@ -38,17 +41,30 @@ void normalize_pp_time(struct pp_time *t)
/* Add a TimeInterval to a pp_time */ /* Add a TimeInterval to a pp_time */
void pp_time_add_interval(struct pp_time *t1, TimeInterval t2) void pp_time_add_interval(struct pp_time *t1, TimeInterval t2)
{ {
t1->scaled_nsecs += t2; struct pp_time t = {
normalize_pp_time(t1); .secs=0,
.scaled_nsecs=t2
};
normalize_pp_time(&t);
pp_time_add(t1,&t);
} }
/* Substract a TimeInterval to a pp_time */ /* Substract a TimeInterval to a pp_time */
void pp_time_sub_interval(struct pp_time *t1, TimeInterval t2) void pp_time_sub_interval(struct pp_time *t1, TimeInterval t2)
{ {
t1->scaled_nsecs -= t2; struct pp_time t = {
normalize_pp_time(t1); .secs=0,
.scaled_nsecs=t2
};
normalize_pp_time(&t);
pp_time_sub(t1,&t);
} }
#define IS_ADD_WILL_OVERFLOW(a,b) \
( (((a > 0) && (b > INT64_MAX - a))) ||\
(((a < 0) && (b < INT64_MIN - a))) \
)
void pp_time_add(struct pp_time *t1, struct pp_time *t2) void pp_time_add(struct pp_time *t1, struct pp_time *t2)
{ {
t1->secs += t2->secs; t1->secs += t2->secs;
...@@ -56,6 +72,11 @@ void pp_time_add(struct pp_time *t1, struct pp_time *t2) ...@@ -56,6 +72,11 @@ void pp_time_add(struct pp_time *t1, struct pp_time *t2)
normalize_pp_time(t1); normalize_pp_time(t1);
} }
#define IS_SUB_WILL_OVERFLOW(a,b) \
( ((b < 0) && (a > INT64_MAX + b)) ||\
((b > 0) && (a < INT64_MIN + b)) \
)
void pp_time_sub(struct pp_time *t1, struct pp_time *t2) void pp_time_sub(struct pp_time *t1, struct pp_time *t2)
{ {
t1->secs -= t2->secs; t1->secs -= t2->secs;
...@@ -76,28 +97,28 @@ void pp_time_div2(struct pp_time *t) ...@@ -76,28 +97,28 @@ void pp_time_div2(struct pp_time *t)
int64_t pp_time_to_picos(struct pp_time *ts) int64_t pp_time_to_picos(struct pp_time *ts)
{ {
return ts->secs * PP_NSEC_PER_SEC return ts->secs * PP_PSEC_PER_SEC
+ ((ts->scaled_nsecs * 1000 + 0x8000) >> TIME_INTERVAL_FRACBITS); + ((ts->scaled_nsecs * 1000 + TIME_ROUNDING_VALUE) >> TIME_FRACBITS);
} }
void picos_to_pp_time(int64_t picos, struct pp_time *ts) void picos_to_pp_time(int64_t picos, struct pp_time *ts)
{ {
uint64_t sec, nsec; uint64_t sec, nsec;
int phase;
int sign = (picos < 0 ? -1 : 1); int sign = (picos < 0 ? -1 : 1);
picos *= sign; picos *= sign;
nsec = picos; sec=picos/PP_PSEC_PER_SEC;
phase = __div64_32(&nsec, 1000); picos-=sec*PP_PSEC_PER_SEC;
sec = nsec; nsec = picos/1000;
picos-=nsec*1000;
ts->scaled_nsecs = ((int64_t)__div64_32(&sec, PP_NSEC_PER_SEC)) << TIME_INTERVAL_FRACBITS; ts->scaled_nsecs = nsec << TIME_FRACBITS;
ts->scaled_nsecs += (phase << TIME_INTERVAL_FRACBITS) / 1000; ts->scaled_nsecs += (picos << TIME_FRACBITS) / 1000;
ts->scaled_nsecs *= sign; ts->scaled_nsecs *= sign;
ts->secs = sec * sign; ts->secs = sec * sign;
} }
#if 0
/* "Hardwarizes" the timestamp - e.g. makes the nanosecond field a multiple /* "Hardwarizes" the timestamp - e.g. makes the nanosecond field a multiple
* of 8/16ns cycles and puts the extra nanoseconds in the picos result */ * of 8/16ns cycles and puts the extra nanoseconds in the picos result */
void pp_time_hardwarize(struct pp_time *time, int clock_period_ps, void pp_time_hardwarize(struct pp_time *time, int clock_period_ps,
...@@ -105,6 +126,10 @@ void pp_time_hardwarize(struct pp_time *time, int clock_period_ps, ...@@ -105,6 +126,10 @@ void pp_time_hardwarize(struct pp_time *time, int clock_period_ps,
{ {
int32_t s, ns, ps, clock_ns; int32_t s, ns, ps, clock_ns;
if ( clock_period_ps <= 0 ) {
pp_error("%s : Invalid clock period %d\n",__func__, clock_period_ps);
exit(-1);
}
/* clock_period_ps *must* be a multiple of 1000 -- assert()? */ /* clock_period_ps *must* be a multiple of 1000 -- assert()? */
clock_ns = clock_period_ps / 1000; clock_ns = clock_period_ps / 1000;
...@@ -139,7 +164,26 @@ void pp_time_hardwarize(struct pp_time *time, int clock_period_ps, ...@@ -139,7 +164,26 @@ void pp_time_hardwarize(struct pp_time *time, int clock_period_ps,
*ticks = ns; *ticks = ns;
*picos = ps; *picos = ps;
} }
#else
/* "Hardwarizes" the timestamp - e.g. makes the nanosecond field a multiple
* of 8/16ns cycles and puts the extra nanoseconds in the picos result */
void pp_time_hardwarize(struct pp_time *time, int clock_period_ps,
int32_t *ticks, int32_t *picos)
{
int64_t ps, adj_ps;
int32_t sign=(time->scaled_nsecs<0) ? -1 : 1;
int64_t scaled_nsecs=time->scaled_nsecs*sign;
if ( clock_period_ps <= 0 ) {
pp_error("%s : Invalid clock period %d\n",__func__, clock_period_ps);
return;
}
ps = (scaled_nsecs * 1000L+TIME_INTERVAL_ROUNDING_VALUE) >> TIME_INTERVAL_FRACBITS; /* now picoseconds 0..999 -- positive*/
adj_ps=ps - ps%clock_period_ps;
*picos=(int32_t)(ps-adj_ps)*sign;
*ticks = (int32_t)(adj_ps/1000)*sign;
}
#endif
TimeInterval pp_time_to_interval(struct pp_time *ts) TimeInterval pp_time_to_interval(struct pp_time *ts)
{ {
...@@ -165,7 +209,7 @@ TimeInterval picos_to_interval(int64_t picos) ...@@ -165,7 +209,7 @@ TimeInterval picos_to_interval(int64_t picos)
int sign = (picos < 0 ? -1 : 1); int sign = (picos < 0 ? -1 : 1);
picos *= sign; picos *= sign;
scaled_ns=(picos/1000) << TIME_INTERVAL_FRACBITS; /* Calculate nanos */ scaled_ns=(picos/1000) << TIME_INTERVAL_FRACBITS; /* Calculate nanos */
scaled_ns|=((picos%1000) << TIME_INTERVAL_FRACBITS)/1000; /* Add picos */ scaled_ns+=((picos%1000) << TIME_INTERVAL_FRACBITS)/1000; /* Add picos */
return scaled_ns*sign; return scaled_ns*sign;
} }
...@@ -214,3 +258,65 @@ int is_timestamps_incorrect(struct pp_instance *ppsi, int *err_count, int ts_mas ...@@ -214,3 +258,65 @@ int is_timestamps_incorrect(struct pp_instance *ppsi, int *err_count, int ts_mas
} }
return *err_count=0; return *err_count=0;
} }
static char time_as_string[32];
/* Convert pp_time to string */
char *time_to_string(struct pp_time *t)
{
struct pp_time time=*t;
int picos;
char *sign;
if (t->secs < 0 || (t->secs == 0 && t->scaled_nsecs < 0) ) {
sign="-";
time.scaled_nsecs=-t->scaled_nsecs;
time.secs=-t->secs;
} else {
sign="";
time=*t;
}
picos=((int)(time.scaled_nsecs&TIME_FRACMASK)*1000+TIME_ROUNDING_VALUE)>>TIME_FRACBITS;
pp_sprintf(time_as_string, "%s%d.%09d%03d",
sign,
(int)time.secs,
(int)(time.scaled_nsecs >> TIME_FRACBITS),
picos);
return time_as_string;
}
/* Convert TimeInterval to string */
char *interval_to_string(TimeInterval time)
{
int64_t sign,nanos,picos;
if ( time<0 && time !=INT64_MIN) {
sign=-1;
time=-time;
} else {
sign=1;
}
nanos = time >> TIME_INTERVAL_FRACBITS;
picos = (((time & TIME_INTERVAL_FRACMASK) * 1000) + TIME_INTERVAL_ROUNDING_VALUE ) >> TIME_INTERVAL_FRACBITS;
sprintf(time_as_string,"%" PRId64 ".%03" PRId64, sign*nanos,picos);
return time_as_string;
}
/* Convert RelativeInterval to string */
char *relative_interval_to_string(TimeInterval time) {
int32_t nsecs=time >> REL_DIFF_FRACBITS;
uint64_t sub_yocto=0;
int64_t fraction;
uint64_t bitWeight=500000000000000000;
uint64_t mask;
fraction=time & REL_DIFF_FRACMASK;
for (mask=(uint64_t) 1<< (REL_DIFF_FRACBITS-1);mask!=0; mask>>=1 ) {
if ( mask & fraction )
sub_yocto+=bitWeight;
bitWeight/=2;
}
sprintf(time_as_string,"%"PRId32".%018"PRIu64, nsecs, sub_yocto);
return time_as_string;
}
...@@ -101,11 +101,8 @@ typedef struct { /*draft P1588_v_29: page 101 and 340-341 */ ...@@ -101,11 +101,8 @@ typedef struct { /*draft P1588_v_29: page 101 and 340-341 */
/* Add all extension port DS related structure must be store here */ /* Add all extension port DS related structure must be store here */
typedef struct { typedef struct {
wrh_portds_head_t head; /* Must be always at the first place */
L1SyncBasicPortDS_t basic; L1SyncBasicPortDS_t basic;
L1SyncOptParamsPortDS_t opt_params; L1SyncOptParamsPortDS_t opt_params;
Boolean parentExtModeOn;
}l1e_ext_portDS_t; }l1e_ext_portDS_t;
static inline l1e_ext_portDS_t *L1E_DSPOR(struct pp_instance *ppi) static inline l1e_ext_portDS_t *L1E_DSPOR(struct pp_instance *ppi)
...@@ -127,13 +124,23 @@ static inline L1SyncOptParamsPortDS_t *L1E_DSPOR_OP(struct pp_instance *ppi) ...@@ -127,13 +124,23 @@ static inline L1SyncOptParamsPortDS_t *L1E_DSPOR_OP(struct pp_instance *ppi)
/****************************************************************************************/ /****************************************************************************************/
/* l1e_servo interface */ /* l1e_servo interface */
#define L1E_SERVO_RESET_DATA_SIZE (sizeof(struct l1e_servo_state)-offsetof(struct l1e_servo_state,reset_address))
#define L1E_SERVO_RESET_DATA(servo) memset(&servo->reset_address,0,L1E_SERVO_RESET_DATA_SIZE);
struct l1e_servo_state { struct l1e_servo_state {
/* Values used by snmp. Values are increased at servo update when
* erroneous condition occurs. */
uint32_t n_err_state;
uint32_t n_err_offset;
uint32_t n_err_delta_rtt;
/* ----- All data after this line will cleared during a servo reset */
int reset_address;
/* These fields are used by servo code, after setting at init time */ /* These fields are used by servo code, after setting at init time */
int32_t clock_period_ps; int32_t clock_period_ps;
/* Following fields are for monitoring/diagnostics (use w/ shmem) */ /* Following fields are for monitoring/diagnostics (use w/ shmem) */
struct pp_time delayMM;
int64_t delayMM_ps; int64_t delayMM_ps;
int32_t cur_setpoint_ps; int32_t cur_setpoint_ps;
int64_t delayMS_ps; int64_t delayMS_ps;
...@@ -141,15 +148,7 @@ struct l1e_servo_state { ...@@ -141,15 +148,7 @@ struct l1e_servo_state {
int64_t skew_ps; int64_t skew_ps;
int64_t offsetMS_ps; int64_t offsetMS_ps;
/* Values used by snmp. Values are increased at servo update when
* erroneous condition occurs. */
uint32_t n_err_state;
uint32_t n_err_offset;
uint32_t n_err_delta_rtt;
struct pp_time update_time;
/* These fields are used by servo code, across iterations */ /* These fields are used by servo code, across iterations */
struct pp_time t1, t2, t3, t4, t5, t6;
int64_t prev_delayMS_ps; int64_t prev_delayMS_ps;
int missed_iters; int missed_iters;
}; };
...@@ -158,9 +157,9 @@ struct l1e_servo_state { ...@@ -158,9 +157,9 @@ struct l1e_servo_state {
int l1e_servo_init(struct pp_instance *ppi); int l1e_servo_init(struct pp_instance *ppi);
void l1e_servo_reset(struct pp_instance *ppi); void l1e_servo_reset(struct pp_instance *ppi);
void l1e_servo_enable_tracking(int enable); void l1e_servo_enable_tracking(int enable);
int l1e_servo_got_sync(struct pp_instance *ppi, struct pp_time *t1, int l1e_servo_got_sync(struct pp_instance *ppi);
struct pp_time *t2); int l1e_servo_got_resp(struct pp_instance *ppi);
int l1e_servo_got_delay(struct pp_instance *ppi); int l1e_servo_got_presp(struct pp_instance *ppi);
int l1e_servo_update(struct pp_instance *ppi); int l1e_servo_update(struct pp_instance *ppi);
uint8_t l1e_creat_L1Sync_bitmask(int tx_coh, int rx_coh, int congru); uint8_t l1e_creat_L1Sync_bitmask(int tx_coh, int rx_coh, int congru);
void l1e_print_L1Sync_basic_bitmaps(struct pp_instance *ppi, void l1e_print_L1Sync_basic_bitmaps(struct pp_instance *ppi,
...@@ -180,6 +179,9 @@ static inline struct l1e_servo_state *L1E_SRV(struct pp_instance *ppi) ...@@ -180,6 +179,9 @@ static inline struct l1e_servo_state *L1E_SRV(struct pp_instance *ppi)
} }
static inline int l1e_get_rx_tmo_ms(L1SyncBasicPortDS_t * bds) {
return (4 << (bds->logL1SyncInterval + 8)) * bds->L1SyncReceiptTimeout;
}
extern struct pp_ext_hooks l1e_ext_hooks; extern struct pp_ext_hooks l1e_ext_hooks;
......
...@@ -19,7 +19,6 @@ char *l1e_state_name[] = { ...@@ -19,7 +19,6 @@ char *l1e_state_name[] = {
[L1SYNC_UP] = "L1SYNC_UP", [L1SYNC_UP] = "L1SYNC_UP",
}; };
void l1e_print_L1Sync_basic_bitmaps(struct pp_instance *ppi, uint8_t configed, void l1e_print_L1Sync_basic_bitmaps(struct pp_instance *ppi, uint8_t configed,
uint8_t active, char* text) uint8_t active, char* text)
{ {
...@@ -100,6 +99,7 @@ static int l1e_init(struct pp_instance *ppi, void *buf, int len) ...@@ -100,6 +99,7 @@ static int l1e_init(struct pp_instance *ppi, void *buf, int len)
/* Init configuration members of L1SyncOptParamsPortDS */ /* Init configuration members of L1SyncOptParamsPortDS */
L1E_DSPOR_OP(ppi)->timestampsCorrectedTx=TRUE; L1E_DSPOR_OP(ppi)->timestampsCorrectedTx=TRUE;
ppi->ext_enabled=TRUE;
return 0; return 0;
} }
...@@ -112,13 +112,16 @@ static int l1e_handle_signaling(struct pp_instance * ppi, void *buf, int len) ...@@ -112,13 +112,16 @@ static int l1e_handle_signaling(struct pp_instance * ppi, void *buf, int len)
if ( l1e_unpack_signal(ppi, buf, len)==0 ) { if ( l1e_unpack_signal(ppi, buf, len)==0 ) {
/* Valid Sync message */ /* Valid Sync message */
int timeout_tx_sync;
/* Reset reception timeout */ /* Reset reception timeout */
timeout_tx_sync = (4 << (bds->logL1SyncInterval + 8)) * bds->L1SyncReceiptTimeout; __pp_timeout_set(ppi, L1E_TIMEOUT_RX_SYNC, l1e_get_rx_tmo_ms(bds));
__pp_timeout_set(ppi, L1E_TIMEOUT_RX_SYNC, timeout_tx_sync);
bds->L1SyncLinkAlive = TRUE; bds->L1SyncLinkAlive = TRUE;
if ( ppi->link_state==PP_LSTATE_PROTOCOL_DETECTION ||
ppi->link_state==PP_LSTATE_FAILURE) {
ppi->link_state=PP_LSTATE_IN_PROGRESS;
ppi->ext_enabled=TRUE; // Force L1SYNC extension as L1SYNC messages are received
}
} }
return 0; return 0;
} }
...@@ -135,102 +138,64 @@ uint8_t l1e_creat_L1Sync_bitmask(int tx_coh, int rx_coh, int congru) ...@@ -135,102 +138,64 @@ uint8_t l1e_creat_L1Sync_bitmask(int tx_coh, int rx_coh, int congru)
static int l1e_handle_resp(struct pp_instance *ppi) static int l1e_handle_resp(struct pp_instance *ppi)
{ {
struct pp_time *ofm = &SRV(ppi)->offsetFromMaster;
l1e_ext_portDS_t *l1epds = L1E_DSPOR(ppi);
pp_diag(ppi, ext, 2, "hook: %s\n", __func__); pp_diag(ppi, ext, 2, "hook: %s\n", __func__);
if ( l1epds->basic.L1SyncState != L1SYNC_UP )
return 0;
/* This correction_field we received is already part of t4 */ /* This correction_field we received is already part of t4 */
if ( ppi->ext_enabled ) {
/* l1e_servo_got_resp(ppi);
* If no WR mode is on, run normal code, if T2/T3 are valid. }
* After we adjusted the pps counter, stamps are invalid, so else {
* we'll have the Unix time instead, marked by "correct"
*/
if (!l1epds->head.extModeOn) {
if ( is_timestamps_incorrect(ppi, NULL, 0x6 /* mask=t2&t3 */) ) {
pp_diag(ppi, servo, 1,"T2 or T3 incorrect, discarding tuple\n");
return 0;
}
pp_servo_got_resp(ppi); pp_servo_got_resp(ppi);
/* WRH_OPER()->enable_timing_output(ppi,
* pps always on if offset less than 1 second, ppi->state==PPS_SLAVE &&
* until we have a configurable threshold */ SRV(ppi)->offsetFromMaster.secs==0 &&
WRH_OPER()->enable_timing_output(ppi, ofm->secs==0); SRV(ppi)->offsetFromMaster.scaled_nsecs!=0);
} }
l1e_servo_got_delay(ppi);
l1e_servo_update(ppi);
return 0; return 0;
} }
static int l1e_sync_followup(struct pp_instance *ppi, struct pp_time *t1) { static int l1e_sync_followup(struct pp_instance *ppi) {
l1e_ext_portDS_t *pds=L1E_DSPOR(ppi); if ( ppi->ext_enabled ) {
l1e_servo_got_sync(ppi);
if ((pds->basic.L1SyncState != L1SYNC_UP) || !pds->head.extModeOn ) }
return 0; else {
pp_servo_got_sync(ppi);
l1e_servo_got_sync(ppi, t1, &ppi->t2); if (CONFIG_HAS_P2P && ppi->delayMechanism == P2P ) {
/* pps always on if offset less than 1 second,
if (CONFIG_HAS_P2P && ppi->delayMechanism == P2P) * until ve have a configurable threshold
l1e_servo_update(ppi); */
WRH_OPER()->enable_timing_output(ppi,
ppi->state==PPS_SLAVE &&
SRV(ppi)->offsetFromMaster.secs==0 &&
SRV(ppi)->offsetFromMaster.scaled_nsecs!=0);
}
}
return 1; /* the caller returns too */ return 1; /* the caller returns too */
} }
/* Hmm... "execute_slave" should look for errors; but it's off in WR too */ /* Hmm... "execute_slave" should look for errors; but it's off in WR too */
static int l1e_handle_followup(struct pp_instance *ppi, static int l1e_handle_followup(struct pp_instance *ppi)
struct pp_time *t1)
{ {
/* This handle is called in case of two step clock */ /* This handle is called in case of two step clock */
pp_diag(ppi, ext, 2, "hook: %s\n", __func__); pp_diag(ppi, ext, 2, "hook: %s\n", __func__);
return l1e_sync_followup(ppi,t1); return l1e_sync_followup(ppi);
} }
static int l1e_handle_sync(struct pp_instance *ppi, static int l1e_handle_sync(struct pp_instance *ppi)
struct pp_time *t1)
{ {
/* This handle is called in case of one step clock */ /* This handle is called in case of one step clock */
pp_diag(ppi, ext, 2, "hook: %s\n", __func__); pp_diag(ppi, ext, 2, "hook: %s\n", __func__);
return l1e_sync_followup(ppi,t1); return l1e_sync_followup(ppi);
} }
static __attribute__((used)) int l1e_handle_presp(struct pp_instance *ppi) static __attribute__((used)) int l1e_handle_presp(struct pp_instance *ppi)
{ {
struct pp_time *ofm = &SRV(ppi)->offsetFromMaster;
l1e_ext_portDS_t *pds=L1E_DSPOR(ppi);
/* Servo is active only when the state is UP */
if ( pds->basic.L1SyncState != L1SYNC_UP )
return 0;
/*
* If no WR mode is on, run normal code, if T2/T3 are valid.
* After we adjusted the pps counter, stamps are invalid, so
* we'll have the Unix time instead, marked by "correct"
*/
if (!WRH_DSPOR_HEAD(ppi)->extModeOn) {
if ( is_timestamps_incorrect(ppi, NULL, 0x24 /* mask=t3&t6 */) ) {
pp_diag(ppi, servo, 1,
"T3 or T6 incorrect, discarding tuple\n");
return 0;
}
pp_servo_got_presp(ppi);
/*
* pps always on if offset less than 1 second,
* until ve have a configurable threshold */
WRH_OPER()->enable_timing_output(ppi, ofm->secs==0);
return 0;
}
/* FIXME: verify that last-received cField is already accounted for */ /* FIXME: verify that last-received cField is already accounted for */
l1e_servo_got_delay(ppi); if ( ppi->ext_enabled )
l1e_servo_got_presp(ppi);
else
pp_servo_got_presp(ppi);
return 0; return 0;
} }
...@@ -244,8 +209,9 @@ static int l1e_ready_for_slave(struct pp_instance *ppi) ...@@ -244,8 +209,9 @@ static int l1e_ready_for_slave(struct pp_instance *ppi)
return 1; /* Ready for slave */ return 1; /* Ready for slave */
} }
static void l1e_state_change(struct pp_instance *ppi) { static void l1e_state_change(struct pp_instance *ppi) {
if ( !ppi->ext_enabled)
return;
switch (ppi->next_state) { switch (ppi->next_state) {
case PPS_DISABLED : case PPS_DISABLED :
/* In PPSI we go to DISABLE state when the link is down */ /* In PPSI we go to DISABLE state when the link is down */
...@@ -259,6 +225,20 @@ static void l1e_state_change(struct pp_instance *ppi) { ...@@ -259,6 +225,20 @@ static void l1e_state_change(struct pp_instance *ppi) {
} }
} }
static int l1e_new_slave (struct pp_instance *ppi, void *buf, int len) {
if ( ppi->ext_enabled )
l1e_servo_init(ppi);
return 0;
}
static int l1e_require_precise_timestamp(struct pp_instance *ppi) {
return ppi->ext_enabled ? L1E_DSPOR_BS(ppi)->L1SyncState==L1SYNC_UP : 0;
}
static int l1e_get_tmo_lstate_detection(struct pp_instance *ppi) {
return l1e_get_rx_tmo_ms(L1E_DSPOR_BS(ppi));
}
/* The global structure used by ppsi */ /* The global structure used by ppsi */
struct pp_ext_hooks l1e_ext_hooks = { struct pp_ext_hooks l1e_ext_hooks = {
.open = l1e_open, .open = l1e_open,
...@@ -269,9 +249,13 @@ struct pp_ext_hooks l1e_ext_hooks = { ...@@ -269,9 +249,13 @@ struct pp_ext_hooks l1e_ext_hooks = {
.handle_resp = l1e_handle_resp, .handle_resp = l1e_handle_resp,
.handle_sync = l1e_handle_sync, .handle_sync = l1e_handle_sync,
.handle_followup = l1e_handle_followup, .handle_followup = l1e_handle_followup,
.new_slave = l1e_new_slave,
#if CONFIG_HAS_P2P #if CONFIG_HAS_P2P
.handle_presp = l1e_handle_presp, .handle_presp = l1e_handle_presp,
#endif #endif
.state_change = l1e_state_change, .state_change = l1e_state_change,
.servo_reset= l1e_servo_reset,
.require_precise_timestamp=l1e_require_precise_timestamp,
.get_tmo_lstate_detection=l1e_get_tmo_lstate_detection
}; };
...@@ -4,7 +4,8 @@ ...@@ -4,7 +4,8 @@
* *
* Released according to the GNU LGPL, version 2.1 or any later version. * Released according to the GNU LGPL, version 2.1 or any later version.
*/ */
#include <stdint.h>
#include <inttypes.h>
#include <ppsi/ppsi.h> #include <ppsi/ppsi.h>
#include "l1e-constants.h" #include "l1e-constants.h"
#include <libwr/shmem.h> #include <libwr/shmem.h>
...@@ -22,34 +23,14 @@ static const char *l1e_servo_state_name[] = { ...@@ -22,34 +23,14 @@ static const char *l1e_servo_state_name[] = {
/* Enable tracking by default. Disabling the tracking is used for demos. */ /* Enable tracking by default. Disabling the tracking is used for demos. */
static int l1e_tracking_enabled = 1; static int l1e_tracking_enabled = 1;
static struct pp_time l1e_faulty_stamps[6]; /* if unused, dropped at link time */ static struct pp_time l1e_faulty_stamps[6]; /* if unused, dropped at link time */
static int l1e_got_sync = 0;
/* prototypes */ /* prototypes */
static int l1e_p2p_delay(struct pp_instance *ppi, struct l1e_servo_state *s); static int __l1e_servo_update(struct pp_instance *ppi);
static void l1e_apply_faulty_stamp(struct l1e_servo_state *s, int index);
static void l1e_dump_timestamp(struct pp_instance *ppi, char *what, struct pp_time ts);
/* External data */ /* External data */
extern struct wrs_shm_head *ppsi_head; extern struct wrs_shm_head *ppsi_head;
static void l1e_apply_faulty_stamp(struct l1e_servo_state *s, int index)
{
if (PROTO_EXT_HAS_FAULTS) {
assert(index >= 1 && index <= 6, "Wrong T index %i\n", index);
pp_time_add(&s->t1 + index - 1, l1e_faulty_stamps + index - 1);
}
}
static void l1e_dump_timestamp(struct pp_instance *ppi, char *what,struct pp_time ts)
{
pp_diag(ppi, servo, 2, "%s = %ld.%09ld%03ld\n", what, (long)ts.secs,
(long)(ts.scaled_nsecs >> 16),
/* unlikely what we had earlier, third field is not phase */
((long)(ts.scaled_nsecs & 0xffff) * 1000 + 0x8000) >> 16);
}
void l1e_servo_enable_tracking(int enable) void l1e_servo_enable_tracking(int enable)
{ {
l1e_tracking_enabled = enable; l1e_tracking_enabled = enable;
...@@ -58,6 +39,9 @@ void l1e_servo_enable_tracking(int enable) ...@@ -58,6 +39,9 @@ void l1e_servo_enable_tracking(int enable)
int l1e_servo_init(struct pp_instance *ppi) int l1e_servo_init(struct pp_instance *ppi)
{ {
struct l1e_servo_state *s=L1E_SRV(ppi); struct l1e_servo_state *s=L1E_SRV(ppi);
struct pp_servo *gs=SRV(ppi);
pp_servo_init(ppi); // Initialize the standard servo data
/* shmem lock */ /* shmem lock */
wrs_shm_write(ppsi_head, WRS_SHM_WRITE_BEGIN); wrs_shm_write(ppsi_head, WRS_SHM_WRITE_BEGIN);
...@@ -80,17 +64,15 @@ int l1e_servo_init(struct pp_instance *ppi) ...@@ -80,17 +64,15 @@ int l1e_servo_init(struct pp_instance *ppi)
WRH_OPER()->adjust_phase(s->cur_setpoint_ps); WRH_OPER()->adjust_phase(s->cur_setpoint_ps);
s->missed_iters = 0; s->missed_iters = 0;
SRV(ppi)->state = L1E_SYNC_TAI; gs->state = L1E_SYNC_TAI;
strcpy(SRV(ppi)->servo_state_name, l1e_servo_state_name[SRV(ppi)->state]); strcpy(SRV(ppi)->servo_state_name, l1e_servo_state_name[SRV(ppi)->state]);
SRV(ppi)->flags |= PP_SERVO_FLAG_VALID; gs->flags |= PP_SERVO_FLAG_VALID;
SRV(ppi)->update_count = 0; gs->update_count = 0;
ppi->t_ops->get(ppi, &s->update_time); ppi->t_ops->get(ppi, &SRV(ppi)->update_time);
s->tracking_enabled = l1e_tracking_enabled; s->tracking_enabled = l1e_tracking_enabled;
l1e_got_sync = 0;
/* shmem unlock */ /* shmem unlock */
wrs_shm_write(ppsi_head, WRS_SHM_WRITE_END); wrs_shm_write(ppsi_head, WRS_SHM_WRITE_END);
return 0; return 0;
...@@ -99,292 +81,103 @@ int l1e_servo_init(struct pp_instance *ppi) ...@@ -99,292 +81,103 @@ int l1e_servo_init(struct pp_instance *ppi)
void l1e_servo_reset(struct pp_instance *ppi) void l1e_servo_reset(struct pp_instance *ppi)
{ {
/* values from servo_state to be preserved */ if ( ppi->ext_enabled ) {
uint32_t n_err_state; struct l1e_servo_state *s=L1E_SRV(ppi);
uint32_t n_err_offset;
uint32_t n_err_delta_rtt;
struct l1e_servo_state *s=L1E_SRV(ppi); /* shmem lock */
wrs_shm_write(ppsi_head, WRS_SHM_WRITE_BEGIN);
ppi->flags = 0;
/* shmem lock */ L1E_SERVO_RESET_DATA(s);
wrs_shm_write(ppsi_head, WRS_SHM_WRITE_BEGIN);
ppi->flags = 0;
/* preserve some values from servo_state */
n_err_state = s->n_err_state;
n_err_offset = s->n_err_offset;
n_err_delta_rtt = s->n_err_delta_rtt;
/* clear servo_state to display empty fields in wr_mon and SNMP */
memset(s, 0, sizeof(struct l1e_servo_state));
/* restore values from servo_state */
s->n_err_state = n_err_state;
s->n_err_offset = n_err_offset;
s->n_err_delta_rtt = n_err_delta_rtt;
/* shmem unlock */ /* shmem unlock */
wrs_shm_write(ppsi_head, WRS_SHM_WRITE_END); wrs_shm_write(ppsi_head, WRS_SHM_WRITE_END);
}
} }
/** /**
* SYNC/FOLLOW_UP messages have been received: t1/t2 are available * SYNC/FOLLOW_UP messages have been received: t1/t2 are available
*/ */
int l1e_servo_got_sync(struct pp_instance *ppi, struct pp_time *t1, int l1e_servo_got_sync(struct pp_instance *ppi)
struct pp_time *t2)
{ {
struct l1e_servo_state *s=L1E_SRV(ppi); struct pp_servo *gs=SRV(ppi);
s->t1 = *t1; l1e_apply_faulty_stamp(s, 1);
s->t2 = *t2; l1e_apply_faulty_stamp(s, 2);
l1e_got_sync = 1;
return 0;
}
/**
* DELAY_RESPONSE message has been received: t3/t4 are available
*/
int l1e_servo_got_delay(struct pp_instance *ppi)
{
struct l1e_servo_state *s=L1E_SRV(ppi);
/* shmem lock */
wrs_shm_write(ppsi_head, WRS_SHM_WRITE_BEGIN); wrs_shm_write(ppsi_head, WRS_SHM_WRITE_BEGIN);
s->t3 = ppi->t3; l1e_apply_faulty_stamp(s, 3); gs->t1=ppi->t1;pp_servo_apply_faulty_stamp(gs, l1e_faulty_stamps,1);
s->t4 = ppi->t4; l1e_apply_faulty_stamp(s, 4); gs->t2=ppi->t2;pp_servo_apply_faulty_stamp(gs, l1e_faulty_stamps, 2);
if (CONFIG_HAS_P2P && ppi->delayMechanism == P2P) {
s->t5 = ppi->t5; l1e_apply_faulty_stamp(s, 5);
s->t6 = ppi->t6; l1e_apply_faulty_stamp(s, 6);
l1e_p2p_delay(ppi, s); if (CONFIG_HAS_P2P && ppi->delayMechanism == P2P && gs->got_sync) {
gs->got_sync=0;
__l1e_servo_update(ppi);
}else {
gs->got_sync=1;
} }
/* shmem unlock */
wrs_shm_write(ppsi_head, WRS_SHM_WRITE_END); wrs_shm_write(ppsi_head, WRS_SHM_WRITE_END);
return 0;
}
#define BITS_IN_INT64 (sizeof(int64_t)*8)
/* Get the position of the first bit set on the left of a 64 bits integer */
static int getMsbSet(int64_t value) {
if ( value==0 )
return 0; /* value=0 so return bit 0 */
if ( value<0 )
value=-value; /* Negative value: change it to its positive value for the calculation */
return BITS_IN_INT64 - __builtin_clzll(value); /* using gcc built-in function */
}
#define DELAY_ASYM_BASE_FRACTION 50 /* Maxim value that can be used for the calculation */
/**
* Calculate the delayAsymmetry : delayAsymCoeff * meanDelay
*
* This calculation is made in order to use the maximum of bits in the fraction part. It will depend
* on the value of delayAsymCoeff and meanDelay. The smaller these values will be, bigger
* the fraction part will be.
*/
static TimeInterval calculateDelayAsymmetry(RelativeDifference scaledDelayAsymCoeff, TimeInterval scaledMeanDelay) { return 0;
TimeInterval delayAsym;
int64_t rescaledAsymDelayCoeff,rescaledMeanDelay;
int lostBits,fracBitsUsed;
lostBits=getMsbSet(scaledDelayAsymCoeff)-(REL_DIFF_FRACBITS-DELAY_ASYM_BASE_FRACTION)+
getMsbSet(scaledMeanDelay)+(DELAY_ASYM_BASE_FRACTION-TIME_INTERVAL_FRACBITS)-BITS_IN_INT64;
if ( lostBits<0 )
lostBits=0;
fracBitsUsed=DELAY_ASYM_BASE_FRACTION-(lostBits>>1)-1;
rescaledMeanDelay = scaledMeanDelay<<(fracBitsUsed-TIME_INTERVAL_FRACBITS);
rescaledAsymDelayCoeff=scaledDelayAsymCoeff>>(REL_DIFF_FRACBITS-fracBitsUsed);
delayAsym= rescaledAsymDelayCoeff*rescaledMeanDelay;
delayAsym+=(1<<(fracBitsUsed-1));
delayAsym>>=fracBitsUsed;
delayAsym>>=(fracBitsUsed-TIME_INTERVAL_FRACBITS);
return delayAsym;
} }
/** /**
* PDELAY_RESPONSE/PDELAY_RESPONSE_FOLLOW_UP messages have been received: t3/t4/t5/t6 are available * DELAY_RESPONSE message has been received: t3/t4 are available
*/ */
static int l1e_p2p_delay(struct pp_instance *ppi, struct l1e_servo_state *s) int l1e_servo_got_resp(struct pp_instance *ppi)
{ {
static int errcount; struct pp_servo *gs=SRV(ppi);
int64_t meanLinkDelay_ps; int ret;
static int errcount=0;
if ( is_timestamps_incorrect(ppi,&errcount, 0x3C /* mask=t3&t4&t5&t6*/)) if ( !gs->got_sync )
return 0; return 0; /* t1 & t2 not available yet */
gs->got_sync=0;
SRV(ppi)->update_count++;
ppi->t_ops->get(ppi, &s->update_time);
/* if ( is_timestamps_incorrect(ppi,&errcount,0xC /* mask=t3&t4 */) )
* Calculate of the round trip delay (delayMM) return 0;
* delayMM = (t6-t3)-(t5-t4)
*/
{ /* avoid modifying stamps in place */
struct pp_time mtime, stime;
stime = s->t6; pp_time_sub(&stime, &s->t3);
mtime = s->t5; pp_time_sub(&mtime, &s->t4);
s->delayMM = stime; pp_time_sub(&s->delayMM, &mtime);
}
s->delayMM_ps = pp_time_to_picos(&s->delayMM);
/*
* Calculate the meanLinkDelay
* meanLinkDelay=delayMM/2)
*/
if (s->delayMM_ps < 0) {
s->delayMM_ps =meanLinkDelay_ps=0;
picos_to_pp_time(s->delayMM_ps, &s->delayMM);
} else {
meanLinkDelay_ps=s->delayMM_ps>>1; /* meanLinkDelay=delayMM/2 */
}
if (__PP_DIAG_ALLOW(ppi, pp_dt_servo, 1)) {
l1e_dump_timestamp(ppi, "servo:t1", s->t1);
l1e_dump_timestamp(ppi, "servo:t2", s->t2);
l1e_dump_timestamp(ppi, "servo:t3", s->t3);
l1e_dump_timestamp(ppi, "servo:t4", s->t4);
l1e_dump_timestamp(ppi, "servo:t5", s->t5);
l1e_dump_timestamp(ppi, "servo:t6", s->t6);
l1e_dump_timestamp(ppi, "->delayMM", s->delayMM);
}
if ( ppi->asymmetryCorrectionPortDS.enable ) {
/* Enabled: The delay asymmetry must be calculated
* delayAsymmetry=delayAsymCoefficient * meanPathDelay
*/
ppi->portDS->delayAsymmetry=calculateDelayAsymmetry(ppi->portDS->delayAsymCoeff,picos_to_interval(meanLinkDelay_ps));
} else {
/* Disabled: The delay asymmetry is provided by configuration */
ppi->portDS->delayAsymmetry=ppi->asymmetryCorrectionPortDS.constantAsymmetry;
}
/* delayMS = meanLinkDelay + delayAsym */ wrs_shm_write(ppsi_head, WRS_SHM_WRITE_BEGIN);
s->delayMS_ps = meanLinkDelay_ps + interval_to_picos(ppi->portDS->delayAsymmetry);
picos_to_pp_time(s->delayMS_ps, &SRV(ppi)->delayMS);
update_meanDelay(ppi,picos_to_interval(meanLinkDelay_ps)); /* update currentDS.meanDelay and portDS.meanLinkDelay (idf needed) */ gs->t3 = ppi->t3; pp_servo_apply_faulty_stamp(gs, l1e_faulty_stamps,3);
picos_to_pp_time(meanLinkDelay_ps,&SRV(ppi)->meanDelay); /* update servo.meanDelay */ gs->t4 = ppi->t4; pp_servo_apply_faulty_stamp(gs, l1e_faulty_stamps,4);
return 1; ret=__l1e_servo_update(ppi);
wrs_shm_write(ppsi_head, WRS_SHM_WRITE_END);
return ret;
} }
static int l1e_p2p_offset(struct pp_instance *ppi, /**
struct l1e_servo_state *s, struct pp_time *offsetMS) * PDELAY_RESPONSE_FUP message has been received: t3/t4/t5/t6 are available
*/
int l1e_servo_got_presp(struct pp_instance *ppi)
{ {
static int errcount; struct pp_servo *gs=SRV(ppi);
static int errcount=0;
if ( is_timestamps_incorrect(ppi,&errcount, 0x3 /* mask=t1&t2 */))
return 0;
l1e_got_sync = 0;
SRV(ppi)->update_count++;
ppi->t_ops->get(ppi, &s->update_time);
/* Calculate offsetFromMaster : t1-t2+meanLinkDelay+delayAsym=t1-t2+delayMS */
*offsetMS = s->t1;
pp_time_sub(offsetMS, &s->t2);
pp_time_add(offsetMS, &SRV(ppi)->delayMS); /* Add delayMS */
/* is it possible to calculate it in client,
* but then t1 and t2 require shmem locks */
s->tracking_enabled = l1e_tracking_enabled;
SRV(ppi)->offsetFromMaster=*offsetMS; /* Update servo.offsetFromMaster */
DSCUR(ppi)->offsetFromMaster = pp_time_to_interval(offsetMS); /* Update currentDS.offsetFromMaster */
return 1;
}
static int l1e_e2e_offset(struct pp_instance *ppi, struct l1e_servo_state *s,
struct pp_time *offsetMS) {
static int errcount;
int64_t meanPathDelay_ps;
if (is_timestamps_incorrect(ppi, &errcount, 0xF /* mask=t1&t2&t3&t4 */)) if ( is_timestamps_incorrect(ppi,&errcount,0x3C /* mask=&t3&t4&t5&t6 */) )
return 0; return 0;
if (WRH_OPER()->servo_hook) wrs_shm_write(ppsi_head, WRS_SHM_WRITE_BEGIN);
WRH_OPER()->servo_hook(ppi, WRH_SERVO_ENTER);
SRV(ppi)->update_count++;
ppi->t_ops->get(ppi, &s->update_time);
l1e_got_sync = 0;
/*
* Calculate of the round trip delay (delayMM)
* delayMM = t4-t1-(t3-t2)
*/
{
/* Avoid modifying stamps in place*/
struct pp_time mtime, stime;
mtime = s->t4;
pp_time_sub(&mtime, &s->t1);
stime = s->t3;
pp_time_sub(&stime, &s->t2);
s->delayMM = mtime;
pp_time_sub(&s->delayMM, &stime);
}
s->delayMM_ps = pp_time_to_picos(&s->delayMM);
/*
* Calculate the meanPathDelay
* meanPathDelay=delayMM/2)
*/
if (s->delayMM_ps < 0) {
s->delayMM_ps =meanPathDelay_ps=0;
picos_to_pp_time(s->delayMM_ps, &s->delayMM);
} else {
meanPathDelay_ps=s->delayMM_ps>>1; /* meanPathDelay=delayMM/2 */
}
if (__PP_DIAG_ALLOW(ppi, pp_dt_servo, 1)) {
l1e_dump_timestamp(ppi, "t1", s->t1);
l1e_dump_timestamp(ppi, "t2", s->t2);
l1e_dump_timestamp(ppi, "t3", s->t3);
l1e_dump_timestamp(ppi, "t4", s->t4);
l1e_dump_timestamp(ppi, "delayMM", s->delayMM);
}
if ( ppi->asymmetryCorrectionPortDS.enable ) {
/* Enabled: The delay asymmetry must be calculated
* delayAsymmetry=delayAsymCoefficient * meanPathDelay
*/
ppi->portDS->delayAsymmetry=calculateDelayAsymmetry(ppi->portDS->delayAsymCoeff,picos_to_interval(meanPathDelay_ps));
} else {
/* Disabled: The delay asymmetry is provided by configuration */
ppi->portDS->delayAsymmetry=ppi->asymmetryCorrectionPortDS.constantAsymmetry;
}
/* delayMS = meanPathDelay + delayAsym */
s->delayMS_ps = meanPathDelay_ps + interval_to_picos(ppi->portDS->delayAsymmetry);
picos_to_pp_time(s->delayMS_ps, &SRV(ppi)->delayMS);
/* Calculate offsetFromMaster : t1-t2+meanPathDelay+delayAsym=t1-t2+delayMS */ gs->t3 = ppi->t3; pp_servo_apply_faulty_stamp(gs, l1e_faulty_stamps,3);
*offsetMS = s->t1; gs->t4 = ppi->t4; pp_servo_apply_faulty_stamp(gs, l1e_faulty_stamps,4);
pp_time_sub(offsetMS, &s->t2); gs->t5 = ppi->t5; pp_servo_apply_faulty_stamp(gs, l1e_faulty_stamps,5);
pp_time_add(offsetMS, &SRV(ppi)->delayMS); /* Add delayMS */ gs->t6 = ppi->t6; pp_servo_apply_faulty_stamp(gs, l1e_faulty_stamps,6);
s->tracking_enabled = l1e_tracking_enabled; gs->got_sync=1;
SRV(ppi)->offsetFromMaster=*offsetMS; /* Update servo.offsetFromMaster */ wrs_shm_write(ppsi_head, WRS_SHM_WRITE_END);
DSCUR(ppi)->offsetFromMaster = pp_time_to_interval(offsetMS); /* Update currentDS.offsetFromMaster */
picos_to_pp_time(meanPathDelay_ps,&SRV(ppi)->meanDelay); /* update servo.meanDelay */
update_meanDelay(ppi,picos_to_interval(meanPathDelay_ps)); /* update currentDS.meanDelay and portDS.meanLinkDelay (idf needed) */
return 1; return 1;
} }
int l1e_servo_update(struct pp_instance *ppi) static int __l1e_servo_update(struct pp_instance *ppi)
{ {
l1e_ext_portDS_t *pds=L1E_DSPOR(ppi);
struct pp_servo *gs=SRV(ppi);
struct l1e_servo_state *s=L1E_SRV(ppi); struct l1e_servo_state *s=L1E_SRV(ppi);
int remaining_offset; int remaining_offset;
int32_t offset_ticks; int32_t offset_ticks;
...@@ -394,38 +187,34 @@ int l1e_servo_update(struct pp_instance *ppi) ...@@ -394,38 +187,34 @@ int l1e_servo_update(struct pp_instance *ppi)
struct pp_time offsetMS ; struct pp_time offsetMS ;
int32_t offset_ps; int32_t offset_ps;
if (!l1e_got_sync) if ( gs->state==L1E_UNINITIALIZED )
return 0; return 0;
/* shmem lock */
wrs_shm_write(ppsi_head, WRS_SHM_WRITE_BEGIN);
if ( SRV(ppi)->state==L1E_UNINITIALIZED )
goto out;
prev_delayMM_ps = s->delayMM_ps; prev_delayMM_ps = s->delayMM_ps;
if (CONFIG_HAS_P2P && ppi->delayMechanism == P2P) {
if (!l1e_p2p_offset(ppi, s, &offsetMS))
goto out;
} else {
if (!l1e_e2e_offset(ppi, s, &offsetMS))
goto out;
}
if ( !pp_servo_calculate_delays(ppi) )
return 0;
s->delayMM_ps=pp_time_to_picos(&gs->delayMM);
offsetMS=gs->offsetFromMaster;
s->offsetMS_ps=pp_time_to_picos(&offsetMS); s->offsetMS_ps=pp_time_to_picos(&offsetMS);
pp_diag(ppi, servo, 2, s->tracking_enabled = l1e_tracking_enabled;
"ML: scaledDelayCoeff = %lld, delayMS = %lld, offsetMS = %lld [ps]\n",
(long long )ppi->asymmetryCorrectionPortDS.scaledDelayCoefficient,
(long long )s->delayMS_ps,
(long long )s->offsetMS_ps);
l1e_dump_timestamp(ppi,"ML: offsetMS",offsetMS);
// Servo updated
gs->update_count++;
ppi->t_ops->get(ppi, &gs->update_time);
pp_time_hardwarize(&offsetMS, s->clock_period_ps, // if (CONFIG_HAS_P2P && ppi->delayMechanism == P2P) {
&offset_ticks, &offset_ps); // if (!l1e_p2p_offset(ppi, s, &offsetMS))
pp_diag(ppi, servo, 2, "offsetMS: %li sec %09li ticks (%li ps)\n", // goto out;
(long)offsetMS.secs, (long)offset_ticks, // } else {
(long)offset_ps); // if (!l1e_e2e_offset(ppi, s, &offsetMS))
// goto out;
// }
if (pds->basic.L1SyncState != L1SYNC_UP)
return 1; /* State is not UP. We have to wait before to start the synchronisation */
locking_poll_ret = WRH_OPER()->locking_poll(ppi, 0); locking_poll_ret = WRH_OPER()->locking_poll(ppi, 0);
if (locking_poll_ret != WRH_SPLL_READY if (locking_poll_ret != WRH_SPLL_READY
...@@ -438,46 +227,52 @@ int l1e_servo_update(struct pp_instance *ppi) ...@@ -438,46 +227,52 @@ int l1e_servo_update(struct pp_instance *ppi)
/* After each action on the hardware, we must verify if it is over. */ /* After each action on the hardware, we must verify if it is over. */
if (!WRH_OPER()->adjust_in_progress()) { if (!WRH_OPER()->adjust_in_progress()) {
SRV(ppi)->flags &= ~PP_SERVO_FLAG_WAIT_HW; gs->flags &= ~PP_SERVO_FLAG_WAIT_HW;
} else { } else {
pp_diag(ppi, servo, 1, "servo:busy\n"); pp_diag(ppi, servo, 1, "servo:busy\n");
goto out; return 1;
} }
/* So, we didn't return. Choose the right state */ /* So, we didn't return. Choose the right state */
if (offsetMS.secs) /* so bad... */ if (offsetMS.secs) {/* so bad... */
SRV(ppi)->state = L1E_SYNC_TAI; gs->state = L1E_SYNC_TAI;
else if (offset_ticks) /* not that bad */ pp_diag(ppi, servo, 2, "offsetMS: %li sec ...\n",
SRV(ppi)->state = L1E_SYNC_NSEC; (long)offsetMS.secs);
} else {
pp_time_hardwarize(&offsetMS, s->clock_period_ps,
&offset_ticks, &offset_ps);
pp_diag(ppi, servo, 2, "offsetMS: %li sec %09li ticks (%li ps)\n",
(long)offsetMS.secs, (long)offset_ticks,
(long)offset_ps);
if (offset_ticks) /* not that bad */
gs->state = L1E_SYNC_NSEC;
/* else, let the states below choose the sequence */ /* else, let the states below choose the sequence */
}
pp_diag(ppi, servo, 2, "offsetMS: %li.%09li (+%li)\n", /* update string state name */
(long)offsetMS.secs, (long)offset_ticks, strcpy(gs->servo_state_name, l1e_servo_state_name[gs->state]);
(long)offset_ps);
pp_diag(ppi, servo, 1, "l1e_servo state: %s%s\n", pp_diag(ppi, servo, 1, "l1e_servo state: %s%s\n",
l1e_servo_state_name[SRV(ppi)->state], l1e_servo_state_name[gs->state],
SRV(ppi)->flags & PP_SERVO_FLAG_WAIT_HW ? " (wait for hw)" : ""); gs->flags & PP_SERVO_FLAG_WAIT_HW ? " (wait for hw)" : "");
/* update string state name */
strcpy(SRV(ppi)->servo_state_name, l1e_servo_state_name[SRV(ppi)->state]);
switch (SRV(ppi)->state) { switch (gs->state) {
case L1E_SYNC_TAI: case L1E_SYNC_TAI:
WRH_OPER()->adjust_counters(offsetMS.secs, 0); WRH_OPER()->adjust_counters(offsetMS.secs, 0);
SRV(ppi)->flags |= PP_SERVO_FLAG_WAIT_HW; gs->flags |= PP_SERVO_FLAG_WAIT_HW;
/* /*
* If nsec wrong, code above forces SYNC_NSEC, * If nsec wrong, code above forces SYNC_NSEC,
* Else, we must ensure we leave this status towards * Else, we must ensure we leave this status towards
* fine tuning * fine tuning
*/ */
SRV(ppi)->state = L1E_SYNC_PHASE; gs->state = L1E_SYNC_PHASE;
break; break;
case L1E_SYNC_NSEC: case L1E_SYNC_NSEC:
WRH_OPER()->adjust_counters(0, offset_ticks); WRH_OPER()->adjust_counters(0, offset_ticks);
SRV(ppi)->flags |= PP_SERVO_FLAG_WAIT_HW; gs->flags |= PP_SERVO_FLAG_WAIT_HW;
SRV(ppi)->state = L1E_SYNC_PHASE; gs->state = L1E_SYNC_PHASE;
break; break;
case L1E_SYNC_PHASE: case L1E_SYNC_PHASE:
...@@ -488,8 +283,8 @@ int l1e_servo_update(struct pp_instance *ppi) ...@@ -488,8 +283,8 @@ int l1e_servo_update(struct pp_instance *ppi)
pp_diag(ppi, servo, 3, "%s.%d: Adjust_phase: %d\n",__func__,__LINE__,s->cur_setpoint_ps); pp_diag(ppi, servo, 3, "%s.%d: Adjust_phase: %d\n",__func__,__LINE__,s->cur_setpoint_ps);
WRH_OPER()->adjust_phase(s->cur_setpoint_ps); WRH_OPER()->adjust_phase(s->cur_setpoint_ps);
SRV(ppi)->flags |= PP_SERVO_FLAG_WAIT_HW; gs->flags |= PP_SERVO_FLAG_WAIT_HW;
SRV(ppi)->state = L1E_WAIT_OFFSET_STABLE; gs->state = L1E_WAIT_OFFSET_STABLE;
if (ARCH_IS_WRS) { if (ARCH_IS_WRS) {
/* /*
...@@ -500,8 +295,8 @@ int l1e_servo_update(struct pp_instance *ppi) ...@@ -500,8 +295,8 @@ int l1e_servo_update(struct pp_instance *ppi)
struct pp_time t; struct pp_time t;
ppi->t_ops->get(ppi,&t); ppi->t_ops->get(ppi,&t);
unix_time_ops.set(ppi, &t); unix_time_ops.set(ppi, &t);
pp_diag(ppi, time, 1, "system time set to %li TAI\n", pp_diag(ppi, time, 1, "system time set to %s TAI\n",
(long)ppi->t4.secs); time_to_string(&t));
} }
break; break;
...@@ -512,13 +307,13 @@ int l1e_servo_update(struct pp_instance *ppi) ...@@ -512,13 +307,13 @@ int l1e_servo_update(struct pp_instance *ppi)
if(remaining_offset < WRH_SERVO_OFFSET_STABILITY_THRESHOLD) { if(remaining_offset < WRH_SERVO_OFFSET_STABILITY_THRESHOLD) {
WRH_OPER()->enable_timing_output(ppi, 1); WRH_OPER()->enable_timing_output(ppi, 1);
s->prev_delayMS_ps = s->delayMS_ps; s->prev_delayMS_ps = s->delayMS_ps;
SRV(ppi)->state = L1E_TRACK_PHASE; gs->state = L1E_TRACK_PHASE;
} else { } else {
s->missed_iters++; s->missed_iters++;
} }
if (s->missed_iters >= 10) { if (s->missed_iters >= 10) {
s->missed_iters = 0; s->missed_iters = 0;
SRV(ppi)->state = L1E_SYNC_PHASE; gs->state = L1E_SYNC_PHASE;
} }
break; break;
...@@ -529,7 +324,7 @@ int l1e_servo_update(struct pp_instance *ppi) ...@@ -529,7 +324,7 @@ int l1e_servo_update(struct pp_instance *ppi)
if(l1e_tracking_enabled) { if(l1e_tracking_enabled) {
if (abs(offset_ps) > if (abs(offset_ps) >
2 * WRH_SERVO_OFFSET_STABILITY_THRESHOLD) { 2 * WRH_SERVO_OFFSET_STABILITY_THRESHOLD) {
SRV(ppi)->state = WR_SYNC_PHASE; gs->state = L1E_SYNC_PHASE;
break; break;
} }
...@@ -547,11 +342,11 @@ int l1e_servo_update(struct pp_instance *ppi) ...@@ -547,11 +342,11 @@ int l1e_servo_update(struct pp_instance *ppi)
} }
SRV(ppi)->servo_locked=SRV(ppi)->state==L1E_TRACK_PHASE; gs->servo_locked=gs->state==L1E_TRACK_PHASE;
/* Increase number of servo updates with state different than /* Increase number of servo updates with state different than
* L1E_TRACK_PHASE. (Used by SNMP) */ * L1E_TRACK_PHASE. (Used by SNMP) */
if (SRV(ppi)->state != L1E_TRACK_PHASE) if (gs->state != L1E_TRACK_PHASE)
s->n_err_state++; s->n_err_state++;
/* Increase number of servo updates with offset exceeded /* Increase number of servo updates with offset exceeded
...@@ -563,13 +358,5 @@ int l1e_servo_update(struct pp_instance *ppi) ...@@ -563,13 +358,5 @@ int l1e_servo_update(struct pp_instance *ppi)
* SNMP_MAX_DELTA_RTT_PS (Used by SNMP) */ * SNMP_MAX_DELTA_RTT_PS (Used by SNMP) */
if (abs(prev_delayMM_ps - s->delayMM_ps) > SNMP_MAX_DELTA_RTT_PS) if (abs(prev_delayMM_ps - s->delayMM_ps) > SNMP_MAX_DELTA_RTT_PS)
s->n_err_delta_rtt++; s->n_err_delta_rtt++;
return 1;
out:
/* shmem unlock */
wrs_shm_write(ppsi_head, WRS_SHM_WRITE_END);
if (WRH_OPER()->servo_hook)
WRH_OPER()->servo_hook(ppi, WRH_SERVO_LEAVE);
return 0;
} }
...@@ -47,7 +47,6 @@ static l1e_state_machine_t le1_state_actions[] ={ ...@@ -47,7 +47,6 @@ static l1e_state_machine_t le1_state_actions[] ={
}, },
}; };
/* /*
* This hook is called by fsm to run the extension state machine. * This hook is called by fsm to run the extension state machine.
* It is used to send signaling messages. * It is used to send signaling messages.
...@@ -60,6 +59,9 @@ int l1e_run_state_machine(struct pp_instance *ppi) { ...@@ -60,6 +59,9 @@ int l1e_run_state_machine(struct pp_instance *ppi) {
Boolean newState=nextState!=basicDS->L1SyncState; Boolean newState=nextState!=basicDS->L1SyncState;
int delay; int delay;
if ( !ppi->ext_enabled )
return INT_MAX; /* Return a big delay. fsm will then not use it */
if ( nextState>=MAX_STATE_ACTIONS) if ( nextState>=MAX_STATE_ACTIONS)
return pp_next_delay_2(ppi,L1E_TIMEOUT_TX_SYNC, L1E_TIMEOUT_RX_SYNC); return pp_next_delay_2(ppi,L1E_TIMEOUT_TX_SYNC, L1E_TIMEOUT_RX_SYNC);
...@@ -74,8 +76,7 @@ int l1e_run_state_machine(struct pp_instance *ppi) { ...@@ -74,8 +76,7 @@ int l1e_run_state_machine(struct pp_instance *ppi) {
/* Check L1SYNC reception Time-out */ /* Check L1SYNC reception Time-out */
if ( pp_timeout(ppi, L1E_TIMEOUT_RX_SYNC) ) { if ( pp_timeout(ppi, L1E_TIMEOUT_RX_SYNC) ) {
/* Time-out detected */ /* Time-out detected */
int timeout_tx_sync = (4 << (basicDS->logL1SyncInterval + 8)) * basicDS->L1SyncReceiptTimeout; __pp_timeout_set(ppi, L1E_TIMEOUT_RX_SYNC, l1e_get_rx_tmo_ms(basicDS));
__pp_timeout_set(ppi, L1E_TIMEOUT_RX_SYNC, timeout_tx_sync);
basicDS->L1SyncLinkAlive = FALSE; basicDS->L1SyncLinkAlive = FALSE;
execute_state_machine=TRUE; execute_state_machine=TRUE;
} }
...@@ -248,8 +249,6 @@ static int l1e_handle_state_disabled(struct pp_instance *ppi, Boolean new_state) ...@@ -248,8 +249,6 @@ static int l1e_handle_state_disabled(struct pp_instance *ppi, Boolean new_state)
l1e_portDS->basic.peerIsRxCoherent = l1e_portDS->basic.peerIsRxCoherent =
l1e_portDS->basic.peerIsCongruent = l1e_portDS->basic.peerIsCongruent =
FALSE; FALSE;
/* Set extension mode disabled */
l1e_portDS->head.extModeOn = l1e_portDS->parentExtModeOn = 0;
} }
/* Check if state transition needed */ /* Check if state transition needed */
if ( le1_evt_L1_SYNC_ENABLED(ppi) && !le1_evt_L1_SYNC_RESET(ppi) ) { if ( le1_evt_L1_SYNC_ENABLED(ppi) && !le1_evt_L1_SYNC_RESET(ppi) ) {
...@@ -276,8 +275,6 @@ static int l1e_handle_state_idle(struct pp_instance *ppi, Boolean new_state){ ...@@ -276,8 +275,6 @@ static int l1e_handle_state_idle(struct pp_instance *ppi, Boolean new_state){
l1e_portDS->basic.peerIsTxCoherent = l1e_portDS->basic.peerIsTxCoherent =
l1e_portDS->basic.peerIsRxCoherent= l1e_portDS->basic.peerIsRxCoherent=
l1e_portDS->basic.peerIsCongruent = FALSE; l1e_portDS->basic.peerIsCongruent = FALSE;
/* Set extension mode disabled */
l1e_portDS->head.extModeOn = l1e_portDS->parentExtModeOn = 0;
l1e_send_sync_msg(ppi,1); /* Send immediately a message */ l1e_send_sync_msg(ppi,1); /* Send immediately a message */
} }
...@@ -285,6 +282,7 @@ static int l1e_handle_state_idle(struct pp_instance *ppi, Boolean new_state){ ...@@ -285,6 +282,7 @@ static int l1e_handle_state_idle(struct pp_instance *ppi, Boolean new_state){
if ( !le1_evt_L1_SYNC_ENABLED(ppi) || le1_evt_L1_SYNC_RESET(ppi) ) { if ( !le1_evt_L1_SYNC_ENABLED(ppi) || le1_evt_L1_SYNC_RESET(ppi) ) {
/* Go to DISABLE state */ /* Go to DISABLE state */
l1e_portDS->basic.next_state=L1SYNC_DISABLED; l1e_portDS->basic.next_state=L1SYNC_DISABLED;
ppi->link_state=PP_LSTATE_FAILURE;
return 0; /* Treatment required asap */ return 0; /* Treatment required asap */
} }
if ( le1_evt_LINK_OK(ppi) ) { if ( le1_evt_LINK_OK(ppi) ) {
...@@ -303,8 +301,7 @@ static int l1e_handle_state_link_alive(struct pp_instance *ppi, Boolean new_stat ...@@ -303,8 +301,7 @@ static int l1e_handle_state_link_alive(struct pp_instance *ppi, Boolean new_stat
/* State initialization */ /* State initialization */
if ( new_state ) { if ( new_state ) {
/* Initialize time-out peer L1SYNC reception */ /* Initialize time-out peer L1SYNC reception */
int timeout_tx_sync = (4 << (basic->logL1SyncInterval + 8)) * basic->L1SyncReceiptTimeout; __pp_timeout_set(ppi, L1E_TIMEOUT_RX_SYNC, l1e_get_rx_tmo_ms(basic));
__pp_timeout_set(ppi, L1E_TIMEOUT_RX_SYNC, timeout_tx_sync);
} }
/* Check if state transition needed */ /* Check if state transition needed */
...@@ -374,9 +371,9 @@ static int l1e_handle_state_up(struct pp_instance *ppi, Boolean new_state){ ...@@ -374,9 +371,9 @@ static int l1e_handle_state_up(struct pp_instance *ppi, Boolean new_state){
/* State initialization */ /* State initialization */
if ( new_state ) { if ( new_state ) {
l1e_servo_init(ppi); /* The servo can be initialized because the PPL is locked */ // JCB - test one servo
l1e_portDS->head.extModeOn = // l1e_servo_init(ppi); /* The servo can be initialized because the PPL is locked */
l1e_portDS->parentExtModeOn = 1;
WRH_OPER()->enable_ptracker(ppi); WRH_OPER()->enable_ptracker(ppi);
} }
...@@ -384,6 +381,7 @@ static int l1e_handle_state_up(struct pp_instance *ppi, Boolean new_state){ ...@@ -384,6 +381,7 @@ static int l1e_handle_state_up(struct pp_instance *ppi, Boolean new_state){
if ( !le1_evt_LINK_OK(ppi) ) { if ( !le1_evt_LINK_OK(ppi) ) {
/* Go to IDLE state */ /* Go to IDLE state */
next_state=L1SYNC_IDLE; next_state=L1SYNC_IDLE;
ppi->link_state=PP_LSTATE_FAILURE;
} }
if ( !le1_evt_CONFIG_OK(ppi) ) { if ( !le1_evt_CONFIG_OK(ppi) ) {
/* Return to LINK_ALIVE state */ /* Return to LINK_ALIVE state */
...@@ -395,14 +393,13 @@ static int l1e_handle_state_up(struct pp_instance *ppi, Boolean new_state){ ...@@ -395,14 +393,13 @@ static int l1e_handle_state_up(struct pp_instance *ppi, Boolean new_state){
} }
if (next_state!=0 ) { if (next_state!=0 ) {
l1e_portDS->basic.next_state=next_state; l1e_portDS->basic.next_state=next_state;
l1e_portDS->head.extModeOn =
l1e_portDS->parentExtModeOn = 0;
WRH_OPER()->locking_disable(ppi); /* Unlock the PLL */ WRH_OPER()->locking_disable(ppi); /* Unlock the PLL */
l1e_servo_reset(ppi); l1e_servo_reset(ppi);
return 0; /* Treat the next state asap */ return 0; /* Treat the next state asap */
} }
/* Iterative treatment */ /* Iterative treatment */
ppi->link_state=PP_LSTATE_LINKED;
l1e_update_correction_values(ppi); l1e_update_correction_values(ppi);
l1e_send_sync_msg(ppi,0); l1e_send_sync_msg(ppi,0);
return pp_next_delay_2(ppi,L1E_TIMEOUT_TX_SYNC, L1E_TIMEOUT_RX_SYNC); /* Return the shorter timeout */ return pp_next_delay_2(ppi,L1E_TIMEOUT_TX_SYNC, L1E_TIMEOUT_RX_SYNC); /* Return the shorter timeout */
......
...@@ -187,12 +187,12 @@ static int wr_handle_announce(struct pp_instance *ppi) ...@@ -187,12 +187,12 @@ static int wr_handle_announce(struct pp_instance *ppi)
return 0; return 0;
} }
static int wr_sync_followup(struct pp_instance *ppi, struct pp_time *t1) { static int wr_sync_followup(struct pp_instance *ppi) {
if (!WR_DSPOR(ppi)->wrModeOn) if (!WR_DSPOR(ppi)->wrModeOn)
return 0; return 0;
wr_servo_got_sync(ppi, t1, &ppi->t2); wr_servo_got_sync(ppi);
if (CONFIG_HAS_P2P && ppi->delayMechanism == P2P) if (CONFIG_HAS_P2P && ppi->delayMechanism == P2P)
wr_servo_update(ppi); wr_servo_update(ppi);
...@@ -200,18 +200,18 @@ static int wr_sync_followup(struct pp_instance *ppi, struct pp_time *t1) { ...@@ -200,18 +200,18 @@ static int wr_sync_followup(struct pp_instance *ppi, struct pp_time *t1) {
return 1; /* the caller returns too */ return 1; /* the caller returns too */
} }
static int wr_handle_sync(struct pp_instance *ppi, struct pp_time *t1) static int wr_handle_sync(struct pp_instance *ppi)
{ {
/* This handle is called in case of one step clock */ /* This handle is called in case of one step clock */
pp_diag(ppi, ext, 2, "hook: %s\n", __func__); pp_diag(ppi, ext, 2, "hook: %s\n", __func__);
return wr_sync_followup(ppi,t1); return wr_sync_followup(ppi);
} }
static int wr_handle_followup(struct pp_instance *ppi, struct pp_time *t1) static int wr_handle_followup(struct pp_instance *ppi)
{ {
/* This handle is called in case of two step clock */ /* This handle is called in case of two step clock */
pp_diag(ppi, ext, 2, "hook: %s\n", __func__); pp_diag(ppi, ext, 2, "hook: %s\n", __func__);
return wr_sync_followup(ppi,t1); return wr_sync_followup(ppi);
} }
static __attribute__((used)) int wr_handle_presp(struct pp_instance *ppi) static __attribute__((used)) int wr_handle_presp(struct pp_instance *ppi)
...@@ -328,6 +328,10 @@ static void wr_state_change(struct pp_instance *ppi) ...@@ -328,6 +328,10 @@ static void wr_state_change(struct pp_instance *ppi)
} }
} }
static int wr_require_precise_timestamp(struct pp_instance *ppi) {
return WR_DSPOR(ppi)->wrModeOn;
}
struct pp_ext_hooks wr_ext_hooks = { struct pp_ext_hooks wr_ext_hooks = {
.init = wr_init, .init = wr_init,
.open = wr_open, .open = wr_open,
...@@ -347,4 +351,6 @@ struct pp_ext_hooks wr_ext_hooks = { ...@@ -347,4 +351,6 @@ struct pp_ext_hooks wr_ext_hooks = {
.unpack_announce = wr_unpack_announce, .unpack_announce = wr_unpack_announce,
.state_decision = wr_state_decision, .state_decision = wr_state_decision,
.state_change = wr_state_change, .state_change = wr_state_change,
.servo_reset= wr_servo_reset,
.require_precise_timestamp=wr_require_precise_timestamp,
}; };
...@@ -110,8 +110,7 @@ int wr_execute_slave(struct pp_instance *ppi); ...@@ -110,8 +110,7 @@ int wr_execute_slave(struct pp_instance *ppi);
int wr_servo_init(struct pp_instance *ppi); int wr_servo_init(struct pp_instance *ppi);
void wr_servo_reset(struct pp_instance *ppi); void wr_servo_reset(struct pp_instance *ppi);
void wr_servo_enable_tracking(int enable); void wr_servo_enable_tracking(int enable);
int wr_servo_got_sync(struct pp_instance *ppi, struct pp_time *t1, int wr_servo_got_sync(struct pp_instance *ppi);
struct pp_time *t2);
int wr_servo_got_delay(struct pp_instance *ppi); int wr_servo_got_delay(struct pp_instance *ppi);
int wr_servo_update(struct pp_instance *ppi); int wr_servo_update(struct pp_instance *ppi);
......
...@@ -181,7 +181,7 @@ int msg_pack_wrsig(struct pp_instance *ppi, Enumeration16 wr_msg_id) ...@@ -181,7 +181,7 @@ int msg_pack_wrsig(struct pp_instance *ppi, Enumeration16 wr_msg_id)
put_be32(buf+68, wrp->deltaRx.scaledPicoseconds.lsb); put_be32(buf+68, wrp->deltaRx.scaledPicoseconds.lsb);
len = 24; len = 24;
/*JCB: Hack. serrvo_init() called too early. PTP state machine must be modify. */ /*JCB: Hack. servo_init() called too early. PTP state machine must be modify. */
/* We should stay in UNCALIBRATED state during WR protocol */ /* We should stay in UNCALIBRATED state during WR protocol */
s->delta_txm_ps = delta_to_ps(wrp->otherNodeDeltaTx); s->delta_txm_ps = delta_to_ps(wrp->otherNodeDeltaTx);
s->delta_rxm_ps = delta_to_ps(wrp->otherNodeDeltaRx); s->delta_rxm_ps = delta_to_ps(wrp->otherNodeDeltaRx);
......
...@@ -150,14 +150,13 @@ int wr_servo_init(struct pp_instance *ppi) ...@@ -150,14 +150,13 @@ int wr_servo_init(struct pp_instance *ppi)
return 0; return 0;
} }
int wr_servo_got_sync(struct pp_instance *ppi, struct pp_time *t1, int wr_servo_got_sync(struct pp_instance *ppi)
struct pp_time *t2)
{ {
struct wr_servo_state *s = struct wr_servo_state *s =
&((struct wr_data *)ppi->ext_data)->servo_state; &((struct wr_data *)ppi->ext_data)->servo_state;
s->t1 = *t1; apply_faulty_stamp(s, 1); s->t1 = ppi->t1; apply_faulty_stamp(s, 1);
s->t2 = *t2; apply_faulty_stamp(s, 2); s->t2 = ppi->t2; apply_faulty_stamp(s, 2);
got_sync = 1; got_sync = 1;
return 0; return 0;
} }
...@@ -222,8 +221,6 @@ static int wr_p2p_delay(struct pp_instance *ppi, struct wr_servo_state *s) ...@@ -222,8 +221,6 @@ static int wr_p2p_delay(struct pp_instance *ppi, struct wr_servo_state *s)
} }
if (__PP_DIAG_ALLOW(ppi, pp_dt_servo, 1)) { if (__PP_DIAG_ALLOW(ppi, pp_dt_servo, 1)) {
dump_timestamp(ppi, "servo:t1", s->t1);
dump_timestamp(ppi, "servo:t2", s->t2);
dump_timestamp(ppi, "servo:t3", s->t3); dump_timestamp(ppi, "servo:t3", s->t3);
dump_timestamp(ppi, "servo:t4", s->t4); dump_timestamp(ppi, "servo:t4", s->t4);
dump_timestamp(ppi, "servo:t5", s->t5); dump_timestamp(ppi, "servo:t5", s->t5);
...@@ -285,9 +282,6 @@ static int wr_e2e_offset(struct pp_instance *ppi, ...@@ -285,9 +282,6 @@ static int wr_e2e_offset(struct pp_instance *ppi,
if ( is_timestamps_incorrect(ppi,&errcount, 0xF /* mask=t1&t2&t3&t4 */)) if ( is_timestamps_incorrect(ppi,&errcount, 0xF /* mask=t1&t2&t3&t4 */))
return 0; return 0;
if (WRH_OPER()->servo_hook) /* FIXME: check this, missing in p2p */
WRH_OPER()->servo_hook(ppi, WRH_SERVO_ENTER);
SRV(ppi)->update_count++; SRV(ppi)->update_count++;
ppi->t_ops->get(ppi, &s->update_time); ppi->t_ops->get(ppi, &s->update_time);
...@@ -523,8 +517,5 @@ out: ...@@ -523,8 +517,5 @@ out:
/* shmem unlock */ /* shmem unlock */
wrs_shm_write(ppsi_head, WRS_SHM_WRITE_END); wrs_shm_write(ppsi_head, WRS_SHM_WRITE_END);
if (WRH_OPER()->servo_hook)
WRH_OPER()->servo_hook(ppi, WRH_SERVO_LEAVE);
return 0; return 0;
} }
...@@ -284,7 +284,7 @@ void bmc_s1(struct pp_instance *ppi, ...@@ -284,7 +284,7 @@ void bmc_s1(struct pp_instance *ppi,
prop->ptpTimescale = ((frgn_master->flagField[1] & FFB_PTP) != 0); prop->ptpTimescale = ((frgn_master->flagField[1] & FFB_PTP) != 0);
prop->timeSource = frgn_master->timeSource; prop->timeSource = frgn_master->timeSource;
if (ppi->ext_hooks->s1) if (is_ext_hook_available(ppi,s1))
ppi->ext_hooks->s1(ppi, frgn_master); ppi->ext_hooks->s1(ppi, frgn_master);
} }
...@@ -1509,7 +1509,7 @@ int bmc(struct pp_instance *ppi) ...@@ -1509,7 +1509,7 @@ int bmc(struct pp_instance *ppi)
} }
/* Extra states handled here */ /* Extra states handled here */
if (ppi->ext_hooks->state_decision) if (is_ext_hook_available(ppi,state_decision))
next_state = ppi->ext_hooks->state_decision(ppi, next_state); next_state = ppi->ext_hooks->state_decision(ppi, next_state);
return next_state; return next_state;
......
...@@ -21,11 +21,20 @@ static int presp_call_servo(struct pp_instance *ppi) ...@@ -21,11 +21,20 @@ static int presp_call_servo(struct pp_instance *ppi)
return 0; /* not an error, just no data */ return 0; /* not an error, just no data */
pp_timeout_set(ppi, PP_TO_FAULT); pp_timeout_set(ppi, PP_TO_FAULT);
if (ppi->ext_hooks->handle_presp) if (is_ext_hook_available(ppi,handle_presp))
ret = ppi->ext_hooks->handle_presp(ppi); ret = ppi->ext_hooks->handle_presp(ppi);
else else {
pp_servo_got_presp(ppi); if ( pp_servo_got_presp(ppi) && !ppi->ext_enabled ) {
ppi->link_state=PP_LSTATE_LINKED;
}
}
if ( ppi->state==PPS_MASTER) {
/* Called to update meanLinkDelay
* No risk of interaction with the slave servo.
* Each instance has its own servo structure
*/
pp_servo_calculate_delays(ppi);
}
return ret; return ret;
} }
...@@ -146,13 +155,17 @@ int st_com_peer_handle_preq(struct pp_instance *ppi, void *buf, ...@@ -146,13 +155,17 @@ int st_com_peer_handle_preq(struct pp_instance *ppi, void *buf,
if (ppi->delayMechanism != P2P) if (ppi->delayMechanism != P2P)
return 0; return 0;
if (ppi->ext_hooks->handle_preq) if (is_ext_hook_available(ppi,handle_preq))
e = ppi->ext_hooks->handle_preq(ppi); e = ppi->ext_hooks->handle_preq(ppi);
if (e) if (e)
return e; return e;
msg_issue_pdelay_resp(ppi, &ppi->last_rcv_time); msg_issue_pdelay_resp(ppi, &ppi->last_rcv_time);
msg_issue_pdelay_resp_followup(ppi, &ppi->last_snt_time); msg_issue_pdelay_resp_followup(ppi, &ppi->last_snt_time);
if ( !ppi->ext_enabled ) {
ppi->link_state=PP_LSTATE_LINKED;
}
return 0; return 0;
} }
......
...@@ -122,14 +122,14 @@ int st_com_handle_announce(struct pp_instance *ppi, void *buf, int len) ...@@ -122,14 +122,14 @@ int st_com_handle_announce(struct pp_instance *ppi, void *buf, int len)
if ( ! DSPOR(ppi)->masterOnly ) { if ( ! DSPOR(ppi)->masterOnly ) {
bmc_add_frgn_master(ppi, buf, len); bmc_add_frgn_master(ppi, buf, len);
} }
if (ppi->ext_hooks->handle_announce) if (is_ext_hook_available(ppi,handle_announce))
return ppi->ext_hooks->handle_announce(ppi); return ppi->ext_hooks->handle_announce(ppi);
return 0; return 0;
} }
int st_com_handle_signaling(struct pp_instance *ppi, void *buf, int len) int st_com_handle_signaling(struct pp_instance *ppi, void *buf, int len)
{ {
if (ppi->ext_hooks->handle_signaling) if (is_ext_hook_available(ppi,handle_signaling))
return ppi->ext_hooks->handle_signaling(ppi,buf,len); return ppi->ext_hooks->handle_signaling(ppi,buf,len);
return 0; return 0;
} }
...@@ -173,5 +173,3 @@ int __send_and_log(struct pp_instance *ppi, int msglen, int chtype,enum pp_msg_f ...@@ -173,5 +173,3 @@ int __send_and_log(struct pp_instance *ppi, int msglen, int chtype,enum pp_msg_f
void __attribute__((weak)) update_meanDelay(struct pp_instance *ppi, TimeInterval meanDelay) { void __attribute__((weak)) update_meanDelay(struct pp_instance *ppi, TimeInterval meanDelay) {
DSCUR(ppi)->meanDelay=meanDelay; DSCUR(ppi)->meanDelay=meanDelay;
} }
...@@ -237,7 +237,7 @@ static int msg_pack_announce(struct pp_instance *ppi) ...@@ -237,7 +237,7 @@ static int msg_pack_announce(struct pp_instance *ppi)
*(UInteger8 *) (buf + 62) = (UInteger8)DSCUR(ppi)->stepsRemoved; *(UInteger8 *) (buf + 62) = (UInteger8)DSCUR(ppi)->stepsRemoved;
*(Enumeration8 *) (buf + 63) = DSPRO(ppi)->timeSource; *(Enumeration8 *) (buf + 63) = DSPRO(ppi)->timeSource;
if (ppi->ext_hooks->pack_announce) if (is_ext_hook_available(ppi,pack_announce))
len = ppi->ext_hooks->pack_announce(ppi); len = ppi->ext_hooks->pack_announce(ppi);
return len; return len;
} }
...@@ -263,7 +263,7 @@ void msg_unpack_announce(struct pp_instance *ppi, void *buf, MsgAnnounce *ann) ...@@ -263,7 +263,7 @@ void msg_unpack_announce(struct pp_instance *ppi, void *buf, MsgAnnounce *ann)
ann->timeSource = *(Enumeration8 *) (buf + 63); ann->timeSource = *(Enumeration8 *) (buf + 63);
/* this can fill in extention specific flags otherwise just zero them*/ /* this can fill in extention specific flags otherwise just zero them*/
if (ppi->ext_hooks->unpack_announce) if (is_ext_hook_available(ppi,unpack_announce))
ppi->ext_hooks->unpack_announce(buf, ann); ppi->ext_hooks->unpack_announce(buf, ann);
else else
ann->ext_specific = 0; ann->ext_specific = 0;
......
...@@ -158,7 +158,7 @@ int pp_init_globals(struct pp_globals *ppg, struct pp_runtime_opts *pp_rt_opts) ...@@ -158,7 +158,7 @@ int pp_init_globals(struct pp_globals *ppg, struct pp_runtime_opts *pp_rt_opts)
struct pp_instance *ppi = INST(ppg, i); struct pp_instance *ppi = INST(ppg, i);
int r; int r;
if (ppi->ext_hooks->open) { if (is_ext_hook_available(ppi,open)) {
ret=(r=ppi->ext_hooks->open(ppi, rt_opts))==0 ? ret : r; ret=(r=ppi->ext_hooks->open(ppi, rt_opts))==0 ? ret : r;
} }
} }
...@@ -174,7 +174,7 @@ int pp_close_globals(struct pp_globals *ppg) ...@@ -174,7 +174,7 @@ int pp_close_globals(struct pp_globals *ppg)
struct pp_instance *ppi = INST(ppg, i); struct pp_instance *ppi = INST(ppg, i);
int r; int r;
if (ppi->ext_hooks->close) { if (is_ext_hook_available(ppi,close) ){
ret=(r=ppi->ext_hooks->close(ppi))==0 ? ret : r; ret=(r=ppi->ext_hooks->close(ppi))==0 ? ret : r;
} }
} }
......
...@@ -22,11 +22,18 @@ extern struct wrs_shm_head *ppsi_head; ...@@ -22,11 +22,18 @@ extern struct wrs_shm_head *ppsi_head;
static void pp_servo_mpd_fltr(struct pp_instance *, struct pp_avg_fltr *, static void pp_servo_mpd_fltr(struct pp_instance *, struct pp_avg_fltr *,
struct pp_time *); struct pp_time *);
static int pp_servo_offset_master(struct pp_instance *, struct pp_time *, static int pp_servo_offset_master(struct pp_instance *, struct pp_time *);
struct pp_time *, struct pp_time *);
static int64_t pp_servo_pi_controller(struct pp_instance *, struct pp_time *); static int64_t pp_servo_pi_controller(struct pp_instance *, struct pp_time *);
static void _pp_servo_init(struct pp_instance *ppi); static void _pp_servo_init(struct pp_instance *ppi);
static void __pp_servo_update(struct pp_instance *ppi);
void pp_servo_apply_faulty_stamp(struct pp_servo *s, struct pp_time *faulty_stamps, int index)
{
if (PROTO_EXT_HAS_FAULTS) {
assert(index >= 1 && index <= 6, "Wrong T index %i\n", index);
pp_time_add(&s->t1 + index - 1, faulty_stamps + index - 1);
}
}
void pp_servo_init(struct pp_instance *ppi) void pp_servo_init(struct pp_instance *ppi)
{ {
...@@ -38,10 +45,10 @@ void pp_servo_init(struct pp_instance *ppi) ...@@ -38,10 +45,10 @@ void pp_servo_init(struct pp_instance *ppi)
static void _pp_servo_init(struct pp_instance *ppi) static void _pp_servo_init(struct pp_instance *ppi)
{ {
int d; int d;
SRV(ppi)->state=0; struct pp_servo * servo=SRV(ppi);
SRV(ppi)->servo_state_name[0]=0;
SRV(ppi)->mpd_fltr.s_exp = 0; /* clears meanDelay filter */
PP_SERVO_RESET_DATA(servo);
servo->mpd_fltr.s_exp = 0; /* clears meanDelay filter */
if (ppi->t_ops->init_servo) { if (ppi->t_ops->init_servo) {
/* The system may pre-set us to keep current frequency */ /* The system may pre-set us to keep current frequency */
d = ppi->t_ops->init_servo(ppi); d = ppi->t_ops->init_servo(ppi);
...@@ -49,239 +56,305 @@ static void _pp_servo_init(struct pp_instance *ppi) ...@@ -49,239 +56,305 @@ static void _pp_servo_init(struct pp_instance *ppi)
pp_diag(ppi, servo, 1, "error in t_ops->servo_init"); pp_diag(ppi, servo, 1, "error in t_ops->servo_init");
d = 0; d = 0;
} }
SRV(ppi)->obs_drift = -d << 10; /* note "-" */ servo->obs_drift = -d << 10; /* note "-" */
} else { } else {
/* level clock */ /* level clock */
if (pp_can_adjust(ppi)) if (pp_can_adjust(ppi))
ppi->t_ops->adjust(ppi, 0, 0); ppi->t_ops->adjust(ppi, 0, 0);
SRV(ppi)->obs_drift = 0; servo->obs_drift = 0;
} }
SRV(ppi)->flags |= PP_SERVO_FLAG_VALID; servo->flags |= PP_SERVO_FLAG_VALID;
SRV(ppi)->update_count = 0;
pp_timeout_set(ppi, PP_TO_FAULT); pp_timeout_set(ppi, PP_TO_FAULT);
pp_diag(ppi, servo, 1, "Initialized: obs_drift %lli\n", pp_diag(ppi, servo, 1, "Initialized: obs_drift %lli\n",
SRV(ppi)->obs_drift); servo->obs_drift);
} }
/* internal helper, returning static storage to be used immediately */
static char *fmt_ppt(struct pp_time *t) #define BITS_IN_INT64 (sizeof(int64_t)*8)
{
static char s[24]; /* Get the position of the first bit set on the left of a 64 bits integer */
static int getMsbSet(int64_t value) {
pp_sprintf(s, "%s%d.%09d", if ( value==0 )
(t->secs < 0 || (t->secs == 0 && t->scaled_nsecs < 0)) return 0; /* value=0 so return bit 0 */
? "-" : " ", if ( value<0 )
/* FIXME: this is wrong for some of the negatives */ value=-value; /* Negative value: change it to its positive value for the calculation */
(int)abs(t->secs), (int)abs(t->scaled_nsecs >> 16)); return BITS_IN_INT64 - __builtin_clzll(value); /* using gcc built-in function */
return s;
} }
/* Called by slave and uncalib when we have t1 and t2 */ #define DELAY_ASYM_BASE_FRACTION 50 /* Maxim value that can be used for the calculation */
void pp_servo_got_sync(struct pp_instance *ppi)
{
struct pp_time *delayMS = &SRV(ppi)->delayMS;
static int errcount=0;
if ( is_timestamps_incorrect(ppi,&errcount,3 /* mask=t1&t2 */) ) /**
return; * Calculate the delayAsymmetry : delayAsymCoeff * meanDelay
*
* This calculation is made in order to use the maximum of bits in the fraction part. It will depend
* on the value of delayAsymCoeff and meanDelay. The smaller these values will be, bigger
* the fraction part will be.
*/
static TimeInterval calculateDelayAsymmetry(RelativeDifference scaledDelayAsymCoeff, TimeInterval scaledMeanDelay, TimeInterval constantAsymmetry) {
TimeInterval delayAsym;
int64_t rescaledAsymDelayCoeff,rescaledMeanDelay;
int lostBits,fracBitsUsed;
lostBits=getMsbSet(scaledDelayAsymCoeff)-(REL_DIFF_FRACBITS-DELAY_ASYM_BASE_FRACTION)+
getMsbSet(scaledMeanDelay)+(DELAY_ASYM_BASE_FRACTION-TIME_INTERVAL_FRACBITS)-BITS_IN_INT64;
if ( lostBits<0 )
lostBits=0;
fracBitsUsed=DELAY_ASYM_BASE_FRACTION-(lostBits>>1)-1;
rescaledMeanDelay = scaledMeanDelay<<(fracBitsUsed-TIME_INTERVAL_FRACBITS);
rescaledAsymDelayCoeff=scaledDelayAsymCoeff>>(REL_DIFF_FRACBITS-fracBitsUsed);
delayAsym= rescaledAsymDelayCoeff*rescaledMeanDelay;
delayAsym+=(1<<(fracBitsUsed-1));
delayAsym>>=fracBitsUsed;
delayAsym>>=(fracBitsUsed-TIME_INTERVAL_FRACBITS);
delayAsym+=constantAsymmetry;
return delayAsym;
}
static int calculate_p2p_delayMM(struct pp_instance *ppi) {
struct pp_servo *servo=SRV(ppi);
struct pp_time mtime, stime; /* Avoid modifying stamps in place*/
static int errcount;
if ( is_timestamps_incorrect(ppi,&errcount, 0x3C /* mask=t3&t4&t5&t6*/))
return 0; /* Error. Invalid timestamps */
if (__PP_DIAG_ALLOW(ppi, pp_dt_servo, 2)) {
pp_diag(ppi, servo, 2, "T3: %s s\n", time_to_string(&ppi->t3));
pp_diag(ppi, servo, 2, "T4: %s s\n", time_to_string(&ppi->t4));
pp_diag(ppi, servo, 2, "T5: %s s\n", time_to_string(&ppi->t5));
pp_diag(ppi, servo, 2, "T6: %s s\n", time_to_string(&ppi->t6));
}
/* /*
* calc 'master_to_slave_delay'; no correction field * Calculate of the round trip delay (delayMM)
* appears in the formulas because it's already merged with t1 * delayMM = (t6-t3)-(t5-t4)
*/ */
*delayMS = ppi->t2;
pp_time_sub(delayMS, &ppi->t1);
SRV(ppi)->update_count++; stime = servo->t6; pp_time_sub(&stime, &servo->t3);
mtime = servo->t5; pp_time_sub(&mtime, &servo->t4);
servo->delayMM = stime;
pp_time_sub(&servo->delayMM, &mtime);
return 1;
} }
/* Called by slave and uncalib when we have t1 and t2 */ static int calculate_e2e_delayMM(struct pp_instance *ppi) {
void pp_servo_got_psync(struct pp_instance *ppi) struct pp_servo *servo=SRV(ppi);
{ struct pp_time mtime, stime; /* Avoid modifying stamps in place*/
struct pp_time *m_to_s_dly = &SRV(ppi)->delayMS; static int errcount;
struct pp_time *mpd = &SRV(ppi)->meanDelay;
struct pp_time *ofm = &SRV(ppi)->offsetFromMaster;
int adj32;
static int errcount=0;
if ( is_timestamps_incorrect(ppi,&errcount,3 /* mask=t1&t2 */) )
return;
pp_diag(ppi, servo, 2, "T1: %s\n", fmt_ppt(&ppi->t1)); if ( is_timestamps_incorrect(ppi,&errcount, 0xF /* mask=t1&t2&t3&t4*/))
pp_diag(ppi, servo, 2, "T2: %s\n", fmt_ppt(&ppi->t2)); return 0; /* Error. Invalid timestamps */
shmem_lock(); /* Share memory locked */ if (__PP_DIAG_ALLOW(ppi, pp_dt_servo, 2)) {
pp_diag(ppi, servo, 2, "T1: %s s\n", time_to_string(&servo->t1));
pp_diag(ppi, servo, 2, "T2: %s s\n", time_to_string(&servo->t2));
pp_diag(ppi, servo, 2, "T3: %s s\n", time_to_string(&servo->t3));
pp_diag(ppi, servo, 2, "T4: %s s\n", time_to_string(&servo->t4));
}
/* /*
* calc 'master_to_slave_delay'; no correction field * Calculate the round trip delay (delayMM)
* appears in the formulas because it's already merged with t1 * delayMM = t4-t1-(t3-t2)
*/ */
*m_to_s_dly = ppi->t2; mtime = servo->t4;
pp_time_sub(m_to_s_dly, &ppi->t1); pp_time_sub(&mtime, &servo->t1);
stime = servo->t3;
pp_time_sub(&stime, &servo->t2);
servo->delayMM = mtime;
pp_time_sub(&servo->delayMM, &stime);
return 1;
}
/* update 'offsetFromMaster' and possibly jump in time */ int pp_servo_calculate_delays(struct pp_instance *ppi) {
if (!pp_servo_offset_master(ppi, mpd, ofm, m_to_s_dly)) { int64_t meanDelay_ps,delayMM_ps,delayMS_ps;
static int errcount;
struct pp_servo *servo=SRV(ppi);
int ret;
/* PI controller returns a scaled_nsecs adjustment, so shift back */ /* t1/t2 needed by both P2P and E2E calculation */
adj32 = (int)(pp_servo_pi_controller(ppi, ofm) >> 16); if ( is_timestamps_incorrect(ppi,&errcount, 0x3 /* mask=t1&t2 */))
return 0; /* Error. Invalid timestamps */
/* apply controller output as a clock tick rate adjustment, if if (CONFIG_HAS_P2P && ppi->delayMechanism == P2P)
* provided by arch, or as a raw offset otherwise */ ret=calculate_p2p_delayMM(ppi);
if (pp_can_adjust(ppi)) { else
if (ppi->t_ops->adjust_freq) ret=calculate_e2e_delayMM(ppi);
ppi->t_ops->adjust_freq(ppi, -adj32); if ( !ret)
else return 0; /* delays cannot be calculated */
ppi->t_ops->adjust_offset(ppi, -adj32);
}
pp_diag(ppi, servo, 2, "Observed drift: %9i\n", delayMM_ps = pp_time_to_picos(&servo->delayMM);
(int)SRV(ppi)->obs_drift >> 10);
/*
* Calculate the meanDelay
* meanDelay=delayMM/2)
*/
meanDelay_ps=delayMM_ps>>1; /* meanDelay=delayMM/2 */
if ( ppi->asymmetryCorrectionPortDS.enable ) {
/* Enabled: The delay asymmetry must be calculated
* delayAsymmetry=delayAsymCoefficient * meanPathDelay
*/
ppi->portDS->delayAsymmetry=calculateDelayAsymmetry(ppi->portDS->delayAsymCoeff,
picos_to_interval(meanDelay_ps),
ppi->asymmetryCorrectionPortDS.constantAsymmetry);
} else {
/* Disabled: The delay asymmetry is provided by configuration */
ppi->portDS->delayAsymmetry=ppi->asymmetryCorrectionPortDS.constantAsymmetry;
} }
SRV(ppi)->update_count++; /* delayMS = meanDelay + delayAsym */
shmem_unlock(); /* Share memory unlocked */ delayMS_ps = meanDelay_ps + interval_to_picos(ppi->portDS->delayAsymmetry);
picos_to_pp_time(delayMS_ps, &SRV(ppi)->delayMS);
/* Calculate offsetFromMaster : t1-t2+meanDelay+delayAsym=t1-t2+delayMS */
servo->offsetFromMaster = servo->t1;
pp_time_sub(&servo->offsetFromMaster, &servo->t2);
pp_time_add(&servo->offsetFromMaster, &servo->delayMS); /* Add delayMS */
DSCUR(ppi)->offsetFromMaster = pp_time_to_interval(&servo->offsetFromMaster); /* Update currentDS.offsetFromMaster */
picos_to_pp_time(meanDelay_ps,&servo->meanDelay); /* update servo.meanDelay */
update_meanDelay(ppi,picos_to_interval(meanDelay_ps)); /* update currentDS.meanDelay and portDS.meanLinkDelay (if needed) */
if (__PP_DIAG_ALLOW(ppi, pp_dt_servo, 2)) {
pp_diag(ppi, servo, 2,"delayMM : %s s\n", time_to_string(&servo->delayMM));
pp_diag(ppi, servo, 2,"delayMS : %s s\n", time_to_string(&servo->delayMS));
pp_diag(ppi, servo, 2,"delayAsym : %s ns\n", relative_interval_to_string(ppi->portDS->delayAsymCoeff));
pp_diag(ppi, servo, 2,"delayAsymCoeff : %s ns\n", interval_to_string(ppi->portDS->delayAsymmetry));
pp_diag(ppi, servo, 2,"meanDelay : %s s\n", time_to_string(&servo->meanDelay));
pp_diag(ppi, servo, 2,"offsetFromMaster: %s s\n", time_to_string(&servo->offsetFromMaster));
}
return 1;
}
/* Called by slave and uncalib when we have t1 and t2 */
/* t1 & t2 are already checked and they are correct */
void pp_servo_got_sync(struct pp_instance *ppi)
{
struct pp_servo *servo=SRV(ppi);
shmem_lock(); /* Share memory locked */
servo->t1=ppi->t1;
servo->t2=ppi->t2;
if (CONFIG_HAS_P2P && ppi->delayMechanism == P2P && servo->got_sync) {
/* P2P mechanism */
servo->got_sync=0;
__pp_servo_update(ppi);
} else
servo->got_sync=1;
shmem_unlock(); /* Share memory locked */
} }
/* called by slave states when delay_resp is received (all t1..t4 are valid) */ /* called by slave states when delay_resp is received (all t1..t4 are valid) */
void pp_servo_got_resp(struct pp_instance *ppi) int pp_servo_got_resp(struct pp_instance *ppi)
{ {
struct pp_time *delayMS = &SRV(ppi)->delayMS; struct pp_servo *servo=SRV(ppi);
struct pp_time *delaySM = &SRV(ppi)->delaySM;
struct pp_time *mpd = &SRV(ppi)->meanDelay;
struct pp_time *ofm = &SRV(ppi)->offsetFromMaster;
struct pp_avg_fltr *mpd_fltr = &SRV(ppi)->mpd_fltr;
int adj32;
static int errcount=0; static int errcount=0;
if ( !servo->got_sync )
return 0; /* t1 & t2 not available yet */
servo->got_sync=0; /* reseted for next time */
/* We sometimes enter here before we got sync/f-up */
if (ppi->t1.secs == 0 && ppi->t1.scaled_nsecs == 0) {
pp_diag(ppi, servo, 2, "discard T3/T4: we miss T1/T2\n");
return;
}
if ( is_timestamps_incorrect(ppi,&errcount,0xF /* mask=t1&t2&t3&t4 */) ) if ( is_timestamps_incorrect(ppi,&errcount,0xC /* mask=t3&t4 */) ) {
return; return 0;
shmem_lock(); /* Share memory locked */
/*
* calc 'slave_to_master_delay', removing delay_resp correction field
* added by transparent clocks in the path.
*/
*delaySM = ppi->t4;
pp_time_sub(delaySM, &ppi->t3);
pp_diag(ppi, servo, 2, "T1: %s\n", fmt_ppt(&ppi->t1));
pp_diag(ppi, servo, 2, "T2: %s\n", fmt_ppt(&ppi->t2));
pp_diag(ppi, servo, 2, "T3: %s\n", fmt_ppt(&ppi->t3));
pp_diag(ppi, servo, 2, "T4: %s\n", fmt_ppt(&ppi->t4));
pp_diag(ppi, servo, 1, "delayMS: %s\n", fmt_ppt(delayMS));
pp_diag(ppi, servo, 1, "delaySM: %s\n", fmt_ppt(delaySM));
/* Calc mean path delay, used later to calc "offset from master" */
*mpd = SRV(ppi)->delayMS;
pp_time_add(mpd, &SRV(ppi)->delaySM);
pp_time_div2(mpd);
update_meanDelay(ppi,pp_time_to_interval(mpd)); /* update currentDS.meanDelay and portDS.meanLinkDelay (idf needed) */
pp_diag(ppi, servo, 1, "meanDelay: %s\n", fmt_ppt(mpd));
if (mpd->secs) {/* Hmm.... we called this "bad event" */
shmem_unlock(); /* Share memory unlocked */
return;
} }
/* mean path delay filtering */ shmem_lock(); /* Share memory locked */
pp_servo_mpd_fltr(ppi, mpd_fltr, mpd);
/* update 'offsetFromMaster' and possibly jump in time */
if (!pp_servo_offset_master(ppi, mpd, ofm, delayMS)) {
/* PI controller */ /* Save t3 and t4 */
adj32 = (int)(pp_servo_pi_controller(ppi, ofm) >> 16); servo->t3=ppi->t3;
servo->t4=ppi->t4;
/* apply controller output as a clock tick rate adjustment, if __pp_servo_update(ppi);
* provided by arch, or as a raw offset otherwise */
if (pp_can_adjust(ppi)) {
if (ppi->t_ops->adjust_freq) {
ppi->t_ops->adjust_freq(ppi, -adj32);
}
else {
ppi->t_ops->adjust_offset(ppi, -adj32);
}
}
}
SRV(ppi)->update_count++;
shmem_unlock(); /* Share memory unlocked */
pp_diag(ppi, servo, 2, "Observed drift: %9i\n", shmem_unlock(); /* Share memory locked */
(int)SRV(ppi)->obs_drift >> 10); return 1;
} }
/* called by slave states when delay_resp is received (all t1..t4 are valid) */ /* called by slave states when delay_resp is received (all t1..t4 are valid) */
void pp_servo_got_presp(struct pp_instance *ppi) int pp_servo_got_presp(struct pp_instance *ppi)
{ {
struct pp_time *delayMS = &SRV(ppi)->delayMS; struct pp_servo * servo = SRV(ppi);
struct pp_time *delaySM = &SRV(ppi)->delaySM;
struct pp_time *mpd = &SRV(ppi)->meanDelay;
struct pp_avg_fltr *mpd_fltr = &SRV(ppi)->mpd_fltr;
static int errcount=0; static int errcount=0;
if ( is_timestamps_incorrect(ppi,&errcount,0x3C /* mask=&t3&t4&t5&t6 */) ) if ( is_timestamps_incorrect(ppi,&errcount,0x3C /* mask=&t3&t4&t5&t6 */) )
return; return 0;
shmem_lock(); /* Share memory locked */ shmem_lock(); /* Share memory locked */
/*
* calc 'slave_to_master_delay', removing the correction field
* added by transparent clocks in the path.
*/
*delaySM = ppi->t6;
pp_time_sub(delaySM, &ppi->t5);
*delayMS = ppi->t4; servo->t3=ppi->t3;
pp_time_sub(delayMS, &ppi->t3); servo->t4=ppi->t4;
servo->t5=ppi->t5;
servo->t6=ppi->t6;
servo->got_sync=1;
pp_diag(ppi, servo, 2, "T3: %s\n", fmt_ppt(&ppi->t3)); shmem_unlock(); /* Share memory unlocked */
pp_diag(ppi, servo, 2, "T4: %s\n", fmt_ppt(&ppi->t4)); return 1;
pp_diag(ppi, servo, 2, "T5: %s\n", fmt_ppt(&ppi->t5)); }
pp_diag(ppi, servo, 2, "T6: %s\n", fmt_ppt(&ppi->t6));
pp_diag(ppi, servo, 1, "delayMS: %s\n", fmt_ppt(delayMS));
pp_diag(ppi, servo, 1, "delaySM: %s\n", fmt_ppt(delaySM));
/* Calc mean path delay, used later to calc "offset from master" */
*mpd = SRV(ppi)->delayMS;
pp_time_add(mpd, &SRV(ppi)->delaySM);
pp_time_div2(mpd);
update_meanDelay(ppi,pp_time_to_interval(mpd)); /* update currentDS.meanDelay and portDS.meanLinkDelay (idf needed) */
pp_diag(ppi, servo, 1, "meanDelay: %s\n", fmt_ppt(mpd));
if (!mpd->secs) /* =0 Hmm.... we called this "bad event" */ static void __pp_servo_update(struct pp_instance *ppi) {
pp_servo_mpd_fltr(ppi, mpd_fltr, mpd); struct pp_servo *servo=SRV(ppi);
struct pp_time *meanDelay =&servo->meanDelay;
struct pp_avg_fltr *meanDelayFilter = &servo->mpd_fltr;
struct pp_time *offsetFromMaster = &servo->offsetFromMaster;
int adj32;
SRV(ppi)->update_count++; if ( !pp_servo_calculate_delays(ppi) )
return;
if (meanDelay->secs) /* Hmm.... we called this "bad event" */
return;
pp_servo_mpd_fltr(ppi, meanDelayFilter, meanDelay);
/* update 'offsetFromMaster' and possibly jump in time */
if (!pp_servo_offset_master(ppi,offsetFromMaster)) {
/* PI controller returns a scaled_nsecs adjustment, so shift back */
adj32 = (int)(pp_servo_pi_controller(ppi, offsetFromMaster) >> 16);
/* apply controller output as a clock tick rate adjustment, if
* provided by arch, or as a raw offset otherwise */
if (pp_can_adjust(ppi)) {
if (ppi->t_ops->adjust_freq)
ppi->t_ops->adjust_freq(ppi, adj32);
else
ppi->t_ops->adjust_offset(ppi, adj32);
}
pp_diag(ppi, servo, 2, "Observed drift: %9i\n",
(int)SRV(ppi)->obs_drift >> 10);
}
servo->update_count++;
ppi->t_ops->get(ppi, &servo->update_time);
shmem_unlock(); /* Share memory unlocked */
} }
static void pp_servo_mpd_fltr(struct pp_instance *ppi, struct pp_avg_fltr *mpd_fltr, static void pp_servo_mpd_fltr(struct pp_instance *ppi, struct pp_avg_fltr *meanDelayFilter,
struct pp_time *mpd) struct pp_time *meanDelay)
{ {
int s; int s;
uint64_t y; uint64_t y;
if (mpd_fltr->s_exp < 1) { if (meanDelayFilter->s_exp < 1) {
/* First time, keep what we have */ /* First time, keep what we have */
mpd_fltr->y = mpd->scaled_nsecs; meanDelayFilter->y = meanDelay->scaled_nsecs;
if (mpd->scaled_nsecs < 0) if (meanDelay->scaled_nsecs < 0)
mpd_fltr->y = 0; meanDelayFilter->y = 0;
} }
/* avoid overflowing filter: calculate number of bits */ /* avoid overflowing filter: calculate number of bits */
s = OPTS(ppi)->s; s = OPTS(ppi)->s;
while (mpd_fltr->y >> (63 - s)) while (meanDelayFilter->y >> (63 - s))
--s; --s;
if (mpd_fltr->s_exp > 1LL << s) if (meanDelayFilter->s_exp > 1LL << s)
mpd_fltr->s_exp = 1LL << s; meanDelayFilter->s_exp = 1LL << s;
/* crank down filter cutoff by increasing 's_exp' */ /* crank down filter cutoff by increasing 's_exp' */
if (mpd_fltr->s_exp < 1LL << s) if (meanDelayFilter->s_exp < 1LL << s)
++mpd_fltr->s_exp; ++meanDelayFilter->s_exp;
/* /*
* It may happen that mpd appears as negative. This happens when * It may happen that mpd appears as negative. This happens when
...@@ -290,10 +363,10 @@ static void pp_servo_mpd_fltr(struct pp_instance *ppi, struct pp_avg_fltr *mpd_f ...@@ -290,10 +363,10 @@ static void pp_servo_mpd_fltr(struct pp_instance *ppi, struct pp_avg_fltr *mpd_f
* measured in the master. Ignore such values, by keeping the * measured in the master. Ignore such values, by keeping the
* current average instead. * current average instead.
*/ */
if (mpd->scaled_nsecs < 0) if (meanDelay->scaled_nsecs < 0)
mpd->scaled_nsecs = mpd_fltr->y; meanDelay->scaled_nsecs = meanDelayFilter->y;
if (mpd->scaled_nsecs < 0) if (meanDelay->scaled_nsecs < 0)
mpd->scaled_nsecs = 0; meanDelay->scaled_nsecs = 0;
/* /*
* It may happen that mpd appears to be very big. This happens * It may happen that mpd appears to be very big. This happens
...@@ -305,19 +378,19 @@ static void pp_servo_mpd_fltr(struct pp_instance *ppi, struct pp_avg_fltr *mpd_f ...@@ -305,19 +378,19 @@ static void pp_servo_mpd_fltr(struct pp_instance *ppi, struct pp_avg_fltr *mpd_f
* The constant multipliers have been chosed arbitrarily, but * The constant multipliers have been chosed arbitrarily, but
* they work well in testing environment. * they work well in testing environment.
*/ */
if (mpd->scaled_nsecs > 3 * mpd_fltr->y) { if (meanDelay->scaled_nsecs > 3 * meanDelayFilter->y) {
pp_diag(ppi, servo, 1, "Trim too-long mpd: %i\n", pp_diag(ppi, servo, 1, "Trim too-long mpd: %i\n",
(int)(mpd->scaled_nsecs >> 16)); (int)(meanDelay->scaled_nsecs >> 16));
/* add fltr->s_exp to ensure we are not trapped into 0 */ /* add fltr->s_exp to ensure we are not trapped into 0 */
mpd->scaled_nsecs = mpd_fltr->y * 2 + mpd_fltr->s_exp + 1; meanDelay->scaled_nsecs = meanDelayFilter->y * 2 + meanDelayFilter->s_exp + 1;
} }
/* filter 'meanDelay' (running average) -- use an unsigned "y" */ /* filter 'meanDelay' (running average) -- use an unsigned "y" */
y = (mpd_fltr->y * (mpd_fltr->s_exp - 1) + mpd->scaled_nsecs); y = (meanDelayFilter->y * (meanDelayFilter->s_exp - 1) + meanDelay->scaled_nsecs);
__div64_32(&y, mpd_fltr->s_exp); __div64_32(&y, meanDelayFilter->s_exp);
mpd->scaled_nsecs = mpd_fltr->y = y; meanDelay->scaled_nsecs = meanDelayFilter->y = y;
update_meanDelay(ppi,picos_to_interval(pp_time_to_interval(mpd))); /* update currentDS.meanDelay and portDS.meanLinkDelay (idf needed) */ update_meanDelay(ppi,pp_time_to_interval(meanDelay)); /* update currentDS.meanDelay and portDS.meanLinkDelay (idf needed) */
pp_diag(ppi, servo, 1, "After avg(%i), meanDelay: %i\n", pp_diag(ppi, servo, 1, "After avg(%i), meanDelay: %s \n",
(int)mpd_fltr->s_exp, (int)(mpd->scaled_nsecs >> 16)); (int)meanDelayFilter->s_exp, time_to_string(meanDelay));
} }
/* Thresholds are used to decide if we must use time or frequency adjustment /* Thresholds are used to decide if we must use time or frequency adjustment
...@@ -325,14 +398,9 @@ static void pp_servo_mpd_fltr(struct pp_instance *ppi, struct pp_avg_fltr *mpd_f ...@@ -325,14 +398,9 @@ static void pp_servo_mpd_fltr(struct pp_instance *ppi, struct pp_avg_fltr *mpd_f
#define TIME_ADJUST_THRESHOLD_SCALED_NS (((int64_t)20000000)<<TIME_INTERVAL_FRACBITS) /* 20ms */ #define TIME_ADJUST_THRESHOLD_SCALED_NS (((int64_t)20000000)<<TIME_INTERVAL_FRACBITS) /* 20ms */
#define TIME_ADJUST_THRESHOLD_SEC 0 #define TIME_ADJUST_THRESHOLD_SEC 0
static int pp_servo_offset_master(struct pp_instance *ppi, struct pp_time *mpd, static int pp_servo_offset_master(struct pp_instance *ppi, struct pp_time *ofm)
struct pp_time *ofm, struct pp_time *delayMS)
{ {
struct pp_time time_tmp; struct pp_time time_tmp;
*ofm = *delayMS;
pp_time_sub(ofm, mpd);
DSCUR(ppi)->offsetFromMaster=pp_time_to_interval(ofm);
pp_diag(ppi, servo, 1, "Offset from master: %s\n", fmt_ppt(ofm));
if ( !( ofm->secs || if ( !( ofm->secs ||
(ofm->scaled_nsecs>TIME_ADJUST_THRESHOLD_SCALED_NS ) || (ofm->scaled_nsecs>TIME_ADJUST_THRESHOLD_SCALED_NS ) ||
...@@ -345,14 +413,20 @@ static int pp_servo_offset_master(struct pp_instance *ppi, struct pp_time *mpd, ...@@ -345,14 +413,20 @@ static int pp_servo_offset_master(struct pp_instance *ppi, struct pp_time *mpd,
return 0; /* e.g., a loopback test run... "-t" on cmdline */ return 0; /* e.g., a loopback test run... "-t" on cmdline */
ppi->t_ops->get(ppi, &time_tmp); ppi->t_ops->get(ppi, &time_tmp);
pp_time_sub(&time_tmp, ofm); pp_time_add(&time_tmp, ofm);
ppi->t_ops->set(ppi, &time_tmp); ppi->t_ops->set(ppi, &time_tmp);
_pp_servo_init(ppi); _pp_servo_init(ppi);
if (ARCH_IS_WRS) {
/* Enable PPS output */
WRH_OPER()->enable_timing_output(ppi, 1);
}
return 1; /* done */ return 1; /* done */
} }
static static int64_t pp_servo_pi_controller(struct pp_instance * ppi, struct pp_time *ofm)
int64_t pp_servo_pi_controller(struct pp_instance * ppi, struct pp_time *ofm)
{ {
long long I_term; long long I_term;
long long P_term; long long P_term;
......
...@@ -103,7 +103,11 @@ int pp_initializing(struct pp_instance *ppi, void *buf, int len) ...@@ -103,7 +103,11 @@ int pp_initializing(struct pp_instance *ppi, void *buf, int len)
pp_timeout_setall(ppi);/* PP_TO_BMC is not set by default */ pp_timeout_setall(ppi);/* PP_TO_BMC is not set by default */
pp_timeout_set(ppi, PP_TO_BMC); pp_timeout_set(ppi, PP_TO_BMC);
if (ppi->ext_hooks->init) ppi->link_state=PP_LSTATE_PROTOCOL_DETECTION;
ppi->ptp_msg_received=FALSE;
ppi->ext_enabled=(ppi->protocol_extension!=PPSI_EXT_NONE);
if (is_ext_hook_available(ppi,init))
ret = ppi->ext_hooks->init(ppi, buf, len); ret = ppi->ext_hooks->init(ppi, buf, len);
if (ret) { if (ret) {
pp_diag(ppi, ext, 1, "%s: can't init extension\n", __func__); pp_diag(ppi, ext, 1, "%s: can't init extension\n", __func__);
......
...@@ -29,7 +29,7 @@ int pp_listening(struct pp_instance *ppi, void *buf, int len) ...@@ -29,7 +29,7 @@ int pp_listening(struct pp_instance *ppi, void *buf, int len)
MsgHeader *hdr = &ppi->received_ptp_header; MsgHeader *hdr = &ppi->received_ptp_header;
pp_timeout_set(ppi, PP_TO_FAULT); /* no fault as long as we listen */ pp_timeout_set(ppi, PP_TO_FAULT); /* no fault as long as we listen */
if (ppi->ext_hooks->listening) if (is_ext_hook_available(ppi,listening))
e = ppi->ext_hooks->listening(ppi, buf, len); e = ppi->ext_hooks->listening(ppi, buf, len);
if (e) if (e)
goto out; goto out;
......
...@@ -31,7 +31,9 @@ static int master_handle_delay_request(struct pp_instance *ppi, ...@@ -31,7 +31,9 @@ static int master_handle_delay_request(struct pp_instance *ppi,
void *buf, int len) void *buf, int len)
{ {
if (ppi->state == PPS_MASTER) /* not pre-master */ if (ppi->state == PPS_MASTER) /* not pre-master */
msg_issue_delay_resp(ppi, &ppi->last_rcv_time); if ( msg_issue_delay_resp(ppi, &ppi->last_rcv_time)==0 && !ppi->ext_enabled ) {
ppi->link_state=PP_LSTATE_LINKED;
}
return 0; return 0;
} }
...@@ -79,7 +81,7 @@ int pp_master(struct pp_instance *ppi, void *buf, int len) ...@@ -79,7 +81,7 @@ int pp_master(struct pp_instance *ppi, void *buf, int len)
* PPM_NO_MESSAGE * PPM_NO_MESSAGE
*/ */
msgtype = ppi->received_ptp_header.messageType; msgtype = ppi->received_ptp_header.messageType;
if (ppi->ext_hooks->master_msg) if (is_ext_hook_available(ppi,master_msg))
msgtype = ppi->ext_hooks->master_msg(ppi, buf, len, msgtype); msgtype = ppi->ext_hooks->master_msg(ppi, buf, len, msgtype);
if (msgtype < 0) { if (msgtype < 0) {
e = msgtype; e = msgtype;
......
...@@ -36,6 +36,7 @@ static pp_action *actions[] = { ...@@ -36,6 +36,7 @@ static pp_action *actions[] = {
static int slave_handle_sync(struct pp_instance *ppi, void *buf, static int slave_handle_sync(struct pp_instance *ppi, void *buf,
int len) int len)
{ {
static int errcount=0;
MsgHeader *hdr = &ppi->received_ptp_header; MsgHeader *hdr = &ppi->received_ptp_header;
MsgSync sync; MsgSync sync;
...@@ -64,18 +65,19 @@ static int slave_handle_sync(struct pp_instance *ppi, void *buf, ...@@ -64,18 +65,19 @@ static int slave_handle_sync(struct pp_instance *ppi, void *buf,
ppi->t1 = sync.originTimestamp; ppi->t1 = sync.originTimestamp;
pp_time_add(&ppi->t1, &hdr->cField); pp_time_add(&ppi->t1, &hdr->cField);
ppi->syncCF = 0; ppi->syncCF = 0;
/* t1 & t2 are saved in the instance. Check if they are correct */
if ( is_timestamps_incorrect(ppi,&errcount,3 /* mask=t1&t2 */) )
return 0;
/* Call the extension; it may do it all and ask to return */ /* Call the extension; it may do it all and ask to return */
if (ppi->ext_hooks->handle_sync) { if ( is_ext_hook_available(ppi,handle_sync) ) {
int ret = ppi->ext_hooks->handle_sync(ppi, &ppi->t1); int ret = ppi->ext_hooks->handle_sync(ppi);
if (ret == 1) if (ret == 1)
return 0; return 0;
if (ret < 0) if (ret < 0)
return ret; return ret;
} }
if (CONFIG_HAS_P2P && ppi->delayMechanism == P2P) pp_servo_got_sync(ppi);
pp_servo_got_psync(ppi);
else
pp_servo_got_sync(ppi);
} }
return 0; return 0;
} }
...@@ -83,8 +85,8 @@ static int slave_handle_sync(struct pp_instance *ppi, void *buf, ...@@ -83,8 +85,8 @@ static int slave_handle_sync(struct pp_instance *ppi, void *buf,
static int slave_handle_followup(struct pp_instance *ppi, void *buf, static int slave_handle_followup(struct pp_instance *ppi, void *buf,
int len) int len)
{ {
static int errcount=0;
MsgFollowUp follow; MsgFollowUp follow;
int ret = 0;
MsgHeader *hdr = &ppi->received_ptp_header; MsgHeader *hdr = &ppi->received_ptp_header;
...@@ -113,19 +115,19 @@ static int slave_handle_followup(struct pp_instance *ppi, void *buf, ...@@ -113,19 +115,19 @@ static int slave_handle_followup(struct pp_instance *ppi, void *buf,
pp_time_add(&ppi->t1, &follow.preciseOriginTimestamp); pp_time_add(&ppi->t1, &follow.preciseOriginTimestamp);
pp_time_add(&ppi->t1, &hdr->cField); pp_time_add(&ppi->t1, &hdr->cField);
ppi->syncCF = hdr->cField.scaled_nsecs; /* for diag about TC */ ppi->syncCF = hdr->cField.scaled_nsecs; /* for diag about TC */
/* t1 & t2 are saved in the instance. Check if they are correct */
/* Call the extension; it may do it all and ask to return */ if ( is_timestamps_incorrect(ppi,&errcount,3 /* mask=t1&t2 */) )
if (ppi->ext_hooks->handle_followup)
ret = ppi->ext_hooks->handle_followup(ppi, &ppi->t1);
if (ret == 1)
return 0; return 0;
if (ret < 0) /* Call the extension; it may do it all and ask to return */
return ret; if (is_ext_hook_available(ppi,handle_followup) ){
int ret = ppi->ext_hooks->handle_followup(ppi);
if (CONFIG_HAS_P2P && ppi->delayMechanism == P2P) if (ret == 1)
pp_servo_got_psync(ppi); return 0;
else if (ret < 0)
pp_servo_got_sync(ppi); return ret;
}
/* default servo action */
pp_servo_got_sync(ppi);
return 0; return 0;
} }
...@@ -133,9 +135,9 @@ static int slave_handle_followup(struct pp_instance *ppi, void *buf, ...@@ -133,9 +135,9 @@ static int slave_handle_followup(struct pp_instance *ppi, void *buf,
static int slave_handle_response(struct pp_instance *ppi, void *buf, static int slave_handle_response(struct pp_instance *ppi, void *buf,
int len) int len)
{ {
int e = 0;
MsgHeader *hdr = &ppi->received_ptp_header; MsgHeader *hdr = &ppi->received_ptp_header;
MsgDelayResp resp; MsgDelayResp resp;
int ret;
msg_unpack_delay_resp(buf, &resp); msg_unpack_delay_resp(buf, &resp);
...@@ -155,15 +157,17 @@ static int slave_handle_response(struct pp_instance *ppi, void *buf, ...@@ -155,15 +157,17 @@ static int slave_handle_response(struct pp_instance *ppi, void *buf,
/* WARNING: should be "sub" (see README-cfield::BUG) */ /* WARNING: should be "sub" (see README-cfield::BUG) */
pp_timeout_set(ppi, PP_TO_FAULT); pp_timeout_set(ppi, PP_TO_FAULT);
if (ppi->ext_hooks->handle_resp) if (is_ext_hook_available(ppi,handle_resp)) {
e = ppi->ext_hooks->handle_resp(ppi); ret=ppi->ext_hooks->handle_resp(ppi);
else }
pp_servo_got_resp(ppi); else {
if (e) if ( (ret=pp_servo_got_resp(ppi)) && !ppi->ext_enabled ) {
return e; ppi->link_state=PP_LSTATE_LINKED;
}
if (DSPOR(ppi)->logMinDelayReqInterval != }
hdr->logMessageInterval) {
if ( ret &&
DSPOR(ppi)->logMinDelayReqInterval !=hdr->logMessageInterval) {
DSPOR(ppi)->logMinDelayReqInterval = DSPOR(ppi)->logMinDelayReqInterval =
hdr->logMessageInterval; hdr->logMessageInterval;
/* new value for logMin */ /* new value for logMin */
...@@ -200,7 +204,7 @@ static int slave_execute(struct pp_instance *ppi) ...@@ -200,7 +204,7 @@ static int slave_execute(struct pp_instance *ppi)
{ {
int ret = 0; int ret = 0;
if (ppi->ext_hooks->execute_slave) if (is_ext_hook_available(ppi,execute_slave))
ret = ppi->ext_hooks->execute_slave(ppi); ret = ppi->ext_hooks->execute_slave(ppi);
if (ret == 1) /* done: just return */ if (ret == 1) /* done: just return */
return 0; return 0;
...@@ -216,13 +220,13 @@ static int slave_execute(struct pp_instance *ppi) ...@@ -216,13 +220,13 @@ static int slave_execute(struct pp_instance *ppi)
*/ */
int pp_slave(struct pp_instance *ppi, void *buf, int len) int pp_slave(struct pp_instance *ppi, void *buf, int len)
{ {
int e = 0; /* error var, to check errors in msg handling */ int ret = PP_SEND_OK; /* error var, to check errors in msg handling */
int uncalibrated = (ppi->state == PPS_UNCALIBRATED); int uncalibrated = (ppi->state == PPS_UNCALIBRATED);
MsgHeader *hdr = &ppi->received_ptp_header; MsgHeader *hdr = &ppi->received_ptp_header;
/* upgrade from uncalibrated to slave or back*/ /* upgrade from uncalibrated to slave or back*/
if (uncalibrated) { if (uncalibrated) {
if ( ppi->ext_hooks->ready_for_slave != NULL ) { if ( is_ext_hook_available(ppi,ready_for_slave) ) {
if ( (*ppi->ext_hooks->ready_for_slave)(ppi) ) { if ( (*ppi->ext_hooks->ready_for_slave)(ppi) ) {
ppi->next_state = PPS_SLAVE; ppi->next_state = PPS_SLAVE;
} }
...@@ -244,9 +248,9 @@ int pp_slave(struct pp_instance *ppi, void *buf, int len) ...@@ -244,9 +248,9 @@ int pp_slave(struct pp_instance *ppi, void *buf, int len)
pp_diag(ppi, bmc, 2, "Entered to uncalibrated, reset servo\n"); pp_diag(ppi, bmc, 2, "Entered to uncalibrated, reset servo\n");
pp_servo_init(ppi); pp_servo_init(ppi);
if (ppi->ext_hooks->new_slave) if (is_ext_hook_available(ppi,new_slave))
e = ppi->ext_hooks->new_slave(ppi, buf, len); ret = ppi->ext_hooks->new_slave(ppi, buf, len);
if (e) if (ret!=PP_SEND_OK)
goto out; goto out;
} }
...@@ -258,7 +262,7 @@ int pp_slave(struct pp_instance *ppi, void *buf, int len) ...@@ -258,7 +262,7 @@ int pp_slave(struct pp_instance *ppi, void *buf, int len)
*/ */
if (hdr->messageType < ARRAY_SIZE(actions) if (hdr->messageType < ARRAY_SIZE(actions)
&& actions[hdr->messageType]) { && actions[hdr->messageType]) {
e = actions[hdr->messageType](ppi, buf, len); ret = actions[hdr->messageType](ppi, buf, len);
} else { } else {
if (len) if (len)
pp_diag(ppi, frames, 1, "Ignored frame %i\n", pp_diag(ppi, frames, 1, "Ignored frame %i\n",
...@@ -269,25 +273,17 @@ int pp_slave(struct pp_instance *ppi, void *buf, int len) ...@@ -269,25 +273,17 @@ int pp_slave(struct pp_instance *ppi, void *buf, int len)
* This function, common to uncalibrated and slave, * This function, common to uncalibrated and slave,
* is the core of the slave: hook * is the core of the slave: hook
*/ */
e = slave_execute(ppi); ret = slave_execute(ppi);
st_com_check_announce_receive_timeout(ppi); st_com_check_announce_receive_timeout(ppi);
out: out:
switch(e) { if ( ret==PP_SEND_NO_STAMP ) {
case PP_SEND_OK: /* 0 */ ret = PP_SEND_OK;/* nothing, just keep the ball rolling */
break;
case PP_SEND_ERROR:
/* ignore: a lost frame is not the end of the world */
break;
case PP_SEND_NO_STAMP:
/* nothing, just keep the ball rolling */
e = 0;
break;
} }
ppi->next_delay = pp_next_delay_2(ppi, ppi->next_delay = pp_next_delay_2(ppi,
PP_TO_ANN_RECEIPT, PP_TO_REQUEST); PP_TO_ANN_RECEIPT, PP_TO_REQUEST);
return e; return ret;
} }
...@@ -193,28 +193,28 @@ static int unix_time_set(struct pp_instance *ppi, const struct pp_time *t) ...@@ -193,28 +193,28 @@ static int unix_time_set(struct pp_instance *ppi, const struct pp_time *t)
struct timespec tp; struct timespec tp;
if (!t) { /* Change the network notion of the utc/tai offset */ if (!t) { /* Change the network notion of the utc/tai offset */
struct timex t; struct timex tmx;
t.modes = MOD_TAI; tmx.modes = MOD_TAI;
t.constant = DSPRO(ppi)->currentUtcOffset; tmx.constant = DSPRO(ppi)->currentUtcOffset;
if (adjtimex(&t) < 0) if (adjtimex(&tmx) < 0)
clock_fatal_error("change TAI offset"); clock_fatal_error("change TAI offset");
pp_diag(ppi, time, 1, "New TAI offset: %i\n", pp_diag(ppi, time, 1, "New TAI offset: %i\n",
DSPRO(ppi)->currentUtcOffset); DSPRO(ppi)->currentUtcOffset);
return 0;
}
/* UTC = TAI - 35 */
tp.tv_sec = t->secs - DSPRO(ppi)->currentUtcOffset;
tp.tv_nsec = t->scaled_nsecs >> 16;
if ( tp.tv_sec < 0 || tp.tv_nsec<0) {
pp_error("%s: Cannot set clock time with negative values: %lisec %lins\n", __func__,(long int) tp.tv_sec,tp.tv_nsec );
} else { } else {
if (clock_settime(CLOCK_REALTIME, &tp) < 0) {
clock_fatal_error("clock_settime"); /* UTC = TAI - 35 */
tp.tv_sec = t->secs - DSPRO(ppi)->currentUtcOffset;
tp.tv_nsec = t->scaled_nsecs >> 16;
if ( tp.tv_sec < 0 || tp.tv_nsec<0) {
pp_error("%s: Cannot set clock time with negative values: %lisec %lins\n", __func__,(long int) tp.tv_sec,tp.tv_nsec );
} else {
if (clock_settime(CLOCK_REALTIME, &tp) < 0) {
clock_fatal_error("clock_settime");
}
pp_diag(ppi, time, 1, "%s: %9li.%09li\n", __func__,
tp.tv_sec, tp.tv_nsec);
} }
pp_diag(ppi, time, 1, "%s: %9li.%09li\n", __func__,
tp.tv_sec, tp.tv_nsec);
} }
return 0; return 0;
} }
......
...@@ -239,27 +239,28 @@ static int wrs_recv_msg(struct pp_instance *ppi, int fd, void *pkt, int len, ...@@ -239,27 +239,28 @@ static int wrs_recv_msg(struct pp_instance *ppi, int fd, void *pkt, int len,
aux = (struct tpacket_auxdata *)dp; aux = (struct tpacket_auxdata *)dp;
} }
if(sts && t) if ( t ) {
{ if (sts) {
int cntr_ahead = sts->hwtimeraw.tv_sec & 0x80000000 ? 1: 0; int cntr_ahead = sts->hwtimeraw.tv_sec & 0x80000000 ? 1: 0;
t->scaled_nsecs = (long long)sts->hwtimeraw.tv_nsec << 16; t->scaled_nsecs = (long long)sts->hwtimeraw.tv_nsec << 16;
t->secs = sts->hwtimeraw.tv_sec & 0x7fffffff; t->secs = sts->hwtimeraw.tv_sec & 0x7fffffff;
update_dmtd(s, ppi); update_dmtd(s, ppi);
if ( WRH_DSPOR_HEAD(ppi)==NULL || !WRH_DSPOR_HEAD(ppi)->extModeOn) { if ( ppi->ext_hooks->require_precise_timestamp!=NULL &&
goto drop; (*ppi->ext_hooks->require_precise_timestamp)(ppi)) {
} /* Precise time stamp required */
if (s->dmtd_phase_valid) { if (s->dmtd_phase_valid) {
wrs_linearize_rx_timestamp(t, s->dmtd_phase, wrs_linearize_rx_timestamp(t, s->dmtd_phase,
cntr_ahead, s->phase_transition, s->clock_period); cntr_ahead, s->phase_transition, s->clock_period);
} else {
mark_incorrect(t);
}
}
} else { } else {
mark_incorrect(t); mark_incorrect(t);
} }
} else {
mark_incorrect(t);
} }
drop:
/* For UDP, avoid all of the following, as we don't have vlans */ /* For UDP, avoid all of the following, as we don't have vlans */
if (ppi->proto == PPSI_PROTO_UDP) if (ppi->proto == PPSI_PROTO_UDP)
goto out; goto out;
......
...@@ -101,10 +101,10 @@ int wrs_enable_timing_output(struct pp_instance *ppi, int enable) ...@@ -101,10 +101,10 @@ int wrs_enable_timing_output(struct pp_instance *ppi, int enable)
{ {
int ret, rval; int ret, rval;
hexp_pps_params_t p; hexp_pps_params_t p;
static int ppsOutputOn=-1; /* -1 means we don't know the state */
if (enable == WRH_DSPOR_HEAD(ppi)->ppsOutputOn) if (enable == ppsOutputOn)
return WRH_SPLL_OK; return WRH_SPLL_OK;
WRH_DSPOR_HEAD(ppi)->ppsOutputOn = enable;
p.pps_valid = enable; p.pps_valid = enable;
...@@ -113,6 +113,7 @@ int wrs_enable_timing_output(struct pp_instance *ppi, int enable) ...@@ -113,6 +113,7 @@ int wrs_enable_timing_output(struct pp_instance *ppi, int enable)
if ((ret < 0) || (rval < 0)) if ((ret < 0) || (rval < 0))
return WRH_SPLL_ERROR; return WRH_SPLL_ERROR;
ppsOutputOn = enable;
return WRH_SPLL_OK; return WRH_SPLL_OK;
} }
......
...@@ -15,10 +15,11 @@ static const char *timeOutNames[__PP_TO_ARRAY_SIZE]={ ...@@ -15,10 +15,11 @@ static const char *timeOutNames[__PP_TO_ARRAY_SIZE]={
"ANN_SEND", "ANN_SEND",
"FAULT", "FAULT",
"QUAL", "QUAL",
"PROT_STATE",
"EXT_0", "EXT_0",
"EXT_1" "EXT_1"
}; };
#define TIMEOUT_FAULTY_STATE_MS (60*1000) /* define the time to stay on faulty state before to go to initializing state */
#define TIMEOUT_MAX_LOG_VALUE 21 /* 2^21 * 1000 =2097152000ms is the maximum value that can be stored in an integer */ #define TIMEOUT_MAX_LOG_VALUE 21 /* 2^21 * 1000 =2097152000ms is the maximum value that can be stored in an integer */
#define TIMEOUT_MIN_LOG_VALUE -9 /* 2^-9 = 1ms is the minimum value that can be stored in an integer */ #define TIMEOUT_MIN_LOG_VALUE -9 /* 2^-9 = 1ms is the minimum value that can be stored in an integer */
#define TIMEOUT_MAX_VALUE_MS ((1<< TIMEOUT_MAX_LOG_VALUE)*1000) #define TIMEOUT_MAX_VALUE_MS ((1<< TIMEOUT_MAX_LOG_VALUE)*1000)
...@@ -59,14 +60,17 @@ void pp_timeout_init(struct pp_instance *ppi) ...@@ -59,14 +60,17 @@ void pp_timeout_init(struct pp_instance *ppi)
timeouts[PP_TO_QUALIFICATION].which_rand = timeouts[PP_TO_QUALIFICATION].which_rand =
timeouts[PP_TO_ANN_RECEIPT].which_rand = timeouts[PP_TO_ANN_RECEIPT].which_rand =
timeouts[PP_TO_FAULT].which_rand = timeouts[PP_TO_FAULT].which_rand =
timeouts[PP_TO_PROT_STATE].which_rand =
timeouts[PP_TO_EXT_0].which_rand = timeouts[PP_TO_EXT_0].which_rand =
timeouts[PP_TO_EXT_1].which_rand = TO_RAND_NONE; timeouts[PP_TO_EXT_1].which_rand = TO_RAND_NONE;
timeouts[PP_TO_REQUEST].initValueMs= pp_timeout_log_to_ms(logDelayRequest); timeouts[PP_TO_REQUEST].initValueMs= pp_timeout_log_to_ms(logDelayRequest);
/* fault timeout is 4 avg request intervals, not randomized */ /* fault timeout is 4 avg request intervals, not randomized */
timeouts[PP_TO_FAULT].initValueMs = pp_timeout_log_to_ms(logDelayRequest); timeouts[PP_TO_FAULT].initValueMs = pp_timeout_log_to_ms(logDelayRequest);
if ( timeouts[PP_TO_FAULT].initValueMs < (TIMEOUT_MAX_VALUE_MS>>2)) if ( timeouts[PP_TO_FAULT].initValueMs < (TIMEOUT_MAX_VALUE_MS>>2))
timeouts[PP_TO_FAULT].initValueMs<<=2; /* We can multiply by 4. No risk of overload */ timeouts[PP_TO_FAULT].initValueMs<<=2; /* We can multiply by 4. No risk of overload */
timeouts[PP_TO_SYNC_SEND].initValueMs = pp_timeout_log_to_ms(port->logSyncInterval); timeouts[PP_TO_SYNC_SEND].initValueMs = pp_timeout_log_to_ms(port->logSyncInterval);
timeouts[PP_TO_BMC].initValueMs = pp_timeout_log_to_ms(port->logAnnounceInterval); timeouts[PP_TO_BMC].initValueMs = pp_timeout_log_to_ms(port->logAnnounceInterval);
timeouts[PP_TO_ANN_RECEIPT].initValueMs = 1000 * ( timeouts[PP_TO_ANN_RECEIPT].initValueMs = 1000 * (
...@@ -145,9 +149,13 @@ void pp_timeout_setall(struct pp_instance *ppi) ...@@ -145,9 +149,13 @@ void pp_timeout_setall(struct pp_instance *ppi)
{ {
int i; int i;
for (i = 0; i < __PP_TO_ARRAY_SIZE; i++) { for (i = 0; i < __PP_TO_ARRAY_SIZE; i++) {
/* keep BMC timeout */ if ( i==PP_TO_FAULT && ppi->next_state==PPS_FAULTY ){
if (i!=PP_TO_BMC) { __pp_timeout_set(ppi,PP_TO_FAULT,TIMEOUT_FAULTY_STATE_MS);
pp_timeout_set(ppi, i); } else {
/* keep BMC timeout */
if (i!=PP_TO_BMC) {
pp_timeout_set(ppi, i);
}
} }
} }
/* but announce_send must be send soon */ /* but announce_send must be send soon */
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#define CALIBRATED_MASK 0x4 #define CALIBRATED_MASK 0x4
#define WR_CONFIG_MASK 0x3 #define WR_CONFIG_MASK 0x3
#if CONFIG_PROFILE_WR == 1
static char *wr_message_name[] = { static char *wr_message_name[] = {
"SLAVE_PRESENT", "SLAVE_PRESENT",
"LOCK", "LOCK",
...@@ -22,6 +23,7 @@ static char *wr_message_name[] = { ...@@ -22,6 +23,7 @@ static char *wr_message_name[] = {
"CALIBRATED", "CALIBRATED",
"WR_MODE_ON", "WR_MODE_ON",
}; };
#endif
static int dump_vlan(char *prefix, int vlan); static int dump_vlan(char *prefix, int vlan);
...@@ -165,6 +167,8 @@ static void dump_msg_resp_etc(char *prefix, char *s, struct ptp_sync_etc *p) ...@@ -165,6 +167,8 @@ static void dump_msg_resp_etc(char *prefix, char *s, struct ptp_sync_etc *p)
dump_1port(prefix, s, p->port); dump_1port(prefix, s, p->port);
} }
#if CONFIG_PROFILE_WR == 1
/* TLV dumper, now white-rabbit aware */ /* TLV dumper, now white-rabbit aware */
static int wr_dump_tlv(char *prefix, struct ptp_tlv *tlv, int totallen) static int wr_dump_tlv(char *prefix, struct ptp_tlv *tlv, int totallen)
{ {
...@@ -275,6 +279,9 @@ static int wr_dump_tlv(char *prefix, struct ptp_tlv *tlv, int totallen) ...@@ -275,6 +279,9 @@ static int wr_dump_tlv(char *prefix, struct ptp_tlv *tlv, int totallen)
return explen; return explen;
} }
#endif
#if CONFIG_EXT_L1SYNC == 1
static int l1sync_dump_tlv(char *prefix, struct l1sync_tlv *tlv, int totallen) static int l1sync_dump_tlv(char *prefix, struct l1sync_tlv *tlv, int totallen)
{ {
...@@ -299,6 +306,7 @@ static int l1sync_dump_tlv(char *prefix, struct l1sync_tlv *tlv, int totallen) ...@@ -299,6 +306,7 @@ static int l1sync_dump_tlv(char *prefix, struct l1sync_tlv *tlv, int totallen)
explen - sizeof(*tlv)); explen - sizeof(*tlv));
return explen; return explen;
} }
#endif
/* A big function to dump the ptp information */ /* A big function to dump the ptp information */
static void dump_payload(char *prefix, void *pl, int len) static void dump_payload(char *prefix, void *pl, int len)
...@@ -396,12 +404,16 @@ static void dump_payload(char *prefix, void *pl, int len) ...@@ -396,12 +404,16 @@ static void dump_payload(char *prefix, void *pl, int len)
break; break;
} }
switch ( messageType) { switch ( messageType) {
#if CONFIG_PROFILE_WR == 1
case PPM_ANNOUNCE : case PPM_ANNOUNCE :
donelen += wr_dump_tlv(prefix, pl + donelen, n); donelen += wr_dump_tlv(prefix, pl + donelen, n);
break; break;
#endif
#if CONFIG_EXT_L1SYNC == 1
case PPM_SIGNALING : case PPM_SIGNALING :
donelen += l1sync_dump_tlv(prefix, pl + donelen, n); donelen += l1sync_dump_tlv(prefix, pl + donelen, n);
break; break;
#endif
default : default :
goto out; goto out;
} }
......
...@@ -82,8 +82,8 @@ struct dump_info dstp_info [] = { ...@@ -82,8 +82,8 @@ struct dump_info dstp_info [] = {
#define DUMP_STRUCT struct pp_servo #define DUMP_STRUCT struct pp_servo
struct dump_info servo_state_info [] = { struct dump_info servo_state_info [] = {
DUMP_FIELD(int , state), DUMP_FIELD(int , state),
DUMP_FIELD(time, delayMM),
DUMP_FIELD(time, delayMS), DUMP_FIELD(time, delayMS),
DUMP_FIELD(time, delaySM),
DUMP_FIELD(long_long, obs_drift), DUMP_FIELD(long_long, obs_drift),
DUMP_FIELD(Integer64, mpd_fltr.m), DUMP_FIELD(Integer64, mpd_fltr.m),
DUMP_FIELD(Integer64, mpd_fltr.y), DUMP_FIELD(Integer64, mpd_fltr.y),
...@@ -91,7 +91,14 @@ struct dump_info servo_state_info [] = { ...@@ -91,7 +91,14 @@ struct dump_info servo_state_info [] = {
DUMP_FIELD(time, meanDelay), DUMP_FIELD(time, meanDelay),
DUMP_FIELD(time, offsetFromMaster), DUMP_FIELD(time, offsetFromMaster),
DUMP_FIELD(unsigned_long, flags), DUMP_FIELD(unsigned_long, flags),
DUMP_FIELD(time, update_time),
DUMP_FIELD(UInteger32, update_count), DUMP_FIELD(UInteger32, update_count),
DUMP_FIELD(time, t1),
DUMP_FIELD(time, t2),
DUMP_FIELD(time, t3),
DUMP_FIELD(time, t4),
DUMP_FIELD(time, t5),
DUMP_FIELD(time, t6),
DUMP_FIELD_SIZE(char, servo_state_name,32), DUMP_FIELD_SIZE(char, servo_state_name,32),
DUMP_FIELD(int, servo_locked), DUMP_FIELD(int, servo_locked),
}; };
...@@ -101,7 +108,6 @@ struct dump_info servo_state_info [] = { ...@@ -101,7 +108,6 @@ struct dump_info servo_state_info [] = {
#define DUMP_STRUCT struct l1e_servo_state #define DUMP_STRUCT struct l1e_servo_state
struct dump_info l1e_servo_state_info [] = { struct dump_info l1e_servo_state_info [] = {
DUMP_FIELD(Integer32, clock_period_ps), DUMP_FIELD(Integer32, clock_period_ps),
DUMP_FIELD(time, delayMM),
DUMP_FIELD(Integer64, delayMM_ps), DUMP_FIELD(Integer64, delayMM_ps),
DUMP_FIELD(Integer32, cur_setpoint_ps), DUMP_FIELD(Integer32, cur_setpoint_ps),
DUMP_FIELD(Integer64, delayMS_ps), DUMP_FIELD(Integer64, delayMS_ps),
...@@ -111,13 +117,6 @@ struct dump_info l1e_servo_state_info [] = { ...@@ -111,13 +117,6 @@ struct dump_info l1e_servo_state_info [] = {
DUMP_FIELD(UInteger32, n_err_state), DUMP_FIELD(UInteger32, n_err_state),
DUMP_FIELD(UInteger32, n_err_offset), DUMP_FIELD(UInteger32, n_err_offset),
DUMP_FIELD(UInteger32, n_err_delta_rtt), DUMP_FIELD(UInteger32, n_err_delta_rtt),
DUMP_FIELD(time, update_time),
DUMP_FIELD(time, t1),
DUMP_FIELD(time, t2),
DUMP_FIELD(time, t3),
DUMP_FIELD(time, t4),
DUMP_FIELD(time, t5),
DUMP_FIELD(time, t6),
DUMP_FIELD(Integer64, prev_delayMS_ps), DUMP_FIELD(Integer64, prev_delayMS_ps),
DUMP_FIELD(int, missed_iters), DUMP_FIELD(int, missed_iters),
}; };
...@@ -125,7 +124,6 @@ struct dump_info l1e_servo_state_info [] = { ...@@ -125,7 +124,6 @@ struct dump_info l1e_servo_state_info [] = {
#undef DUMP_STRUCT #undef DUMP_STRUCT
#define DUMP_STRUCT l1e_ext_portDS_t #define DUMP_STRUCT l1e_ext_portDS_t
struct dump_info l1e_ext_portDS_info [] = { struct dump_info l1e_ext_portDS_info [] = {
DUMP_FIELD(Boolean, parentExtModeOn),
DUMP_FIELD(Boolean, basic.L1SyncEnabled), DUMP_FIELD(Boolean, basic.L1SyncEnabled),
DUMP_FIELD(Boolean, basic.txCoherentIsRequired), DUMP_FIELD(Boolean, basic.txCoherentIsRequired),
DUMP_FIELD(Boolean, basic.rxCoherentIsRequired), DUMP_FIELD(Boolean, basic.rxCoherentIsRequired),
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment