请参阅 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);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////






