/** * * A New Announce Packet has been written to this device to transmit. We need to * decode it and rerun the Best Master Clock Algorithm (BMCA) * * @param InstancePtr is a pointer to the XAvb instance to be worked on * * @return None. But an updated True/False decision as to whether this device * should operate as a clock master or a slave is written into the * CurrentBmc data structure. * * @note None. * *****************************************************************************/ void XAvb_DecodeTxAnnounceFrame(XAvb * InstancePtr) { u32 NewMaster = 0; XAvb_BmcData TxAnnounceFrame; /** Read the attributes for the new Announce frame in the Tx PTP buffer */ XAvb_ReadAnnounceFrame(InstancePtr->Config.BaseAddress, (XAVB_PTP_TX_ANNOUNCE_OFFSET + 8), &TxAnnounceFrame); /** Compare the clock attributes between then new Announce frame and the * current master */ NewMaster = XAvb_BestMasterClockAlgorithm(&TxAnnounceFrame, &InstancePtr->CurrentBmc); if ((NewMaster == 1) | (InstancePtr->CurrentBmc.IAmTheRtcMaster == 1)) { /** Update records with the NEW best master */ XAvb_UpdateBmcRecords(&TxAnnounceFrame, &InstancePtr->CurrentBmc); #ifdef DEBUG_XAVB_LEVEL1 xil_printf("\r\nXAvb_DecodeTxAnnounceFrame()"); xil_printf("\r\n* BMC : I am the MASTER"); xil_printf("\r\n-----------------------"); xil_printf("\r\nLocal Announce Frame"); xil_printf("\r\n-----------------------"); xil_printf("\r\nGM ID upper %x", InstancePtr->CurrentBmc.GrandmasterIdentity.ClockIdentityUpper); xil_printf("\r\nGM ID lower %x", InstancePtr->CurrentBmc.GrandmasterIdentity.ClockIdentityLower); xil_printf("\r\nPriority1 %x", InstancePtr->CurrentBmc.GrandmasterPriority1); xil_printf("\r\nclockClass %x", InstancePtr->CurrentBmc.ClockQuality.clockClass); xil_printf("\r\nPriority2 %x", InstancePtr->CurrentBmc.GrandmasterPriority2); #endif /** Our new Tx Announce Packet has won - so this device must be the * master */ xil_printf("\r\n*** XAvb_DecodeTxAnnounceFrame() : Call XAvb_BecomeRtcMaster() *** \r\n"); XAvb_BecomeRtcMaster(InstancePtr,1); } }
/** * * The Interrupt subroutine for the "interruptPtpTimer" signal. This interrupt * fires reguarly on a 1/128 second period (based on the RTC). * * @param InstancePtr is a pointer to the XAvb instance to be worked on * * @return None. * * @note None. * *****************************************************************************/ void XAvb_PtpTimerInterruptHandler(XAvb * InstancePtr) { /** Clear Interrupt */ XAvb_WriteReg(InstancePtr->Config.BaseAddress, XAVB_RTC_CLEAR_INT_OFFSET, XAVB_RTC_CLEAR_INT_MASK); /** If PTP functions are marked as not running, then take no further action */ if (InstancePtr->PtpIsRunning == 1) { /** If the Link Partner is not AS capable, then take no further action */ if (InstancePtr->PeerASCapable == 1) { /** If a Master, then initiate Sync Frames and Announce frames at the * correct intervals */ if (InstancePtr->CurrentBmc.IAmTheRtcMaster == 1) { /** Master will initiate a Sync Frame when the SyncIntervalDuration * expires (SyncIntervalDuration is used to count/time the duration) * - unless a Signalling frame has told us not to send Sync Frames */ if ((InstancePtr->SignallingFrameData.SyncIntervalDuration != XAVB_PKT_TYPE_DISABLED) && (InstancePtr->PtpCounters.CounterSyncInterval >= (InstancePtr->SignallingFrameData.SyncIntervalDuration-1))) { XAvb_MasterSendSync(InstancePtr); InstancePtr->PtpCounters.CounterSyncInterval = 0; /** Following a Sync Frame, a Follow Up frame should always be sent */ XAvb_MasterSendFollowUp(InstancePtr); } else { InstancePtr->PtpCounters.CounterSyncInterval = InstancePtr->PtpCounters.CounterSyncInterval + 1; } /** Master will initiate an Announce Frame when the * AnnounceIntervalDuration expires (CounterAnnounceInterval is used * to count/time the duration) * - unless a Signalling frame has told us not to send Announce Frames */ if ((InstancePtr->SignallingFrameData.AnnounceIntervalDuration != XAVB_PKT_TYPE_DISABLED) && (InstancePtr->PtpCounters.CounterAnnounceInterval >= (InstancePtr->SignallingFrameData.AnnounceIntervalDuration-1))) { XAvb_MasterSendAnnounce(InstancePtr); InstancePtr->PtpCounters.CounterAnnounceInterval = 0; } else { InstancePtr->PtpCounters.CounterAnnounceInterval = InstancePtr->PtpCounters.CounterAnnounceInterval + 1; } /** If a Slave, monitor Announce/Sync Packet reception from the Master */ } else { /** Timeout for Announce Packet reception: XAVB_ANNOUNCE_RECEIPT_TIMEOUT * The AnnounceIntervalDuration is stored with the GrandMaster BMCA data * as it is captured from the last Announce frame that was received. */ if (InstancePtr->PtpCounters.CounterAnnounceInterval >= ((InstancePtr->CurrentBmc.AnnounceIntervalDuration-1) * XAVB_ANNOUNCE_RECEIPT_TIMEOUT) ) { #ifdef XAVB_DEBUG_LEVEL1 xil_printf("XAVB_ANNOUNCE_RECEIPT_TIMEOUT: Becoming GM! CounterAnnounceInterval = %d\r\n", InstancePtr->PtpCounters.CounterAnnounceInterval); #endif InstancePtr->PtpCounters.CounterAnnounceInterval = 0; /** No Announce received from GM for timeout interval: we become the master */ xil_printf("\r\n*** Announce timeout : Call XAvb_BecomeRtcMaster() *** \r\n"); XAvb_BecomeRtcMaster(InstancePtr,0); } else { InstancePtr->PtpCounters.CounterAnnounceInterval = InstancePtr->PtpCounters.CounterAnnounceInterval + 1; } /** Timeout for Sync Packet reception: XAVB_SYNC_RECEIPT_TIMEOUT * * The SyncIntervalDuration is stored with the Received Sync data * as it is captured from the last Sync frame that was received. */ if( InstancePtr->PtpCounters.CounterSyncInterval >= ((InstancePtr->latestMDSyncReceive.SyncIntervalDuration-1) * XAVB_SYNC_RECEIPT_TIMEOUT) ) { #ifdef XAVB_DEBUG_LEVEL1 xil_printf("\r\nXAVB_SYNC_RECEIPT_TIMEOUT: Becoming GM! CounterSyncInterval = %d\r\n", InstancePtr->PtpCounters.CounterSyncInterval); xil_printf("\r\nXAVB_SYNC_RECEIPT_TIMEOUT: SyncIntervalDuration = %d\r\n", InstancePtr->SignallingFrameData.SyncIntervalDuration); #endif InstancePtr->PtpCounters.CounterSyncInterval = 0; /** No Syncs received from GM for timeout interval: we become * the master */ xil_printf("\r\n*** Sync Timeout : Call XAvb_BecomeRtcMaster() *** \r\n"); XAvb_BecomeRtcMaster(InstancePtr,0); } else { InstancePtr->PtpCounters.CounterSyncInterval = InstancePtr->PtpCounters.CounterSyncInterval + 1; } } } /** Both Master and Slave will initiate a link delay measurement when the * LinkDelayIntervalDuration expires (LinkDelayIntervalDuration is used to * count/time the duration) * - unless a Signalling frame has told us not to send PdelayReq Frames */ if ((InstancePtr->SignallingFrameData.LinkDelayIntervalDuration != XAVB_PKT_TYPE_DISABLED) && (InstancePtr->PtpCounters.CounterLinkDelayInterval >= (InstancePtr->SignallingFrameData.LinkDelayIntervalDuration-1))) { /** Check to see if we've received PDelayResp and * PDelayRespFollowUp messages since the last PDelayReq was * sent */ if( InstancePtr->StateMachineData.rcvdPDelayResp && InstancePtr->StateMachineData.rcvdPDelayRespFollowUp ) { InstancePtr->StateMachineData.lostResponses = 0; } else { InstancePtr->StateMachineData.lostResponses++; } if( InstancePtr->StateMachineData.lostResponses >= XAVB_ALLOWED_LOST_RESPONSES ) { /** the peer is no longer ASCapable */ XAvb_ChangePeerASCapability(InstancePtr, 0); xil_printf("\r\n** XAvb_PtpTimerInterruptHandler(): The peer is no longer ASCapable **"); xil_printf("\r\n** XAvb_PtpTimerInterruptHandler(): StateMachineData.lostResponses >= %d **", XAVB_ALLOWED_LOST_RESPONSES); /** avoid potential overflow */ InstancePtr->StateMachineData.lostResponses = XAVB_ALLOWED_LOST_RESPONSES; } XAvb_SendPDelayReq(InstancePtr); InstancePtr->StateMachineData.rcvdPDelayResp = 0; InstancePtr->StateMachineData.rcvdPDelayRespFollowUp = 0; InstancePtr->PtpCounters.CounterLinkDelayInterval = 0; } else { InstancePtr->PtpCounters.CounterLinkDelayInterval = InstancePtr->PtpCounters.CounterLinkDelayInterval + 1; } } /** end of 'if (InstancePtr->PtpIsRunning == 1)' */ }
/** * * This function resets all of the AVB device driver functions to the start-up * (reset) defaults. * * @param InstancePtr is a pointer to the Xavb instance to be worked on. * * @return None. * * @note None. * ******************************************************************************/ void XAvb_Reset(XAvb * InstancePtr) { /** Assert bad arguments and conditions */ Xil_AssertVoid(InstancePtr != NULL); Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); /** * Perform a Software Reset of the AVB Core. * This will reset both the transmitter and receiver paths. * The RTC counter is not reset here. */ XAvb_WriteReg(InstancePtr->Config.BaseAddress, XAVB_SW_RESET_OFFSET, XAVB_SW_RESET_TX_AND_RX_PATHS); /** * Set IEEE specification default values in the device's data structure */ xil_printf("\r\n*** XAvb_Reset() : Call XAvb_BecomeRtcMaster() *** \r\n"); XAvb_BecomeRtcMaster(InstancePtr,0); XAvb_ChangePeerASCapability(InstancePtr, 0); InstancePtr->PtpIsRunning = 0; InstancePtr->PtpRecords.LinkDelay = 0; InstancePtr->SignallingFrameData.SyncIntervalDuration = XAvb_ConvertLogMeanToDuration(XAVB_DEFAULT_LOG_MEAN_SYNC_INTERVAL); InstancePtr->SignallingFrameData.LinkDelayIntervalDuration = XAvb_ConvertLogMeanToDuration(XAVB_DEFAULT_LOG_MEAN_PDELAY_REQ_INTERVAL); InstancePtr->SignallingFrameData.AnnounceIntervalDuration = XAvb_ConvertLogMeanToDuration(XAVB_DEFAULT_LOG_MEAN_ANNOUNCE_INTERVAL); InstancePtr->latestMDSyncReceive.SyncIntervalDuration = XAvb_ConvertLogMeanToDuration(XAVB_DEFAULT_LOG_MEAN_SYNC_INTERVAL); /** Update logMeanMessageInterval in the pre-loaded TX SYNC message buffer */ XAvb_UpdateLogMeanMessageInterval(InstancePtr->Config.BaseAddress, XAVB_PTP_TX_SYNC_OFFSET, InstancePtr->SignallingFrameData.SyncIntervalDuration); /** Update logMeanMessageInterval in the pre-loaded TX FOLLOW_UP message buffer */ XAvb_UpdateLogMeanMessageInterval(InstancePtr->Config.BaseAddress, XAVB_PTP_TX_FOLLOW_UP_OFFSET, InstancePtr->SignallingFrameData.SyncIntervalDuration); /** Update logMeanMessageInterval in the pre-loaded TX PDELAYREQ message buffer */ XAvb_UpdateLogMeanMessageInterval(InstancePtr->Config.BaseAddress, XAVB_PTP_TX_PDELAYREQ_OFFSET, InstancePtr->SignallingFrameData.LinkDelayIntervalDuration); /** Update logMeanMessageInterval in the pre-loaded TX ANNOUNCE message buffer */ XAvb_UpdateLogMeanMessageInterval(InstancePtr->Config.BaseAddress, XAVB_PTP_TX_ANNOUNCE_OFFSET, InstancePtr->SignallingFrameData.AnnounceIntervalDuration); /** * Initialise other driver variables in the device's data structure */ InstancePtr->PtpCounters.RxPtpHardPointer = 0; InstancePtr->PtpCounters.RxPtpSoftPointer = 0xFF; InstancePtr->PtpCounters.CounterSyncInterval = 0; InstancePtr->PtpCounters.CounterLinkDelayInterval = 0; InstancePtr->PtpCounters.CounterAnnounceInterval = 0; InstancePtr->PtpCounters.CounterSyncEvents = 0; InstancePtr->StateMachineData.lostResponses = 0; InstancePtr->StateMachineData.rcvdPDelayResp = 0; InstancePtr->StateMachineData.rcvdPDelayRespFollowUp = 0; #ifdef DEBUG_XAVB_LEVEL1 xil_printf("\r\n** XAvb_Reset(): PTP Driver Reset **"); #endif }