aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--host/lib/usrp/mpmd/mpmd_mboard_impl.cpp39
-rwxr-xr-xmpm/python/usrp_hwd.py3
-rw-r--r--mpm/python/usrp_mpm/dboard_manager/base.py3
-rw-r--r--mpm/python/usrp_mpm/dboard_manager/eiscat.py27
-rw-r--r--mpm/python/usrp_mpm/periph_manager/base.py9
-rw-r--r--mpm/python/usrp_mpm/periph_manager/n310.py3
-rw-r--r--mpm/python/usrp_mpm/rpc_server.py42
7 files changed, 98 insertions, 28 deletions
diff --git a/host/lib/usrp/mpmd/mpmd_mboard_impl.cpp b/host/lib/usrp/mpmd/mpmd_mboard_impl.cpp
index 82967ecad..135d2973e 100644
--- a/host/lib/usrp/mpmd/mpmd_mboard_impl.cpp
+++ b/host/lib/usrp/mpmd/mpmd_mboard_impl.cpp
@@ -22,7 +22,12 @@
#include <thread>
namespace {
- const size_t MPMD_RECLAIM_INTERVAL_MS = 1000;
+ //! Time between reclaims (ms)
+ const size_t MPMD_RECLAIM_INTERVAL_MS = 1000;
+ //! Default timeout value for the init() RPC call (ms)
+ const size_t MPMD_DEFAULT_INIT_TIMEOUT = 30000;
+ //! Default timeout value for RPC calls (ms)
+ const size_t MPMD_DEFAULT_RPC_TIMEOUT = 2000;
const std::string MPMD_DEFAULT_SESSION_ID = "UHD";
}
@@ -43,12 +48,6 @@ mpmd_mboard_impl::mpmd_mboard_impl(
<< rpc_server_addr
<< " mboard args: " << mb_args.to_string()
;
- auto device_info_dict = rpc->request<dev_info>("get_device_info");
- for (const auto &info_pair: device_info_dict) {
- device_info[info_pair.first] = info_pair.second;
- }
- UHD_LOGGER_TRACE("MPMD")
- << "MPM reports device info: " << device_info.to_string();
// Claim logic
auto rpc_token = rpc->request<std::string>("claim",
@@ -68,6 +67,32 @@ mpmd_mboard_impl::mpmd_mboard_impl(
);
});
+ // Init and query info
+ std::map<std::string, std::string> mpm_device_args;
+ const std::set<std::string> key_blacklist{ // TODO put this somewhere else
+ "serial", "claimed", "type", "rev", "addr"
+ };
+ for (const auto &key : mb_args.keys()) {
+ if (not key_blacklist.count(key)) {
+ mpm_device_args[key] = mb_args[key];
+ }
+ }
+ rpc->set_timeout(mb_args.cast<size_t>(
+ "init_timeout", MPMD_DEFAULT_INIT_TIMEOUT
+ ));
+ if (not rpc->request_with_token<bool>("init", mpm_device_args)) {
+ throw uhd::runtime_error("Failed to initialize device.");
+ }
+ auto device_info_dict = rpc->request<dev_info>("get_device_info");
+ for (const auto &info_pair : device_info_dict) {
+ device_info[info_pair.first] = info_pair.second;
+ }
+ UHD_LOGGER_TRACE("MPMD")
+ << "MPM reports device info: " << device_info.to_string();
+ rpc->set_timeout(mb_args.cast<size_t>(
+ "rpc_timeout", MPMD_DEFAULT_RPC_TIMEOUT
+ ));
+
// Initialize properties
this->num_xbars = rpc->request<size_t>("get_num_xbars");
// Local addresses are not yet valid after this!
diff --git a/mpm/python/usrp_hwd.py b/mpm/python/usrp_hwd.py
index 27c2870df..8abc89923 100755
--- a/mpm/python/usrp_hwd.py
+++ b/mpm/python/usrp_hwd.py
@@ -115,8 +115,8 @@ def main():
"type": mgr._get_device_info()["type"],
"serial": mgr._get_device_info()["serial"]
}
- mgr.init(args.default_args) # TODO really this should be called by the UHD session
if args.init_only:
+ mgr.init(args.default_args)
log.info("Terminating on user request before launching RPC server.")
mgr.deinit()
return True
@@ -130,7 +130,6 @@ def main():
signal.signal(signal.SIGTERM, kill_time)
signal.signal(signal.SIGINT, kill_time)
signal.pause()
- mgr.deinit() # TODO Really this should be called when a device is unclaimed
return True
if __name__ == '__main__':
diff --git a/mpm/python/usrp_mpm/dboard_manager/base.py b/mpm/python/usrp_mpm/dboard_manager/base.py
index 724558445..56655f946 100644
--- a/mpm/python/usrp_mpm/dboard_manager/base.py
+++ b/mpm/python/usrp_mpm/dboard_manager/base.py
@@ -52,6 +52,7 @@ class DboardManagerBase(object):
device_args -- Arbitrary dictionary of info, typically user-defined
"""
return []
+ ### End of overridables #################################################
def __init__(self, slot_idx, **kwargs):
self.log = get_logger('dboardManager')
@@ -82,7 +83,7 @@ class DboardManagerBase(object):
Run the dboard initialization. This typically happens at the beginning
of a UHD session.
- Must be overridden.
+ Must be overridden. Must return True/False on success/failure.
args -- A dictionary of arbitrary settings that can be used by the
dboard code. Similar to device args for UHD.
diff --git a/mpm/python/usrp_mpm/dboard_manager/eiscat.py b/mpm/python/usrp_mpm/dboard_manager/eiscat.py
index dc4ee1cac..980a64fcc 100644
--- a/mpm/python/usrp_mpm/dboard_manager/eiscat.py
+++ b/mpm/python/usrp_mpm/dboard_manager/eiscat.py
@@ -17,10 +17,10 @@
"""
EISCAT rx board implementation module
"""
-from builtins import range
-from builtins import object
import time
+from builtins import range
+from builtins import object
from ..mpmlog import get_logger
from ..uio import UIO
from . import lib
@@ -28,8 +28,6 @@ from .base import DboardManagerBase
from .lmk_eiscat import LMK04828EISCAT
from usrp_mpm.cores import ClockSynchronizer
-N_CHANS = 8 # Chans per dboard
-
def create_spidev_iface_sane(dev_node):
"""
Create a regs iface from a spidev node (sane values)
@@ -410,6 +408,12 @@ class EISCAT(DboardManagerBase):
self.clock_synchronizer = None
self._spi_ifaces = None
+ def is_initialized(self):
+ """
+ Returns True if the daughterboard is a usable state and ready to stream
+ """
+ return self.initialized
+
def init(self, args):
"""
Execute necessary actions to bring up the daughterboard:
@@ -425,6 +429,9 @@ class EISCAT(DboardManagerBase):
For operation (streaming), the ADCs and deframers still need to be
initialized.
+
+ Note that this function will do nothing if the device was previously
+ initialized.
"""
def _init_dboard_regs():
" Create a UIO object to talk to dboard regs "
@@ -493,6 +500,12 @@ class EISCAT(DboardManagerBase):
adc.reset()
return adcs
# Go, go, go!
+ if self.initialized and not args.get("force_init", False):
+ self.log.info(
+ "Dboard was previously initialized; skipping init. " \
+ "Specify force_init=1 to force initialization."
+ )
+ return True
self.log.info("init() called with args `{}'".format(
",".join(['{}={}'.format(x, args[x]) for x in args])
))
@@ -534,6 +547,7 @@ class EISCAT(DboardManagerBase):
self._spi_ifaces['adc0'], self._spi_ifaces['adc1'],
))
self.log.trace("ADC Reset Sequence Complete!")
+ return True
def send_sysref(self):
@@ -582,12 +596,13 @@ class EISCAT(DboardManagerBase):
def shutdown(self):
"""
- Safely turn off the daughterboard
+ Safely turn off the daughterboard. This will take away power to the
+ components; a re-initialization will be necessary after calling this.
"""
self.log.info("Shutting down daughterboard")
+ self.initialized = False
self._deinit_power(self.radio_regs)
-
def _init_power(self, regs):
"""
Turn on power to the dboard.
diff --git a/mpm/python/usrp_mpm/periph_manager/base.py b/mpm/python/usrp_mpm/periph_manager/base.py
index 89282265f..c0e64ade3 100644
--- a/mpm/python/usrp_mpm/periph_manager/base.py
+++ b/mpm/python/usrp_mpm/periph_manager/base.py
@@ -302,6 +302,12 @@ class PeriphManagerBase(object):
passed to the daughterboard's init calls. For additional features,
this needs to be overridden.
+ The main requirement of this function is, after calling it successfully,
+ all RFNoC blocks must be reachable via CHDR interfaces (i.e., clocks
+ need to be on).
+
+ Return False on failure, True on success.
+
args -- A dictionary of args for initialization. Similar to device args
in UHD.
"""
@@ -312,8 +318,7 @@ class PeriphManagerBase(object):
self.log.info("Identifying available network interfaces...")
self._init_interfaces()
self.log.debug("Initializing dboards...")
- for dboard in self.dboards:
- dboard.init(args)
+ return all((dboard.init(args) for dboard in self.dboards))
def deinit(self):
"""
diff --git a/mpm/python/usrp_mpm/periph_manager/n310.py b/mpm/python/usrp_mpm/periph_manager/n310.py
index 7b43aec38..537f43ee8 100644
--- a/mpm/python/usrp_mpm/periph_manager/n310.py
+++ b/mpm/python/usrp_mpm/periph_manager/n310.py
@@ -141,13 +141,14 @@ class n310(PeriphManagerBase):
Calls init() on the parent class, and then programs the Ethernet
dispatchers accordingly.
"""
- super(n310, self).init(args)
+ result = super(n310, self).init(args)
self._eth_dispatchers = {
x: EthDispatcherTable(self.eth_tables.get(x))
for x in list(self._chdr_interfaces.keys())
}
for ifname, table in iteritems(self._eth_dispatchers):
table.set_ipv4_addr(self._chdr_interfaces[ifname]['ip_addr'])
+ return result
def _allocate_sid(self, sender_addr, port, sid, xbar_src_addr, xbar_src_port, new_ep):
"""
diff --git a/mpm/python/usrp_mpm/rpc_server.py b/mpm/python/usrp_mpm/rpc_server.py
index 43843cff5..982e94c91 100644
--- a/mpm/python/usrp_mpm/rpc_server.py
+++ b/mpm/python/usrp_mpm/rpc_server.py
@@ -153,12 +153,13 @@ class MPMServer(RPCServer):
def claim(self, session_id):
"""
- claim `token` - tries to claim MPM device and provides a human readable session_id
- This is a safe method which can be called without a claim on the device
+ claim `token` - tries to claim MPM device and provides a human readable
+ session_id.
"""
self._state.lock.acquire()
if self._state.claim_status.value:
- return ""
+ self.log.warning("Someone tried to claim this device again")
+ raise RuntimeError("Double-claim")
self.log.debug(
"Claiming from: %s, Session ID: %s",
self.client_host,
@@ -169,11 +170,34 @@ class MPMServer(RPCServer):
), 'ascii')
self._state.claim_status.value = True
self._state.lock.release()
- self.session_id = session_id
+ self.session_id = session_id + " ({})".format(self.client_host)
self._reset_timer()
- self.log.debug("giving token: %s to host: %s", self._state.claim_token.value, self.client_host)
+ self.log.debug(
+ "giving token: %s to host: %s",
+ self._state.claim_token.value,
+ self.client_host
+ )
return self._state.claim_token.value
+
+ def init(self, token, args):
+ """
+ Initialize device. See PeriphManagerBase for details. This is forwarded
+ from here import to give extra control over the claim release timeout.
+ """
+ if not self._check_token_valid(token):
+ self.log.warning(
+ "Attempt to init without valid claim from {}".format(
+ self.client_host
+ )
+ )
+ raise RuntimeError("init() called without valid claim.")
+ self._timer.kill() # Stop the timer, inits can take some time.
+ result = self.periph_manager.init(args)
+ self.log.debug("init() result: {}".format(result))
+ self._reset_timer()
+ return result
+
def reclaim(self, token):
"""
reclaim a MPM device with a token. This operation will fail
@@ -203,8 +227,8 @@ class MPMServer(RPCServer):
"""
unconditional unclaim - for internal use
"""
- self.log.debug("Releasing claim on session `{}' by `{}'".format(
- self.session_id, self.client_host
+ self.log.debug("Releasing claim on session `{}'".format(
+ self.session_id
))
self._state.claim_status.value = False
self._state.claim_token.value = b''
@@ -213,12 +237,12 @@ class MPMServer(RPCServer):
self.periph_manager.deinit()
self._timer.kill()
- def _reset_timer(self):
+ def _reset_timer(self, timeout=TIMEOUT_INTERVAL):
"""
reset unclaim timer
"""
self._timer.kill()
- self._timer = spawn_later(TIMEOUT_INTERVAL, self._unclaim)
+ self._timer = spawn_later(timeout, self._unclaim)
def unclaim(self, token):
"""