在一些使用场景中,我们需要使用主时钟来同步工控机或PC机。如下图所示。下面我们介绍一下如何在利用飞灵科技的FlySync 主时钟同步一个Linux 主机。
在工控机安装linuxprp 软件包
使用apt 安装linuxptp:sudo apt-get install linuxptp 或者其他方式。
使用ethtool 工具查看主机网口是否具有硬件时间戳能力
root@pc:~$ ethtool -T eth0
Time stamping parameters for eth0:
Capabilities:
hardware-transmit (SOF_TIMESTAMPING_TX_HARDWARE)
software-transmit (SOF_TIMESTAMPING_TX_SOFTWARE)
hardware-receive (SOF_TIMESTAMPING_RX_HARDWARE)
software-receive (SOF_TIMESTAMPING_RX_SOFTWARE)
software-system-clock (SOF_TIMESTAMPING_SOFTWARE)
hardware-raw-clock (SOF_TIMESTAMPING_RAW_HARDWARE)
PTP Hardware Clock: 0
Hardware Transmit Timestamp Modes:
off (HWTSTAMP_TX_OFF)
on (HWTSTAMP_TX_ON)
Hardware Receive Filter Modes:
none (HWTSTAMP_FILTER_NONE)
all (HWTSTAMP_FILTER_ALL)
ptpv1-l4-sync (HWTSTAMP_FILTER_PTP_V1_L4_SYNC)
ptpv1-l4-delay-req (HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ)
ptpv2-l4-sync (HWTSTAMP_FILTER_PTP_V2_L4_SYNC)
ptpv2-l4-delay-req (HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ)
ptpv2-l2-sync (HWTSTAMP_FILTER_PTP_V2_L2_SYNC)
ptpv2-l2-delay-req (HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ)
ptpv2-event (HWTSTAMP_FILTER_PTP_V2_EVENT)
ptpv2-sync (HWTSTAMP_FILTER_PTP_V2_SYNC)
ptpv2-delay-req (HWTSTAMP_FILTER_PTP_V2_DELAY_REQ)
从上面可以看出,网口eth0支持硬件和软件时间戳,并且对应的ptp时钟为/dev/ptp0。
查看主时钟配置的参数
同步工控机上的时间
root@pc:~$ sudo ptp4l -i eth0 -p /dev/ptp1 -s -m -H -E
ptp4l[8706866.391]: selected /dev/ptp1 as PTP clock
ptp4l[8706866.393]: port 1: INITIALIZING to LISTENING on INIT_COMPLETE
ptp4l[8706866.393]: port 0: INITIALIZING to LISTENING on INIT_COMPLETE
ptp4l[8706867.209]: port 1: new foreign master 180373.fffe.31a803-1
ptp4l[8706871.209]: selected best master clock 180373.fffe.31a803
ptp4l[8706871.209]: running in a temporal vortex
ptp4l[8706871.209]: port 1: LISTENING to UNCALIBRATED on RS_SLAVE
ptp4l[8706872.214]: master offset 2185 s0 freq -7043 path delay 13428
ptp4l[8706873.214]: master offset 1977 s2 freq -7251 path delay 13428
ptp4l[8706873.214]: port 1: UNCALIBRATED to SLAVE on MASTER_CLOCK_SELECTED
ptp4l[8706874.214]: master offset 2384 s2 freq -4867 path delay 13369
ptp4l[8706875.214]: master offset 364 s2 freq -6172 path delay 13428
ptp4l[8706876.214]: master offset -588 s2 freq -7015 path delay 13579
ptp4l[8706877.214]: master offset -701 s2 freq -7304 path delay 13444
ptp4l[8706878.214]: master offset -139 s2 freq -6952 path delay 13425
ptp4l[8706879.215]: master offset -202 s2 freq -7057 path delay 13428
ptp4l[8706880.215]: master offset -520 s2 freq -7436 path delay 13453
ptp4l[8706881.215]: master offset -9 s2 freq -7081 path delay 13434
ptp4l[8706882.215]: master offset 127 s2 freq -6947 path delay 13410
ptp4l[8706883.215]: master offset 62 s2 freq -6974 path delay
获取同步后的时间
#include <time.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define CLOCKFD 3
#define FD_TO_CLOCKID(fd) ((~(clockid_t) (fd) << 3) | CLOCKFD)
#define CLOCKID_TO_FD(clk) ((unsigned int) ~((clk) >> 3))
int
main(int argc, char *argv[])
{
struct timespec ts;
clockid_t clkid;
int fd;
fd = open("/dev/ptp0", O_RDWR);
clkid = FD_TO_CLOCKID(fd);
if (clock_gettime(clkid, &ts) == -1) {
perror("clock_gettime");
exit(EXIT_FAILURE);
}
printf("Date: %s \n", ctime(&ts.tv_sec));
exit(EXIT_SUCCESS);
}