diff options
| -rw-r--r-- | mpm/python/usrp_mpm/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | mpm/python/usrp_mpm/components.py | 99 | ||||
| -rw-r--r-- | mpm/python/usrp_mpm/periph_manager/base.py | 3 | ||||
| -rw-r--r-- | mpm/python/usrp_mpm/periph_manager/n3xx.py | 75 | 
4 files changed, 105 insertions, 73 deletions
diff --git a/mpm/python/usrp_mpm/CMakeLists.txt b/mpm/python/usrp_mpm/CMakeLists.txt index a3585cc6b..8d2af75ce 100644 --- a/mpm/python/usrp_mpm/CMakeLists.txt +++ b/mpm/python/usrp_mpm/CMakeLists.txt @@ -12,6 +12,7 @@ SET(USRP_MPM_TOP_FILES      ${CMAKE_CURRENT_SOURCE_DIR}/__init__.py      ${CMAKE_CURRENT_SOURCE_DIR}/aurora_control.py      ${CMAKE_CURRENT_SOURCE_DIR}/bfrfs.py +    ${CMAKE_CURRENT_SOURCE_DIR}/components.py      ${CMAKE_CURRENT_SOURCE_DIR}/discovery.py      ${CMAKE_CURRENT_SOURCE_DIR}/eeprom.py      ${CMAKE_CURRENT_SOURCE_DIR}/ethtable.py diff --git a/mpm/python/usrp_mpm/components.py b/mpm/python/usrp_mpm/components.py new file mode 100644 index 000000000..5d1a31325 --- /dev/null +++ b/mpm/python/usrp_mpm/components.py @@ -0,0 +1,99 @@ +# +# Copyright 2018 Ettus Research, a National Instruments Company +# +# SPDX-License-Identifier: GPL-3.0-or-later +# +""" +MPM Component management +""" +import os +import shutil +import subprocess +from usrp_mpm.rpc_server import no_rpc + + +class ZynqComponents(object): +    """ +    Mixin class that update Zynq FPGA and devicetree components. + +    Note: this assumes that the class that you are mixing ZynqComponents into +    initializes `updateable_components`, `device_info`, and `log`. +    """ +    # Declare required members here +    updateable_components = {} +    device_info = {} +    # Note: the logger is created by derived class (the class we are mixing +    #       into), so all logs in the ZynqComponents class will be under the +    #       derived class's category. +    log = None + +    ########################################################################### +    # Component updating +    ########################################################################### +    @no_rpc +    def update_fpga(self, filepath, metadata): +        """ +        Update the FPGA image in the filesystem and reload the overlay +        :param filepath: path to new FPGA image +        :param metadata: Dictionary of strings containing metadata +        """ +        self.log.trace("Updating FPGA with image at {} (metadata: `{}')" +                       .format(filepath, str(metadata))) +        _, file_extension = os.path.splitext(filepath) +        # Cut off the period from the file extension +        file_extension = file_extension[1:].lower() +        binfile_path = self.updateable_components['fpga']['path'].format( +            self.device_info.get('product')) +        if file_extension == "bit": +            self.log.trace("Converting bit to bin file and writing to {}" +                           .format(binfile_path)) +            from usrp_mpm.fpga_bit_to_bin import fpga_bit_to_bin +            fpga_bit_to_bin(filepath, binfile_path, flip=True) +        elif file_extension == "bin": +            self.log.trace("Copying bin file to %s", binfile_path) +            shutil.copy(filepath, binfile_path) +        else: +            self.log.error("Invalid FPGA bitfile: %s", filepath) +            raise RuntimeError("Invalid N3xx FPGA bitfile") +        # RPC server will reload the periph manager after this. +        return True + +    @no_rpc +    def update_dts(self, filepath, metadata): +        """ +        Update the DTS image in the filesystem +        :param filepath: path to new DTS image +        :param metadata: Dictionary of strings containing metadata +        """ +        dtsfile_path = self.updateable_components['dts']['path'].format( +            self.device_info.get('product')) +        self.log.trace("Updating DTS with image at %s to %s (metadata: %s)", +                       filepath, dtsfile_path, str(metadata)) +        shutil.copy(filepath, dtsfile_path) +        dtbofile_path = self.updateable_components['dts']['output'].format( +            self.device_info.get('product')) +        self.log.trace("Compiling to %s...", dtbofile_path) +        dtc_command = [ +            'dtc', +            '--symbols', +            '-O', 'dtb', +            '-q',  # Suppress warnings +            '-o', +            dtbofile_path, +            dtsfile_path, +        ] +        self.log.trace("Executing command: `$ %s'", " ".join(dtc_command)) +        try: +            out = subprocess.check_output(dtc_command) +            if out.strip() != "": +                # Keep this as debug because dtc is an external tool and +                # something could go wrong with it that's outside of our control +                self.log.debug("`dtc' command output: \n%s", out) +        except OSError: +            self.log.error("Could not execute `dtc' command. Binary probably " +                           "not installed. Please compile DTS by hand.") +            # No fatal error here, in order not to break the current workflow +        except subprocess.CalledProcessError as ex: +            self.log.error("Error executing `dtc': %s", str(ex)) +            return False +        return True diff --git a/mpm/python/usrp_mpm/periph_manager/base.py b/mpm/python/usrp_mpm/periph_manager/base.py index f920c9387..5eedb27e7 100644 --- a/mpm/python/usrp_mpm/periph_manager/base.py +++ b/mpm/python/usrp_mpm/periph_manager/base.py @@ -1,5 +1,5 @@  # -# Copyright 2017 Ettus Research, a National Instruments Company +# Copyright 2017-2018 Ettus Research, a National Instruments Company  #  # SPDX-License-Identifier: GPL-3.0-or-later  # @@ -205,6 +205,7 @@ class PeriphManagerBase(object):              self.log.error("Failed to initialize device: %s", str(ex))              self._device_initialized = False              self._initialization_status = str(ex) +        super(PeriphManagerBase, self).__init__()      def _read_mboard_eeprom(self):          """ diff --git a/mpm/python/usrp_mpm/periph_manager/n3xx.py b/mpm/python/usrp_mpm/periph_manager/n3xx.py index be21dd0b4..707668a47 100644 --- a/mpm/python/usrp_mpm/periph_manager/n3xx.py +++ b/mpm/python/usrp_mpm/periph_manager/n3xx.py @@ -8,16 +8,14 @@ N3xx implementation module  """  from __future__ import print_function -import os  import copy -import shutil -import subprocess  import json  import datetime  import re  import threading  from six import iteritems, itervalues  from usrp_mpm.cores import WhiteRabbitRegsControl +from usrp_mpm.components import ZynqComponents  from usrp_mpm.gpsd_iface import GPSDIfaceExtension  from usrp_mpm.periph_manager import PeriphManagerBase  from usrp_mpm.mpmtypes import SID @@ -87,7 +85,7 @@ class N3xxXportMgrLiberio(XportMgrLiberio):  ###############################################################################  # Main Class  ############################################################################### -class n3xx(PeriphManagerBase): +class n3xx(ZynqComponents, PeriphManagerBase):      """      Holds N3xx specific attributes and methods      """ @@ -888,34 +886,7 @@ class n3xx(PeriphManagerBase):      ###########################################################################      # Component updating      ########################################################################### -    @no_rpc -    def update_fpga(self, filepath, metadata): -        """ -        Update the FPGA image in the filesystem and reload the overlay -        :param filepath: path to new FPGA image -        :param metadata: Dictionary of strings containing metadata -        """ -        self.log.trace("Updating FPGA with image at {} (metadata: `{}')" -                       .format(filepath, str(metadata))) -        _, file_extension = os.path.splitext(filepath) -        # Cut off the period from the file extension -        file_extension = file_extension[1:].lower() -        binfile_path = self.updateable_components['fpga']['path'].format( -            self.device_info['product']) -        if file_extension == "bit": -            self.log.trace("Converting bit to bin file and writing to {}" -                           .format(binfile_path)) -            from usrp_mpm.fpga_bit_to_bin import fpga_bit_to_bin -            fpga_bit_to_bin(filepath, binfile_path, flip=True) -        elif file_extension == "bin": -            self.log.trace("Copying bin file to %s", binfile_path) -            shutil.copy(filepath, binfile_path) -        else: -            self.log.error("Invalid FPGA bitfile: %s", filepath) -            raise RuntimeError("Invalid N3xx FPGA bitfile") -        # RPC server will reload the periph manager after this. -        return True - +    # Note: Component updating functions defined by ZynqComponents      @no_rpc      def _update_fpga_type(self):          """Update the fpga type stored in the updateable components""" @@ -923,46 +894,6 @@ class n3xx(PeriphManagerBase):          self.log.debug("Updating mboard FPGA type info to {}".format(fpga_type))          self.updateable_components['fpga']['type'] = fpga_type -    @no_rpc -    def update_dts(self, filepath, metadata): -        """ -        Update the DTS image in the filesystem -        :param filepath: path to new DTS image -        :param metadata: Dictionary of strings containing metadata -        """ -        dtsfile_path = self.updateable_components['dts']['path'].format( -            self.device_info['product']) -        self.log.trace("Updating DTS with image at %s to %s (metadata: %s)", -                       filepath, dtsfile_path, str(metadata)) -        shutil.copy(filepath, dtsfile_path) -        dtbofile_path = self.updateable_components['dts']['output'].format( -            self.device_info['product']) -        self.log.trace("Compiling to %s...", dtbofile_path) -        dtc_command = [ -            'dtc', -            '--symbols', -            '-O', 'dtb', -            '-q', # Suppress warnings -            '-o', -            dtbofile_path, -            dtsfile_path, -        ] -        self.log.trace("Executing command: `$ %s'", " ".join(dtc_command)) -        try: -            out = subprocess.check_output(dtc_command) -            if out.strip() != "": -                # Keep this as debug because dtc is an external tool and -                # something could go wrong with it that's outside of our control -                self.log.debug("`dtc' command output: \n%s", out) -        except OSError as ex: -            self.log.error("Could not execute `dtc' command. Binary probably "\ -                           "not installed. Please compile DTS by hand.") -            # No fatal error here, in order not to break the current workflow -        except subprocess.CalledProcessError as ex: -            self.log.error("Error executing `dtc': %s", str(ex)) -            return False -        return True -      #######################################################################      # Claimer API      #######################################################################  | 
