LinuxPTP没那么简单

Posted 姚家湾

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LinuxPTP没那么简单相关的知识,希望对你有一定的参考价值。

        分布式实时系统的时间同步是十分重要的。典型的分布式实时系统包括了电信分组网或者电力控制网络,和同步数据采集网。

实现分布式实时系统同步的方式有下面几种方式

  • 通过独立的参考时钟
  • 通过分时通信网(例如电信的TDM,SDH 传输网)提取时钟
  • 通过IEEE1588/PTP 精确时钟协议分组网上实现时钟同步
  • 通过GPS/北斗 系统实现时钟同步

        在具体的应用中,也可能是上述几种同步方式的组合。已经有许多的文章介绍IEEE1599/PTP 协议。也有一些关于使用Linux 操作系统下的PTP 工具PTP4L。但是并没有多少文章探讨在Linux 系统下PTP 协议的实现细节以及如何在应用程序中如何使用,通过PTP 协议实现的同步时钟来实现实时任务的时间同步。

        在Ubuntu 上使用PTP4L 进行IEEE1588/PTP 测试感觉还算简单,但是开始研究在xilinx zynq 芯片上开发LinuxPTP才发现,它们并没有那么简单,无论是硬件还是软件都比较复杂。

分布式系统的时间同步

        所谓分布式系统的时间同步是指系统中的所有设备具有一个与某一个统一的参考时钟源同步的时钟。从而保证系统的设备的各种操作是同步的。在电信网络中是通过同步网实现全网同步的,并且全国电信网络同步与单一的基准时钟源。

分布式系统中的所有设备实现时间同步的方式是

从外部参考时钟或者同步时钟协议中提取参考时钟

内部维护一个本地时钟,通过硬件锁相或者软件伺服控制方式实现时间同步,也可以进一步实现相位同步。

本地时钟提供了系统其它应用所需要同步时钟或者中断。

LinuxPTP系统

        在Linux 系统中,支持PTP协议的条件是具有支持IEEE1588/PTP的硬件。可以是MAC 层也可以是PHY 层支持IEEE1588。并且具有相应的设备驱动。

可以通过ethtool -T eth0 命令来检测系统是否硬件支持IEEE1588 协议

Time stamping parameters for eth6:
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: 1
Hardware Transmit Timestamp Modes:
       off                   (HWTSTAMP_TX_OFF)
        on                    (HWTSTAMP_TX_ON)
Hardware Receive Filter Modes:
        none                  (HWTSTAMP_FILTER_NONE)
        all                   (HWTSTAMP_FILTER_ALL)

Linux下PTP 功能实现是一个开源项目,可以在下列地址下载

linuxptp download | SourceForge.net

目前已经为3.1版本

Linux PTP通过下面四个部分支持PTP协议

  • 用户空间的软件实现IEEE1588协议栈和PTP时钟伺服。
  • 与PHY和MAC集成的硬件时间标签单元(TSU)
  • PTP硬件时钟(PHC)提供TSU的时间参考,并且通过PTP时钟伺服控制。
  • Linux 内核

LinuxPTP 基本架构

 

         从上图可见,在Linux中有两个硬件的驱动,一个是PHY/MAC ,内部带有硬件时间标签单元(TSU local time stamp unit)。另一个是PTP 硬件时钟(PHC-PTP Hardware Clock),内部的计数器称为TOD (Time of Day)。

PHY/MAC 的TSU和PHC 的相互关系如下:

        这两个单元可以是同一个组件,也可以是分别的组件。最简单的方法也许是直接将系统时钟作为PHC。通过PTP协议调整系统时钟和TSU。

        有些PHY/MAC器件输出的时钟频率很低,没有办法构建高速精确同步时钟。例如AR8031 只是输出一个1Hz的PPS。DP83640 能够输出10M,而STM32 MAC 产生的时钟为几百K。如果系统要求导出诸多特定的高速时钟频率(例如ADC采样频率,通信系统的时钟等等)的话,我们就需要一个独立的PHC 组件了。独立的时钟器件(PHC),可以是ASIC 芯片,也可以使用FPGA 构建。

        PHY/MAC中的TSU和PHC 之间的关系如下,PHC 向TSU提供时钟,用户端协议栈提取以太网上的帧,通过伺服算法调整PHC 输出的时钟。

