arch/arm/stm32h7: timestamp the transmitted frames in hardware - #20213
Draft
daniel-p-carvalho wants to merge 6 commits into
Draft
daniel-p-carvalho wants to merge 6 commits into
daniel-p-carvalho wants to merge 6 commits into
Conversation
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
…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>
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
Contributor
|
@daniel-p-carvalho please fix the conflict |
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_Reqfrom the hardware.This PR adds
STM32_ETH_TIMESTAMP_TXfor the STM32H7, the option that #20148 defines for the legacy STM32 driver, delivered through the genericSO_TIMESTAMPINGmechanism 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 theAF_PACKETsocket, whererecvmsg(..., 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.Impact
STM32_ETH_TIMESTAMP_TX(default n, needsSTM32_ETH_PTPandNET_TIMESTAMP), so boards that do not enable it are not affected./dev/ptp0as its clock.appsside,ptpdreading the transmit timestamp from the error queue, is netutils/ptpd: hardware TX timestamps via MSG_ERRQUEUE and egress latency compensation nuttx-apps#3791, which builds on netutils/ptpd: IEEE 1588 P2P delay mechanism, hardware clock phase-lock and outlier rejection nuttx-apps#3782.Testing
Built with
STM32_ETH_TIMESTAMP_TXwith and withoutSTM32_ETH_TIMESTAMP_RX, without errors or warnings../tools/checkpatch.sh -g upstream/master..HEADpasses.On hardware, with a custom STM32H753 board and a DP83848 PHY, against a GNSS-referenced
ptp4lgrandmaster using the IEC/IEEE 61850-9-3 profile, overAF_PACKET, withptpd -2 -s -H -p /dev/ptp0 -B -P -i eth0from apache/nuttx-apps#3782 and the transmit timestamps of apache/nuttx-apps#3791:/dev/ptp0.The end-to-end mechanism, master mode and a long run were not tested.