PTP (IEEE 1588) Library

macaba

Well-known member
This thread is really to firstly gauge the interest there might be in a Teensy PTP library, then to possibly document any progress.

PTP aka IEEE1588 allows for much tighter synchronization between systems on the same subnet.

I am tempted to write one and do a proof of concept where it triggers a digitalWriteFast to occur at the same time on 2 networked Teensy's and see how close they come...

The likely platform will be a Teensy 3.1 with a WIZ820IO module, using the interrupt line for consistent timestamping (crucial for PTP).
 
Yes, please

This thread is now several years old but still a top Google search result on Teensy IEEE1588.
I want it to reflect at least some level of interest.
I would use such a library if it existed.
My use case would be synchronizing output events outdoors (light show, fountains), with input events indoors(music, touch panel, script).
 
Just to confirm my background...I am actively using 801.1AS software on an Analog Devices FIDO5200. I am synchronizing at 20 nSec between 2 development boards.
 
It makes sense on any teensy, hardware support isn't a necessity for a PTP implementation. Hardware support only changes the layer at which the NIC packet timestamping occurs, and hence the quality of syncronisation.
 
It makes sense on any teensy, hardware support isn't a necessity for a PTP implementation. Hardware support only changes the layer at which the NIC packet timestamping occurs, and hence the quality of syncronisation.

I have mainly used PTP in situations where high quality synchronization was desired (e.g. AVB).
In my reference to the Teensy 4.1 I was also thinking of the convenience that the hardware is largely already there on the board.
 
Note that the T4 has a tweak-able audio clock rate - so good use can be made of synchronization.

A 1 pps single wire input to the teensy also works fine. Even a once per second byte from a USB attached PC works well enough.
 
I would say ptp on teensy 4.1 would be extremely useful, I might even be interested in giving a shot implementing it if no one has yet, since according to the RT1060 manual, the ethernet module has the IEEE 1588 hardware timestamping capability:

The Ethernet Media Access Controller (MAC) is
designed to support 10/100 Mbit/s Ethernet/IEEE 802.3
networks. An external transceiver interface and
transceiver function are required to complete the
interface to the media. The module has dedicated
hardware to support the IEEE 1588 standard. See the
ENET chapter of the reference manual for details.

And NXP has a fairly detailed 27-page application note (Implementing an IEEE 1588 V2 on i.MX RT Using PTPd, FreeRTOS, and lwIP TCP/IP stack):

A dedicated hardware with
timestamping capabilities (such as the MAC-NET peripheral module or the 10/100-Mbps Ethernet MAC
(ENET) of the NXP i.MX RT 1050 and 1020) enables synchronization with significantly improved
accuracy.
3. IEEE 1588 functions on i.MX RT
The i.MX RT10xx devices integrate the MAC-NET core (in conjunction with a 10/100-Mbit/s MAC) to
accelerate the processing of various common networking protocols, such as IP, TCP, UDP, and ICMP,
providing wire speed services to client applications. The unified DMA (uDMA), internal to the ENET
module, optimizes data transfer between the ENET core and the SoC and supports the enhanced buffer
descriptor programming model to support IEEE 1588 functionality. To enable IEEE 1588 (or similar)
time synchronization protocol implementations, the MAC is combined with a timestamping module to
support precise timestamping of incoming and outgoing frames. Set the EN1588 bit in the ENET_ECR
(Ethernet Control Register) to enable 1588 support.

though it seems they are using their own SDK which implements the "NXP ENET driver"...so I'm guessing that driver code is something that still needs to be done on Teensy's end:

The MIMXRT10xx Evaluation Kit (EVK) board is used as the hardware platform for hardware
timestamping-based IEEE 1588 V2 PTP. The solution uses the MCUXpresso SDK IDE for the
i.MX RT10xx EVK board, which includes the NXP ENET driver of the i.MX RT10xx MCU, the PHY
driver, the ported FreeRTOS OS, and the ported lwIP TCP/IP stack for the EVK-MIMXRT10xx board.
The IEEE1588 V2 PTP is implemented by the PTP daemon application, which is an open-source
implementation of the PTP

