当前位置: 首页 > article >正文

linux内核驱动:ptp内核phc框架

目录

    • 一、介绍
    • 二、PHC驱动文件
    • 三、主要数据结构
    • 四、初始化和调用流程
    • 五、总结

一、介绍

本文基于linux内核5.10.xxx总结ptp1588精确时间协议实现过程中,内核部分的8A34002实现的phc(PTP hardware clock)驱动支持;

ptp的系统框架

在这里插入图片描述
.红圈部分为本笔记总结的phc驱动的部分;
.紫圈为用户层的ptp协议栈,如开源的ptp4l;
.蓝圈为集成在用户层ptp协议栈中时钟伺服控制部分,会根据ptp主时钟和本地时间的差值采用pid算法,调用linux的中的通用接口去控制phc驱动进行本地时间和频率的调整,进而和主时钟进行同步;
.红圈中的phc主要作用为通过用户空间的时钟伺服逻辑控制phc驱动进行微调时间递增的频率,实现phc功能的芯片如瑞萨的8A34002;
.MAC部分内置支持TSU时间标签单元寄存器时,时间信息可以在ptp数据包接收和发送的时机从TSU中获取或者调整TSU的时间;
.图中phc和mac中都有TSU时间标签单元,但是mac中的时间标签和通过网络传输过来的数据在驱动上更好集成时间精度更高,图中的方案是phc部分产生时钟频率,mac中的TSU以外部的时钟频率进行时间计时;

二、PHC驱动文件

1、ptp_chardev.c

实现结构struct posix_clock_operations *ops中的部分函数如下标注接口;

struct posix_clock_operations
{
struct module *owner;
int (*clock_adjtime)(struct posix_clock *pc, struct __kernel_timex *tx);
int (*clock_gettime)(struct posix_clock *pc, struct timespec64 *ts);
int (*clock_getres) (struct posix_clock *pc, struct timespec64 *ts);
int (*clock_settime)(struct posix_clock *pc,
const struct timespec64 ts);
/

* Optional character device methods:
*/
long (*ioctl) (struct posix_clock *pc,unsigned int cmd, unsigned long arg);
int (*open) (struct posix_clock *pc, fmode_t f_mode);
__poll_t (*poll) (struct posix_clock *pc,struct file *file, poll_table *wait);
int (*release) (struct posix_clock *pc);
ssize_t (*read) (struct posix_clock *pc,uint flags, char __user *buf, size_t cnt);
}

2、ptp_clock.c

ptp子系统的创建函数;
struct ptp_clock 的注册函数。创建/dev/ptp0、/dev/ptp1等设备节点;
static struct posix_clock_operations ptp_clock_ops 变量的定义;

实现static struct posix_clock_operations ptp_clock_ops 中的部分函数:
struct posix_clock_operations结构
{
struct module owner;
int (*clock_adjtime)(struct posix_clock *pc, struct __kernel_timex *tx);
int (*clock_gettime)(struct posix_clock *pc, struct timespec64 *ts);
int (*clock_getres) (struct posix_clock *pc, struct timespec64 *ts);
int (*clock_settime)(struct posix_clock *pc,const struct timespec64 *ts);
/

* Optional character device methods:
*/
long (*ioctl) (struct posix_clock *pc,unsigned int cmd, unsigned long arg);
int (*open) (struct posix_clock *pc, fmode_t f_mode);
__poll_t (*poll) (struct posix_clock *pc,struct file *file, poll_table *wait);
int (*release) (struct posix_clock *pc);
ssize_t (*read) (struct posix_clock *pc,uint flags, char __user *buf, size_t cnt);
}

3、ptp_sysfs.c

ptp设备的属性组定义;

定义如下属性:
static struct attribute *ptp_attrs[] = {
&dev_attr_clock_name.attr,
&dev_attr_max_adjustment.attr,
&dev_attr_n_alarms.attr,
&dev_attr_n_external_timestamps.attr,
&dev_attr_n_periodic_outputs.attr,
&dev_attr_n_programmable_pins.attr,
&dev_attr_pps_available.attr,
&dev_attr_extts_enable.attr,
&dev_attr_fifo.attr,
&dev_attr_period.attr,
&dev_attr_pps_enable.attr,
NULL
};

