![]() |
RT-Thread RTOS
An open source embedded real-time operating system
|
Header: **components/drivers/include/drivers/ptp.h**. Core: **components/drivers/ptp/ptp.c**.
The PTP layer wraps IEEE 1588 hardware clocks (PHC) behind a small, Linux-style **rt_ptp_ops** interface. Hardware drivers expose read/set time, frequency and phase adjustment, external timestamp (EXTTS), periodic output (PEROUT), PPS, optional GPIO pin routing, and snapshot reads. Upper layers (PTP protocol stacks, time sync services, test tools) call the **rt_ptp_*** helpers directly; the registered **rt_device** is mainly a named handle for lookup (ptp0, ptp1, …).
Requires **RT_USING_PTP** (Kconfig) and **RT_USING_DM**.
| Use PTP when… | Prefer something else when… |
|---|---|
| The SoC or NIC provides a dedicated PHC with sub-microsecond discipline. | Calendar time only — RTC Device or POSIX time(). |
| You need ppb frequency trim, phase step, or hardware timestamping of external events. | OS tick / hrtimer scheduling — HWTIMER Device or Clock Time Core. |
| Firmware or DT describes EXTTS / PEROUT / PPS pins on a PTP block. | Software NTP only — no PHC driver required. |
SoC-specific options may be added under **/Kconfig** when present.
| Role | Responsibility |
|---|---|
| PHC driver | Fills **struct rt_ptp_clock**, implements **rt_ptp_ops**, calls **rt_ptp_clock_register**. Reports capabilities (max_freq, alarm_nr, extts_nr, perout_nr, pps, pins_nr). Raises **rt_ptp_clock_event** from ISR or bottom-half when hardware events occur. |
| Client / stack | Obtains **struct rt_ptp_clock *** (from probe, DT phandle, or **rt_device_find("ptp0")** + **rt_device_to_ptp_clock**). Uses **rt_ptp_gettime / rt_ptp_adjfreq / …** and optional **rt_ptp_clock_notifier** callbacks. |
The core registers each clock as **RT_Device_Class_Char** with **RT_DEVICE_FLAG_DEACTIVATE**. There is no standard read/write/control path in **ptp.c** — all operations go through the **rt_ptp_*** API.
Convert from a generic device pointer:
| Callback | Purpose |
|---|---|
**adjfreq** | Fine frequency adjustment in parts per billion (ppb). Core clamps to **±max_freq**. |
**adjphase** | Phase shift in nanoseconds; core clamps using **getmaxphase**. |
**getmaxphase** | Reports maximum absolute phase adjustment. |
**adjtime** | Step the clock by **delta** nanoseconds (signed). |
**gettime / settime** | Read or write absolute PHC time. |
**enable** | Enable/disable EXTTS, PEROUT, or PPS (see **struct rt_ptp_clock_request**). |
**verify** | Validate pin/function/channel routing before metadata is updated. Required when **pins_nr > 0**. |
**getsnapshot** | Read a latched / snapshot time (hardware-specific). |
Unimplemented ops return **-RT_ENOSYS** from the matching **rt_ptp_*** wrapper.
**rt_ptp_clock_register** checks:
| Condition | Error |
|---|---|
**ptp or ops is NULL** | **-RT_EINVAL** |
**pins_nr > 0** but **pins is NULL** or **verify is NULL** | **-RT_EINVAL** |
**extts_nr or perout_nr > 0** but **enable is NULL** | **-RT_EINVAL** |
**adjfreq is non-NULL** but **max_freq <= 0** | **-RT_EINVAL** |
| IDA exhausted | **-RT_EFULL** |
On success the device name is **ptp<N>** (for example **ptp0**).
**rt_ptp_clock_unregister**:
-RT_EINVAL** if **ref_count != 0**pin_mutex** when **pins_nr > 0****rt_ptp_adjtime** converts **ts->sec / ts->nsec** to a signed nanosecond delta and forwards it to **ops->adjtime**. **nsec** must be in **[0, 10⁹)**.
**rt_ptp_adjfreq**: if **max_freq <= 0**, only **freq == 0** is accepted (no-op success).
chan** must be **< extts_nr**PTP_STRICT_FLAGS**, enabling requires at least one of **PTP_RISING_EDGE** or **PTP_FALLING_EDGE**PTP_ENABLE_FEATURE** (or zero flags) disables the channel via **enable(..., RT_FALSE)**chan** must be **< perout_nr**PTP_STRICT_FLAGS**: duty **on** must not exceed **period**; **start_phase** must be strictly less than one period when **PTP_PEROUT_PHASE** is setperiod.sec || period.nsec**Uses **request.type = PTP_CLK_REQ_PPS** and **ops->enable**.
When **pins_nr > 0**, the core keeps a **pins[]** table describing which physical pin is mapped to which function and channel.
Important: **rt_ptp_set_pin_func** only updates routing metadata and disables the previous function on affected pins. It does not start EXTTS or PEROUT hardware. After assigning a pin, call **rt_ptp_request_extts** or **rt_ptp_request_perout** separately.
**rt_ptp_set_pin_func** flow:
func** / **chan** against **extts_nr**, **perout_nr**, or PHYSYNC rulesops->verify**func + chan**Access to **pins[]** is serialized with **pin_mutex**.
Hardware drivers call **rt_ptp_clock_event** when an alarm fires, an external timestamp is captured, PPS is observed, etc.
**event_mask** must be non-zero at register time. **rt_ptp_clock_event** walks registered notifiers under **nodes_lock** and invokes matching callbacks without holding the lock during the callback.
When **RT_USING_POSIX_CLOCK**, **RT_USING_POSIX_FS**, and **RT_USING_PTP** are enabled, PHC devices follow the Linux dynamic clock model:
Macros in **sys/time.h**: **CLOCKFD**, **FD_TO_CLOCKID**, **CLOCKID_TO_FD**. Implementation: **components/libc/compilers/common/ctime.c**.
The fd must refer to an open /dev/ptpN device node (devfs). **CLOCK_REALTIME** still uses RTC; dynamic **clockid_t** values are separate from fixed POSIX clock IDs.
| Issue | Mitigation |
|---|---|
**set_pin_func without request_extts / request_perout** | Pin table updates only; explicitly enable the feature afterward. |
**adjfreq without max_freq** | Registration fails; set **max_freq** to the hardware ppb limit. |
| Notifier left registered at unregister | Core logs a warning; unregister notifiers in client teardown. |
Calling rt_ptp_clock_event with wrong type | **RT_ASSERT** in debug builds; keep **type < PTP_CLOCK_EV_MAX**. |
| Blocking in notifier callback | Callback runs with lock dropped but may be invoked from interrupt context depending on the driver — keep callbacks short or defer work. |
| Confusing PTP with RTC | RTC is wall-clock calendar time; PTP PHC is for precision sync and hardware timestamping. |
components/drivers/ptp/ptp.ccomponents/drivers/include/drivers/ptp.h