我在 Raspberry Pi 上构建了一个支持 PPS 的 GPS 时钟,为了让它工作,我需要使用 udev 创建到硬件串行端口以及内核 GPIO PPS/dev/gps0
和 的符号链接/dev/gpspps0
。它不必是 0,我只需要两个数字相同,以便 NTP 可以接收到 PPS 信号。我创建了以下 udev 规则文件来执行此操作:
# Symlink /dev/ttyAMA0 to /dev/gps0
KERNEL=="ttyAMA0", SUBSYSTEM=="tty", DRIVER=="", SYMLINK+="gps0"
# Symlink /dev/pps0 to /dev/gpspps0
KERNEL=="pps0", SUBSYSTEM=="pps", DRIVER=="", SYMLINK+="gpspps0"
就其本身而言,这表现得很好。创建符号链接后,NTP 愉快地获取设备上的 PPS 锁。生成以下设备:
pi@srv-GPiS-00:~ $ ls -al /dev/gps*
lrwxrwxrwx 1 root root 7 Aug 12 16:31 /dev/gps0 -> ttyAMA0
lrwxrwxrwx 1 root root 4 Aug 12 16:31 /dev/gpspps0 -> pps0
60-gpsd.rules
但是,如果在启动时插入由 处理的 USB GPS ,则符号链接gps0
将被覆盖以指向ttyUSB0
,如下所示:
pi@srv-GPiS-00:~ $ ls -al /dev/gps*
lrwxrwxrwx 1 root root 7 Aug 12 16:45 /dev/gps0 -> ttyUSB0
lrwxrwxrwx 1 root root 4 Aug 12 16:45 /dev/gpspps0 -> pps0
(在你问为什么我有两个 GPS 插入同一台计算机之前,我正在尝试根据我已知的工作系统调试和校准第二个 GPS)
拔掉设备可以让符号链接返回到ttyAMA0
.有趣的是,当第二个 GPS 重新插入时,udev 有一个次要行为,将其放置并获取其ttyUSB1
符号链接:gps1
pi@srv-GPiS-00:~ $ ls -al /dev/gps*
lrwxrwxrwx 1 root root 7 Aug 12 16:48 /dev/gps0 -> ttyAMA0
lrwxrwxrwx 1 root root 7 Aug 12 16:48 /dev/gps1 -> ttyUSB1
lrwxrwxrwx 1 root root 4 Aug 12 16:45 /dev/gpspps0 -> pps0
我希望系统具有这种次要行为,以便在连接第二个 GPS 的情况下重新启动系统时 NTP 不会受到干扰。
我尝试将 udev 规则的文件名从 90 更改为 50,但没有效果,并且我还尝试在规则文件中指定gps%n
/而不是/ (如),这会导致完全消除次要行为。我还知道udev 的运算符最终设置了一个参数,但我不知道它如何与争夺相同符号链接的两个设备进行交互,而且我也不想破坏其他文件中的任何其他符号链接规则。gpspps%n
gps0
gpspps0
60-gpsd.rules
:=
当然,是的,我可以将我的设备硬编码为gps3
/ gpspps3
,我相信这是 NTP 支持的最大设备数量。然而,我想弄清楚为什么 udev 正在做它正在做的事情。我还想避免删除/禁用 60-gpsd.rules 文件,因为它是管道胶带,并且在许多操作系统升级中其行为都不稳定。
有什么想法吗?
附加信息:
pi@srv-GPiS-00:~ $ udevadm info --name=/dev/ttyAMA0 --attribute-walk
...
looking at device '/devices/platform/soc/3f201000.serial/tty/ttyAMA0':
KERNEL=="ttyAMA0"
SUBSYSTEM=="tty"
DRIVER==""
looking at parent device '/devices/platform/soc/3f201000.serial':
KERNELS=="3f201000.serial"
SUBSYSTEMS=="amba"
DRIVERS=="uart-pl011"
ATTRS{id}=="00241011"
ATTRS{irq0}=="87"
ATTRS{driver_override}==""
looking at parent device '/devices/platform/soc':
KERNELS=="soc"
SUBSYSTEMS=="platform"
DRIVERS==""
ATTRS{driver_override}=="(null)"
looking at parent device '/devices/platform':
KERNELS=="platform"
SUBSYSTEMS==""
DRIVERS==""
pi@srv-GPiS-00:~ $ udevadm info --name=/dev/ttyUSB1 --attribute-walk
...
looking at device '/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.4/1-1.4:1.0/ttyUSB1/tty/ttyUSB1':
KERNEL=="ttyUSB1"
SUBSYSTEM=="tty"
DRIVER==""
looking at parent device '/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.4/1-1.4:1.0/ttyUSB1':
KERNELS=="ttyUSB1"
SUBSYSTEMS=="usb-serial"
DRIVERS=="garmin_gps"
ATTRS{port_number}=="0"
looking at parent device '/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.4/1-1.4:1.0':
KERNELS=="1-1.4:1.0"
SUBSYSTEMS=="usb"
DRIVERS=="garmin_gps"
ATTRS{bInterfaceProtocol}=="ff"
ATTRS{bInterfaceNumber}=="00"
ATTRS{bInterfaceSubClass}=="ff"
ATTRS{bInterfaceClass}=="ff"
ATTRS{bAlternateSetting}==" 0"
ATTRS{authorized}=="1"
ATTRS{bNumEndpoints}=="03"
ATTRS{supports_autosuspend}=="1"
looking at parent device '/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.4':
KERNELS=="1-1.4"
SUBSYSTEMS=="usb"
DRIVERS=="usb"
ATTRS{bDeviceClass}=="ff"
ATTRS{bmAttributes}=="c0"
ATTRS{bConfigurationValue}=="1"
ATTRS{version}==" 1.10"
ATTRS{devnum}=="7"
ATTRS{bMaxPower}=="0mA"
ATTRS{idProduct}=="0003"
ATTRS{avoid_reset_quirk}=="0"
ATTRS{urbnum}=="3412"
ATTRS{bDeviceSubClass}=="ff"
ATTRS{maxchild}=="0"
ATTRS{bcdDevice}=="0001"
ATTRS{bMaxPacketSize0}=="8"
ATTRS{idVendor}=="091e"
ATTRS{speed}=="12"
ATTRS{removable}=="removable"
ATTRS{ltm_capable}=="no"
ATTRS{bNumConfigurations}=="1"
ATTRS{busnum}=="1"
ATTRS{authorized}=="1"
ATTRS{quirks}=="0x0"
ATTRS{configuration}==""
ATTRS{devpath}=="1.4"
ATTRS{bDeviceProtocol}=="ff"
ATTRS{bNumInterfaces}==" 1"
looking at parent device '/devices/platform/soc/3f980000.usb/usb1/1-1':
KERNELS=="1-1"
SUBSYSTEMS=="usb"
DRIVERS=="usb"
ATTRS{bDeviceClass}=="09"
ATTRS{bmAttributes}=="e0"
ATTRS{bConfigurationValue}=="1"
ATTRS{version}==" 2.00"
ATTRS{devnum}=="2"
ATTRS{bMaxPower}=="2mA"
ATTRS{idProduct}=="9514"
ATTRS{avoid_reset_quirk}=="0"
ATTRS{urbnum}=="81"
ATTRS{bDeviceSubClass}=="00"
ATTRS{maxchild}=="5"
ATTRS{bcdDevice}=="0200"
ATTRS{bMaxPacketSize0}=="64"
ATTRS{idVendor}=="0424"
ATTRS{speed}=="480"
ATTRS{removable}=="unknown"
ATTRS{ltm_capable}=="no"
ATTRS{bNumConfigurations}=="1"
ATTRS{busnum}=="1"
ATTRS{authorized}=="1"
ATTRS{quirks}=="0x0"
ATTRS{configuration}==""
ATTRS{devpath}=="1"
ATTRS{bDeviceProtocol}=="02"
ATTRS{bNumInterfaces}==" 1"
looking at parent device '/devices/platform/soc/3f980000.usb/usb1':
KERNELS=="usb1"
SUBSYSTEMS=="usb"
DRIVERS=="usb"
ATTRS{bDeviceClass}=="09"
ATTRS{manufacturer}=="Linux 4.9.35-v7+ dwc_otg_hcd"
ATTRS{bmAttributes}=="e0"
ATTRS{bConfigurationValue}=="1"
ATTRS{version}==" 2.00"
ATTRS{devnum}=="1"
ATTRS{bMaxPower}=="0mA"
ATTRS{idProduct}=="0002"
ATTRS{avoid_reset_quirk}=="0"
ATTRS{urbnum}=="25"
ATTRS{bDeviceSubClass}=="00"
ATTRS{maxchild}=="1"
ATTRS{bcdDevice}=="0409"
ATTRS{bMaxPacketSize0}=="64"
ATTRS{idVendor}=="1d6b"
ATTRS{product}=="DWC OTG Controller"
ATTRS{speed}=="480"
ATTRS{authorized_default}=="1"
ATTRS{interface_authorized_default}=="1"
ATTRS{removable}=="unknown"
ATTRS{ltm_capable}=="no"
ATTRS{serial}=="3f980000.usb"
ATTRS{bNumConfigurations}=="1"
ATTRS{busnum}=="1"
ATTRS{authorized}=="1"
ATTRS{quirks}=="0x0"
ATTRS{configuration}==""
ATTRS{devpath}=="0"
ATTRS{bDeviceProtocol}=="01"
ATTRS{bNumInterfaces}==" 1"
looking at parent device '/devices/platform/soc/3f980000.usb':
KERNELS=="3f980000.usb"
SUBSYSTEMS=="platform"
DRIVERS=="dwc_otg"
ATTRS{wr_reg_test}=="Time to write GNPTXFSIZ reg 10000000 times: 690 msecs (69 jiffies)"
ATTRS{grxfsiz}=="GRXFSIZ = 0x00000306"
ATTRS{srpcapable}=="SRPCapable = 0x1"
ATTRS{buspower}=="Bus Power = 0x1"
ATTRS{bussuspend}=="Bus Suspend = 0x0"
ATTRS{hptxfsiz}=="HPTXFSIZ = 0x02000406"
ATTRS{hnp}=="HstNegScs = 0x0"
ATTRS{mode}=="Mode = 0x1"
ATTRS{mode_ch_tim_en}=="Mode Change Ready Timer Enable = 0x0"
ATTRS{hsic_connect}=="HSIC Connect = 0x1"
ATTRS{gsnpsid}=="GSNPSID = 0x4f54280a"
ATTRS{driver_override}=="(null)"
ATTRS{hcd_frrem}=="HCD Dump Frame Remaining"
ATTRS{gotgctl}=="GOTGCTL = 0x001c0001"
ATTRS{gpvndctl}=="GPVNDCTL = 0x00000000"
ATTRS{hnpcapable}=="HNPCapable = 0x1"
ATTRS{spramdump}=="SPRAM Dump"
ATTRS{regoffset}=="0xffffffff"
ATTRS{gnptxfsiz}=="GNPTXFSIZ = 0x01000306"
ATTRS{guid}=="GUID = 0x2708a000"
ATTRS{regdump}=="Register Dump"
ATTRS{hprt0}=="HPRT0 = 0x00001005"
ATTRS{hcddump}=="HCD Dump"
ATTRS{rem_wakeup_pwrdn}==""
ATTRS{regvalue}=="invalid offset"
ATTRS{gusbcfg}=="GUSBCFG = 0x20001700"
ATTRS{fr_interval}=="Frame Interval = 0x1d4b"
ATTRS{busconnected}=="Bus Connected = 0x1"
ATTRS{remote_wakeup}=="Remote Wakeup Sig = 0 Enabled = 0 LPM Remote Wakeup = 0"
ATTRS{devspeed}=="Device Speed = 0x0"
ATTRS{rd_reg_test}=="Time to read GNPTXFSIZ reg 10000000 times: 940 msecs (94 jiffies)"
ATTRS{enumspeed}=="Device Enumeration Speed = 0x1"
ATTRS{inv_sel_hsic}=="Invert Select HSIC = 0x0"
ATTRS{ggpio}=="GGPIO = 0x00000000"
ATTRS{srp}=="SesReqScs = 0x1"
looking at parent device '/devices/platform/soc':
KERNELS=="soc"
SUBSYSTEMS=="platform"
DRIVERS==""
ATTRS{driver_override}=="(null)"
looking at parent device '/devices/platform':
KERNELS=="platform"
SUBSYSTEMS==""
DRIVERS==""