4、posix-timers.c

封装了关于获取时间、设置时间、调节频率的对应用户空间的系统调用函数,以 SYSCALL_DEFINE4 宏进行了注册,详见文件中定义;
定义了一个以时钟ID为数组下标的struct k_clock * const posix_clocks[] 数组;

5、posix-clock.c

字符设备节点/dev/ptp0、/dev/ptp1等的标准字符驱动函数实现;

static const struct file_operations posix_clock_file_operations = {
.owner = THIS_MODULE,
.llseek = no_llseek,
.read = posix_clock_read,
.poll = posix_clock_poll,
.unlocked_ioctl = posix_clock_ioctl,
.open = posix_clock_open,
.release = posix_clock_release,
#ifdef CONFIG_COMPAT
.compat_ioctl = posix_clock_compat_ioctl,
#endif
};

注册动态时钟:
const struct k_clock clock_posix_dynamic = {
.clock_getres = pc_clock_getres,
.clock_set = pc_clock_settime,
.clock_get_timespec = pc_clock_gettime,
.clock_adj = pc_clock_adjtime,
};

6、ptp_clockmatrix.c

8A34002芯片实现phc驱动的驱动文件;
具体实现struct ptp_clock_info 中的底层钩子函数;

三、主要数据结构

1、struct ptp_clock

定义于ptp_private.h;
是对phc设备的整体封装表示,包括设备信息的描述和操作集;

2、struct posix_clock

定义于posix-clock.h ;
可以理解成是struct ptp_clock的抽象父类,struct ptp_clock为具体实现,应用调用时逐渐从抽象结构 struct ptp_clock 向具体实现 struct ptp_clock 调用;

3、struct posix_clock_operations ops;

定义于posix-clock.h ;
struct posix_clock 中的操作函数集成员;

4、struct ptp_clock_info

定义于ptp_clock_kernel.h;
struct ptp_cloc中操作集成员info的表示;
驱动需要具体实现的是此结构

5、关系
在这里插入图片描述

四、初始化和调用流程

在这里插入图片描述

五、总结

1、实现phc驱动方案或者芯片可以有多种选择,支持程序控制调节时钟频率且能达到调节精度要求即可;
2、ptp本地时间的TSU时间标签也可能在网络的phy芯片中,实际应用中需要实现网络底层驱动和tsu时间标签驱动接口的结合;


http://www.kler.cn/a/301185.html

相关文章:

  • nodejs入门(1):nodejs的前后端分离
  • 关于Qt C++中connect的几种写法
  • Qt 的 QThread:多线程编程的基础
  • React教程第二节之虚拟DOM与Diffing算法理解
  • 笔记01----Transformer高效语义分割解码器模块DEPICT(即插即用)
  • django——创建 Django 项目和 APP
  • rman compress
  • starrocks结合同步和异步物化视图建立数据湖和数据仓库
  • java的ReentrantLock原理
  • ARM32开发——DMA内存到内存
  • CSS实现前端布局更巧妙的方案!在 flex 布局中通过使用 margin 实现水平垂直居中以及其他常见的前端布局
  • html初体验标准标签
  • MDK平台 - 变量和函数定义绝对位置
  • RISC-V (十一)软件定时器
  • 巧用抖音关键词视频列表 API 和视频评论 API 深度解析用户互动
  • 在 Jenkins 上通过 SSH 控制 Windows 目标计算机时,出现中文乱码
  • Redis——通用命令
  • 【原创教程】自动化工程案例01:8工位插针装配机02
  • 校园管理|基于springboot+vue的校园管理系统(源码+数据库+文档)
  • Leetcode 188. 买卖股票的最佳时机 Ⅳ 状态机dp C++实现
  • MAC配置chromedriver
  • EasyExcel 学习之 导出 “类型及精度问题”
  • Tomact的基本使用
  • 中国大数据产业的融资热潮来袭,哪些领域最受资本青睐?
  • 设计模式】Listener模式和Visitor模式的区别
  • 在JavaScript中实现简单的发布/订阅模式