PTP简介及Linux phy ptp驱动实现

1、PTP简介

        PTP(precision time protocol)精确时间协议,是一种时间同步的协议,对应 IEEE 1588 标准,是基于网络数据包的一种时间同步协议,1588v2的同步精度可以达到ns级,但1588协议对硬件有依赖。

2、PTP原理  

        时间同步的核心就是不同时钟源之间的“对齐”,那么多个时钟源实体之间,要解决两个问题:

a、主从关系:两个设备或端口,谁作为基准方,谁作为跟随方。

b、对齐跟踪:如何实现从端RTC对齐主端RTC。

        1588协议针对两个问题分别给出了解决方案;实际上1588中存在两套协议,一套是控制面协议,用于确定主从关系,一套是业务面协议,用于主从之间时间对齐。

        控制面协议采用基于STP协议(生成树算法)的自动选源协议,被称为BMCA。

        具体实现是依赖Announce报文携带信息,选出根节点和设备上的根端口,从而生成树状的结构,在我们的应用场景中这不是重点。

        数据面协议采用双向打戳定时协议, 1588的理论依据需要来回路径严格对称,协议默认收发物理链路上的时延相等。下面重点介绍双向打戳的技术原理。

           图1:delay one step                     

t1:master向slave发送sync报文的时间,包含在sync报文内,slave通过解析sync报文得到。

t2:slave接收到sync报文的时间,slave的硬件解析到sync报文时记录时间戳,并传递给slave。

t3:slave向master发送delay_req报文,slave的硬件解析到报文的发送,记录发送时间戳并传递给slave

t4:master获取到slave发送过来的delay_req报文,master硬件解析到delay_req报文,记录到时间戳,并传递给master,master随后将t4放在Delay_resp中传递给slave,slave通过解析delay_resp报文获取到t4

slave获取到t1,t2,t3,t4后通过下面的公式,即可计算出与master时间之间的偏移,从而调整时间。

从上面的公式可以看出,master与slave之间的传输时延越稳定,则算出的offset越准确,时间同步也越精确。理想的时间戳如下方左图,精准地在报文在物理链路上收发的时刻打上时间戳,但是在实际中,会因为各种因素带来误差。

3、软件PTP和硬件PTP

        软件PTP是在报文发送和接收时,在协议栈使用系统时间打时间戳,由于软件处理与物理链路实际发送存在gap,且软件处理的时延不可预测,必然带来时间同步抖动的问题,精度难以保障。

        硬件PTP是在报文发送和接收时,由MAC/PHY内部的PHC时钟对报文打时间戳,精度可以达到1us以下。

        

图2:软件时间戳和硬件时间戳(图片来自网络)

4、以phy驱动说明如何支持硬件PTP

4.1 phy ptp驱动需求分析

        由上面对协议的介绍可知,Phy PTP驱动的核心是实现对1588报文识别并记录时间戳。因此驱动首先要实现的功能是时间戳相关的功能。

  1. 时间戳功能:根据Linux社区文档(linux/kernel_doc/networking/timestamping)指导,phy支持时间戳功能的核心数据结构是mii_timestamper,如下:
struct mii_timestamper {bool (*rxtstamp)(struct mii_timestamper *mii_ts,struct sk_buff *skb, int type);void (*txtstamp)(struct mii_timestamper *mii_ts,struct sk_buff *skb, int type);int  (*hwtstamp)(struct mii_timestamper *mii_ts,struct ifreq *ifreq);void (*link_state)(struct mii_timestamper *mii_ts,struct phy_device *phydev);int  (*ts_info)(struct mii_timestamper *mii_ts,struct ethtool_ts_info *ts_info);struct device *device;
};

rxtstamp:接收方向的报文获取时间戳

txtstamp:发送方向的报文获取时间戳

hwtstamp:phy硬件PTP配置

ts_info:上报phy硬件PTP的能力,对接ethtool。

4.2 PHC时钟功能

        在进行时钟同步时,必然少不了要获取并比对时间,phy硬件要支持打时间戳,内部有一个PHC时钟,需要使能PHC时钟,并提供时钟相关接口,根据社区文档(Documentation\driver-api\ptp.rst),驱动要实现的核心数据结构是ptp_clock_info