用户程序访问本地时间标签(TSU)

        可以通过 SIO_TIMESTAMPING IOCTL 配置接收时间戳接收。 使用该 IOCTL 启用接收时间戳接收。能够在接收的包中读到时间标签。

TSU和PHC之间的同步

        当TSU和PHC 分开实现时,系统集成者必须TODtus和TODphc同步,保持TODtsu与TODphc 相同。在系统启动时,必须取消TOStsu和TODphc 之间的静态时间差。开源ts2phc 完成这一功能。先决条件是TSU 的驱动必须遵循PHC 架构。

PHC与Linux 系统时钟挂钩

        在linux 中有各种定时器,最重要的时钟是系统时钟和RTC时钟。

实时钟RTC:它由板上电池驱动的“Real Time Clock”也叫做RTC或者叫CMOS时钟,硬件时钟。当操作系统关机的时候,用这个来记录时间。但是系统是不用该时钟来做实时任务时间同步。

系统时钟:“System clock”也叫内核时钟或者软件时钟,是由软件根据时间中断来进行计数的,内核时钟在系统关机的情况下是不存在的,所以,当操作系统启动的时候,内核时钟是要读取RTC时间来进行时间同步.。

                Linux 的系统时钟是基于系统的主时钟产生的滴答时钟,或者是某个硬件定时器产生,能够产生时钟中断维护系统时钟和调度。

                如果要实现PTP PHC 时钟与系统时钟同步,应用程序就能够实现实时任务的同步运行了。LinuxPTP 项目中有一个phcsys 程序,它实现了PHC 与系统时钟挂钩。

如此一来,应用程序能够不加修改的使用系统时钟来实现应用程序的实时同步机制。

        两种同步linux system clock 方法

        当然实现起来涉及到系统时钟的伺服控制,可能会麻烦一点。比如可能使用压控晶振。对于一般自动控制设备而言,似乎没有必要搞得这么复杂。

除了使用PPS以外,Linux 系统时钟的调整需要使用函数adjtimex。具体用法就不再细说了。

一些简化的方法

        在LinuxPTP 时钟架构的具体实现中,也可以采取一些简化的方式,例如:

        在这种结构中,PHC 通过直接访问TSU实现,使用用户空间的程序实现系统时钟与PTP 硬件时钟的同步,在STM32 的PTP实现中我们就采取了这样的方式。

        在顶端,可以通过SO_TIMESTAMPING socket  选项读取时间标签的包,PTP栈计算和调整PHC和POSIX 时间的差。PPS 产生内核的中断服务。

        可以为PHC编写POSIX 兼容的驱动程序,通过POSIX Timer 方式去访问PHC,也可以在用户空间的程序编写PHC接口访问程序。

LinuxPPS

        一个更加简单的同步PTP与 Linux 系统时钟的方法似乎是LinuxPPS。LinuxPPS 提供了一个编程接口 ( API ) 来在系统中定义多个 PPS 源。

        PPS 的意思是“每秒脉冲”,而 PPS 源只是每秒提供高精度信号的设备,以便应用程序可以使用它来调整系统时钟时间。

        PPS 源可以连接到串行端口(通常连接到 Data Carrier Detect 引脚)或并行端口(ACK 引脚)或特殊 CPU 的 GPIO(这在嵌入式系统中很常见),但在每种情况下,当一个新的脉冲到达,系统必须为其应用一个时间戳并为用户空间记录它。

        常见的用途是将 NTPD 作为用户程序,与 GPS 接收器作为 PPS 源的组合,以获得与 UTC 亚毫秒同步的挂钟时间。

        为在使用 PPS 作为选定时间参考时获得最佳结果,请确保提供 PPS 信号的设备提供稳定、一致的 1 Hz 信号。当 OCXO、TCXO 或更好的振荡器驱动源信号时,您可以获得最佳结果。

