Repository navigation
{bp-20213} arch/arm/stm32h7: timestamp the transmitted frames in hardware - #20339
Merged
Merged
Conversation
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>
…G loopback Implement hardware TX timestamping support for STM32 Ethernet MAC (stm32_eth_m3m4_v1.c) following the upstream SO_TIMESTAMPING loopback architecture (PR apache#20161). When an outgoing packet is flagged with SO_TIMESTAMPING (dev->d_iob->io_conn != NULL): - Clone the IOB and hold a reference in priv->txmeta[txindex] - Set ETH_TDES0_TTSE on the transmit DMA descriptor - On transmission completion (stm32_freeframe), retrieve the hardware timestamp from TDES6/TDES7, convert to timespec via ptp_to_timespec(), and enqueue the clone onto priv->txtstampq - Deliver pending TX timestamp clones back to netdev RX path in stm32_receive using pkt_input(), where net/pkt intercepts the frame and delivers it to userspace via recvmsg(..., MSG_ERRQUEUE) - Properly drain pending queues and clones on interface down (stm32_ifdown) Assisted-by: Gemini:gemini-3.8-pro Signed-off-by: Daniel P. Carvalho <danieloak@gmail.com>
- Under CONFIG_NET_PROMISCUOUS, forward all control frames (ETH_MACFFR_PCF_ALL) instead of only non-PAUSE ones, so link-local PTP multicast reaches the DMA. - Move ptp_to_timespec() above its first user so the TX timestamp path can call it. - stm32_receive(): do not log frames already delivered to packet sockets (PTP, IPv6) as "Dropped, Unknown type". - stm32_txtstamp_flush(): clear io_conn before freeing the looped-back IOB. Signed-off-by: Daniel P. Carvalho <danieloak@gmail.com> Assisted-by: Claude:claude-sonnet-5
This reverts commit 19d5f48. because it is included in a later patch Signed-off-by: Alin Jerpelea <alin.jerpelea@sony.com>
The driver configured the pulse-per-second pin whenever STM32_ETH_PTP was set, so a board that uses the timestamp unit without the pin still had to define GPIO_ETH_PPS_OUT, and the pin was taken away from other uses. The STM32F4 driver configures the pin with STM32_ETH_PTP_GPIO, the option meant for it, but that option could not be selected on the STM32H7, because it depended on the legacy STM32 families. Configure the pin only with STM32_ETH_PTP_GPIO, and allow that option on the STM32H7 and STM32H5. Signed-off-by: Daniel P. Carvalho <danieloak@gmail.com> Assisted-by: Claude:claude-sonnet-5
The MAC has a system time that is the base of the PTP hardware timestamps, but the driver never started it, and STM32_ETH_PTP only printed a warning. Add the registers of the timestamp unit and start the system time with the fine update method and the digital rollover, so that the nanoseconds count up to 10^9. The increment is 2 * 10^9 / HCLK ns, and the addend makes the update rate half of HCLK, which leaves room to trim the frequency in both directions. The time starts at zero right after the MAC reset, not with the MAC configuration, so it does not depend on the PHY having a link. The reset clears it, so it starts again each time the interface goes up. With STM32_ETH_PTP_GPIO, start the pulse-per-second output as a pulse train with a period of one second and a width of half of it, at the whole seconds of the system time. The fixed frequency mode of the MAC gives a pulse too short to be seen, so the flexible mode is used. The interrupt of the timestamp unit is not enabled in the MAC: it is set each time the target time of the PPS output is reached and is cleared by reading MACTSSR, which the interrupt handler does not do, so it would stay pending and keep the handler running until the network stops. Register /dev/ptp0 when CONFIG_PTP_CLOCK is set, so that a PTP daemon can read and set the system time and correct its frequency and its phase. The frequency is corrected by changing the addend, by up to 50% each way. A step of the time is added or subtracted with the update register; with the digital rollover a subtraction is programmed with the negated seconds and with 10^9 minus the nanoseconds. The pulse train counts by itself, so it does not follow a step of the system time and would be displaced by the same amount: after the time is set or stepped, it is started again at the next whole second. With HCLK at 200 MHz the system time advanced 10.0018 s while a host clock advanced 10.002 s, and the pulse train was seen on the pin. Reading, setting, steps of +0.5 s and -1.25 s and a change of 100 ppm were done through /dev/ptp0 on hardware, and the edges of the PPS output stayed at the whole seconds of the system time. Signed-off-by: Daniel P. Carvalho <danieloak@gmail.com> Assisted-by: Claude:claude-sonnet-5
The STM32H7 page did not say anything about the Ethernet MAC. - Describe the time counter of the MAC, the STM32_ETH_PTP option and its behavior when the interface goes down. - Describe the pulse-per-second output and the pins it can use. - Describe the /dev/ptp0 clock the driver registers and the operations it offers, and show a configuration that enables all of it. Signed-off-by: Daniel P. Carvalho <danieloak@gmail.com> Assisted-by: Claude:claude-sonnet-5
Add STM32_ETH_TIMESTAMP_RX for the STM32H7, as the one of the legacy STM32 that provides the timestamp of the frames received. Timestamp the PTP version 2 messages, over Ethernet and over UDP, except for the announce, management and signaling messages. The MAC writes the timestamp in a context descriptor after the last descriptor of the frame. The driver reads it before giving the frame to the network stack and passes it in d_rxtime, in the time of the system time of the MAC, the same as /dev/ptp0. A frame that is not timestamped has a time of zero. The timestamp goes over the address of the buffer of the context descriptor, and the code that dropped the context descriptors used a pointer that was never set. Keep the address of the buffer of each RX descriptor, and restore it when a context descriptor is given back. The timestamps of the PTP frames of a grandmaster clock were checked on hardware against the system time of the MAC, and were within the delay of the reads. Signed-off-by: Daniel P. Carvalho <danieloak@gmail.com> Assisted-by: Claude:claude-sonnet-5
Support STM32_ETH_TIMESTAMP_TX on the STM32H7, as the legacy STM32 do, with the timestamp returned through SO_TIMESTAMPING. When a packet socket asks for the transmit timestamp of a frame, keep a copy of the frame and ask the MAC to timestamp it in the descriptor. When the transmission is done, take the timestamp from the descriptor and give the copy back to the network stack with it, that delivers it to the error queue of the socket. The MAC writes the timestamp over the address of the buffer in the descriptor, so the driver keeps the buffer of these descriptors. The copies that still wait for their timestamp are released when the interface goes down. With a PTP daemon using the peer-to-peer delay mechanism against a grandmaster clock, the path delay measured was between 9.0 and 9.1 us. Signed-off-by: Daniel P. Carvalho <danieloak@gmail.com> Assisted-by: Claude:claude-sonnet-5
jerpelea
requested review from
acassis,
cederom,
linguini1 and
xiaoxiang781216
September 24, 2026 11:26
jerpelea
requested review from
davids5,
fjpanag and
raiden00pl
as code owners
September 24, 2026 11:26
cederom
approved these changes
Sep 24, 2026
linguini1
approved these changes
Sep 24, 2026
acassis
approved these changes
Sep 24, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The STM32H7 MAC can capture a timestamp for every transmitted frame, but the driver only timestamped received frames (#20212). A PTP daemon using the peer-to-peer delay mechanism needs the transmit time of its Pdelay_Req from the hardware.
This PR adds STM32_ETH_TIMESTAMP_TX for the STM32H7, the option that #20148 defines for the legacy STM32 driver, delivered through the generic SO_TIMESTAMPING mechanism of the network stack (#20161): when a frame is flagged for timestamping, the driver keeps a copy of it, sets the timestamp enable bit in its descriptor and, when the transmission is done, reads the timestamp from the descriptor and loops the copy back to the AF_PACKET socket, where recvmsg(..., MSG_ERRQUEUE) returns it. The MAC writes the timestamp over the address of the buffer in the descriptor, so the driver keeps the buffer of these descriptors.
It builds on #20148 and #20212, which are merged, so it is a single commit now.
includes
#20148
#20180
#20212
Impact
RELEASE
Testing
CI