LXR | KVM | PM | Time | Interrupt | Systems Performance | Bootup Optimization

Linux PPS子系统:PPS子系统框架、PPS-GPIO驱动、pps-tools等介绍

PPS(Pulse Per Second)指的是“每秒脉冲”,它是一种高精度的时间信号,每秒钟提供一个脉冲,通常用于时间同步和时钟校准。PPS源可以是各种设备,比如GPS接收器、网络时间协议(NTP)服务器或其他能够提供精确时间信号的设备。

PPS信号的发送时机通常是在每秒的开始,即在UTC时间的整秒时刻。这种信号可以用于校准计算机或其他设备的时钟,以确保时间的准确性。

1 PPS子系统框架

PPS子系统分为:

  • PPS核心层:负责PPS注册和去注册,以及事件上报接口。
  • PPS驱动层:负责特定PPS源使能,并将其注册到系统中。
  • PPS用户层应用:通过/dev/ppsX去读PPS时间等信息。

2 PPS核心层

2.1 PPS子系统初始化

pps子系统初始化:

pps_int
  class_create--创建pps设备类。
  alloc_chrdev_region--分配pps设备主设备号。
pps_exit
  class_destroy
  unregister_chrdev_region

pps类的属性包括:

static struct attribute *pps_attrs[] = {
        &dev_attr_assert.attr,--PPS信号的“assert”事件的时间戳和序列号。
        &dev_attr_clear.attr,--PPS信号的“clear”事件的时间戳和序列号。
        &dev_attr_mode.attr,
        &dev_attr_echo.attr,--PPS源是否具有回声(echo)功能。如果PPS源支持回声功能,它可以将PPS信号反馈到输出,这在某些应用中可能很有用。
        &dev_attr_name.attr,--报告PPS源的名称。
        &dev_attr_path.attr,
        NULL,
};

pps支持的mode有:

/* Device/implementation parameters */
#define PPS_CAPTUREASSERT       0x01    /* capture assert events */
#define PPS_CAPTURECLEAR        0x02    /* capture clear events */
#define PPS_CAPTUREBOTH         0x03    /* capture assert and clear events */

#define PPS_OFFSETASSERT        0x10    /* apply compensation for assert event */
#define PPS_OFFSETCLEAR         0x20    /* apply compensation for clear event */

#define PPS_CANWAIT             0x100   /* can we wait for an event? */
#define PPS_CANPOLL             0x200   /* bit reserved for future use */

/* Kernel actions */
#define PPS_ECHOASSERT          0x40    /* feed back assert event to output */
#define PPS_ECHOCLEAR           0x80    /* feed back clear event to output */

/* Timestamp formats */
#define PPS_TSFMT_TSPEC         0x1000  /* select timespec format */
#define PPS_TSFMT_NTPFP         0x2000  /* select NTP format */

2.2 PPS核心层API 

pps子系统核心层提供一下功能:

  • pps_register_source:将PPS源注册到系统中。PPS源是指能够提供每秒一个脉冲信号的设备或接口。
  • pps_unregister_source:用于从系统中注销一个已经注册的PPS源。
pps_register_source
  pps_register_cdev
    cdev_init--初始化字符设备结构体,操作函数集为ops_cdef_fops。
    cdev_add
    device_create
pps_unregister_source
  pps_kc_remove
  pps_unregister_cdev
  •  pps_event:用于报告一个PPS事件。当PPS源检测到一个脉冲时,驱动需要调用此函数来通知系统发生了PPS事件。
pps_event
  --更新assert_tu/clear_tu。
  pps_kc_event
    hardpps
  wake_up_interruptible_all--唤醒所有poll上可中断等待的进程。
  kill_fasync--唤醒所有fasync上等待的进程。

 pps字符设备文件操作函数集pps_cdef_fops:

static const struct file_operations pps_cdev_fops = {
        .owner          = THIS_MODULE,
        .llseek         = no_llseek,
        .poll           = pps_cdev_poll,
        .fasync         = pps_cdev_fasync,
        .compat_ioctl   = pps_cdev_compat_ioctl,
        .unlocked_ioctl = pps_cdev_ioctl,
        .open           = pps_cdev_open,
        .release        = pps_cdev_release,
};

 其中pps_cdev_ioctl处理ioctl配置:

  • PPS_GETPARAMS:用于从PPS设备获取当前的参数设置。用户空间程序可以通过这个ioctl调用获取PPS源的当前参数,如时间戳的格式、边缘检测模式等。
  • PPS_SETPARAMS:用于设置PPS设备的参数。用户空间程序可以通过这个ioctl调用修改PPS源的参数,如时间戳的格式、边缘检测模式等。
  • PPS_GETCAP:用于获取PPS设备的能力。用户空间程序可以通过这个ioctl调用获取PPS源支持的功能,如是否支持硬件时间戳等。
  • PPS_FETCH:用于从PPS设备获取事件数据。用户空间程序可以通过这个ioctl调用获取PPS事件的时间戳和其他相关信息。
  • PPS_KC_BIND:用于将PPS源绑定到特定的内核消费者。用户空间程序可以通过这个ioctl调用指定PPS源应该向哪个内核消费者发送事件。

3 PPS Souce驱动:pps-gpio

PPS-GPIO是Linux内核中用于处理通过GPIO引脚输入的PPS(Pulse Per Second,每秒一个脉冲)信号的驱动框架。

  • GPIO作为PPS信号源:PPS-GPIO驱动允许使用GPIO引脚作为PPS信号源。

  • 中断处理:PPS-GPIO驱动通过注册GPIO中断来处理PPS信号。当检测到GPIO电平变化时,驱动会记录当前系统运行时刻,并把事件发送到用户空间。
  • 时间同步:PPS信号可以用于高精度时间同步。通过结合PPS信号和NTP(Network Time Protocol)或其他时间同步协议,可以实现系统级的精确时间同步。
  • PPS信号的生成和输出:除了作为PPS信号的消费者,PPS-GPIO也可以用于生成PPS信号。有些项目,如pps-gen-gpio,提供了通过GPIO引脚生成PPS信号的功能,这在测试和模拟PPS信号时非常有用。
module_platform_driver
    pps_gpio_driver
        pps_gpio_probe
      pps_gpio_setup--根据dts配置获取GPIO pin、是否assert-falling-edge、echo、echo-active-ms等。
      gpiod_to_irq--配置GPIO为中断。
      pps_register_source
      devm_request_irq
        pps_gpio_irq_handler
          pps_get_ts--获取当前时间戳。
          gpiod_get_value--读取GPIO当前值,判断是上升沿(PPS_CAPTUREASSERT)还是下降沿(PPS_CAPTURECLEAR)。
          pps_event--处理PPS事件。
     pps_gpio_remove

4 pps-tools

4.1 pps-tools编译

Utilities
   pps-tools...................................................... PPS-tools

4.2 ppsctl

ppsctl用于管理和配置PPS(Pulse Per Second,每秒脉冲)信号。

  • -b: 选项来绑定内核PPS消费者。
  • -B: 选项来解除绑定内核PPS消费者。
  • -f: 选项来设置内核NTP PPS标志。
  • -F: 选项来取消设置内核NTP PPS标志。
  • -a: 选项来使用assert edge。
  • -c: 选项来使用clear edge(默认)。

4.3 ppstest

ppstest用于测试 LinuxPPS API 接口。这个工具可以帮助用户检查和验证系统中的PPS(Pulse Per Second,每秒脉冲)信号源。

 assert 表示PPS信号的上升沿,clear 表示下降沿。时间戳显示了PPS信号发生的时刻,序列编号用于跟踪PPS信号的顺序。

4.4 ppswatch

ppswatch连续打印PPS(Pulse Per Second,每秒脉冲)时间戳。这个工具对于需要高精度时间同步的应用非常有用,因为它可以显示PPS信号的时间戳,这些时间戳可以用来校准系统时间或进行其他时间相关的测量。

ppswatch 会输出PPS事件的时间戳,格式通常包括时间戳、序列号和偏移量。例如:

 timestamp 是PPS事件发生的Unix时间戳,sequence 是PPS事件的序列号,offset 是PPS事件与预期时间的偏移量。

posted on 2024-11-22 23:59  ArnoldLu  阅读(68)  评论(0编辑  收藏  举报

导航