Skip to content

arch/arm/stm32: implement PTP hardware clock driver (/dev/ptp0) - #20180

Merged
acassis merged 6 commits into
apache:masterfrom
daniel-p-carvalho:feat/stm32-ptp-posix
Sep 19, 2026
Merged

acassis merged 6 commits into
apache:masterfrom
daniel-p-carvalho:feat/stm32-ptp-posix

Conversation

@daniel-p-carvalho

Copy link
Copy Markdown
Contributor

Summary

This PR implements lower-half PTP hardware clock operations (struct ptp_lowerhalf_s and struct ptp_ops_s) in the STM32 Ethernet driver (arch/arm/src/common/stm32/stm32_eth_m3m4_v1.c) and registers it with the generic PTP clock framework (drivers/timers/ptp_clock.c) to expose the standard POSIX character driver /dev/ptp0.

Supported operations:

  • adjfine: adjust PTP clock frequency in parts per billion (ppb) via the addend register (PTPTSAR)
  • adjphase: adjust PTP clock phase via hardware TSSTU
  • adjtime: shift PTP clock time by signed delta in nanoseconds
  • gettime: atomic double-read of hardware timestamp counter with second rollover handling
  • settime: initialize/jump hardware timestamp counter via TSSTI
  • getres: report 1 ns clock resolution

It also includes necessary fixes to support hardware PTP clock operation:

  • Deliver direct raw hardware counter timestamps in d_rxtimestamp so the PTP servo can close the feedback loop against the master clock.
  • Fix RX timestamp conversion order so stm32_eth_ptp_convert_rxtime() runs before pkt_input().
  • Fix sign bug in stm32_eth_ptp_adjust() where uint64_t addend promoted negative ppb adjustments to unsigned, corrupting frequency trim for crystals running fast.
  • Add TMRDEPPATH/TMRVPATH for PTP clock drivers in drivers/timers/Make.defs.
  • Set ETH_MACCR_ROD to disable reception of self-transmitted frames.

Follow-up to #20148 per @xiaoxiang781216's review suggestion to replace custom socket ioctls (SIOCS_PTP_ADJFREQ, SIOCS_PTP_ADJPHASE) with the standard POSIX character driver /dev/ptp0. Hardware transmit timestamping will follow in a separate PR aligned with #20161 (SO_TIMESTAMPING).

Impact

Enables standard POSIX hardware clock disciplining via clock_adjtime() on /dev/ptp0 on STM32 Ethernet interfaces. Fully compatible with ptpd -p /dev/ptp0.

Testing

Tested on real hardware (stm32f4discovery-ext:ethraw / STM32F407) connected via L2 Ethernet P2P to a GNSS-referenced PTP Grandmaster (IEC/IEEE 61850-9-3 profile):

Running ptpd -2 -s -p /dev/ptp0 -B -H -P -i eth0:

nsh> ptpd -t 5
PTPD (PID 5) status:
- clock_source_valid: 1
|- id: 00 14 2d ff fe 61 2b b5
|- utcoffset: 37
|- priority1: 128
|- class: 6
|- accuracy: 34
|- variance: 20061
|- priority2: 128
|- gm_id: 00 14 2d ff fe 61 2b b5
|- stepsremoved: 0
'- timesource: 160
- last_clock_update: 2026-09-17T20:25:40.759091596
- last_delta_ns: -383
- last_adjtime_ns: -80539
- drift_ppb: -82636
- path_delay_ns: 0

Phase locked to -383 ns residual error with crystal drift disciplined at -82636 ppb.

@github-actions github-actions Bot added Arch: arm Issues related to ARM (32-bit) architecture Area: Drivers Drivers issues Size: M The size of the change in this PR is medium labels Sep 17, 2026
@github-actions

github-actions Bot commented Sep 17, 2026

Copy link
Copy Markdown

MemBrowse Memory Report

No memory changes detected for:

acassis
acassis previously approved these changes Sep 17, 2026
Comment thread arch/arm/src/common/stm32/stm32_eth_m3m4_v1.c Outdated
Comment thread arch/arm/src/common/stm32/stm32_eth_m3m4_v1.c Outdated
Comment thread arch/arm/src/common/stm32/stm32_eth_m3m4_v1.c Outdated
Comment thread arch/arm/src/common/stm32/stm32_eth_m3m4_v1.c Outdated
Comment thread arch/arm/src/common/stm32/stm32_eth_m3m4_v1.c Outdated
Comment thread arch/arm/src/common/stm32/stm32_eth_m3m4_v1.c Outdated
Comment thread arch/arm/src/common/stm32/stm32_eth_m3m4_v1.c Outdated
jerpelea
jerpelea previously approved these changes Sep 18, 2026
@xiaoxiang781216