系统设计时的权衡

        上面讨论了许多种方法,在系统设计时要做出适当的权衡。

        设备要与哪几种时钟源同步?仅仅以IEEE1588 为时钟源,还是需要另外的时钟源,例如外接时钟,还是GPS?如果是PTP master,tsu的时钟来自于master,还是内置的恒温晶振?如果多种同步时钟源,需要通过PL 逻辑来添加独立的PHC 。在整机设计时充分考虑这些因素。

zynq MPsoc 中实现PTP 的探讨

        从网络上了解,zynq 7000 的PS 硬千兆以太网不支持IEEE1588,但是zynq MPsoc的PS 硬千兆以太网支持IEEE1588。

下面的内容来自于

zynq MPsoc PS and PL Ethernet example Projects

Zynq 的PS 端装备了4个GEM,每个控制器都可以独立地配置,使用RGMII接口。通过MIO连接到外部的RGMII PHY。器件。也可以通过EMIO 路由到PL 端。

外部TSU

        在GEM中的1588 时间标签单元是一个128位的寄存器。高48位是秒计数器,随后30位是nanoseconds 计数器,后24bit 是sub nanoseconds计数器。后54位计数1秒。

GEM 的TSU(硬件时间标签单元) 可以暴露到PL 端,由于PS/PL 端的引脚有限,只有GEM0 的TSU能够暴露在PL 端。

通过将TSU 暴露在PL 端,想必能够构建更为灵活的同步时钟系统。

GEM 内部寄存器

ZYNQ MP 的内部寄存器都在ug1087 中定义,其中GEM 模块定义了一大堆的寄存器。

Documentation Portal

有关IEEE1588的相关寄存器如下:

tsu_timer_incr_sub_nsec

1588 Timer Increment Register sub nsec

tsu_timer_msb_sec

1588 Timer Seconds Register 47:32

tsu_strobe_msb_sec

1588 Timer Sync Strobe Seconds Register 47:32

tsu_strobe_sec

1588 Timer Sync Strobe Seconds Register 31:0

tsu_strobe_nsec

1588 Timer Sync Strobe Nanoseconds Register

tsu_timer_sec

1588 Timer Seconds Register 31:0

tsu_timer_nsec

1588 Timer Nanoseconds Register

tsu_timer_adjust

This register returns all zeroes when read.

tsu_timer_incr

1588 Timer Increment Register

tsu_ptp_tx_sec

PTP Event Frame Transmitted Seconds Register 31:0

tsu_ptp_tx_nsec

PTP Event Frame Transmitted Nanoseconds Register

tsu_ptp_rx_sec

PTP Event Frame Received Seconds Register 31:0

tsu_ptp_rx_nsec

PTP Event Frame Received Nanoseconds Register

tsu_peer_tx_sec

PTP Peer Event Frame Transmitted Seconds Register 31:0

tsu_peer_tx_nsec

PTP Peer Event Frame Transmitted Nanoseconds Register

tsu_peer_rx_sec

PTP Peer Event Frame Received Seconds Register 31:0

tsu_peer_rx_nsec

PTP Peer Event Frame Received Nanoseconds Register

tsu_timer_msb_sec  1588 Timer Seconds Register 47:32

tsu_timer_sec       1588 Timer Seconds Register 31:0

tsu_timer_nsec      588 Timer Nanoseconds Register

应该是GEM的TSU 寄存器。也就是说,通过这三个寄存器能够访问TSU。

这些寄存器的使用还是非常复杂的。但愿Petalinux 上有完整的驱动。

结束语

        本文讨论的是在Linux 下实现PTP机制的问题,它依赖于Linux下内核,驱动,硬件对PTP的支持程度。对于特定的应用系统而言,通过用户层程序实现同步时钟,也许会简单一点。

以上是关于LinuxPTP没那么简单的主要内容,如果未能解决你的问题,请参考以下文章

手轮脉冲发生器与PLC连接,PLC控制伺服,如何用手轮脉冲发生器及时控制伺服马达

arduino 能检测脉冲信号吗

(转)Python: super 没那么简单

使用iOS8 WKWebView的浏览器模块,脉冲动画层-b

在曲线上找到最佳权衡点

用 alsa 录制 8 位签名单声道 16khz 声音的最简单方法(以与脉冲兼容的方式)?