/**
*
* 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);

  }

}
Example #2
0
/**
*
* 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)' */

}
Example #3
0
/**
*
* 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
}