Copy link
Copy Markdown
Contributor

please fix:

Error: ./common/stm32/stm32_eth_m3m4_v1.c:4666:2: error: #endif without #if
 4666 | #endif /* CONFIG_NET && CONFIG_STM32_ETHMAC */

Every other timer driver block in this Make.defs sets TMRDEPPATH and
TMRVPATH so DEPPATH/VPATH include this directory. CONFIG_PTP_CLOCK
and CONFIG_PTP_CLOCK_DUMMY were the only two missing it, leaving
ptp_clock.c/ptp_clock_dummy.c unreachable via VPATH and without a
generated dependency file when no other timer driver in this file is
also selected.

Assisted-by: Claude:claude-sonnet-5
Signed-off-by: Daniel P. Carvalho <danieloak@gmail.com>
(cherry picked from commit 6d38122)
stm32_receive() called pkt_input() before
stm32_eth_ptp_convert_rxtime(), so every packet handed to a packet
socket carried the previous frame's RX timestamp instead of its own
in dev->d_rxtime. Reorder so the timestamp is converted first.

Assisted-by: Claude:claude-sonnet-5
Signed-off-by: Daniel P. Carvalho <danieloak@gmail.com>
(cherry picked from commit 9bfa20d)
Set ETH_MACCR_ROD unconditionally when configuring the MAC. In
half-duplex mode the MAC otherwise reflects every frame it transmits
back to its own receiver, flooding the receive path with our own
traffic right as a genuine reply arrives. The bit has no effect in
full-duplex (confirmed on our hardware: fduplex=1), so setting it
unconditionally is safe and changes nothing observable for boards
already running full-duplex.

The sibling stm32f7 driver has the same gap (ETH_MACCR_ROD cleared
but never set) and stm32h7's equivalent ETH_MACCR_DO bit has the same
issue; both are left out of scope here since only m3m4_v1 hardware
was available to validate against.

Assisted-by: Claude:claude-sonnet-5
Signed-off-by: Daniel P. Carvalho <danieloak@gmail.com>
(cherry picked from commit 41536cb)
The MAC hardware counter is the PTP clock reference. Delivering its
raw timestamp directly (instead of synthesizing one against
CLOCK_REALTIME, which starts at an arbitrary boot-time phase) lets the
PTP daemon close the feedback loop and phase-lock the MAC counter -
and therefore the physical PPS output - to the master.

Assisted-by: Gemini:gemini-3.8-flash-medium
Signed-off-by: Daniel P. Carvalho <danieloak@gmail.com>
Implement lower-half PTP hardware clock operations (struct ptp_lowerhalf_s
and struct ptp_ops_s) in the STM32 Ethernet driver and register it with the
generic PTP clock framework (drivers/timers/ptp_clock.c) to expose /dev/ptp0.

Supported operations:
- adjfine: adjust PTP clock frequency in parts per billion (ppb)
- adjphase: adjust PTP clock phase via hardware TSSTU
- adjtime: shift PTP clock time by signed delta in nanoseconds
- gettime: atomic double-read of hardware timestamp registers
- settime: initialize hardware timestamp counter via TSSTI
- getres: return 1 ns clock resolution

Also fix a sign bug in stm32_eth_ptp_adjust() where uint64_t addend
promoted negative ppb adjustments to unsigned, corrupting frequency trim
for crystals running faster than nominal.

Follow-up to apache#20148 per review recommendation to use the standard POSIX
/dev/ptp0 character driver instead of custom socket ioctls.

Assisted-by: Gemini:gemini-3.8-pro
Signed-off-by: Daniel P. Carvalho <danieloak@gmail.com>
Variable conn is declared and initialized in append_timestamping()
but never referenced, triggering -Wunused-variable compiler warning.

Assisted-by: Gemini:gemini-3.8-pro
Signed-off-by: Daniel P. Carvalho <danieloak@gmail.com>
@acassis

acassis commented Sep 19, 2026

Copy link
Copy Markdown
Contributor

@xiaoxiang781216 @simbit18 PTAL

@acassis
acassis requested a review from simbit18 September 19, 2026 19:37
@daniel-p-carvalho

Copy link
Copy Markdown
Contributor Author

Heads-up for ordering: #20148 (hardware TX timestamping for the STM32 MAC) is now rebased on top of this PR and depends on it, so it has to be merged after this one. It is a draft until then.

@acassis
acassis merged commit ee23dd0 into apache:master Sep 19, 2026
53 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Arch: arm Issues related to ARM (32-bit) architecture Area: Drivers Drivers issues Size: M The size of the change in this PR is medium

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants