DP83640: Issue with IEEE1588 PTP timestamps

Part Number: DP83640
Other Parts Discussed in Thread: USB-2-MDIO

Hi,

Before doing this, the state of the PHY is that it is working as intended for receiving/sending network packets. I am able to send/receive UDP/TCP packets using the LWIP library. (The micro is STM32F7 if relevant)

I am sending PTP version2 messages using the linux PTPD daemon manpages.debian.org/.../ptpd.8.en.html that acts as a master.

On wireshark, I see that sync messages are being sent periodically.

On the micro side, I use an STM32F7x microcontroller with the DP83640 PHY. I configure the registers in the following order, as suggested by the PHYTER_Software_Development_Guide.pdf, cross referenced with the DP83640 datasheet. I also had a look at PTPControl.c to see how it is done there, I noticed version 1 PTP was used in that example. Using the epl_1588.c library provided, here are the initialisation configurations:

PTPEnable(pEPL_HANDLE, FALSE);

First, 0x2 is written to the PTP_CTRL register, to disable the clock.

PTPClockSetRateAdjustment( pEPL_HANDLE, 0, FALSE, FALSE);

The clock rate adjustment is set to be none, by writing 0 to PTP_RATEL and PTP_RATEH. I believe those are the default values too.

PTPClockSet( pEPL_HANDLE, 1, 0);

Then, the PTP clock is set to be 1 second and 0 nanoseconds.

PTPSetClockConfig (pEPL_HANDLE, CLKOPT_CLK_OUT_EN, 0x0A, 0x00, 8u);

After that, the PTP clock is configured by writing 0x800a to PTP_COC. This represents enabling the CLK_OUT and a divider of 10. 0x8 is written to the PTP_CLKSRC register, to represent the internal 125MHz clock to be used, and 8 ns period.

PTPEnable(pEPL_HANDLE, TRUE);

We enable the clock again.

PTPSetTransmitConfig(pEPL_HANDLE, TXOPT_TS_EN | TXOPT_IPV4_EN, 2, 0, 0);

Here, we write 0x25 (0b100101) to the PTP_TXCFG0 register. This represents enabling IPv4 timestamp TX_IPV4_EN, TX_PTP_VER being 2 and TX_TS_EN being 1.

PTPSetReceiveConfig(pEPL_HANDLE, RXOPT_IP1588_EN0|RXOPT_IP1588_EN1|RXOPT_IP1588_EN2| RXOPT_RX_IPV4_EN|RXOPT_RX_TS_EN|RXOPT_ACC_UDP|RXOPT_ACC_CRC|RXOPT_RX_SLAVE , &rx_cfg_items);

Here, we write 0xf25 to the PTP_RXCFG0 register. This represents RX_SLAVE being 1, IP1588_EN being 0b111, RX_IPV4_EN being 1 and TX_PTP_VER being 2 and RX_TS_EN being 1.

After those configurations, I constantly read the register PTP_STS to see if there is a receive timestamp. If there is, I get it by calling PTPGetReceiveTimestamp.

Problem 1:

I am only able to successfully get the PTP timestamps (i.e. PTP_STS implies that there is a receive timestamp) if I run the above startup in debug mode. Specifically, stepping through them one by one, with some pause after the PTPSetClockConfig command. If the startup code is ran without any breakpoints, further reads of PTP_STS always results in 0. I am not sure why this is the case. Maybe the ClockConfig is not done setting up before we enable the PTP clock again?

Problem 2: Assuming I am able to get the timestamps, if I stop the linux PTP master, then restart it, the PHY is never able to get new timestamps.

