Commit b66d61fe authored by Jean-Claude BAU's avatar Jean-Claude BAU

[Feature:#128] Improve GM status

- Add a new state machine available for all timing modes ( Free running
master, Grand master and boundary clock)
- State is stored in pp_globals, field timingModeLockingState
- The 3 main states are :
-- Locking: Waiting for PLL locked
-- Locked: PLL is locked
-- Error: PLL is unlocked but was locked before
- Changing the timing mode will reset the state to 'Locking'
parent 2f5b29aa
......@@ -389,6 +389,8 @@ int main(int argc, char **argv)
int nbRetry;
int enablePPS;
ppg->timingModeLockingState=TM_LOCKING_STATE_LOCKING;
if ( ppg->defaultDS->clockQuality.clockClass == PP_PTP_CLASS_GM_LOCKED ) {
if (prev_timing_mode==-1) {
fprintf(stderr, "ppsi: Cannot get current timing mode\n");
......@@ -400,8 +402,8 @@ int main(int argc, char **argv)
if ( prev_timing_mode != TM_GRAND_MASTER ){
/* Timing mode was not GM before */
WRH_OPER()->set_timing_mode(ppg,TM_GRAND_MASTER);
ppg->waitGmLocking=1; /* We might wait PPL locking ... see below */
}
} else
ppg->timingMode=TM_GRAND_MASTER; // set here because set_timing_mode() is not called
} else {
/* Timing mode will be set to BC when a port will become slave */
WRH_OPER()->set_timing_mode(ppg,TM_FREE_MASTER);
......@@ -416,23 +418,16 @@ int main(int argc, char **argv)
break;
sleep(1); // wait 1s
nbRetry--;
} // if nbRetry>0 it means that the PLL is locked
if ( (ppg->waitGmLocking=ppg->waitGmLocking && nbRetry==0)==1 ) {
/* we degrade the clockClass to be sure that all instances will stay in
* initializing state until the clock class goes to PP_PTP_CLASS_GM_LOCKED
*/
//GDSDEF(ppg)->clockQuality.clockClass = PP_PTP_CLASS_GM_UNLOCKED;
}
/* Enable the PPS generation only if
* - Grand master and PLL is locked
* OR
* - Free running master (no condition required)
* OOR
* OR
* - Timing output is forced (for testing only)
*/
enablePPS=(nbRetry>0 && ppg->defaultDS->clockQuality.clockClass == PP_PTP_CLASS_GM_LOCKED) ||
enablePPS=(ppg->timingModeLockingState== TM_LOCKING_STATE_LOCKED && ppg->defaultDS->clockQuality.clockClass == PP_PTP_CLASS_GM_LOCKED) ||
( ppg->defaultDS->clockQuality.clockClass == PP_PTP_CLASS_GM_UNLOCKED ||
GOPTS(ppg)->forcePpsGen);
WRH_OPER()->enable_timing_output(ppg,enablePPS);
......
......@@ -35,15 +35,6 @@
#define WRH_SERVO_OFFSET_STABILITY_THRESHOLD 60 /* psec */
/* Parameter of wrs_set_timing_mode */
typedef enum {
TM_GRAND_MASTER=HAL_TIMING_MODE_GRAND_MASTER,
TM_FREE_MASTER= HAL_TIMING_MODE_FREE_MASTER,
TM_BOUNDARY_CLOCK=HAL_TIMING_MODE_BC,
TM_DISABLED=HAL_TIMING_MODE_DISABLED
}timing_mode_t;
/* White Rabbit hw-dependent functions (code in arch-wrpc and arch-wrs) */
struct wrh_operations {
int (*locking_enable)(struct pp_instance *ppi);
......
......@@ -117,6 +117,13 @@ typedef enum {
PP_TIMING_MODE_STATE_UNKNOWN
}timing_mode_state_t;
typedef enum {
TM_GRAND_MASTER=0,
TM_FREE_MASTER,
TM_BOUNDARY_CLOCK,
TM_DISABLED
}timing_mode_t;
#define PP_ALTERNATE_MASTER_FLAG 1
#define PP_TWO_STEP_FLAG 2
......
......@@ -294,6 +294,14 @@ struct pp_globals_cfg {
int cur_ppi_n; /* Remember which instance we are configuring */
};
typedef enum {
TM_LOCKING_STATE_NONE=0,
TM_LOCKING_STATE_LOCKING,
TM_LOCKING_STATE_LOCKED,
TM_LOCKING_STATE_HOLDOVER,
TM_LOCKING_STATE_ERROR
}timing_mode_locking_state_t;
/*
* Structure for the multi-port ppsi instance.
*/
......@@ -322,8 +330,8 @@ struct pp_globals {
void *arch_data; /* if arch needs it */
void *global_ext_data; /* if protocol ext needs it */
Boolean waitGmLocking; /* If set, instances must stay in initializing state until the GM PLL is locked */
timing_mode_locking_state_t timingModeLockingState; /* Locking state for PLL */
timing_mode_t timingMode; /* Timing mode: Grand master, Free running,...*/
/* FIXME Here include all is common to many interfaces */
};
......
......@@ -1394,6 +1394,9 @@ static void bmc_update_clock_quality(struct pp_globals *ppg)
}
};
// Called here because get_timing_mode_state() updates timingModeLockingState field in pp_globals
timing_mode_state=WRH_OPER()->get_timing_mode_state(ppg);
if (rt_opts_clock_quality_clockClass >= 128)
return;
......@@ -1413,7 +1416,7 @@ static void bmc_update_clock_quality(struct pp_globals *ppg)
return;
}
if ((timing_mode_state=WRH_OPER()->get_timing_mode_state(ppg))==PP_TIMING_MODE_STATE_ERROR) {
if (timing_mode_state==PP_TIMING_MODE_STATE_ERROR) {
pp_diag(NULL, bmc, 1,
"Could not get timing mode locking state, taking old clock class: %i\n",
ppg->defaultDS->clockQuality.clockClass);
......
......@@ -45,8 +45,14 @@ int pp_initializing(struct pp_instance *ppi, void *buf, int len)
int i;
int initds = 1;
if ( ppg->waitGmLocking ) {
/* Waithing for GM locking */
Boolean waitGmLocking;
waitGmLocking= ppg->rt_opts->clock_quality_clockClass == PP_PTP_CLASS_GM_LOCKED &&
(ppg->timingModeLockingState == TM_LOCKING_STATE_LOCKING ||
ppg->timingModeLockingState == TM_LOCKING_STATE_ERROR);
if (waitGmLocking) {
/* Waiting for GM locking */
if ( ppi->is_new_state ) {
/* Init time-out for next calls : Wait 2 x the BMCA tmo */
pp_timeout_set(ppi,PP_TO_IN_STATE,TMO_DEFAULT_BMCA_MS<<1);
......@@ -54,7 +60,7 @@ int pp_initializing(struct pp_instance *ppi, void *buf, int len)
if ( pp_timeout(ppi,PP_TO_IN_STATE)) {
/* At this point, the BMCA already run. We can check the clockClass */
if ( DSDEF(ppi)->clockQuality.clockClass == PP_PTP_CLASS_GM_LOCKED) {
ppg->waitGmLocking=0; /* The clock is locked now */
waitGmLocking=FALSE;
pp_timeout_disable(ppi,PP_TO_IN_STATE);
}
else {
......@@ -151,7 +157,7 @@ int pp_initializing(struct pp_instance *ppi, void *buf, int len)
msg_init_header(ppi, ppi->tx_ptp); /* This is used for all tx */
if ( ppg->waitGmLocking ) {
if ( waitGmLocking ) {
/* must leave the BMC running before to check next time the clockClass */
ppi->next_delay = pp_gtimeout_get(ppg,PP_TO_BMC) << 1; /* wait 2 x BMCA tmo */
return 0;
......
......@@ -119,6 +119,9 @@ int wrs_set_timing_mode(struct pp_globals * ppg,timing_mode_t tm)
if ((ret < 0) || (rval < 0))
return -1;
ppg->timingMode=tm;
ppg->timingModeLockingState=TM_LOCKING_STATE_LOCKING;
return 0;
}
......@@ -157,7 +160,10 @@ timing_mode_state_t wrs_get_timing_mode_state(struct pp_globals *ppg)
}
}
}
if ( ppg->timingModeLockingState == TM_LOCKING_STATE_LOCKED)
ppg->timingModeLockingState = TM_LOCKING_STATE_ERROR;
} else {
ppg->timingModeLockingState = TM_LOCKING_STATE_LOCKED;
if (tmoIndex > 0 ) {
/* Free the timer: Next unlock state, we will wait then 60s again
* before to set again the Timing mode.
......@@ -181,6 +187,7 @@ timing_mode_t wrs_get_timing_mode(struct pp_globals *ppg)
if (ret < 0)
return -1;
ppg->timingMode=rval; // Update timing mode
return rval;
}
......@@ -198,8 +205,8 @@ int wrs_locking_enable(struct pp_instance *ppi)
{
int ret, rval;
GLBS(ppi)->timingModeLockingState=TM_LOCKING_STATE_LOCKING;
wrs_set_timing_mode(GLBS(ppi),TM_BOUNDARY_CLOCK);
pp_diag(ppi, time, 1, "Start locking\n");
ret = minipc_call(hal_ch, DEFAULT_TO, &__rpcdef_lock_cmd,
&rval, ppi->iface_name, HEXP_LOCK_CMD_START, 0);
......@@ -220,6 +227,7 @@ int wrs_locking_reset(struct pp_instance *ppi)
if ( wrs_set_timing_mode(GLBS(ppi),TM_FREE_MASTER)<0 ) {
return -1;
}
GLBS(ppi)->timingModeLockingState=TM_LOCKING_STATE_LOCKING;
ret = minipc_call(hal_ch, DEFAULT_TO, &__rpcdef_lock_cmd,
&rval, ppi->iface_name, HEXP_LOCK_CMD_RESET, 0);
......@@ -240,9 +248,13 @@ int wrs_locking_poll(struct pp_instance *ppi)
return WRH_SPLL_ERROR; /* FIXME should be WRH_SPLL_NOT_READY */
}
if (rval != HEXP_LOCK_STATUS_LOCKED) {
if ( GLBS(ppi)->timingModeLockingState==TM_LOCKING_STATE_LOCKED )
GLBS(ppi)->timingModeLockingState=TM_LOCKING_STATE_ERROR;
pp_diag(ppi, time, 2, "PLL not locked(%d)\n",rval);
return WRH_SPLL_ERROR; /* FIXME should be WRH_SPLL_NOT_READY */
}
GLBS(ppi)->timingModeLockingState=TM_LOCKING_STATE_LOCKED;
pp_diag(ppi, time, 2, "PLL is locked\n");
return WRH_SPLL_READY;
}
......
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