and conclusion says:

This application note describes the IEEE 1588 Precision Time Protocol demo application based on the
open-source PTP daemon, FreeRTOS OS, lwIP TCP/IP stack, SDK for i.MX RT10xx, and the
i.MX RT10xx Evaluation Kit (EVK-MIMXRT1050) board. This demo can be easily ported to other
processors from the i.MX RT series with the FreeRTOS OS, lwIP, and TCP/IP stack support.
The demo system is targeted for applications that require precise clock synchronization between devices
with accuracy in the sub-microsecond range.

And I have plenty of ptp network interfaces to test with, as well as a couple AVB Motu interfaces. Though I wonder if there is anything particular with the board EVK-MIMXRT1050 that is missing, but I don't think so.

I notice there is a port of FreeRTOS for teensy 4.1 (https://github.com/tsandmann/freertos-teensy) so maybe that would need to be used, or at least to make the ptp quicker to implement.

Would be great to use a ptp-synced teensy for generating midi/osc note events with precision timestamping sent through the ethernet.
 
I would say ptp on teensy 4.1 would be extremely useful, I might even be interested in giving a shot implementing it if no one has yet....

That would be more than appreciated!
I can support you with some beta-testing if needed..
 
With hardware time stamping, I'd expect excellent performance without a RTOS.

PTPv2 is a required part of AES67.
 
I'm experimenting with adding IEEE 1588 stuff to QNEthernet. To make sure I'm going in the right direction, here's the features I've added so far:

  1. Read the timer register (ENET_ATVR):
    1. uint32_t Ethernet.readIEEE1588Timer()
    2. Low-level: uint32_t enet_read_1588_timer()
  2. Get the timestamp of a received UDP packet. I'm thinking of changing this to a single function instead, to match how I'm doing this with the TX timestamp.
    1. bool EthernetUDP::hasIEEE1588Timestamp()
    2. uint32_t EthernetUDP::ieee1588Timestamp()
  3. Send a UDP or raw packet with a timestamp:
    1. Send raw: Ethernet.sendRaw(..., bool doTimestamp)
    2. Send UDP: EthernetUDP::endPacketWithTimestamp()
    3. Get the TX timestamp: bool EthernetUDP::ieee1588TXTimestamp(uint32_t *timestamp)
    4. Low-level: bool enet_read_1588_tx_timestamp(uint32_t *timestamp)

Is there also a need for having an API for an external signal as well?

There's two things to do:
  1. Validate that the API is useful, and
  2. Verify that the code works as expected.

I'll need help with these two things from people more experienced than I with PTP/IEEE 1588 timestamping/timers.

Here's the experimental branch: https://github.com/ssilverman/QNEthernet/tree/ieee1588
Note that neither the README nor CHANGELOG show the changes.
 
I'll need help with these two things from people more experienced than I with PTP/IEEE 1588 timestamping/timers.

Thank you Shawn for starting these activities, I am looking forward to use your PTP implementation.
Is there anything an inexperienced user can help you with, i.e. testing your code etc.?
If so, can you explain how to use your code and what software do you use on the computer side?
 
I just provided an interface to the low-level timestamping and timer functions. I’m not well versed in using them or what the “actual needs” are yet.

The requirements are knowing how to use a GitHub branch in the Arduino libraries.

I like to think of it as me providing the hammer and nails, but not the house plans or lumber.
 
Last edited:
For the server side, this link might help for Linux users:
http://linuxptp.sourceforge.net/

I just checked my hardware, and it seems I have only software time-stamping available:
Code:
sudo ethtool -T enp4s0
Time stamping parameters for enp4s0:
Capabilities:
	software-transmit     (SOF_TIMESTAMPING_TX_SOFTWARE)
	software-receive      (SOF_TIMESTAMPING_RX_SOFTWARE)
	software-system-clock (SOF_TIMESTAMPING_SOFTWARE)
PTP Hardware Clock: none
Hardware Transmit Timestamp Modes: none
Hardware Receive Filter Modes: none

Can someone suggest what hardware is required on PC side for hardware time-stamping?
 
I did a new version and here's the list of PTP/IEEE 1588 building blocks:

1. Read the timer,
2. Write the timer,
3. Get the timestamp of RX frames,
4. Timestamp TX frames and get the timestamp,
5. Adjust the timer by nanoseconds per second as time progresses,
6. Adjust the timer with a new adjustment period and increment (called by the previous),
7. Set channel mode (there's a bunch of modes that include input capture and output compare; I refer you to the chip docs),
8. Set channel output pulse width,
9. Set channel compare value, and
10. Get channel input capture or output compare status.

And of course, raw frames (both RX and TX) are supported, so low-level PTP packets are also supported.

I believe that should cover what's needed to build a complete NTP/PTP/IEEE 1588 application. Am I missing anything?

Update: I'm missing using an exernal reference clock instead of the internal 25MHz one, but that shouldn't be too hard to add...
 
ptp implementation

Hi all. Is anyone working on the next steps to have a PTP synchronized teensy using these building blocks? We're building a distributed conrol system using about 40 teensy 4.1 based embedded systems, and we'd like to keep them synchronized. Their local clocks are a bit drifty. If this is something currently not being worked on, we may start on a project to implement it. It seems like it would be best implemented as part of the Ethernet library, as it would be a background task that keeps the clock in sync with the PTP time.

Although we don't need sub-microsecond timing, the currently available Arduino NTP clients are not really suitable for precision timekeeping, as they simply query a server and set the NTP time, rather than disciplining the local clock with updates through a filter. Setting the time outright isn't necessarily a good idea, as it can jump forwards and backwards depending on network status.

Another option for us would be to implement a robust version of NTP that behaves like ntpd and disciplines the clock instead of simply setting the time when it queries the server.

Does any of this sound like a useful project for anyone else, or is it just that I've missed the parts of the library that already do these things?

John


I did a new version and here's the list of PTP/IEEE 1588 building blocks:

1. Read the timer,
2. Write the timer,
3. Get the timestamp of RX frames,
4. Timestamp TX frames and get the timestamp,
5. Adjust the timer by nanoseconds per second as time progresses,
6. Adjust the timer with a new adjustment period and increment (called by the previous),
7. Set channel mode (there's a bunch of modes that include input capture and output compare; I refer you to the chip docs),
8. Set channel output pulse width,
9. Set channel compare value, and
10. Get channel input capture or output compare status.

And of course, raw frames (both RX and TX) are supported, so low-level PTP packets are also supported.

I believe that should cover what's needed to build a complete NTP/PTP/IEEE 1588 application. Am I missing anything?

Update: I'm missing using an exernal reference clock instead of the internal 25MHz one, but that shouldn't be too hard to add...
 
I have interest in this as well, but haven't had the time to spend on it, but slowly gathering up components to build it.

From what I understand, you will need a grand master clock, which can be pricey, cheapest I found was this one for a $500: https://timemachinescorp.com/product/gps-ntpptp-network-time-server-tm2000/

Then all your network switches need to be IEEE 1588 v2 compliant, which are also not cheap.

I think this will change over time, making it cheaper in the future.

Perhaps a T4.1 tied to GPS could become a grand master clock?
 
What is the status of IEEE 1588 in QNEthernet, or anywhere else for the Teensy4.1? I've cloned the QNEthernet repo and cannot locate any examples on how to implement, sync the teensy to a 1588 grandmaster. Kinda new at PTP but trying to get this to work. Glad @shawn took the time to do all the work, thank you, and thanks in advance for any guidance.
 
BTW, for all the QNEthernet examples, I get this error when trying to compile:

Compilation error: 'stdPrint' was not declared in this scope; did you mean 'Print'?
 
Back
Top