这部分主要讲解时钟如何利用偏移量和延时进行时钟同步。
如何实现时钟同步
void process_sync(struct port *p, struct ptp_message *m)
{
enum syfu_event event;
switch (p->state) {
case PS_INITIALIZING:
case PS_FAULTY:
case PS_DISABLED:
case PS_LISTENING:
case PS_PRE_MASTER:
case PS_MASTER:
case PS_GRAND_MASTER:
case PS_PASSIVE:
return;
case PS_UNCALIBRATED:
case PS_SLAVE:
break;
}
if (check_source_identity(p, m)) {
return;
}
if (!msg_unicast(m) &&
m->header.logMessageInterval != p->log_sync_interval) {
p->log_sync_interval = m->header.logMessageInterval;
clock_sync_interval(p->clock, p->log_sync_interval);
}
m->header.correction += p->asymmetry;
if (one_step(m)) {
port_synchronize(p, m->header.sequenceId,
m->hwts.ts, m->ts.pdu,
m->header.correction, 0,
m->header.logMessageInterval);
flush_last_sync(p);
return;
}
if (p->syfu == SF_HAVE_FUP &&
fup_sync_ok(p->last_syncfup, m) &&
p->last_syncfup->header.sequenceId == m->header.sequenceId) {
event = SYNC_MATCH;
} else {
event = SYNC_MISMATCH;
}
port_syfufsm(p, event, m);
}
static void port_synchronize(struct port *p,
uint16_t seqid,
tmv_t ingress_ts,
struct timestamp origin_ts,
Integer64 correction1, Integer64 correction2,
Integer8 sync_interval)
{
enum servo_state state, last_state;
tmv_t t1, t1c, t2, c1, c2;
port_set_sync_rx_tmo(p);
t1 = timestamp_to_tmv(origin_ts);
t2 = ingress_ts;
c1 = correction_to_tmv(correction1);
c2 = correction_to_tmv(correction2);
//如果是p2p使用延迟机制,则这里的
t1c = tmv_add(t1, tmv_add(c1, c2));
switch (p->state) {
case PS_UNCALIBRATED:
case PS_SLAVE:
//记录t1,t2,还有修正域的和,为了延迟不对称或者有小数ns
monitor_sync(p->slave_event_monitor,
clock_parent_identity(p->clock), seqid,
t1, tmv_add(c1, c2), t2);
break;
default:
break;
}
last_state = clock_servo_state(p->clock);
//保持时钟的同步
state = clock_synchronize(p->clock, t2, t1c);
switch (state) {
case SERVO_UNLOCKED:
port_dispatch(p, EV_SYNCHRONIZATION_FAULT, 0);
if (servo_offset_threshold(clock_servo(p->clock)) != 0 &&
sync_interval != p->initialLogSyncInterval) {
p->logPdelayReqInterval = p->logMinPdelayReqInterval;
p->logSyncInterval = p->initialLogSyncInterval;
port_tx_interval_request(p, SIGNAL_NO_CHANGE,
SIGNAL_SET_INITIAL,
SIGNAL_NO_CHANGE);
}
break;
case SERVO_JUMP:
port_dispatch(p, EV_SYNCHRONIZATION_FAULT, 0);
flush_delay_req(p);
if (p->peer_delay_req) {
msg_put(p->peer_delay_req);
p->peer_delay_req = NULL;
}
break;
case SERVO_LOCKED:
port_dispatch(p, EV_MASTER_CLOCK_SELECTED, 0);
break;
case SERVO_LOCKED_STABLE:
message_interval_request(p, last_state, sync_interval);
break;
}
}
enum servo_state clock_synchronize(struct clock *c, tmv_t ingress, tmv_t origin)
{
enum servo_state state = SERVO_UNLOCKED;
double adj, weight;
int64_t offset;
c->ingress_ts = ingress;
tsproc_down_ts(c->tsproc, origin, ingress);
//更新offset,保持时钟同步
if (tsproc_update_offset(c->tsproc, &c->master_offset, &weight)) {
if (c->free_running) {
return clock_no_adjust