By Toradex秦海
1). 简介
IEEE 802.1 TSN(Time-Sensitive Networking) 工作组定义了一个基于 802.x 网络架构上提供同步时间低延迟服务能力的协议,其前身为 IEEE AVB(Audio Video Bridgin) 工作组,后于2012年重命名为 TSN 工作组以便于将相关协议标准更广泛推广; AVB/TSN 包含多种具体协议标准(见如下表格),其中最重要的协议标准之一就是 IEEE 802.1AS 时钟同步协议标准,它基于 IEEE 1588 协议进行精简和修改,也称为 gPTP 协议。
PTP 协议是一种精确的时间同步协议,IEEE 1588 标准为时钟分配定义了一个主从式架构,由一个或多个网段及一个或多个时钟组成。在局域网中能将时间同步精度控制在亚微秒级。 PTP 协议对时间戳在 MAC 层进行加盖, 消除了数据包在网络协议栈中的处理时间延迟; 对时间戳的记录和发送进行确认, 得到数据包准确的发送和接收时间。 相比于其它时间同步协议(如 NTP ), PTP 协议的同步精度是最高的。
本文就基于 NXP 最新的 i.MX8 系列 ARM 处理器平台进行 TSN 时钟同步的简单测试。
本文所演示的平台来自于Toradex Verdin iMX8M Plus 和 Apalis iMX8 嵌入式平台,这两个平台是基于近年发布的 NXP iMX8 系列 ARM 处理器,核心为 Cortex-A53/A72 。
2). 硬件准备
a). Verdin iMX8MP ARM 核心版配合 Dahlia Carrier Board 载板,并连接调试串口,后续测试中作为TSN网络中的 Master Clock 节点平台。Verdin iMX8MP核心板板载 PHY 芯片的一路千兆网络是完整支持包括TSN/AVB/IEEE1588等相关协议标准的网口,另外一路RGMII接口的MAC则支持AVB/IEEE1588。
b). Apalis iMX8 ARM 核心版配合 Apalis Eva Board 载板,并连接调试串口,后续测试中作为TSN网络中的 Slave Clock 节点平台。Apalis iMX8核心板提供的两路千兆网络都是只支持 AVB/IEEE1588 ,而不支持完整的 TSN ,不过由于本文仅测试时钟同步因此也可以正常和Verdin iMX8MP搭配使用。
c). 两个平台的千兆网口通过一根网线直通连接。
3). 软件准备
a). 如下图,Toradex Verdin iMXMP 模块标准 Ycoto Linux BSP 中已经包含了测试 IEEE 802.1AS 时钟同步的 Linuxptp 工具,可以参考这里说明分别在 Verdin iMX8MP 模块以及 Apalis iMX8 模块上面安装目前最新的LTS 5.7.2版本。
b). 如果需要在本文基础上进一步测试 IEEE 802.1Qav/Qbu/Qbv 等队列转发协议,则需要如下方式在 Ycoto 编译环境或者 Linux BSP Runtime 环境手动安装 ipoute2-tc 工具软件,并且可能需要对Linux Kernel/Device Tree做适当的修改,可以参考这里一个 NXP Application Note 文章说明。
---------------------------------------
### Ycoto Environment ###
# Add below to <oe-core>/build/conf/local.conf #
IMAGE_INSTALL_append = " iproute2-tc"
### Linux BSP Runtime ###
$ opkg install iproute2-tc_5.5.0-r0_aarch64.ipk
---------------------------------------
3). 具体测试流程
a). Toradex Ycoto Linux 默认使能了 NTP 时间同步协议,这是目前应用最为广泛的网络时间同步协议,精度可以达到毫秒级别,在大多数对于时间同步精度要求没有那么高的场景都可以应用,本文为了测试 gPTP 高精度时间同步,具体测试过程中需要关闭 NTP 服务,详细步骤后续说明会提供。
b). 实际的 TSN 网络中,Master Clock 节点通常会产生一个高精度时钟,来源一般是 GNSS(Global Navigation Satellite System) 结合 PPS(Pulse Per Second)信号来进行卫星授时,本文重点不在于此,因此对于作为 Master Clock 节点的 Verdin iMX8MP 设备在安装好 Linux 系统后,先仅只通过默认开启的 NTP 服务来进行 System Clock 的同步校准,来简单替代卫星授时的功能。
./ NTP服务详细配置方法可以参考这里,首先在Verdin iMX8MP Linux 下完成 NTP 时间同步。
---------------------------------------
### NTP 同步完成前的状态信息 ###
root@verdin-imx8mp-07250979:~# timedatectl
Local time: Thu 2023-03-16 04:20:08 UTC
Universal time: Thu 2023-03-16 04:20:08 UTC
RTC time: Thu 2023-03-16 04:20:07
Time zone: Universal (UTC, +0000)
System clock synchronized: no
NTP service: active
RTC in local TZ: no
### NTP同步完成后的状态信息 ###
root@verdin-imx8mp-07250979:~# timedatectl
Local time: Thu 2023-03-16 06:12:27 UTC
Universal time: Thu 2023-03-16 06:12:27 UTC
RTC time: Thu 2023-03-16 06:12:28
Time zone: Universal (UTC, +0000)
System clock synchronized: yes
NTP service: active
RTC in local TZ: no
---------------------------------------
./ 同步完成后关闭 NTP 服务
---------------------------------------
root@verdin-imx8mp-07250979:~# timedatectl set-ntp false
root@verdin-imx8mp-07250979:~# timedatectl
Local time: Thu 2023-03-16 06:17:49 UTC
Universal time: Thu 2023-03-16 06:17:49 UTC
RTC time: Thu 2023-03-16 06:17:50
Time zone: Universal (UTC, +0000)
System clock synchronized: yes
NTP service: inactive
RTC in local TZ: no
---------------------------------------
b). Verdin iMX8MP Master Clock 节点上面通过 linuxptp 工具来配置 gPTP 服务
./ 主要使用的工具如下
ptp4l: daemon that synchronizes the PTP Hardware Clock (PHC) from the NIC
phc2sys: daemon that synchronizes the PHC and the System clock
pmc: utility tool to configure ptp4l in run-time
./ 首先后台加载 ptp4l daemon 进程,用于同步 PHC
---------------------------------------
root@verdin-imx8mp-07250979:~# ptp4l -i eth0 -f ./gPTP.cfg --step_threshold=1 -m &
[1] 1092
ptp4l[1140.933]: selected /dev/ptp0 as PTP clock
root@verdin-imx8mp-07250979:~# ptp4l[1140.972]: port 1: INITIALIZING to LISTENING on INIT_COMPLE
TE
ptp4l[1140.972]: port 0: INITIALIZING to LISTENING on INIT_COMPLETE
ptp4l[1144.641]: port 1: LISTENING to MASTER on ANNOUNCE_RECEIPT_TIMEOUT_EXPIRES
ptp4l[1144.641]: selected local clock 00142d.fffe.6ea423 as best master
ptp4l[1144.641]: assuming the grand master role
---------------------------------------
// 参数说明如下,更多参数选项以及详细说明可以查看 ptp4l manpage
-f 选项指定 gPTP.cfg 配置文件,这个文件用于配置 ptp4l 工作于 gPTP 模式的设置参数
-i 选项指定 ptp4l 所要控制的 NIC 网口界面
--step_threshold 选项用于配置步进时钟的阈值,超过阈值,直接调整时钟时间,单位秒
-m 参数使能 log 信息打印输出,这个可以视测试需要打开或者关闭
// Master 所需的 gPTP.cfg 文件如下,更详细的配置文件参考说明和模板可以参考这里。需要主要目前 Linux 系统里面的 linuxptp 软件版本是 2.0.1 ,请查看对应branch的信息。
---------------------------------------
#
# 802.1AS example configuration containing those attributes which
# differ from the defaults. See the file, default.cfg, for the
# complete list of available options.
#
[global]
gmCapable 1
priority1 248
priority2 248
logAnnounceInterval 0
logSyncInterval -3
syncReceiptTimeout 3
neighborPropDelayThresh 800
min_neighbor_prop_delay -20000000
assume_two_step 1
path_trace_enabled 1
follow_up_info 1
transportSpecific 0x1
ptp_dst_mac 01:80:C2:00:00:0E
network_transport L2
delay_mechanism P2P
masterOnly 1
---------------------------------------
// 默认情况下, ptp4l 通过 BMCA(Best Master Clock Algorithm) 来判定当前 PHC 是否可以被作为 Grand Master 职责,也可以通过 masterOnly 或者 slaveOnly 参数来强制指定,本文使用后者。
---------------------------------------
ptp4l[1144.641]: selected local clock 00142d.fffe.6ea423 as best master
ptp4l[1144.641]: assuming the grand master role
---------------------------------------
./ PHC 同步完成后,接下来进行 System Clock同步,这个步骤主要针对那些依赖于 System clock 工作的应用,比如 ALSA/GStreamer frameworks AVTP 插件。
// 由于 PHC 时间采用 TAI(International Atomic Time) 标准,而 System Clock 采用(Coordinated Universal Time) 标准,需要通过 pmc runtime 工具配置相应的转换参数
---------------------------------------
root@verdin-imx8mp-07250979:~# pmc -u -b 0 -t 1 "SET GRANDMASTER_SETTINGS_NP clockClass 248 \
clockAccuracy 0xfe offsetScaledLogVariance 0xffff \
currentUtcOffset 37 leap61 0 leap59 0 currentUtcOffsetValid 1 \
ptpTimescale 1 timeTraceable 1 frequencyTraceable 0 \
timeSource 0xa0"
sending: SET GRANDMASTER_SETTINGS_NP
ptp4l[3021.662]: selected local clock 00142d.fffe.6ea423 as best master
00142d.fffe.6ea423-0 seq 0 RESPONSE MANAGEMENT GRANDMASTER_SETTINGS_NP
clockClass 248
clockAccuracy 0xfe
offsetScaledLogVariance 0xffff
currentUtcOffset 37
leap61 0
ptp4l[3021.662]: assuming the grand master role
leap59 0
currentUtcOffsetValid 1
ptpTimescale 1
timeTraceable 1
frequencyTraceable 0
timeSource 0xa0
---------------------------------------
// 然后通过 phc2sys 工具来同步 PHC 和 System Clock
---------------------------------------
root@verdin-imx8mp-07250979:~# phc2sys -s eth0 -c CLOCK_REALTIME --step_threshold=1 --transportSpecific=1 -w -m &
[2] 1058
phc2sys[600.436]: CLOCK_REALTIME phc offset 37000001087 s0 freq +0 delay 875
phc2sys[601.437]: CLOCK_REALTIME phc offset 37000001117 s1 freq +30 delay 875
phc2sys[602.437]: CLOCK_REALTIME phc offset -75 s2 freq -45 delay 875
phc2sys[603.437]: CLOCK_REALTIME phc offset 30 s2 freq +37 delay 875
phc2sys[604.437]: CLOCK_REALTIME phc offset -58 s2 freq -42 delay 875
---------------------------------------
// 参数说明如下,更多参数选项以及详细说明可以查看 ptp4l manpage
-s 选项指定来自于对应 NIC(eth0) 设备的 PHC 作为 master clock
-c 选项指定 System Clock 作为 slave clock
--step_threshold 选项用于配置步进时钟的阈值,超过阈值,直接调整时钟时间,单位秒
--transportSpecific 选项在基于 gPTP domain 运行是必要选项
-w 参数使得 phc2sys 处于等待状态直到 ptp4l 完成同步
-m 参数使能 log 信息打印输出,这个可以视测试需要打开或者关闭
// 打印的 log 信息中,当 phc offset 小于 100ns 即表示时钟同步成功
c). Apalis iMX8 Slave Clock 节点上面通过 linuxptp 工具来配置 gPTP 服务,具体的流程和命令和 Master 一致,只是在 gPTP.cfg 配置文件中将 masterOnly 修改未 slaveOnly 。
./ 首先由于是 Slave 节点设备,保持 Linux System Clock 为系统安装后的默认时间设置,直接关闭 NTP 服务不进行任何时间同步操作
---------------------------------------
root@apalis-imx8-07308034:~# timedatectl
Local time: Wed 2023-03-01 07:21:21 UTC
Universal time: Wed 2023-03-01 07:21:21 UTC
RTC time: Wed 2023-03-01 07:21:21
Time zone: Universal (UTC, +0000)
System clock synchronized: no
NTP service: inactive
RTC in local TZ: no
---------------------------------------
./ 通过和 Verdin iMX8MP 设备的直连网络和 Master Clock同步 PHC 时间,由于 gPTP协议都是基于 MAC 层的,因此网口无需设置 IP 地址也没有问题。
---------------------------------------
root@apalis-imx8-07308034:~# ptp4l -i eth0 -f ./gPTP.cfg --step_threshold=1 -m &
[1] 28567
ptp4l[2838.949]: selected /dev/ptp0 as PTP clock
root@apalis-imx8-07308034:~# ptp4l[2838.996]: port 1: INITIALIZING to LISTENING on INIT_COMPLETE
ptp4l[2838.996]: port 0: INITIALIZING to LISTENING on INIT_COMPLETE
ptp4l[2842.064]: selected local clock 00142d.fffe.6f8302 as best master
ptp4l[2842.197]: port 1: new foreign master 00142d.fffe.6ea423-1
ptp4l[2844.197]: selected best master clock 00142d.fffe.6ea423
ptp4l[2844.197]: updating UTC offset to 37
ptp4l[2844.197]: port 1: LISTENING to UNCALIBRATED on RS_SLAVE
ptp4l[2845.348]: port 1: UNCALIBRATED to SLAVE on MASTER_CLOCK_SELECTED
ptp4l[2845.973]: rms 646417001599952 max 1292834003200590 freq +9621 +/- 3636 delay 668 +/- 0
ptp4l[2846.973]: rms 8 max 10 freq +10997 +/- 6 delay 668 +/- 0
ptp4l[2847.974]: rms 9 max 10 freq +11008 +/- 1 delay 668 +/- 0
ptp4l[2848.974]: rms 4 max 6 freq +11006 +/- 3 delay 668 +/- 0
......
---------------------------------------
// 打印 log 信息中,rms 为 PHC 和 Grand Master clock 之间 offset 的平方值,当 rms 输出持续小于 100ns 时候,表示同步成功。
// 同时在 Verdin iMX8MP 的 Master 端,ptp4l 也会打印如下信息,证明 Slave 以及连接 Master 进行精准时间同步。
---------------------------------------
ptp4l[4137.874]: port 1: link up
ptp4l[4137.924]: port 1: FAULTY to LISTENING on INIT_COMPLETE
ptp4l[4141.728]: port 1: LISTENING to MASTER on ANNOUNCE_RECEIPT_TIMEOUT_EXPIRES
ptp4l[4141.728]: selected local clock 00142d.fffe.6ea423 as best master
ptp4l[4141.728]: assuming the grand master role
---------------------------------------
// 此时查看 System Clock 还是未同步的时间
---------------------------------------
### synchronous System clock on Verdin iMX8MP ###
root@verdin-imx8mp-07250979:~# date +%Y-%m-%d' '%H:%M:%S.%N | cut -b 1-25
2023-03-16 08:01:22.94530
### non- synchronous System clock on Apalis iMX8 ###
root@apalis-imx8-07308034:~# date +%Y-%m-%d' '%H:%M:%S.%N | cut -b 1-25
2023-03-01 08:02:46.75497
---------------------------------------
./ 通过 phc2sys 工具来同步 PHC 和 System Clock
---------------------------------------
root@apalis-imx8-07308034:~# phc2sys -s eth0 -c CLOCK_REALTIME --step_threshold=1 --transportSpecific=1 -w -m &
[2] 15230
phc2sys[1487.465]: CLOCK_REALTIME phc offset -1295917493725168 s0 freq +0 delay 2625
phc2sys[1488.466]: CLOCK_REALTIME phc offset -1295917493714065 s1 freq +11096 delay 2625
phc2sys[1489.466]: CLOCK_REALTIME phc offset -64 s2 freq +11032 delay 2625
phc2sys[1490.467]: CLOCK_REALTIME phc offset -71 s2 freq +11006 delay 2624
phc2sys[1491.467]: CLOCK_REALTIME phc offset 34 s2 freq +11090 delay 2625
---------------------------------------
// 打印 log 信息中 phc offset 小于 100ns 即表示时钟同步成功
// 此时查看 System Clock 则已经和 Grand Master 同步
---------------------------------------
### synchronous System clock on Verdin iMX8MP ###
root@verdin-imx8mp-07250979:~# date +%Y-%m-%d' '%H:%M:%S.%N | cut -b 1-25
2023-03-16 08:07:39.33336
### synchronous System clock on Apalis iMX8 ###
root@apalis-imx8-07308034:~# date +%Y-%m-%d' '%H:%M:%S.%N | cut -b 1-25
2023-03-16 08:07:40.54055
---------------------------------------
d). 另外为了更方便的测试 PHC 和 System Clock 是否同步成功,可以使用 check_clocks 工具,下载源码后参考这里说明用如下命令进行交叉编译,生成可执行文件在设备 Linux 下运行验证时钟同步情况
---------------------------------------
### compile binary on developing host ###
$ ${CROSS_COMPILE}gcc -o check_clocks check_clocks.c
### check on Verdin iMX8MP Master ###
root@verdin-imx8mp-07250979:~# ./check_clocks -v -d eth0
Dumping timestamps and deltas
rt tstamp: 1678954738288637418
tai tstamp: 1678954775288637543
phc tstamp: 1678954775288641175
rt latency: 125
tai latency: 125
phc latency: 1860
phc-rt delta: 37000003757
phc-tai delta: 3632
Clocks on this system are synchronized :)
### check on Apalis iMX8 Slave ###
root@apalis-imx8-07308034:~# ./check_clocks -v -d eth0
Dumping timestamps and deltas
rt tstamp: 1678954739151415597
tai tstamp: 1678954776151415847
phc tstamp: 1678954776151421106
rt latency: 125
tai latency: 250
phc latency: 3468
phc-rt delta: 37000005509
phc-tai delta: 5259
Clocks on this system are synchronized :)
---------------------------------------
5). 总结
本文基于NXP iMX8系列处理器简单演示了 TSN 通过 gPTP 协议进行网络时间同步的机制。
参考文档
https://community.nxp.com/t5/i-MX-Processors-Knowledge-Base/AVB-TSN-demo-on-i-MX8MP/ta-p/1123791