struct ptp_clock_info {struct module *owner;char name[16];s32 max_adj;int n_alarm;int n_ext_ts;int n_per_out;int n_pins;int pps;struct ptp_pin_desc *pin_config;int (*adjfine)(struct ptp_clock_info *ptp, long scaled_ppm);int (*adjfreq)(struct ptp_clock_info *ptp, s32 delta);int (*adjphase)(struct ptp_clock_info *ptp, s32 phase);int (*adjtime)(struct ptp_clock_info *ptp, s64 delta);int (*gettime64)(struct ptp_clock_info *ptp, struct timespec64 *ts);int (*gettimex64)(struct ptp_clock_info *ptp, struct timespec64 *ts,struct ptp_system_timestamp *sts);int (*getcrosststamp)(struct ptp_clock_info *ptp,struct system_device_crosststamp *cts);int (*settime64)(struct ptp_clock_info *p, const struct timespec64 *ts);int (*enable)(struct ptp_clock_info *ptp,struct ptp_clock_request *request, int on);int (*verify)(struct ptp_clock_info *ptp, unsigned int pin,enum ptp_pin_function func, unsigned int chan);long (*do_aux_work)(struct ptp_clock_info *ptp);
};

        在这里我们看到了很多和系统时钟类似的接口,例如adjtime,adjfreq,gettime等,在内核态注册PHC时钟后,用户态调用clock_gettime类似的接口就可以获取到相关的时间或是调整时间。

        至于这些接口的具体实现可参考Linux社区中的代码,如果大家细心去看就会发现很多厂家的驱动里面通过timecounter来维护时间,是不是和前面的内容关联上了呢。

4.3 PHC时间与系统时间的同步

        仅仅在PHC时钟之间完成同步是不够的,毕竟对内核或者用户态应用来说可便宜地获取时间的方法是获取系统时间,那么PHC时钟需要实现与系统时钟的同步。Phy PTP与gmac驱动及Linux ptp应用的对接:master设备需要同步系统时间到phy的phc时钟,slave设备需要同步phc时钟到系统时间,高精度的方法为使用pps定时校准,可参考社区文档(\Documentation\driver-api\pps.rst)

4.4 PPS时间同步

        //todo

五、发送和接收流程中的时间戳处理

发送流程中时间戳获取流程:

接收流程中时间戳获取流程:

        由RX和TX流程可知,TX方向是软件先发送1588报文,需要等待获取时间戳,RX方向是软件已收到时间戳,需等待相匹配的1588报文,时间戳与报文需一一对应,严格匹配。

        具体实现略过。事实上不同厂家的gamc/phy对协议和时间戳支持的程度不同,具体的获取时间戳的方式也不一样,所以需要具体情况具体处理。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/30455.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

DFS(一)

问题一(指数级选择) 从1~n这n个整数中任意选取多个,输出所有可能的选择方案。 首先想一下,在现实世界中,我们要如何解决这个问题。 应该是一个一个枚举,即每个数都可以有两个选择(选/不选)。共有种结果。 想一下,如…

PHP转Go系列 | 字符串的使用姿势

大家好&#xff0c;我是码农先森。 输出 在 PHP 语言中的输出比较简单&#xff0c;直接使用 echo 就可以。此外&#xff0c;在 PHP 中还有一个格式化输出函数 sprintf 可以用占位符替换字符串。 <?phpecho 码农先森; echo sprintf(码农:%s, 先森);在 Go 语言中调用它的输…

创建进程的常用方式

自学python如何成为大佬(目录):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 在Python中有多个模块可以创建进程&#xff0c;比较常用的有os.fork()函数、multiprocessing模块和Pool进程池。由于os.fork()函数只适用于Unix/Linu…

0617,递归问题(详细——好好好一入递归深似海)

目录 第七章&#xff08;函数&#xff09;思维导图总结&#xff1a;递归三问 01&#xff0c;电影院问题 理解递归的执行过程 02&#xff0c;FIBNACCI数列 不是说具有递归结构的问题&#xff0c;就可以用递归求解——存在大量的重复计算 法一&#xff1a;自顶向下求解 BUG…

ruoyi框架第二天,自定义接口,在若依框架显示数据

书接上文&#xff0c;搭建好若依&#xff0c;并且创建自己想要的模块。 让ruoyi框架显示自己想要的模块。 今天&#xff0c;我们就要自定义接口&#xff0c;模仿ruoyi框架收发数据模式&#xff0c;来创建自己的模块。 我们创建好自己想要的接口&#xff0c;我这个是无参的查…

【Java】已解决java.util.EmptyStackException异常

文章目录 一、问题背景二、可能出错的原因三、错误代码示例四、正确代码示例五、注意事项 已解决java.util.EmptyStackException异常 一、问题背景 java.util.EmptyStackException是Java在使用java.util.Stack类时可能会遇到的一个异常。这个异常通常在尝试从空的栈中弹出&am…

四连杆机构运动学仿真 | Matlab源码+理论文本【超详细】

【程序简介】&#x1f4bb;&#x1f50d; 本程序通过matlab实现了四连杆机构的运动学仿真编程&#xff0c;动态展现了四连杆机构的角位移、角速度和角加速度的时程曲线&#xff0c;除了程序本身&#xff0c;还提供了机构运动学详细的公式推导文档&#xff0c;从而帮助大家更好…

2024年化学、能源与核工程国际会议(ICCENE 2024)

