This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] DP83630:在两个 PHY 之间同步#39;PTP 时钟精度不低于纳秒

Guru**** 2482225 points
Other Parts Discussed in Thread: DP83630

请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/interface-group/interface/f/interface-forum/671281/dp83630-synchronize-between-two-phys-ptp-clock-accuracy-is-not-sub-nanosecond

器件型号:DP83630

请参阅 AN-1794第4.1节图6、我将两个 DP83630连接到一个具有两个 RMII 模式 MAC 的 MCU、一个用于上行端口、另一个用于下行端口。

对于上行端口、PHY 在启用 SYNC_ENET_EN 的 RMII 主模式下工作;对于下行端口、PHY 在禁用 SYNC_ENET_EN 的 RMII 从模式下工作。

上行端口 PHY 通过25MHz TCXO 进行馈送、通过 TX_CLK 输出50MHz、并馈送至下行端口的 X1输入。

使用上述拓扑、上行端口 PHY 和下行端口 PHY 在同一时钟域中工作、因此我希望其 PTP 时钟能够同步到亚纳秒级精度。

请参阅 AN-1838第3.1节图2、我在上游 PHY 和下游 PHY 之间实现了 PTP 同步时钟。

但是、当我使用示波器测试每个 PHY 的 PPS 输出时、我发现相位误差是不确定的。  

每次给系统上电、PTP 同步完成后、PPS 相位误差在三个值(0ns、4ns 和8ns、这是4ns 的倍数)之间变化。   

您是否认为相位误差是预期误差?

是否可以在两个 PHY 的 PTP 时钟之间实现亚纳秒精度?

我的源代码如下所示:

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

NS_UINT SimpleSyncTwoPHY (RunTimeOpts * rtOpts、NS_BOOL SyncEth1ToEth0、NS_BOOL DoSync)

NS_UINT eventNum[2]={0xFF、0xFF};
NS_UINT RiseFlag[2];
NS_UINT 事件 Missed[2];
NS_UINT 事件;
NS_STATUS 状态;
int deltaRate;
Int WaitTime;

NS_UINT 相位错误;

NS_BOOL 负可调;

TimeInternal EventTime[2];
时间内部时间差异;
TimeInternal TimeDiffPhy1ToPhy2;
TimeInternal TimeDiffPhy2ToPhy1;

长整型 val;
长整型 val1;
长整型 val2;
long long deltaT;
Long Long DeltaP;

//刷新 eth0 PHY 的事件时间戳
while ((事件= PTPCheckForEvents (pEPL_HANDLE1)))

if (事件和 PTPEVT_EVENT_TIMESTAMP_BIT)

PTPGetEvent (pEPL_HANDLE1、&eventNum[0]、&riseFlag[0]、&(EventTime[0].seconds)、&EventTime[0].nanoseconds、&eventsMissed[0]);

其他

中断;



//刷新 eth1 PHY 的事件时间戳
while ((事件= PTPCheckForEvents (pEPL_HANDLE2)))

if (事件和 PTPEVT_EVENT_TIMESTAMP_BIT)

PTPGetEvent (pEPL_HANDLE2、&eventNum[1]、&riseFlag[1]、&(EventTime[1].sec)、&EventTime[1].nanoseconds、 &eventsMised[1]);

其他

中断;

//将 PHY1的 GPIO3 (SYNC_TRIGGER)设置为边沿事件编号0捕捉
PTPSetEventConfig (pEPL_HANDLE1、0、true、false、true、 3);

//将 PHY2的 GPIO3 (SYNC_TRIGGER)设置为一个边沿事件编号0捕捉
PTPSetEventConfig (pEPL_HANDLE2、0、true、false、true、 3);


//将 MCU 的 SYNC_TRIGGER 引脚设置为输入、以避免与 PHY 的触发输出冲突
FM3_GPIO->PFRA &=~(1U<<0x0);// PA0,非特殊功能
FM3_GPIO->DDRA &=~(1U<<0x0);//将 SYNC_TRIGGER 引脚设置为输入



//Calculate the trigger timing offset from current PHY1的 PTP time 500ms
PTPClockReadCurrent (pEPL_HANDLE1、&(EventTime[0].seconds)、&(EventTime[0].nanoseconds));
Val =(long long)(EventTime[0].seconds * 1e9)+(long long) EventTime[0].nanoseconds;
Val += 50000000;

//相位对齐触发信号
Val = val - val % 8;

EventTime[0].seconds =(int)(val / 1e9);
EventTime[0].nanoseconds =(int)(val %(long long) 1e9);

//将 PHY1的 GPIO3 (SYNC_TRIGGER)设置为触发1输出、并输出1us 正脉冲
PTPCancelTrigger (pEPL_HANDLE1、1);
PTPSetTriggerConfig (pEPL_HANDLE1、1、TRGOPT_PULSE | TRGOPT_NOTIFY_EN、3);
PTPArmTrigger (pEPL_HANDLE1、1、EventTime[0].seconds、EventTime[0].nanoseconds、
false、false、10000、10000);

