Beispiel #1
0
 def set_time_source(self, time_source):
     " Set a time source "
     assert time_source in self.get_time_sources()
     self._time_source = time_source
     self.mboard_regs_control.set_time_source(time_source, self.get_ref_clock_freq())
     if time_source == 'sfp0':
         # This error is specific to slave and master mode for White Rabbit.
         # Grand Master mode will require the external or gpsdo sources (not supported).
         if (time_source == 'sfp0' or time_source == 'sfp1') and \
           self.get_clock_source() != 'internal':
             error_msg = "Time source sfp(0|1) requires the internal clock source!"
             self.log.error(error_msg)
             raise RuntimeError(error_msg)
         if self.updateable_components['fpga']['type'] != 'WX':
             self.log.error("{} time source requires 'WX' FPGA type" \
                            .format(time_source))
             raise RuntimeError("{} time source requires 'WX' FPGA type" \
                            .format(time_source))
         # Only open UIO to the WR core once we're guaranteed it exists.
         wr_regs_control = WhiteRabbitRegsControl(
             self.wr_regs_label, self.log)
         # Wait for time source to become ready. Only applies to SFP0/1. All other
         # targets start their PPS immediately.
         self.log.debug("Waiting for {} timebase to lock..." \
                        .format(time_source))
         if not poll_with_timeout(
                 lambda: wr_regs_control.get_time_lock_status(),
                 40000, # Try for x ms... this number is set from a few benchtop tests
                 1000, # Poll every... second! why not?
             ):
             self.log.error("{} timebase failed to lock within 40 seconds. Status: 0x{:X}" \
                            .format(time_source, wr_regs_control.get_time_lock_status()))
             raise RuntimeError("Failed to lock SFP timebase.")
Beispiel #2
0
    def set_sync_source(self, args):
        """
        Selects reference clock and PPS sources. Unconditionally re-applies the time
        source to ensure continuity between the reference clock and time rates.
        """

        clock_source = args.get('clock_source', self._clock_source)
        assert clock_source in self.get_clock_sources()
        time_source = args.get('time_source', self._time_source)
        assert time_source in self.get_time_sources()
        if (clock_source == self._clock_source) and (time_source
                                                     == self._time_source):
            # Nothing change no need to do anything
            self.log.trace("New sync source assignment matches"
                           "previous assignment. Ignoring update command.")
            return
        assert (clock_source, time_source) in self.valid_sync_sources
        # Start setting sync source
        self.log.debug("Setting clock source to `{}'".format(clock_source))
        # Place the DB clocks in a safe state to allow reference clock
        # transitions. This leaves all the DB clocks OFF.
        for slot, dboard in enumerate(self.dboards):
            if hasattr(dboard, 'set_clk_safe_state'):
                self.log.trace(
                    "Setting dboard %d components to safe clocking state...",
                    slot)
                dboard.set_clk_safe_state()
        # Disable the Ref Clock in the FPGA before throwing the external switches.
        self.mboard_regs_control.enable_ref_clk(False)
        # Set the external switches to bring in the new source.
        if clock_source == 'internal':
            self._gpios.set("CLK-MAINSEL-EX_B")
            self._gpios.set("CLK-MAINSEL-25MHz")
            self._gpios.reset("CLK-MAINSEL-GPS")
        elif clock_source == 'gpsdo':
            self._gpios.set("CLK-MAINSEL-EX_B")
            self._gpios.reset("CLK-MAINSEL-25MHz")
            self._gpios.set("CLK-MAINSEL-GPS")
        else:  # external
            self._gpios.reset("CLK-MAINSEL-EX_B")
            self._gpios.reset("CLK-MAINSEL-GPS")
            # SKY13350 needs to be in known state
            self._gpios.set("CLK-MAINSEL-25MHz")
        self._clock_source = clock_source
        self.log.debug("Reference clock source is: {}" \
                       .format(self._clock_source))
        self.log.debug("Reference clock frequency is: {} MHz" \
                       .format(self.get_ref_clock_freq()/1e6))
        # Enable the Ref Clock in the FPGA after giving it a chance to
        # settle. The settling time is a guess.
        time.sleep(0.100)
        self.mboard_regs_control.enable_ref_clk(True)
        self.log.debug("Setting time source to `{}'".format(time_source))
        self._time_source = time_source
        ref_clk_freq = self.get_ref_clock_freq()
        self.mboard_regs_control.set_time_source(time_source, ref_clk_freq)
        if time_source == 'sfp0':
            # This error is specific to slave and master mode for White Rabbit.
            # Grand Master mode will require the external or gpsdo
            # sources (not supported).
            if time_source in ('sfp0', 'sfp1') \
                    and self.get_clock_source() != 'internal':
                error_msg = "Time source {} requires `internal` clock source!".format(
                    time_source)
                self.log.error(error_msg)
                raise RuntimeError(error_msg)
            sfp_time_source_images = ('WX', )
            if self.updateable_components['fpga'][
                    'type'] not in sfp_time_source_images:
                self.log.error("{} time source requires FPGA types {}" \
                               .format(time_source, sfp_time_source_images))
                raise RuntimeError("{} time source requires FPGA types {}" \
                               .format(time_source, sfp_time_source_images))
            # Only open UIO to the WR core once we're guaranteed it exists.
            wr_regs_control = WhiteRabbitRegsControl(self.wr_regs_label,
                                                     self.log)
            # Wait for time source to become ready. Only applies to SFP0/1. All other
            # targets start their PPS immediately.
            self.log.debug("Waiting for {} timebase to lock..." \
                           .format(time_source))
            if not poll_with_timeout(
                    lambda: wr_regs_control.get_time_lock_status(),
                    40000,  # Try for x ms... this number is set from a few benchtop tests
                    1000,  # Poll every... second! why not?
            ):
                self.log.error("{} timebase failed to lock within 40 seconds. Status: 0x{:X}" \
                               .format(time_source, wr_regs_control.get_time_lock_status()))
                raise RuntimeError("Failed to lock SFP timebase.")
        # Update the DB with the correct Ref Clock frequency and force a re-init.
        for slot, dboard in enumerate(self.dboards):
            self.log.trace(
                "Updating reference clock on dboard %d to %f MHz...", slot,
                ref_clk_freq / 1e6)
            dboard.update_ref_clock_freq(ref_clk_freq,
                                         time_source=time_source,
                                         clock_source=clock_source,
                                         skip_rfic=args.get('skip_rfic', None))
Beispiel #3
0
    def set_sync_source(self, args):
        """
        Selects reference clock and PPS sources. Unconditionally re-applies the time
        source to ensure continuity between the reference clock and time rates.
        """

        clock_source = args.get('clock_source', self._clock_source)
        assert clock_source in self.get_clock_sources()
        time_source = args.get('time_source', self._time_source)
        assert time_source in self.get_time_sources()
        if (clock_source == self._clock_source) and (time_source == self._time_source):
            # Nothing change no need to do anything
            self.log.trace("New sync source assignment matches"
                           "previous assignment. Ignoring update command.")
            return
        assert (clock_source, time_source) in self.valid_sync_sources
        # Start setting sync source
        self.log.debug("Setting clock source to `{}'".format(clock_source))
        # Place the DB clocks in a safe state to allow reference clock
        # transitions. This leaves all the DB clocks OFF.
        for slot, dboard in enumerate(self.dboards):
            if hasattr(dboard, 'set_clk_safe_state'):
                self.log.trace(
                    "Setting dboard %d components to safe clocking state...", slot)
                dboard.set_clk_safe_state()
        # Disable the Ref Clock in the FPGA before throwing the external switches.
        self.mboard_regs_control.enable_ref_clk(False)
        # Set the external switches to bring in the new source.
        if clock_source == 'internal':
            self._gpios.set("CLK-MAINSEL-EX_B")
            self._gpios.set("CLK-MAINSEL-25MHz")
            self._gpios.reset("CLK-MAINSEL-GPS")
        elif clock_source == 'gpsdo':
            self._gpios.set("CLK-MAINSEL-EX_B")
            self._gpios.reset("CLK-MAINSEL-25MHz")
            self._gpios.set("CLK-MAINSEL-GPS")
        else: # external
            self._gpios.reset("CLK-MAINSEL-EX_B")
            self._gpios.reset("CLK-MAINSEL-GPS")
            # SKY13350 needs to be in known state
            self._gpios.set("CLK-MAINSEL-25MHz")
        self._clock_source = clock_source
        self.log.debug("Reference clock source is: {}" \
                       .format(self._clock_source))
        self.log.debug("Reference clock frequency is: {} MHz" \
                       .format(self.get_ref_clock_freq()/1e6))
        # Enable the Ref Clock in the FPGA after giving it a chance to
        # settle. The settling time is a guess.
        time.sleep(0.100)
        self.mboard_regs_control.enable_ref_clk(True)
        self.log.debug("Setting time source to `{}'".format(time_source))
        self._time_source = time_source
        ref_clk_freq = self.get_ref_clock_freq()
        self.mboard_regs_control.set_time_source(time_source, ref_clk_freq)
        if time_source == 'sfp0':
            # This error is specific to slave and master mode for White Rabbit.
            # Grand Master mode will require the external or gpsdo
            # sources (not supported).
            if time_source in ('sfp0', 'sfp1') \
                    and self.get_clock_source() != 'internal':
                error_msg = "Time source {} requires `internal` clock source!".format(
                    time_source)
                self.log.error(error_msg)
                raise RuntimeError(error_msg)
            sfp_time_source_images = ('WX',)
            if self.updateable_components['fpga']['type'] not in sfp_time_source_images:
                self.log.error("{} time source requires FPGA types {}" \
                               .format(time_source, sfp_time_source_images))
                raise RuntimeError("{} time source requires FPGA types {}" \
                               .format(time_source, sfp_time_source_images))
            # Only open UIO to the WR core once we're guaranteed it exists.
            wr_regs_control = WhiteRabbitRegsControl(
                self.wr_regs_label, self.log)
            # Wait for time source to become ready. Only applies to SFP0/1. All other
            # targets start their PPS immediately.
            self.log.debug("Waiting for {} timebase to lock..." \
                           .format(time_source))
            if not poll_with_timeout(
                    lambda: wr_regs_control.get_time_lock_status(),
                    40000, # Try for x ms... this number is set from a few benchtop tests
                    1000, # Poll every... second! why not?
                ):
                self.log.error("{} timebase failed to lock within 40 seconds. Status: 0x{:X}" \
                               .format(time_source, wr_regs_control.get_time_lock_status()))
                raise RuntimeError("Failed to lock SFP timebase.")
        # Update the DB with the correct Ref Clock frequency and force a re-init.
        for slot, dboard in enumerate(self.dboards):
            self.log.trace(
                "Updating reference clock on dboard %d to %f MHz...",
                slot, ref_clk_freq/1e6
            )
            dboard.update_ref_clock_freq(
                ref_clk_freq,
                time_source=time_source,
                clock_source=clock_source,
                skip_rfic=args.get('skip_rfic', None)
            )