2024年化学、能源与核工程国际会议(ICCENE 2024) 2024 International Conference on Chemical, Energy and Nuclear Engineering (ICCENE 2024) 会议地点&#xff1a;三亚&#xff0c;中国 网址&#xff1a;www.iccene.com 邮箱: iccenesub-conf.com 投稿主题请注明:ICCEN…

【面试题】Spring常见面试题整理2024(全是干货!!!)

备战实习&#xff0c;会定期给大家整理常考的面试题&#xff0c;大家一起加油&#xff01; &#x1f3af; 注意&#xff1a;文章若有错误的地方&#xff0c;欢迎评论区里面指正 &#x1f36d; 系列文章目录 【面试题】MySQL常见面试题总结【面试题】面试题分享之JVM篇【面试题…

信息学奥赛初赛天天练-29-CSP-J2022阅读程序-掌握递归、递推、动态规划、二分与极值函数应用

PDF文档公众号回复关键字:20240619 2022 CSP-J 阅读程序2 阅读程序(判断题1.5分 选择题3分 共计40分 ) 01 #include <algorithm> 02 #include <iostream> 03 #include <limits> 04 05 using namespace std; 06 07 const int MAXN 105; 08 const int MAX…

C/C++ string模拟实现

1.模拟准备 1.1因为是模拟string&#xff0c;防止与库发生冲突&#xff0c;所以需要命名空间namespace隔离一下&#xff0c;我们来看一下基本内容 namespace yx {class string{private://char _buff[16]; lunix下小于16字节就存buff里char* _str;size_t _size;size_t _capac…

2713. 矩阵中严格递增的单元格数

题目 给定一个 m x n 的整数矩阵 mat&#xff0c;我们需要找出从某个单元格出发可以访问的最大单元格数量。移动规则是可以从当前单元格移动到同一行或同一列的任何其他单元格&#xff0c;但目标单元格的值必须严格大于当前单元格的值。需要返回最大可访问的单元格数量。 示例…

服务器流量收发测试

文章目录 一、概述二、实现方式一&#xff1a;编码1. 主要流程2. 核心代码3. 布署 三、实现方式二&#xff1a;脚本1.脚本编写2. 新增crontab任务 四、查看结果 一、概述 我们在安装vnStat、wondershaper便想通过实际的数据收发来进行测试。 二、实现方式一&#xff1a;编码 …

C#客户端

控件 打开链接 Socket socket; // 打开连接 private void button1_Click(object sender, EventArgs e) {button1.Enabled false;button2.Enabled true;//1 创建socket客户端对象socket new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);// 2…

ChatGPT 提示词技巧一本速通

目录 一、基本术语 二、提示词设计的基本原则 三、书写技巧 2.1 赋予角色 2.2 使用分隔符 2.2 结构化输出 2.3 指定步骤 2.4 提供示例 2.5 指定长度 2.6 使用或引用参考文本 2.7 提示模型进行自我判断 2.8 思考问题的解决过程 ​编辑 2.10 询问是否有遗漏 2.11 …

Studio One 6中文官网下载-Studio One软件下载-音乐编曲软件下载安装

​众多使用者向我们证明了轨道预设保存并调用您喜欢的曲目设置的快照&#xff0c;将您的工作流程效率升级到最新水平&#xff01;存储指定轨道或频道的每项设置&#xff0c;以便即时调用&#xff0c;即使对于多个选定的曲目/频道也同样支持&#xff0c;轨道预设可存储轨道延迟、…

如何将本地代码上传到git上面

精简步骤&#xff1a; git init git add . git commit -m "first init" git remote add origin 远程仓库地址 git push -u origin master 目录 1、初始化本地仓库 2、添加所有文件到本地仓库 3、提交更改到本地仓库 4、添加github仓库作为远程仓库 5、推送更改…

国际期货投机交易的常见操作方法:

一、在开仓阶段&#xff0c;入市时机的选择&#xff1a; &#xff08;1&#xff09;通过基本分析法&#xff0c;判断市场处于牛市还是熊市 开仓阶段&#xff0c;入市时机的选择&#xff1a;当需求增加、供给减少&#xff0c;此时价格上升&#xff0c;买入期货合约&#xff1b…

# 消息中间件 RocketMQ 高级功能和源码分析(五)

消息中间件 RocketMQ 高级功能和源码分析&#xff08;五&#xff09; 一、 消息中间件 RocketMQ 源码分析&#xff1a;NameServer 路由元数据 1、消息中间件 RocketMQ 中&#xff0c;NameServer 路由管理 NameServer 的主要作用是为消息的生产者和消息消费者提供关于主题 To…

一个小的画布Canvas页面,记录点的轨迹

Hello大家好&#xff0c;好久没有更新了&#xff0c;最近在忙一些其他的事&#xff0c;今天说一下画布canvas&#xff0c;下面是我的代码&#xff0c;实现了一个点从画布的&#xff08;0,0&#xff09;到&#xff08;canvas.width&#xff0c;canvas.height&#xff09;的一个实…