Does anyone have any ideas? 

  • Hi Andrew,

    This is an interesting issue. As a further debug step, would it be possible to group a portion of the configuration steps and run the groups one at a time, rather than each step individually? This may help us see which sequential steps are causing the issue, and if one configuration step needs additional time to converge. 

    We will look into this internally and provide additional feedback by Thursday of this week.

    Thank you,

    Nikhil

  • Nikhil Menon said:

    Hi Andrew,

    This is an interesting issue. As a further debug step, would it be possible to group a portion of the configuration steps and run the groups one at a time, rather than each step individually? This may help us see which sequential steps are causing the issue, and if one configuration step needs additional time to converge. 

    We will look into this internally and provide additional feedback by Thursday of this week.

    Thank you,

    Nikhil

    Hi Nikhil,

    After trying various groupings, I realised that when I put all the configurations into one group, and have a breakpoint after it, it works. Whereas without a breakpoint, it does not work.

    After that, I added a HAL_delay of 1000 ms after all the configurations are done, but that doesn't change anything. It only works if I breakpoint after all the configurations, then continue from there.

    Additionally, nothing gets read from the receive timestamp register unless I add a breakpoint on the "PTPGetReceiveTimestamp" function.

    Optimisation is turned off, I have added the volatile keyword to events, PTP_seconds and PTP_nanoseconds, so not quite sure what is going on.

    while ( (events = PTPCheckForEvents( pEPL_HANDLE)))
    {
    if ( events & PTPEVT_RECEIVE_TIMESTAMP_BIT)
    {
    PTPGetReceiveTimestamp( pEPL_HANDLE, &PTP_seconds, &PTP_nanoseconds, &overflowCount, &seqId, &msgType, &hashValue);
    }
    }

  • Hi Andrew,

    We are looking into this issue internally and will provide an update by the end of the week.

    Thank you,

    Nikhil

  • Hi Andrew,

    We have a tool USB-2-MDIO that can be used to program registers. As an extra debug step, are you able to use this tool to program the registers of the PHY? Do you run into the same issue?

    Thank you,

    Nikhil

  • Hi Nikhil,

    I had a play around with that tool, and read the user's guide. It seems like you need an MSP430 launchpad?

    I don't have that at all, so it doesn't seem like I can use this tool?

    I'm communicating to the PHY via MDIO at the moment, with an STM32 microcontroller.

    Keep in mind that sending TCP/UDP msgs from my PC to the micro works completely fine.

    Regards,

    Andrew

  • Hi Andrew,

    We are looking into this issue and will provide additional feedback by the end of the week.

    Thank you,

    Nikhil

  • Hi Andrew,

    It seems as though this is becoming a debugger mode vs delay issue which becomes difficult to debug and may be outside the scope of this forum. However from a PHY perspective, I have a few questions I would like to clarify.

    • When you are not able to read the timestamp, are you not able to read the register at all or are you reading garbage value?
    • Can you add read statements after all write statements to confirm the read/write path is working as expected?

    Thank you,

    Nikhil

  • Hi Nikhil, Sorry this message didn't send earlier for some weird reason - maybe the new website.

    For your questions: I am reading 0s from the register when I am not able to read the timestamps.

    Regarding reading after all writes, I will try that out shortly.

    Thinking of reading the registers and storing them in variables to be read after all the initialisation is complete, since I feel like stepping through breakpoints will cause it to work regardless.

    Regards,

    Andrew

  • Hi Andrew,

    I think these two experiments, reading register values after all writes, and storing registers as variables, may be helpful. Please let me know what you observe.

    Thank you,

    Nikhil

  • Hi Nikhil,

    Here's what I got. Note that I didnt read the ip address register, since I was writing 0 to it anyway.

    I've also typed the data and mask both being 0x00 before, it doesn't change the behaviour.

    The behaviour is still that when there is no breakpoint at the following code:

    if ( events & PTPEVT_RECEIVE_TIMESTAMP_BIT)
    {
    PTPGetReceiveTimestamp( pEPL_HANDLE, &PTP_seconds, &PTP_nanoseconds, &overflowCount, &seqId, &msgType, &hashValue);
    }

    The variable PTP_seconds does not change. My next idea will be to modify the function PTPGetReceiveTimestamp to put all volatile references there.

    What I wrote:
    PTP_RATEH = 0,
    PTP_RATEL = 0,
    PTP_COC = 32778,
    PTP_CLKSRC = 8,
    PHYCR2 = 0,
    PTP_CTL = 4,
    PTP_TXCFG0 = 37,
    PTP_TXCFG1 = 0,
    PTP_RXCFG0 = 3877,
    PTP_RXCFG1 = 65280,
    PTP_RXCFG3 = 3072,
    PTP_RXCFG4 = 0, PTP_RXHASH = 0

    What I read after writing it:
    PTP_RATEH = 0,
    PTP_RATEL = 0,
    PTP_COC = 32778,
    PTP_CLKSRC = 8,
    PHYCR2 = 0,
    PTP_CTL = 4,
    PTP_TXCFG0 = 37,
    PTP_TXCFG1 = 0,
    PTP_RXCFG0 = 3877,
    PTP_RXCFG1 = 65280,
    PTP_RXCFG3 = 3072,
    PTP_RXCFG4 = 0, PTP_RXHASH = 0

    Regards,

    Andrew

  • Hi Andrew,

    Please let me know the results of the modifying the PTPGetReceiveTimestamp function.

    Thank you,

    Nikhil

  • Hi Nikhil,

    Modifying the function didn't solve the issue, but I had an idea.

    I noticed that even when it was 'working', it still stops working after about 15 reads from the timestamp register.

    I added a seperate command to read the relevant PTP registers, and I called that command once the PTP timestamp has stopped working (it no longer stops at the breakpoint). I see that the registers have changed. My suspicions are that the PHY has reset? Then, I put a breakpoint at any code that would reset the PHY (mainly in the initialisation function and when there is a change in network), and the breakpoints was not hit.

    Is there any other reason the PHY would reset the registers?

    Andrew

  • Hi Andrew,

    Reset should be initiated by hardware (pulling the reset pin low), or register access. There are different resets that can be initiated by registers, software reset, soft reset, and PTP reset. Please review section 5.4.10 of the datasheet for more info on each type of reset. If the PTP reset, software reset, or hardware reset are being triggered, this may clear the PTP registers. 

    Thank you,

    Nikhil

  • Hi Nikhil,

    I had a look at all the different resets, andhad a look at the code too.

    PTP reset is only being done in initialization, as shown in the above code segments.
    Soft reset bit is never set, plus it doesn't reset the register configurations anyway.

    Hardware reset pin seems to be pulled high, so no reset there.

    Full software reset bit is never set.

    Andrew

  • Hi Andrew,

    Some of the bits in the PTP register set are self-clearing, designated with an "SC" in the register tables. Are non-self-clearing bits also being reset?

    Thank you,

    Nikhil

  • Hi Nikhil,

    Thanks for all your help. I figured out where somewhere else was resetting the registers (when the network changes). It is now working.

    Another question - how do you get the absolute s and ns value in the PTP packet from the PHY (without decoding it in firmware). It seems to only store relative in the registers since it resets to 0 at the start.

    Thanks,

    Andrew

  • Hi Andrew,

    I'm glad to hear that your code is now working! 

    I am looking into your question regarding reading the s and ns value in PTP packet, and will provide feedback by Tuesday of next week.

    Thank you,

    Nikhil

  • Hi Andrew,

    Apologies, I'm not clear on your goal of reading timestamp without decoding in firmware. The transmit and receive timestamps in seconds and nanoseconds can be found by reading registers 0x1C and 0x1D respectively. Is this the register read you are looking for?

    Thank you,

    Nikhil Menon

    All information in this correspondence and in any related correspondence is provided “as is” and “with all faults”, and it is subject to TI’s Important Notice (http://www.ti.com/corp/docs/legal/important-notice.shtml).

  • Hi Nikhil,

    From my understanding, On startup, the PTP IEEE1588 clock is set to 1 second and 0 nanoseconds. After that, whenever it gets a receive timestamp, the PHY chip will update the register 0x1D. If we use that register to drive a periodic GPIO signal using PTPArmTrigger and PTPSetTriggerConfig, two different phy/micros will not sync up, because their PTP timestamps will be 'relative' based on startup time.

    The PHY does receive the absolute PTP timestamps at some point, and I am wondering if it is stored anywhere.

    At the moment, I've written some code to parse a sync/followup PTP msg to get the absolute PTP seconds and ns, but it strikes me that the PTP internal logic already does that in order to get the relative PTP timestamps.

    Regards,

    Andrew

  • Hi Andrew,

    We are looking into your question and will provide an update by Monday latest.

    Thank you,

    Nikhil

    All information in this correspondence and in any related correspondence is provided “as is” and “with all faults”, and it is subject to TI’s Important Notice (http://www.ti.com/corp/docs/legal/important-notice.shtml).