//等待触发器1触发
WaitTime = 0x10000000;
STATUS = PTPHasTriggerExpired (pEPL_HANDLE1、1);
while ((ns_status_Success!= status)&&(WaitTime>0))

STATUS = PTPHasTriggerExpired (pEPL_HANDLE1、1);
WaitTime--;


if (!WaitTime)


printf ("等待触发时出错!\n");
返回-1;

其他


printf ("PHY1触发器!\n");

PTPCancelTrigger (pEPL_HANDLE1、1);
PTPSetTriggerConfig (pEPL_HANDLE1、1、TRGOPT_PULSE | TRGOPT_NOTIFY_EN、0);

//刷新发送和接收时间戳并获取事件时间戳
while ((事件= PTPCheckForEvents (pEPL_HANDLE1)))

IF (事件和 PTPEVT_Transmit、TIMESTAMP_BIT)
PTPGetTransmitTimestamp (pEPL_HANDLE1、&(EventTime[0].seconds)、&(EventTime[0].nanoseconds)、&eventsMissed[0]);
否则(事件和 PTPEVT_Receive_TIMESTAMP_BIT)
PTPGetTransmitTimestamp (pEPL_HANDLE1、&(EventTime[0].seconds)、&(EventTime[0].nanoseconds)、&eventsMissed[0]);
如果(事件和 PTPEVT_EVENT_TIMESTAMP_BIT)

PTPGetEvent (pEPL_HANDLE1、&eventNum[0]、&riseFlag[0]、&(EventTime[0].seconds)、&(EventTime[0].nanoseconds)、 &eventsMised[0]);
if (eventNum[0]&(1<0))
中断;


if (!(eventNum[0]&(1<0)))

printf ("错误、PHY1未捕获 SYNC_Trigger 事件!!!!\n");
返回-1;

//断开事件0与 GPIO 3的连接
PTPSetEventConfig (pEPL_HANDLE1、0、false、false、false、 0);



//刷新发送和接收时间戳并获取事件时间戳
while ((事件= PTPCheckForEvents (pEPL_HANDLE2)))

IF (事件和 PTPEVT_Transmit、TIMESTAMP_BIT)
PTPGetTransmitTimestamp (pEPL_HANDLE2、&(EventTime[1].seconds)、&(EventTime[1].nanoseconds)、&eventsMissed[1]);
否则(事件和 PTPEVT_Receive_TIMESTAMP_BIT)
PTPGetTransmitTimestamp (pEPL_HANDLE2、&(EventTime[1].seconds)、&(EventTime[1].nanoseconds)、&eventsMissed[1]);
如果(事件和 PTPEVT_EVENT_TIMESTAMP_BIT)

PTPGetEvent (pEPL_HANDLE2、&eventNum[1]、&riseFlag[1]、&(EventTime[1].Seconds)、&(EventTime[1].nanoseconds)、 &eventsMised[1]);
if (eventNum[1]和(1<0))
中断;


if (!(eventNum[1]和(1<0)))

printf ("错误、PHY2未捕获 SYNC_Trigger 事件!!!!\n");
返回-1;

//断开事件0与 GPIO 3的连接
PTPSetEventConfig (pEPL_HANDLE2、0、false、false、false、 0);

SubTime (&TimeDiffPhy1ToPhy2、&EventTime[0]、&EventTime[1]);
Val =(long long)(TimeDiffPhy1ToPhy2.seconds * 1e9)+(long long) TimeDiffPhy1ToPhy2.纳 秒;

Val +=16;

负 Adj = false;
if (val < 0)
负 Adj = true;

TimeDiff.seconds =(int)(val / 1e9);
TimeDiff.纳秒=(int)(val %(long long) 1e9);

PTPClockStepAdjustment (pEPL_HANDLE2、ABS (TimeDiff.seconds)、ABS (TimeDifel.nanoseconds)、negAdj);

PTPClockReadCurrent (pEPL_HANDLE1、&(EventTime[0].seconds)、&(EventTime[0].nanoseconds));
Val =(long long)(EventTime[0].seconds * 1e9)+(long long) EventTime[0].nanoseconds;
Val += 50000000;

//PPS 相位对齐
Val = val - val%32;

EventTime[0].seconds =(int)(val / 1e9);
EventTime[0].nanoseconds =(int)(val %(long long) 1e9);



//设置 PHY1的 PPS 配置
PTPSetTriggerConfig (pEPL_HANDLE1、0、TRGOPT_PULSE |TRGOPT_PERiod| TRGOPT_NOTIFY_EN、0);
PTPCancelTrigger (pEPL_HANDLE1、0);
PTPSetTriggerConfig (pEPL_HANDLE1、0、TRGOPT_PULSE|TRGOPT_PERiod|TRGOPT_NOTIFY_EN、1);
PTPArmTrigger (pEPL_HANDLE1、0、EventTime[0].seconds、EventTime[0].nanoseconds、
false、false、16、16);

