Commit ada5fb06 authored by Jean-Claude BAU's avatar Jean-Claude BAU Committed by Adam Wujek

Fix issues with standart ptp (e2e & p2p)

In the ptp servo the adjustment of the time was too slow. When the
difference of the time with the master was less than 1 second, the
adjustment was done only with the frequency. In case if the difference
is 0.999s, it can take a very long time to adjust the time.
Changes made :
- Adjust with frequency only when time difference is below 20ms
- Check the timestamp validity before each calculation
- Create a new function to check the timestamps and use it on all
servos. This improve significantly the size of the code.
- Add verification in order not to set an invalid UNIX time
parent 41635c92
......@@ -584,6 +584,7 @@ extern int64_t pp_time_to_picos(struct pp_time *ts);
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 int64_t interval_to_picos(TimeInterval interval);
extern int is_timestamps_incorrect(struct pp_instance *ppsi, int *err_count, int ts_mask);
/*
......
......@@ -175,3 +175,42 @@ int64_t interval_to_picos(TimeInterval interval)
{
return (interval * 1000) >> TIME_INTERVAL_FRACBITS;
}
/*
* Check the timestamps (t1 to t6).
* err_count is a counter to avoid printing the first time the error messages
* ts_mask is the mask of the timestamps to check.
* Returns 1 if a timestamp is incorrect otherwise 0.
*/
int is_timestamps_incorrect(struct pp_instance *ppsi, int *err_count, int ts_mask) {
static int ts_ppsi_offset[6]={
offsetof(struct pp_instance,t1),
offsetof(struct pp_instance,t2),
offsetof(struct pp_instance,t3),
offsetof(struct pp_instance,t4),
offsetof(struct pp_instance,t5),
offsetof(struct pp_instance,t6)
};
int mask=1,i,local_err_count;
if ( err_count==NULL ) {
/* Optimize the execution of the next code avoiding checking err_count at each step */
err_count=&local_err_count;
local_err_count=5; /* Force printing immediately if a timestamp is incorrect */
}
for ( i=0; i<6 && ts_mask; i++ ) { // Check up to 6 timestamps
if ( mask & ts_mask ) {
struct pp_time *ts=(void *) ppsi + ts_ppsi_offset[i] ;
if ( is_incorrect(ts) ) {
if ( (*err_count)++ > 5 ) {
pp_error("%s: t%d is incorrect\n",__func__,i+1);
}
return 1;
}
}
ts_mask &=~mask;
mask<<=1;
}
return *err_count=0;
}
......@@ -157,9 +157,8 @@ static int l1e_handle_resp(struct pp_instance *ppi)
* we'll have the Unix time instead, marked by "correct"
*/
if (!l1epds->head.extModeOn) {
if (is_incorrect(&ppi->t2) || is_incorrect(&ppi->t3)) {
pp_diag(ppi, servo, 1,
"T2 or T3 incorrect, discarding tuple\n");
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);
......@@ -209,7 +208,7 @@ static __attribute__((used)) int l1e_handle_presp(struct pp_instance *ppi)
*/
if (!WRH_DSPOR_HEAD(ppi)->extModeOn) {
if (is_incorrect(&ppi->t3) || is_incorrect(&ppi->t6)) {
if ( is_timestamps_incorrect(ppi, NULL, 0x24 /* mask=t3&t6 */) ) {
pp_diag(ppi, servo, 1,
"T3 or T6 incorrect, discarding tuple\n");
return 0;
......
......@@ -179,17 +179,8 @@ static int l1e_p2p_delay(struct pp_instance *ppi, struct l1e_servo_state *s)
{
static int errcount;
if (is_incorrect(&s->t3) || is_incorrect(&s->t4)
|| is_incorrect(&s->t5) || is_incorrect(&s->t6)) {
errcount++;
if (errcount > 5) /* a 2-3 in a row are expected */
pp_error("%s: TimestampsIncorrect: %d %d %d %d\n",
__func__, !is_incorrect(&s->t3),
!is_incorrect(&s->t4), !is_incorrect(&s->t5),
!is_incorrect(&s->t6));
if ( is_timestamps_incorrect(ppi,&errcount, 0x3C /* mask=t3&t4&t5&t6*/))
return 0;
}
errcount = 0;
SRV(ppi)->update_count++;
ppi->t_ops->get(ppi, &s->update_time);
......@@ -227,15 +218,9 @@ static int l1e_p2p_offset(struct pp_instance *ppi,
{
static int errcount;
if (is_incorrect(&s->t1) || is_incorrect(&s->t2)) {
errcount++;
if (errcount > 5) /* a 2-3 in a row are expected */
pp_error("%s: TimestampsIncorrect: %d %d \n",
__func__, !is_incorrect(&s->t1),
!is_incorrect(&s->t2));
if ( is_timestamps_incorrect(ppi,&errcount, 0x3 /* mask=t1&t2 */))
return 0;
}
errcount = 0;
l1e_got_sync = 0;
SRV(ppi)->update_count++;
......@@ -257,22 +242,12 @@ static int l1e_e2e_offset(struct pp_instance *ppi,
{
static int errcount;
if (is_incorrect(&s->t1) || is_incorrect(&s->t2)
|| is_incorrect(&s->t3) || is_incorrect(&s->t4)) {
errcount++;
if (errcount > 5) /* a 2-3 in a row are expected */
pp_error("%s: TimestampsIncorrect: %d %d %d %d\n",
__func__, !is_incorrect(&s->t1),
!is_incorrect(&s->t2), !is_incorrect(&s->t3),
!is_incorrect(&s->t4));
if ( is_timestamps_incorrect(ppi,&errcount, 0xF /* mask=t1&t2&t3&t4 */))
return 0;
}
if (WRH_OPER()->servo_hook)
WRH_OPER()->servo_hook(ppi, WRH_SERVO_ENTER);
errcount = 0;
SRV(ppi)->update_count++;
ppi->t_ops->get(ppi, &s->update_time);
......
......@@ -112,7 +112,7 @@ static int wr_handle_resp(struct pp_instance *ppi)
* we'll have the Unix time instead, marked by "correct"
*/
if (!wrp->head.extModeOn) {
if (is_incorrect(&ppi->t2) || is_incorrect(&ppi->t3)) {
if ( is_timestamps_incorrect(ppi, NULL, 0x6 /* mask=t2&t3 */) ) {
pp_diag(ppi, servo, 1,
"T2 or T3 incorrect, discarding tuple\n");
return 0;
......@@ -214,7 +214,7 @@ static __attribute__((used)) int wr_handle_presp(struct pp_instance *ppi)
*/
if (!wrp->head.extModeOn) {
if (is_incorrect(&ppi->t3) || is_incorrect(&ppi->t6)) {
if ( is_timestamps_incorrect(ppi, NULL, 0x24 /* mask=t3&t6 */) ) {
pp_diag(ppi, servo, 1,
"T3 or T6 incorrect, discarding tuple\n");
return 0;
......
......@@ -205,17 +205,8 @@ static int wr_p2p_delay(struct pp_instance *ppi, struct wr_servo_state *s)
uint64_t big_delta_fix_ps;
static int errcount;
if (is_incorrect(&s->t3) || is_incorrect(&s->t4)
|| is_incorrect(&s->t5) || is_incorrect(&s->t6)) {
errcount++;
if (errcount > 5) /* a 2-3 in a row are expected */
pp_error("%s: TimestampsIncorrect: %d %d %d %d\n",
__func__, !is_incorrect(&s->t3),
!is_incorrect(&s->t4), !is_incorrect(&s->t5),
!is_incorrect(&s->t6));
if ( is_timestamps_incorrect(ppi,&errcount, 0x3C /* mask=t3&t4&t5&t6*/))
return 0;
}
errcount = 0;
SRV(ppi)->update_count++;
ppi->t_ops->get(ppi, &s->update_time);
......@@ -262,15 +253,9 @@ static int wr_p2p_offset(struct pp_instance *ppi,
{
static int errcount;
if (is_incorrect(&s->t1) || is_incorrect(&s->t2)) {
errcount++;
if (errcount > 5) /* a 2-3 in a row are expected */
pp_error("%s: TimestampsIncorrect: %d %d \n",
__func__, !is_incorrect(&s->t1),
!is_incorrect(&s->t2));
if ( is_timestamps_incorrect(ppi,&errcount, 0x3 /* mask=t1&t2 */))
return 0;
}
errcount = 0;
got_sync = 0;
SRV(ppi)->update_count++;
......@@ -297,22 +282,12 @@ static int wr_e2e_offset(struct pp_instance *ppi,
uint64_t delay_ms_fix;
static int errcount;
if (is_incorrect(&s->t1) || is_incorrect(&s->t2)
|| is_incorrect(&s->t3) || is_incorrect(&s->t4)) {
errcount++;
if (errcount > 5) /* a 2-3 in a row are expected */
pp_error("%s: TimestampsIncorrect: %d %d %d %d\n",
__func__, !is_incorrect(&s->t1),
!is_incorrect(&s->t2), !is_incorrect(&s->t3),
!is_incorrect(&s->t4));
if ( is_timestamps_incorrect(ppi,&errcount, 0xF /* mask=t1&t2&t3&t4 */))
return 0;
}
if (WRH_OPER()->servo_hook) /* FIXME: check this, missing in p2p */
WRH_OPER()->servo_hook(ppi, WRH_SERVO_ENTER);
errcount = 0;
SRV(ppi)->update_count++;
ppi->t_ops->get(ppi, &s->update_time);
......
......@@ -81,7 +81,10 @@ static char *fmt_ppt(struct pp_time *t)
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;
/*
* calc 'master_to_slave_delay'; no correction field
* appears in the formulas because it's already merged with t1
......@@ -99,6 +102,10 @@ void pp_servo_got_psync(struct pp_instance *ppi)
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));
pp_diag(ppi, servo, 2, "T2: %s\n", fmt_ppt(&ppi->t2));
......@@ -142,6 +149,7 @@ void pp_servo_got_resp(struct pp_instance *ppi)
struct pp_time *ofm = &SRV(ppi)->offsetFromMaster;
struct pp_avg_fltr *mpd_fltr = &SRV(ppi)->mpd_fltr;
int adj32;
static int errcount=0;
/* We sometimes enter here before we got sync/f-up */
......@@ -150,6 +158,9 @@ void pp_servo_got_resp(struct pp_instance *ppi)
return;
}
if ( is_timestamps_incorrect(ppi,&errcount,0xF /* mask=t1&t2&t3&t4 */) )
return;
shmem_lock(); /* Share memory locked */
/*
* calc 'slave_to_master_delay', removing delay_resp correction field
......@@ -172,8 +183,10 @@ void pp_servo_got_resp(struct pp_instance *ppi)
DSCUR(ppi)->meanDelay=pp_time_to_interval (mpd); /* Update currentDS */
pp_diag(ppi, servo, 1, "meanDelay: %s\n", fmt_ppt(mpd));
if (mpd->secs) /* Hmm.... we called this "bad event" */
if (mpd->secs) {/* Hmm.... we called this "bad event" */
shmem_unlock(); /* Share memory unlocked */
return;
}
/* mean path delay filtering */
pp_servo_mpd_fltr(ppi, mpd_fltr, mpd);
......@@ -187,10 +200,12 @@ void pp_servo_got_resp(struct pp_instance *ppi)
/* 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)
if (ppi->t_ops->adjust_freq) {
ppi->t_ops->adjust_freq(ppi, -adj32);
else
}
else {
ppi->t_ops->adjust_offset(ppi, -adj32);
}
}
}
SRV(ppi)->update_count++;
......@@ -207,7 +222,10 @@ void pp_servo_got_presp(struct pp_instance *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;
if ( is_timestamps_incorrect(ppi,&errcount,0x3C /* mask=&t3&t4&t5&t6 */) )
return;
shmem_lock(); /* Share memory locked */
/*
......@@ -301,6 +319,11 @@ static void pp_servo_mpd_fltr(struct pp_instance *ppi, struct pp_avg_fltr *mpd_f
(int)mpd_fltr->s_exp, (int)(mpd->scaled_nsecs >> 16));
}
/* Thresholds are used to decide if we must use time or frequency adjustment
* 20ms: This is the minimum value because it is used as a threshold to set the time in wrs_set_time() */
#define TIME_ADJUST_THRESHOLD_SCALED_NS (((int64_t)20000000)<<TIME_INTERVAL_FRACBITS) /* 20ms */
#define TIME_ADJUST_THRESHOLD_SEC 0
static int pp_servo_offset_master(struct pp_instance *ppi, struct pp_time *mpd,
struct pp_time *ofm, struct pp_time *delayMS)
{
......@@ -310,8 +333,12 @@ static int pp_servo_offset_master(struct pp_instance *ppi, struct pp_time *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)
)) {
return 0; /* proceeed with adjust */
}
if (!pp_can_adjust(ppi))
return 0; /* e.g., a loopback test run... "-t" on cmdline */
......
......@@ -207,10 +207,15 @@ static int unix_time_set(struct pp_instance *ppi, const struct pp_time *t)
/* UTC = TAI - 35 */
tp.tv_sec = t->secs - DSPRO(ppi)->currentUtcOffset;
tp.tv_nsec = t->scaled_nsecs >> 16;
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);
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);
}
return 0;
}
......
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