diff options
Diffstat (limited to 'mpm/python')
-rw-r--r-- | mpm/python/usrp_mpm/dboard_manager/e31x_db.py | 58 | ||||
-rw-r--r-- | mpm/python/usrp_mpm/periph_manager/base.py | 40 | ||||
-rw-r--r-- | mpm/python/usrp_mpm/periph_manager/e31x.py | 98 | ||||
-rw-r--r-- | mpm/python/usrp_mpm/periph_manager/e320.py | 14 | ||||
-rw-r--r-- | mpm/python/usrp_mpm/rpc_server.py | 6 |
5 files changed, 115 insertions, 101 deletions
diff --git a/mpm/python/usrp_mpm/dboard_manager/e31x_db.py b/mpm/python/usrp_mpm/dboard_manager/e31x_db.py index 358b69f88..add77553f 100644 --- a/mpm/python/usrp_mpm/dboard_manager/e31x_db.py +++ b/mpm/python/usrp_mpm/dboard_manager/e31x_db.py @@ -1,5 +1,6 @@ # # Copyright 2018 Ettus Research, a National Instruments Company +# Copyright 2019 Ettus Research, a National Instruments Brand # # SPDX-License-Identifier: GPL-3.0-or-later # @@ -7,21 +8,19 @@ E310 dboard (RF and control) implementation module """ -import threading -import time -from six import iterkeys, iteritems from usrp_mpm import lib # Pulls in everything from C++-land -from usrp_mpm.bfrfs import BufferFS from usrp_mpm.dboard_manager import DboardManagerBase from usrp_mpm.mpmlog import get_logger -from usrp_mpm.sys_utils.udev import get_eeprom_paths -from usrp_mpm.sys_utils.uio import UIO from usrp_mpm.periph_manager.e31x_periphs import MboardRegsControl from usrp_mpm.mpmutils import async_exec ############################################################################### # Main dboard control class ############################################################################### +DEFAULT_MASTER_CLOCK_RATE = 16E6 +MIN_MASTER_CLK_RATE = 220E3 +MAX_MASTER_CLK_RATE = 61.44E6 + class E31x_db(DboardManagerBase): """ Holds all dboard specific information and methods of the E31x_db dboard @@ -41,12 +40,10 @@ class E31x_db(DboardManagerBase): 'ad9361_temperature': 'get_catalina_temp_sensor', } # Maps the chipselects to the corresponding devices: - spi_chipselect = {"catalina": 0, - } - - default_master_clock_rate = 16e6 - MIN_MASTER_CLK_RATE = 220e3 - MAX_MASTER_CLK_RATE = 61.44e6 + spi_chipselect = {"catalina": 0} + ### End of overridables ################################################# + # MB regs label: Needed to access the lock bit + mboard_regs_label = "mboard-regs" def __init__(self, slot_idx, **kwargs): super(E31x_db, self).__init__(slot_idx, **kwargs) @@ -67,9 +64,8 @@ class E31x_db(DboardManagerBase): try: self._init_periphs() self._periphs_initialized = True - except Exception as ex: - self.log.error("Failed to initialize peripherals: %s", - str(ex)) + except BaseException as ex: + self.log.error("Failed to initialize peripherals: %s", str(ex)) self._periphs_initialized = False def _init_periphs(self): @@ -106,14 +102,17 @@ class E31x_db(DboardManagerBase): setattr(self, method, export_method(cat, method)) def init(self, args): + """ + Initialize RF. Remember that we might have to do this from scratch every + time because of the FPGA reload. + """ if not self._periphs_initialized: error_msg = "Cannot run init(), peripherals are not initialized!" self.log.error(error_msg) raise RuntimeError(error_msg) master_clock_rate = \ - float(args.get('master_clock_rate', - self.default_master_clock_rate)) - assert self.MIN_MASTER_CLK_RATE <= master_clock_rate <= self.MAX_MASTER_CLK_RATE, \ + float(args.get('master_clock_rate', DEFAULT_MASTER_CLOCK_RATE)) + assert MIN_MASTER_CLK_RATE <= master_clock_rate <= MAX_MASTER_CLK_RATE, \ "Invalid master clock rate: {:.02f} MHz".format( master_clock_rate / 1e6) master_clock_rate_changed = master_clock_rate != self.master_clock_rate @@ -125,7 +124,6 @@ class E31x_db(DboardManagerBase): # Some default chains on -- needed for setup purposes self.catalina.set_active_chains(True, False, True, False) self.set_catalina_clock_rate(self.master_clock_rate) - return True def get_master_clock_rate(self): @@ -140,16 +138,15 @@ class E31x_db(DboardManagerBase): Return LO lock status (Boolean!) of AD9361. 'which' must be either 'tx' or 'rx' """ - self.mboard_regs_label = "mboard-regs" - self.mboard_regs_control = MboardRegsControl( - self.mboard_regs_label, self.log) + mboard_regs_control = \ + MboardRegsControl(self.mboard_regs_label, self.log) if which == "tx": - locked = self. mboard_regs_control.get_ad9361_tx_lo_lock() + return mboard_regs_control.get_ad9361_tx_lo_lock() elif which == "rx": - locked = self. mboard_regs_control.get_ad9361_rx_lo_lock() - else: - locked = False - return locked + return mboard_regs_control.get_ad9361_rx_lo_lock() + self.log.warning("get_ad9361_lo_lock(): Invalid which param `{}'" + .format(which)) + return False def get_lo_lock_sensor(self, which): """ @@ -160,8 +157,8 @@ class E31x_db(DboardManagerBase): return { 'name': 'ad9361_lock', 'type': 'BOOLEAN', - 'unit': 'locked' if lo_locked else 'unlocked', - 'value': str(lo_locked).lower(), + 'unit': 'locked' if lo_locked else 'unlocked', + 'value': str(lo_locked).lower(), } def get_catalina_temp_sensor(self, _): @@ -185,7 +182,8 @@ class E31x_db(DboardManagerBase): def get_rssi_sensor(self, chan): """ - Return a sensor dictionary containing the current RSSI of `which` chain in Catalina + Return a sensor dictionary containing the current RSSI of `which` chain + in the RFIC """ which = 'RX' + str(chan+1) return { diff --git a/mpm/python/usrp_mpm/periph_manager/base.py b/mpm/python/usrp_mpm/periph_manager/base.py index 3cfab6c79..6d363fd89 100644 --- a/mpm/python/usrp_mpm/periph_manager/base.py +++ b/mpm/python/usrp_mpm/periph_manager/base.py @@ -1,5 +1,6 @@ # # Copyright 2017-2018 Ettus Research, a National Instruments Company +# Copyright 2019 Ettus Research, a National Instruments Brand # # SPDX-License-Identifier: GPL-3.0-or-later # @@ -40,6 +41,12 @@ def get_dboard_class_from_pid(pid): return None +# We need to disable the no-self-use check, because we might require self to +# become an RPC method, but PyLint doesnt' know that. We'll also disable +# warnings about this being a god class. +# pylint: disable=no-self-use +# pylint: disable=too-many-public-methods +# pylint: disable=too-many-instance-attributes class PeriphManagerBase(object): """" Base class for all motherboards. Common function and API calls should @@ -136,8 +143,11 @@ class PeriphManagerBase(object): # to RPC methods caused by removal of overlay on unclaim() by peripheral # manager. Additionally the RPC server will re-register all methods on # a claim(). Override and set to True in the derived class if desired. - clear_rpc_method_registry_on_unclaim = False + clear_rpc_registry_on_unclaim = False + # Disable checks for unused args in the overridables, because the default + # implementations don't need to use them. + # pylint: disable=unused-argument @staticmethod def generate_device_info(eeprom_md, mboard_info, dboard_infos): """ @@ -150,8 +160,8 @@ class PeriphManagerBase(object): try: from usrp_mpm import __version__, __githash__ version_string = __version__ - if len(__githash__): - version_string += "-g" + __githash__ + if __githash__: + version_string += "-g" + str(__githash__) except ImportError: version_string = "" mboard_info["mpm_version"] = version_string @@ -169,6 +179,7 @@ class PeriphManagerBase(object): device_args -- Arbitrary dictionary of info, typically user-defined """ return [] + # pylint: enable=unused-argument ### End of overridables ################################################### @@ -199,7 +210,7 @@ class PeriphManagerBase(object): self.mboard_info, self.dboard_infos ) - except Exception as ex: + except BaseException as ex: self.log.error("Failed to initialize device: %s", str(ex)) self._device_initialized = False self._initialization_status = str(ex) @@ -291,8 +302,7 @@ class PeriphManagerBase(object): "Found invalid PID in EEPROM: 0x{:04X}. " \ "Valid PIDs are: {}".format( eeprom_head['pid'], - ", ".join(["0x{:04X}".format(x) - for x in self.pids.keys()]), + ", ".join(["0x{:04X}".format(x) for x in self.pids]), ) ) raise RuntimeError("Invalid PID found in EEPROM.") @@ -389,8 +399,8 @@ class PeriphManagerBase(object): if periph_section_name is not None: prefs_cache.read_dict({periph_section_name: default_args}) return dict(prefs_cache[periph_section_name]) - else: - return default_args + # else: + return default_args def _init_mboard_overlays(self): """ @@ -421,7 +431,7 @@ class PeriphManagerBase(object): self.log.warning("Overriding daughterboard PIDs with: {}" .format(",".join(override_dboard_pids))) assert len(dboard_infos) <= self.max_num_dboards - if len(override_dboard_pids) and \ + if override_dboard_pids and \ len(override_dboard_pids) < len(dboard_infos): self.log.warning("--override-db-pids is going to skip dboards.") dboard_infos = dboard_infos[:len(override_dboard_pids)] @@ -476,7 +486,7 @@ class PeriphManagerBase(object): self.log.error( "Cannot run init(), device was never fully initialized!") return False - if len(self.dboards) == 0: + if not self.dboards: return True if args.get("serialize_init", False): self.log.debug("Initializing dboards serially...") @@ -515,7 +525,7 @@ class PeriphManagerBase(object): self.log.trace("Teardown called for Peripheral Manager base.") ########################################################################### - # RFNoC and Device info + # RFNoC & Device Info ########################################################################### def set_device_id(self, device_id): """ @@ -655,8 +665,6 @@ class PeriphManagerBase(object): # We need a 'metadata' and a 'data' for each file we want to update assert (len(metadata_l) == len(data_l)),\ "update_component arguments must be the same length" - # TODO: Update the manifest file - # Iterate through the components, updating each in turn for metadata, data in zip(metadata_l, data_l): id_str = metadata['id'] @@ -692,8 +700,8 @@ class PeriphManagerBase(object): self.log.trace("Creating directory {}".format(basepath)) os.makedirs(basepath) self.log.trace("Writing data to {}".format(filepath)) - with open(filepath, 'wb') as f: - f.write(data) + with open(filepath, 'wb') as comp_file: + comp_file.write(data) update_func = \ getattr(self, self.updateable_components[id_str]['callback']) self.log.info("Updating component `%s'", id_str) @@ -777,7 +785,6 @@ class PeriphManagerBase(object): self.log.warn("Called set_mb_eeprom(), but not implemented!") self.log.debug("Skipping writing EEPROM keys: {}" .format(list(eeprom_vals.keys()))) - raise NotImplementedError def get_db_eeprom(self, dboard_idx): """ @@ -807,7 +814,6 @@ class PeriphManagerBase(object): "is not implemented.", dboard_idx) self.log.debug("Skipping writing EEPROM keys: {}" .format(list(eeprom_data.keys()))) - raise NotImplementedError ####################################################################### # Transport API diff --git a/mpm/python/usrp_mpm/periph_manager/e31x.py b/mpm/python/usrp_mpm/periph_manager/e31x.py index 8ba8ff034..fb0624117 100644 --- a/mpm/python/usrp_mpm/periph_manager/e31x.py +++ b/mpm/python/usrp_mpm/periph_manager/e31x.py @@ -1,5 +1,6 @@ # # Copyright 2018-2019 Ettus Research, a National Instruments Company +# Copyright 2019 Ettus Research, a National Instruments Brand # # SPDX-License-Identifier: GPL-3.0-or-later # @@ -8,11 +9,8 @@ E310 implementation module """ from __future__ import print_function -import bisect import copy -import re -import threading -from six import iteritems, itervalues +from six import itervalues from usrp_mpm.components import ZynqComponents from usrp_mpm.dboard_manager import E31x_db from usrp_mpm.mpmtypes import SID @@ -30,20 +28,24 @@ from usrp_mpm import e31x_legacy_eeprom E310_DEFAULT_CLOCK_SOURCE = 'internal' E310_DEFAULT_TIME_SOURCE = 'internal' E310_DEFAULT_ENABLE_FPGPIO = True -E310_FPGA_COMPAT = (5,0) +E310_FPGA_COMPAT = (5, 0) E310_DBOARD_SLOT_IDX = 0 ############################################################################### # Transport managers ############################################################################### - +# pylint: disable=too-few-public-methods class E310XportMgrLiberio(XportMgrLiberio): " E310-specific Liberio configuration " max_chan = 5 +# pylint: enable=too-few-public-methods ############################################################################### # Main Class ############################################################################### +# We need to disable the no-self-use check, because we might require self to +# become an RPC method, but PyLint doesnt' know that. +# pylint: disable=no-self-use class e31x(ZynqComponents, PeriphManagerBase): """ Holds E310 specific attributes and methods @@ -101,7 +103,7 @@ class e31x(ZynqComponents, PeriphManagerBase): # in stale references to methods in the RPC server. Setting # this to True ensures that the RPC server clears all registered # methods on unclaim() and registers them on the following claim(). - clear_rpc_method_registry_on_unclaim = True + clear_rpc_registry_on_unclaim = True @classmethod def generate_device_info(cls, eeprom_md, mboard_info, dboard_infos): @@ -145,6 +147,15 @@ class e31x(ZynqComponents, PeriphManagerBase): """ Does partial initialization which loads low power idle image """ + self._do_not_reload = False + self._tear_down = False + self._clock_source = None + self._time_source = None + self.dboards = [] + self.dboard = None + self.mboard_regs_control = None + self._xport_mgrs = {} + self._initialization_status = "" super(e31x, self).__init__() # Start clean by removing MPM-owned overlays. active_overlays = self.list_active_overlays() @@ -160,7 +171,9 @@ class e31x(ZynqComponents, PeriphManagerBase): def _init_normal(self): """ - Does full initialization + Does full initialization. This gets called during claim(), because the + E310 usually gets freshly initialized on every UHD session for power + usage reasons. """ if self._device_initialized: return @@ -179,7 +192,7 @@ class e31x(ZynqComponents, PeriphManagerBase): self.dboard = self.dboards[E310_DBOARD_SLOT_IDX] try: self._init_peripherals(self.args_cached) - except Exception as ex: + except BaseException as ex: self.log.error("Failed to initialize motherboard: %s", str(ex)) self._initialization_status = str(ex) self._device_initialized = False @@ -193,32 +206,20 @@ class e31x(ZynqComponents, PeriphManagerBase): override_dboard_pids -- List of dboard PIDs to force default_args -- Default args """ - # Override the base class's implementation in order to avoid initializing our one "dboard" - # in the same way that, for example, N310's dboards are initialized. Specifically, - # - skip dboard EEPROM setup (we don't have one) - # - change the way we handle SPI devices + # Overriding DB PIDs doesn't work here, the DB is coupled to the MB if override_dboard_pids: - self.log.warning("Overriding daughterboard PIDs with: {}" - .format(override_dboard_pids)) raise NotImplementedError("Can't override dboard pids") # We have only one dboard dboard_info = dboard_infos[0] # Set up the SPI nodes - spi_nodes = [] - for spi_addr in self.dboard_spimaster_addrs: - for spi_node in get_spidev_nodes(spi_addr): - bisect.insort(spi_nodes, spi_node) - - self.log.trace("Found spidev nodes: {0}".format(spi_nodes)) - - if not spi_nodes: - self.log.warning("No SPI nodes for dboard %d.", E310_DBOARD_SLOT_IDX) - else: - dboard_info.update({ - 'spi_nodes': spi_nodes, - 'default_args': default_args, - }) - + assert len(self.dboard_spimaster_addrs) == 1 + spi_nodes = [get_spidev_nodes(self.dboard_spimaster_addrs[0])] + self.log.trace("Found spidev node: {0}".format(spi_nodes[0])) + assert spi_nodes + dboard_info.update({ + 'spi_nodes': spi_nodes, + 'default_args': default_args, + }) self.dboards.append(E31x_db(E310_DBOARD_SLOT_IDX, **dboard_info)) self.log.info("Found %d daughterboard(s).", len(self.dboards)) @@ -292,7 +293,7 @@ class e31x(ZynqComponents, PeriphManagerBase): If no EEPROM is defined, returns empty values. """ - if len(self.mboard_eeprom_addr): + if not self.mboard_eeprom_addr: (eeprom_head, eeprom_rawdata) = e31x_legacy_eeprom.read_eeprom( True, # isMotherboard get_eeprom_paths(self.mboard_eeprom_addr)[self.mboard_eeprom_path_index], @@ -301,10 +302,8 @@ class e31x(ZynqComponents, PeriphManagerBase): e31x_legacy_eeprom.MboardEEPROM.eeprom_header_keys, self.mboard_eeprom_max_len ) - self.log.trace("Found EEPROM metadata: `{}'" - .format(str(eeprom_head))) - self.log.trace("Read {} bytes of EEPROM data." - .format(len(eeprom_rawdata))) + self.log.trace("Found EEPROM metadata: `%s'", str(eeprom_head)) + self.log.trace("Read %d bytes of EEPROM data.", len(eeprom_rawdata)) return eeprom_head, eeprom_rawdata # Nothing defined? Return defaults. self.log.trace("No mboard EEPROM path defined. " @@ -372,9 +371,9 @@ class e31x(ZynqComponents, PeriphManagerBase): """ super(e31x, self).claim() try: - self._init_normal() - except Exception as ex: - self.log.error("e31x claim() failed: %s", str(ex)) + self._init_normal() + except BaseException as ex: + self.log.error("e31x claim() failed: %s", str(ex)) def init(self, args): """ @@ -396,7 +395,6 @@ class e31x(ZynqComponents, PeriphManagerBase): xport_mgr.init(args) return result - def apply_idle_overlay(self): """ Load all overlays required to go into idle power savings mode. @@ -487,8 +485,9 @@ class e31x(ZynqComponents, PeriphManagerBase): """ See PeriphManagerBase.get_chdr_link_options() for docs. """ - if xport_type == 'liberio': - return self._xport_mgrs['liberio'].get_chdr_link_options() + assert xport_type == 'liberio', \ + "Invalid xport_type! Must be 'liberio'" + self._xport_mgrs['liberio'].get_chdr_link_options() ########################################################################### # Device info @@ -556,7 +555,6 @@ class e31x(ZynqComponents, PeriphManagerBase): ########################################################################### # Hardware peripheral controls ########################################################################### - def set_fp_gpio_master(self, value): """set driver for front panel GPIO Arguments: @@ -619,12 +617,13 @@ class e31x(ZynqComponents, PeriphManagerBase): data_probes = ['temp1_input'] try: for data_probe in data_probes: - raw_val[data_probe] = read_sysfs_sensors_value('jc-42.4-temp', data_probe, 'hwmon', 'name')[0] + raw_val[data_probe] = read_sysfs_sensors_value( + 'jc-42.4-temp', data_probe, 'hwmon', 'name')[0] temp = str(raw_val['temp1_input'] / 1000) except ValueError: self.log.warning("Error when converting temperature value") except KeyError: - self.log.warning("Can't read temp on thermal_zone".format(sensor)) + self.log.warning("Can't read MB temperature!") return { 'name': 'temp_mb', 'type': 'REALNUM', @@ -642,12 +641,14 @@ class e31x(ZynqComponents, PeriphManagerBase): data_probes = ['in_temp0_raw', 'in_temp0_scale', 'in_temp0_offset'] try: for data_probe in data_probes: - raw_val[data_probe] = read_sysfs_sensors_value('xadc', data_probe, 'iio', 'name')[0] - temp = str((raw_val['in_temp0_raw'] + raw_val['in_temp0_offset']) * raw_val['in_temp0_scale'] / 1000) + raw_val[data_probe] = read_sysfs_sensors_value( + 'xadc', data_probe, 'iio', 'name')[0] + temp = str((raw_val['in_temp0_raw'] + raw_val['in_temp0_offset']) \ + * raw_val['in_temp0_scale'] / 1000) except ValueError: self.log.warning("Error when converting temperature value") except KeyError: - self.log.warning("Can't read temp on thermal_zone".format(sensor)) + self.log.warning("Can't read FPGA temperature!") return { 'name': 'temp_fpga', 'type': 'REALNUM', @@ -688,6 +689,9 @@ class e31x(ZynqComponents, PeriphManagerBase): return db_eeprom_data def set_db_eeprom(self, dboard_idx, eeprom_data): + """ + See PeriphManagerBase.set_db_eeprom() for docs. + """ self.log.warn("Called set_db_eeprom(), but not implemented!") raise NotImplementedError diff --git a/mpm/python/usrp_mpm/periph_manager/e320.py b/mpm/python/usrp_mpm/periph_manager/e320.py index 90cc1c049..f206ef26a 100644 --- a/mpm/python/usrp_mpm/periph_manager/e320.py +++ b/mpm/python/usrp_mpm/periph_manager/e320.py @@ -40,6 +40,7 @@ E320_DBOARD_SLOT_IDX = 0 ############################################################################### # Transport managers ############################################################################### +# pylint: disable=too-few-public-methods class E320XportMgrUDP(XportMgrUDP): "E320-specific UDP configuration" iface_config = { @@ -51,10 +52,14 @@ class E320XportMgrUDP(XportMgrUDP): class E320XportMgrLiberio(XportMgrLiberio): " E320-specific Liberio configuration " max_chan = 6 +# pylint: enable=too-few-public-methods ############################################################################### # Main Class ############################################################################### +# We need to disable the no-self-use check, because we might require self to +# become an RPC method, but PyLint doesnt' know that. +# pylint: disable=no-self-use class e320(ZynqComponents, PeriphManagerBase): """ Holds E320 specific attributes and methods @@ -141,7 +146,7 @@ class e320(ZynqComponents, PeriphManagerBase): setattr(self, sensor_cb_name, partial(self.get_temp_sensor, sensor_name)) try: self._init_peripherals(args) - except Exception as ex: + except BaseException as ex: self.log.error("Failed to initialize motherboard: %s", str(ex)) self._initialization_status = str(ex) self._device_initialized = False @@ -387,7 +392,8 @@ class e320(ZynqComponents, PeriphManagerBase): - rx_dev: RX device (/dev/rx-dma*) """ if xport_type not in self._xport_mgrs: - self.log.warning("Can't get link options for unknown link type: `{}'.") + self.log.warning("Can't get link options for unknown link type: `{}'." + .format(xport_type)) return [] return self._xport_mgrs[xport_type].get_chdr_link_options() @@ -473,8 +479,8 @@ class e320(ZynqComponents, PeriphManagerBase): clock_source = self.get_clock_source() if clock_source == "internal" or clock_source == "gpsdo": return E320_DEFAULT_INT_CLOCK_FREQ - elif clock_source == "external": - return self._ext_clock_freq + # elif clock_source == "external": + return self._ext_clock_freq def get_time_sources(self): " Returns list of valid time sources " diff --git a/mpm/python/usrp_mpm/rpc_server.py b/mpm/python/usrp_mpm/rpc_server.py index 17179f04d..1dc9d7065 100644 --- a/mpm/python/usrp_mpm/rpc_server.py +++ b/mpm/python/usrp_mpm/rpc_server.py @@ -286,7 +286,7 @@ class MPMServer(RPCServer): self._state.claim_status.value = True self.periph_manager.claimed = True self.periph_manager.claim() - if self.periph_manager.clear_rpc_method_registry_on_unclaim: + if self.periph_manager.clear_rpc_registry_on_unclaim: self._init_rpc_calls(self.periph_manager) self._state.lock.release() self.session_id = session_id + " ({})".format(self.client_host) @@ -339,14 +339,14 @@ class MPMServer(RPCServer): self._state.claim_status.value = False self._state.claim_token.value = b'' self.session_id = None - if self.periph_manager.clear_rpc_method_registry_on_unclaim: + if self.periph_manager.clear_rpc_registry_on_unclaim: self.clear_method_registry() try: self.periph_manager.claimed = False self.periph_manager.unclaim() self.periph_manager.set_connection_type(None) self.periph_manager.deinit() - except Exception as ex: + except BaseException as ex: self._last_error = str(ex) self.log.error("deinit() failed: %s", str(ex)) # Don't want to propagate this failure -- the session is over |