//设置 PHY2的 PPS 配置
PTPSetTriggerConfig (pEPL_HANDLE2、0、TRGOPT_PULSE |TRGOPT_PERiod| TRGOPT_NOTIFY_EN、0);
PTPCancelTrigger (pEPL_HANDLE2、0);
PTPSetTriggerConfig (pEPL_HANDLE2、0、TRGOPT_PULSE|TRGOPT_PERiod|TRGOPT_NOTIFY_EN、1);
PTPArmTrigger (pEPL_HANDLE2、0、EventTime[0].seconds、EventTime[0].nanoseconds、
false、false、16、16);

 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

 

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好!

    a.您能否测量 Phy1的 CLK_OUT 与两个 PHY 在复位和共享之间的 PPS 之间的相位差?
    b.此外、您能否尝试使用 CLK_OUT of Intenral PTP 时钟25MHz 从 PHY 1更改为 Phy2 (以下来自数据表)

    ----------
    时钟输出:该引脚提供高度可配置的系统时钟、
    可能有四个来源之一:
    1、相对于内部 PTP 时钟、缺省频率为25MHz
    (默认值)
    RMII 主模式下的2.50MHz RMII 参考时钟
    100MB 模式下的3.25MHz 接收时钟(与 RX_CLK 相同)
    4. X1参考时钟的25MHz 或50MHz 直通
    时钟输入:该引脚用于输入外部 IEEE 1588基准
    用于 IEEE 1588逻辑的时钟。 CLK_OUT_EN 设置应为
    禁用以防止可能的争用。 PTP_CLKSRC
    必须事先配置寄存器
    --------------------------------------

    此致、
    GET
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    "跨越重置并共享?"

    在这里、"共享"意味着什么?

    BTW:我为每个 PHY 实现两个单独的复位、这是因为 MCU 的两个不同 GPIO 的复位、这意味着这两个 PHY 不能同时复位。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    “共享”:共享测试结果。

    重置:您可以先使用 XTAL 重置 PHY,然后使用 CLK_OUT 重置 PHY。

    此致、
    GET

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    感谢您的快速响应。

    对于您提到的情况 A、每次这三个信号之间的相位对齐不同时、我都会进行8次上电测试。 然后、我尝试仅在保持电路板通电的同时复位 MCU、这种现象是相同的。 因此、我只在后面记录加电测试结果。

     

    对于您提到的情况 B、我无法接受 PHY2的 PTP 功能在低至25MHz 时钟下工作、我仍然希望 PHY1和 PH2都具有125MHz PTP 时钟、因此我还没有尝试过。

     

    以下是我的案例 A 的测试结果:

     

    ===================================================================================

    示波器设置:

    C1:PHY1的25MHz PTP 时钟(写颜色)

    C2:PHY1的 PPS 输出(绿色)

    C3:PHY2的 PPS 输出(棕色)

    ===================================================================================

     

    ===================================================================================

    软件序列:

    设置 PHY1以生成第一个触发信号

    捕获到 PHY1和 PHY2事件、记录事件时间戳

    3.计算从 PHY2到 PHY1的偏移

    4.进行步进调整

    设置 PHY1以生成第二个触发信号

    6. PHY1和 PHY2事件已捕获,请记录事件时间戳

    7.再次确认 PHY2与 PHY1之间的偏差

    ================================================================================================================

     

    在中、按照测试日志和波形的八次操作、在步骤7中、PHY1和 PHY2没有时间偏移、这意味着同步成功。 但是、波形具有相位误差、因为事件时间戳的精度为8ns、因此我怀疑 PHY1和 PHY2实际上没有同步。

     

    首次测试日志:

    PHY1触发器!

    设置触发时间为20s983520000ns

    PHY1事件时间为20s983520000ns

    PHY2事件时间为1s7155856ns

    Timediff 为1997-6364144ns

    PHY1触发器!

    设置触发时间为21s487240000ns

    PHY1事件时间为21s487240000ns

    PHY2事件时间为21s487240000ns

    Timediff 为0ns

     

    首次从示波器获取快照:

     

    第二次测试日志:

    PHY1触发器!

    设置触发时间为17s979580000ns

    PHY1事件时间为17s979580000ns

    PHY2事件时间为1s7139000ns

    Timediff 为16972441000ns

    D0

    PHY1触发器!

    设置触发时间为18s483320000ns

    PHY1事件时间为18s483320000ns

    PHY2事件时间为18s483320000ns

    Timediff 为0ns

     

     

    第二次从示波器获取快照:

     

    第三次测试日志:

    PHY1触发器!

    设置触发时间为17s982380000ns

    PHY1事件时间为17s982380000ns

    PHY2事件时间为1s7133208ns

    Timediff 为16975246792ns

    D0

    PHY1触发器!

    设置触发时间为18s486120000ns

    PHY1事件时间为18s486120000ns

    PHY2事件时间为18s486120000ns

    Timediff 为0ns

     

    第三次从示波器获取快照:

     

    第4次测试日志:

    PHY1触发器!

    设置触发时间为17s983100000ns

    PHY1事件时间为17s983100000ns

    PHY2事件时间为1s7161264ns

    Timediff 为16975938736ns

    D0

    PHY1触发器!

    设置触发时间为18s486820000ns

    PHY1事件时间为18s486820000ns

    PHY2事件时间为18s486820000ns

    Timediff 为0ns

     

     

    第4次从示波器获取快照:

    第5次测试日志:

    PHY1触发器!

    设置触发时间为26s982240000ns

    PHY1事件时间为26s982240000ns

    PHY2事件时间为1s7137488ns

    Timediff 为25975102512ns

    D0

    PHY1触发器!

    设置触发时间为27s485980000ns

    PHY1事件时间为27s485980000ns

    PHY2事件时间为27s485980000ns

    Timediff 为0ns

     

     

    第5次、从示波器获取快照:

     

    第6次测试日志:

    PHY1触发器!

    设置触发时间为26s982080000ns

    PHY1事件时间为26s982080000ns

    PHY2事件时间为1s7148464ns

    Timediff 为25974931536ns

    D0

    PHY1触发器!

    设置触发时间为27s485820000ns

    PHY1事件时间为27s485820000ns

    PHY2事件时间为27s485820000ns

    Timediff 为0ns

     

    第6次、示波器快照:

    第7次测试日志:

    PHY1触发器!

    设置触发时间为26s981960000ns

    PHY1事件时间为26s981960004ns

    PHY2事件时间为1s7162112ns

    Timediff 为25974797892ns

    D0

    PHY1触发器!

    设置触发时间为27s485680000ns

    PHY1事件时间为27s485680004ns

    PHY2事件时间为27s485680004ns

    Timediff 为0ns

     

    第7次、从示波器获取快照:

    第8次测试日志:

    PHY1触发器!

    设置触发时间为17s983380000ns

    PHY1事件时间为17s983380000ns

    PHY2事件时间为1s7135864ns

    Timediff 为16976244136ns

    D0

    PHY1触发器!

    设置触发时间为18s487120000ns

    PHY1事件时间为18s487120000ns

    PHY2事件时间为18s487120000ns

    Timediff 为0ns

    第8次、示波器快照:

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    执行  上述测试时、遵循的是 PHY2与 PHY1源代码的同步实现:  

    NS_UINT SimpleSyncTwoPHY (RunTimeOpts * rtOpts、NS_BOOL SyncEth1ToEth0、NS_BOOL DoSync)

    NS_UINT eventNum[2]={0xFF、0xFF};
    NS_UINT RiseFlag[2];
    NS_UINT 事件 Missed[2];
    NS_UINT 事件;
    NS_STATUS 状态;
    int deltaRate;
    Int WaitTime;
    NS_UINT x;

    NS_UINT 相位错误;

    NS_BOOL 负可调;

    TimeInternal EventTime[2];
    时间内部时间差异;
    TimeInternal TimeDiffPhy1ToPhy2;
    TimeInternal TimeDiffPhy2ToPhy1;

    长整型 val;
    长整型 val1;
    长整型 val2;
    long long deltaT;
    Long Long DeltaP;

    //将 MCU 的 SYNC_TRIGGER 引脚设置为输入、以避免与 PHY 的触发输出冲突
    FM3_GPIO->PFRA &=~(1U<<0x0);// PA0,非特殊功能
    FM3_GPIO->DDRA |=(1U<<0x0);//将 SYNC_TRIGGER 引脚设置为输出
    *SYNC_TRIGGER_PIN = 0;//Initialize SYNC_TRIGGER_PIN 处于低电平
    FM3_GPIO->DDRA &=~(1U<<0x0);//将 SYNC_TRIGGER 引脚设置为输入


    //从事件0断开 PHY1的 GPIO3
    PTPSetEventConfig (pEPL_HANDLE1、0、false、false、false、 0);
    //从事件0断开 PHY2的 GPIO3
    PTPSetEventConfig (pEPL_HANDLE2、0、false、false、false、 0);


    //刷新 eth0 PHY 的事件时间戳
    while ((事件= PTPCheckForEvents (pEPL_HANDLE1)))

    if (事件和 PTPEVT_EVENT_TIMESTAMP_BIT)

    PTPGetEvent (pEPL_HANDLE1、&eventNum[0]、&riseFlag[0]、&(EventTime[0].seconds)、&EventTime[0].nanoseconds、&eventsMissed[0]);

    其他

    中断;



    //刷新 eth1 PHY 的事件时间戳
    while ((事件= PTPCheckForEvents (pEPL_HANDLE2)))

    if (事件和 PTPEVT_EVENT_TIMESTAMP_BIT)

    PTPGetEvent (pEPL_HANDLE2、&eventNum[1]、&riseFlag[1]、&(EventTime[1].sec)、&EventTime[1].nanoseconds、 &eventsMised[1]);

    其他

    中断;



    //Calculate the trigger timing offset from current PHY1的 PTP time 500ms
    PTPClockReadCurrent (pEPL_HANDLE1、&(EventTime[0].seconds)、&(EventTime[0].nanoseconds));
    Val =(long long)(EventTime[0].seconds * 1e9)+(long long) EventTime[0].nanoseconds;
    Val += 500000000;

    //相位对齐触发信号
    Val = val - val % 20000;

    EventTime[0].seconds =(int)(val / 1e9);
    EventTime[0].nanoseconds =(int)(val %(long long) 1e9);



    //将 PHY1的 GPIO3 (SYNC_TRIGGER)设置为触发1输出、并输出1us 正脉冲
    PTPCancelTrigger (pEPL_HANDLE1、1);
    PTPSetTriggerConfig (pEPL_HANDLE1、1、TRGOPT_PULSE | TRGOPT_NOTIFY_EN、3);


    PTPArmTrigger (pEPL_HANDLE1、1、EventTime[0].seconds、EventTime[0].nanoseconds、
    false、false、10000、10000);

    //将 PHY1的 GPIO3 (SYNC_TRIGGER)设置为边沿事件编号0捕捉
    PTPSetEventConfig (pEPL_HANDLE1、0、true、false、true、 3);

    //将 PHY2的 GPIO3 (SYNC_TRIGGER)设置为一个边沿事件编号0捕捉
    PTPSetEventConfig (pEPL_HANDLE2、0、true、false、true、 3);


    //等待触发器1触发
    WaitTime = 0x10000000;
    STATUS = PTPHasTriggerExpired (pEPL_HANDLE1、1);
    while ((ns_status_Success!= status)&&(WaitTime>0))

    STATUS = PTPHasTriggerExpired (pEPL_HANDLE1、1);
    WaitTime--;


    if (!WaitTime)


    printf ("等待触发时出错!\n");
    返回-1;

    其他


    printf ("PHY1触发器!\n");

    PTPCancelTrigger (pEPL_HANDLE1、1);
    PTPSetTriggerConfig (pEPL_HANDLE1、1、TRGOPT_PULSE | TRGOPT_NOTIFY_EN、0);

    printf ("设置触发时间为%DS%DNS\n"、EventTime[0].seconds、EventTime[0].noseconds);

    //刷新发送和接收时间戳并获取事件时间戳
    while ((事件= PTPCheckForEvents (pEPL_HANDLE1)))

    IF (事件和 PTPEVT_Transmit、TIMESTAMP_BIT)
    PTPGetTransmitTimestamp (pEPL_HANDLE1、&(EventTime[0].seconds)、&(EventTime[0].nanoseconds)、&eventsMissed[0]);
    否则(事件和 PTPEVT_Receive_TIMESTAMP_BIT)
    PTPGetTransmitTimestamp (pEPL_HANDLE1、&(EventTime[0].seconds)、&(EventTime[0].nanoseconds)、&eventsMissed[0]);
    如果(事件和 PTPEVT_EVENT_TIMESTAMP_BIT)

    PTPGetEvent (pEPL_HANDLE1、&eventNum[0]、&riseFlag[0]、&(EventTime[0].seconds)、&(EventTime[0].nanoseconds)、 &eventsMised[0]);
    if (eventNum[0]&(1<0))

    中断;



    if (!(eventNum[0]&(1<0)))

    printf ("错误、PHY1未捕获 SYNC_Trigger 事件!!!!\n");
    返回-1;

    //断开事件0与 GPIO 3的连接
    PTPSetEventConfig (pEPL_HANDLE1、0、false、false、false、 0);

    printf ("PHY1事件时间为%DS%DNS\n"、EventTime[0].seconds、EventTime[0].noseconds);

    //刷新发送和接收时间戳并获取事件时间戳
    while ((事件= PTPCheckForEvents (pEPL_HANDLE2)))

    IF (事件和 PTPEVT_Transmit、TIMESTAMP_BIT)
    PTPGetTransmitTimestamp (pEPL_HANDLE2、&(EventTime[1].seconds)、&(EventTime[1].nanoseconds)、&eventsMissed[1]);
    否则(事件和 PTPEVT_Receive_TIMESTAMP_BIT)
    PTPGetTransmitTimestamp (pEPL_HANDLE2、&(EventTime[1].seconds)、&(EventTime[1].nanoseconds)、&eventsMissed[1]);
    如果(事件和 PTPEVT_EVENT_TIMESTAMP_BIT)

    PTPGetEvent (pEPL_HANDLE2、&eventNum[1]、&riseFlag[1]、&(EventTime[1].Seconds)、&(EventTime[1].nanoseconds)、 &eventsMised[1]);
    if (eventNum[0]&(1<0))

    中断;



    if (!(eventNum[1]和(1<0)))

    printf ("错误、PHY2未捕获 SYNC_Trigger 事件!!!!\n");
    返回-1;

    //断开事件0与 GPIO 3的连接
    PTPSetEventConfig (pEPL_HANDLE2、0、false、false、false、 0);

    printf ("PHY2事件时间为%DS%DNS\n"、EventTime[1].seconds、EventTime[1].noseconds);

    SubTime (&TimeDiffPhy1ToPhy2、&EventTime[0]、&EventTime[1]);
    Val =(long long)(TimeDiffPhy1ToPhy2.seconds * 1e9)+(long long) TimeDiffPhy1ToPhy2.纳 秒;

    printf ("Timediff 为%lldns\n"、val);

    Val +=16;

    负 Adj = false;
    if (val < 0)
    负 Adj = true;

    TimeDiff.seconds =(int)(val / 1e9);
    TimeDiff.纳秒=(int)(val %(long long) 1e9);

    PTPClockStepAdjustment (pEPL_HANDLE2、ABS (TimeDiff.seconds)、ABS (TimeDifel.nanoseconds)、negAdj);




    //第二次触发以确认同步结果

    //刷新 eth0 PHY 的事件时间戳
    while ((事件= PTPCheckForEvents (pEPL_HANDLE1)))

    if (事件和 PTPEVT_EVENT_TIMESTAMP_BIT)

    PTPGetEvent (pEPL_HANDLE1、&eventNum[0]、&riseFlag[0]、&(EventTime[0].seconds)、&EventTime[0].nanoseconds、&eventsMissed[0]);

    其他

    中断;



    //刷新 eth1 PHY 的事件时间戳
    while ((事件= PTPCheckForEvents (pEPL_HANDLE2)))

    if (事件和 PTPEVT_EVENT_TIMESTAMP_BIT)

    PTPGetEvent (pEPL_HANDLE2、&eventNum[1]、&riseFlag[1]、&(EventTime[1].sec)、&EventTime[1].nanoseconds、 &eventsMised[1]);

    其他

    中断;



    //Calculate the trigger timing offset from current PHY1的 PTP time 500ms
    PTPClockReadCurrent (pEPL_HANDLE1、&(EventTime[0].seconds)、&(EventTime[0].nanoseconds));
    Val =(long long)(EventTime[0].seconds * 1e9)+(long long) EventTime[0].nanoseconds;
    Val += 500000000;

    //相位对齐触发信号
    Val = val - val % 20000;

    EventTime[0].seconds =(int)(val / 1e9);
    EventTime[0].nanoseconds =(int)(val %(long long) 1e9);

    //将 PHY1的 GPIO3 (SYNC_TRIGGER)设置为触发1输出、并输出1us 正脉冲
    PTPCancelTrigger (pEPL_HANDLE1、1);
    PTPSetTriggerConfig (pEPL_HANDLE1、1、TRGOPT_PULSE | TRGOPT_NOTIFY_EN、3);
    PTPArmTrigger (pEPL_HANDLE1、1、EventTime[0].seconds、EventTime[0].nanoseconds、
    false、false、10000、10000);

    //将 PHY1的 GPIO3 (SYNC_TRIGGER)设置为边沿事件编号0捕捉
    PTPSetEventConfig (pEPL_HANDLE1、0、true、false、true、 3);

    //将 PHY2的 GPIO3 (SYNC_TRIGGER)设置为一个边沿事件编号0捕捉
    PTPSetEventConfig (pEPL_HANDLE2、0、true、false、true、 3);

    //等待触发器1触发
    WaitTime = 0x10000000;
    STATUS = PTPHasTriggerExpired (pEPL_HANDLE1、1);
    while ((ns_status_Success!= status)&&(WaitTime>0))

    STATUS = PTPHasTriggerExpired (pEPL_HANDLE1、1);
    WaitTime--;


    if (!WaitTime)


    printf ("等待触发时出错!\n");
    返回-1;

    其他


    printf ("PHY1触发器!\n");

    PTPCancelTrigger (pEPL_HANDLE1、1);
    PTPSetTriggerConfig (pEPL_HANDLE1、1、TRGOPT_PULSE | TRGOPT_NOTIFY_EN、0);

    printf ("设置触发时间为%DS%DNS\n"、EventTime[0].seconds、EventTime[0].noseconds);

    //刷新发送和接收时间戳并获取事件时间戳
    while ((事件= PTPCheckForEvents (pEPL_HANDLE1)))

    IF (事件和 PTPEVT_Transmit、TIMESTAMP_BIT)
    PTPGetTransmitTimestamp (pEPL_HANDLE1、&(EventTime[0].seconds)、&(EventTime[0].nanoseconds)、&eventsMissed[0]);
    否则(事件和 PTPEVT_Receive_TIMESTAMP_BIT)
    PTPGetTransmitTimestamp (pEPL_HANDLE1、&(EventTime[0].seconds)、&(EventTime[0].nanoseconds)、&eventsMissed[0]);
    如果(事件和 PTPEVT_EVENT_TIMESTAMP_BIT)

    PTPGetEvent (pEPL_HANDLE1、&eventNum[0]、&riseFlag[0]、&(EventTime[0].seconds)、&(EventTime[0].nanoseconds)、 &eventsMised[0]);
    if (eventNum[0]&(1<0))
    中断;


    if (!(eventNum[0]&(1<0)))

    printf ("错误、PHY1未捕获 SYNC_Trigger 事件!!!!\n");
    返回-1;

    //断开事件0与 GPIO 3的连接
    PTPSetEventConfig (pEPL_HANDLE1、0、false、false、false、 0);

    printf ("PHY1事件时间为%DS%DNS\n"、EventTime[0].seconds、EventTime[0].noseconds);


    //刷新发送和接收时间戳并获取事件时间戳
    while ((事件= PTPCheckForEvents (pEPL_HANDLE2)))

    IF (事件和 PTPEVT_Transmit、TIMESTAMP_BIT)
    PTPGetTransmitTimestamp (pEPL_HANDLE2、&(EventTime[1].seconds)、&(EventTime[1].nanoseconds)、&eventsMissed[1]);
    否则(事件和 PTPEVT_Receive_TIMESTAMP_BIT)
    PTPGetTransmitTimestamp (pEPL_HANDLE2、&(EventTime[1].seconds)、&(EventTime[1].nanoseconds)、&eventsMissed[1]);
    如果(事件和 PTPEVT_EVENT_TIMESTAMP_BIT)

    PTPGetEvent (pEPL_HANDLE2、&eventNum[1]、&riseFlag[1]、&(EventTime[1].Seconds)、&(EventTime[1].nanoseconds)、 &eventsMised[1]);
    if (eventNum[1]和(1<0))
    中断;


    if (!(eventNum[1]和(1<0)))

    printf ("错误、PHY2未捕获 SYNC_Trigger 事件!!!!\n");
    返回-1;

    //断开事件0与 GPIO 3的连接
    PTPSetEventConfig (pEPL_HANDLE2、0、false、false、false、 0);

    printf ("PHY2事件时间为%DS%DNS\n"、EventTime[1].seconds、EventTime[1].noseconds);

    SubTime (&TimeDiffPhy1ToPhy2、&EventTime[0]、&EventTime[1]);
    Val =(long long)(TimeDiffPhy1ToPhy2.seconds * 1e9)+(long long) TimeDiffPhy1ToPhy2.纳 秒;

    printf ("Timediff 为%lldns\n"、val);

    PTPClockReadCurrent (pEPL_HANDLE1、&(EventTime[0].seconds)、&(EventTime[0].nanoseconds));


    //设置 PHY1的 PPS 配置
    PTPSetTriggerConfig (pEPL_HANDLE1、0、TRGOPT_PULSE |TRGOPT_PERiod| TRGOPT_NOTIFY_EN、0);
    PTPCancelTrigger (pEPL_HANDLE1、0);
    PTPSetTriggerConfig (pEPL_HANDLE1、0、TRGOPT_PULSE|TRGOPT_PERiod|TRGOPT_NOTIFY_EN、1);
    PTPArmTrigger (pEPL_HANDLE1、0、EventTime[0].Seconds+2、0、
    false、false、500000000、500000000);

    //设置 PHY2的 PPS 配置
    PTPSetTriggerConfig (pEPL_HANDLE2、0、TRGOPT_PULSE |TRGOPT_PERiod| TRGOPT_NOTIFY_EN、0);
    PTPCancelTrigger (pEPL_HANDLE2、0);
    PTPSetTriggerConfig (pEPL_HANDLE2、0、TRGOPT_PULSE|TRGOPT_PERiod|TRGOPT_NOTIFY_EN、1);
    PTPArmTrigger (pEPL_HANDLE2、0、EventTime[0].Seconds+2、0、
    false、false、500000000、500000000);

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    感谢您提供信息。 我再次在应用手册和您的时钟图上链接。 我相信您是"图6"时钟、而对于同步以太网、您需要遵循"图7"时钟树。

    主要区别在于:

    CLK_OUT 被配置为在 PHY 1上向 MAC 提供50MHz RMII 时钟
    2. TX_CLK 配置为输出25MHz 时钟同步到 PHY 的 PTP 时钟1. 该时钟充当 Phy2的输入。




    此致、
    GET
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    是的、当然、我是"图6"时钟模式。

    首先、我也更喜欢"图7"时钟模式、但我发现它要求每个 MAC 都有 单独的 REFCLK、很遗憾、我的 MCU 只有一个共用的 REFCLK 份额用于两个 MAC、因此我不得不放弃它。

    在我放弃之前、我在以下条件下对图7进行了长时间测试:

    PHY1和 PHY2均在 RMII 主模式下工作

    2.使用25MHz TCXO 馈入 PHY1的 X1

    3.将 PHY1 (上行端口)设置为 SYN_ATE_EN 使能模式

    4.设置 PHY2 (下行端口)在 SYN_ATE_EN 禁用模式下的工作

    5.设置 PHY1的 TX_CLK 输出25MHz 时钟并馈入 PHY2的 X1输入

    6.将 PHY2输出50MHz RMII 时钟设置为 MCU 的 REFCLK。

    除了 PHY1和 PHY2共用 PHY2的 RMII 50MHz 时钟外、上述时钟均来自图7。 经过长时间测试后、我发现 MAC + PHY1路径中的通信帧 CRC 错误问题经过多次上电测试。 很明显、PHY1的 RMII 接口 RX 信号与 PHY2的50MHz RMII 时钟相位不对齐。 这就是出现 CRC 错误问题的原因。  

    总之、由于我的 MCU 的局限性、使用图6时钟模式时、它可以在以太网通信方面正常工作、但遗憾的是、它无法在两个 PHY 之间提供精确的 PTP 时钟同步、使用图7时钟模式时、RMII REFCLK 相位未对齐问题不可避免地出现。  

    我是对的吗?

    或者您还有其他一些时钟建议吗?   

      

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好!

    感谢您尝试的实验的详细信息。  为了实现同步以太网、我们应坚持使用图7、因为在本例中、只有时钟是锁相的。

    在您使用图7进行的实验中:

     答:当您观察到 CRC 错误时,所有数据包或某些数据包中的这些错误是否已损坏?

    b.您观察到 CRC 错误的 PHY 是什么?

    c.您是否了解了数据和时钟之间的相位差?

    d. 您是否也看到 RX_ERR?

    此致、
    GET

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    >a. 当您观察到 CRC 错误时,所有数据包或某些数据包中的这些错误是否已损坏?
    部分数据包、而不是全部数据包。 但是、有时误差率非常高。

    >b. 您观察到了哪个 PHY 的 CRC 错误?
    不响应向 MAC 馈送 REFCLK 的 PHY 将是 CRC 错误。 没有 CRC 错误的另一个 MAC+PHY。

    >c. 您是否了解了数据和时钟之间的相位差?
    是的、每次打开系统电源时都会更改相位。
    我还尝试观察每个 PHY 的 RMII 时钟相位、对于 PHY1、我将 CLKOUT 设置为输出 RMII 时钟、对于 PHY2、我将 RX_CLK 设置为输出 RMII 时钟。 当我检查它们之间的相位时、我发现每次打开系统电源时它都会发生变化。 相位误差太大、无法忽略以满足 RMII 接口时序要求。

    >d. 您是否也看到 RX_ERR?
    否、RX_ERR 正常

    我可以确认、如果使用图7时钟图、每个 MAC+PHY 对的单独 REFCLK 非常重要。 但在我的情况下、我的 MCU 有两个 MAC 共享同一个 REFCLK。 因此、我无法使用图7、图6是我的唯一选择。

    在图7中、我可以实现 PHY1和 PHY2之间的亚纳秒精度、我同意您的观点、图7是亚纳秒应用的更好选择。

    但是、图6中绑定了我、我现在无法更改我的平台。

    我想尝试一下您在3月13日的回复中提到的"计划 B"。 我的想法是:
    1.设置图6时钟图
    2.让 PHY1从 CLKOUT 引脚输出125MHz PTP 时钟
    3.将 PHY2的 CLKOUT 引脚用作 PTP 时钟输入引脚。
    我认为 PHY1和 PHY2的 PTP 部分将在相同的时钟域中工作、在本例中、固定相位不同、它可能会实现亚纳秒的精度。

    我将向您报告我的结果。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    很抱歉,我犯了个错误。
    计划 B 仍有问题、即使 PHY1和 PHY2是同步的、但当 PHY2连接到其链路伙伴时、它们无法实现同步、因为 PHY2的以太网时钟和 PTP 时钟是分离的、并且没有相位对齐、因此 PHY2的链路伙伴无法与 PHY2的 PTP 时钟同步。
    尚无解决方案。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您需要找到使用图7的方法。 如果您需要进一步的帮助、请告诉我。

    此致、
    GET