aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Braun <martin.braun@ettus.com>2020-03-06 14:48:54 -0800
committerAaron Rossetto <aaron.rossetto@ni.com>2020-03-12 07:35:15 -0500
commit910d95af2f7df9f52bcfed3fc08c5db6b3b39fd0 (patch)
tree247cf1de51ba3c419b91dd675278f8cd2bd0a0a9
parent3b2f712ff9ceb6875f9e875d8e3424cd858d0a10 (diff)
downloaduhd-910d95af2f7df9f52bcfed3fc08c5db6b3b39fd0.tar.gz
uhd-910d95af2f7df9f52bcfed3fc08c5db6b3b39fd0.tar.bz2
uhd-910d95af2f7df9f52bcfed3fc08c5db6b3b39fd0.zip
multi_usrp: Provide valid return value for multi_usrp::get_device()
For RFNoC devices, multi_usrp::get_device() no longer returns a device pointer, rather, it returns a nullptr. This is intentional because access to the underlying device is no longer allowed. However, legacy code can segfault (e.g. portions ofr gr-uhd). This patch returns a faux uhd::device class, which almost mimicks the original behaviour perfectly, by redirecting its class methods back to multi_usrp_rfnoc. The only exception is recv_async_msg(), which requires a TX streamer. This function will always return false now.
-rw-r--r--host/include/uhd/device.hpp11
-rw-r--r--host/include/uhd/usrp/multi_usrp.hpp15
-rw-r--r--host/lib/usrp/multi_usrp_rfnoc.cpp54
3 files changed, 72 insertions, 8 deletions
diff --git a/host/include/uhd/device.hpp b/host/include/uhd/device.hpp
index f4594504d..a70a396a7 100644
--- a/host/include/uhd/device.hpp
+++ b/host/include/uhd/device.hpp
@@ -88,11 +88,18 @@ public:
*/
virtual tx_streamer::sptr get_tx_stream(const stream_args_t& args) = 0;
- /*!
- * Receive and asynchronous message from the device.
+ /*! Receive asynchronous message from the device
+ *
+ * Note that when calling multi_usrp::get_device() on an RFNoC-capable device,
+ * the returned uhd::device (while still being a valid object) will not be
+ * able to execute this method. Instead, query the asynchronous messages
+ * from the appropriate Tx streamer.
+ *
* \param async_metadata the metadata to be filled in
* \param timeout the timeout in seconds to wait for a message
* \return true when the async_metadata is valid, false for timeout
+ * \throws uhd::runtime_error if called on a device returned by
+ * multi_usrp::get_device on an RFNoC device.
*/
virtual bool recv_async_msg(
async_metadata_t& async_metadata, double timeout = 0.1) = 0;
diff --git a/host/include/uhd/usrp/multi_usrp.hpp b/host/include/uhd/usrp/multi_usrp.hpp
index ac80cc15a..93ef7d090 100644
--- a/host/include/uhd/usrp/multi_usrp.hpp
+++ b/host/include/uhd/usrp/multi_usrp.hpp
@@ -120,9 +120,18 @@ public:
*/
static sptr make(const device_addr_t& dev_addr);
- /*!
- * Get the underlying device object.
- * This is needed to get access to the streaming API and properties.
+ /*! Get the underlying device object
+ *
+ * Note that it is not recommended to use this method. The property tree can
+ * be accessed by calling get_tree() on this object, and the streamers own
+ * all the streaming-related functionality. get_tx_stream() and
+ * get_rx_stream() can also be called on this object.
+ *
+ * For RFNoC devices, this won't return a true uhd::device anyway, because
+ * direct device access is locked for those. The returned pointer will
+ * still point to a valid device object, however, it has reduced
+ * functionality (in particular, recv_async_msg() won't work).
+ *
* \return the device object within this USRP
*/
virtual device::sptr get_device(void) = 0;
diff --git a/host/lib/usrp/multi_usrp_rfnoc.cpp b/host/lib/usrp/multi_usrp_rfnoc.cpp
index b34860989..9a3169e38 100644
--- a/host/lib/usrp/multi_usrp_rfnoc.cpp
+++ b/host/lib/usrp/multi_usrp_rfnoc.cpp
@@ -37,6 +37,50 @@ constexpr char DEFAULT_OTW_FORMAT[] = "sc16";
constexpr double RX_SIGN = +1.0;
constexpr double TX_SIGN = -1.0;
+//! A faux container for a UHD device
+//
+// Note that multi_usrp_rfnoc no longer gives access to the underlying device
+// class. Legacy code might use multi_usrp->get_device()->get_tree() or
+// similar functionalities; these can be faked with this redirector class.
+//
+// The only exception is recv_async_msg(), which depends on the streamer. It
+// will throw a uhd::runtime_error now.
+class redirector_device : public uhd::device
+{
+public:
+ redirector_device(multi_usrp* musrp_ptr) : _musrp(musrp_ptr) {}
+
+ rx_streamer::sptr get_rx_stream(const stream_args_t& args)
+ {
+ return _musrp->get_rx_stream(args);
+ }
+
+ tx_streamer::sptr get_tx_stream(const stream_args_t& args)
+ {
+ return _musrp->get_tx_stream(args);
+ }
+
+ bool recv_async_msg(async_metadata_t&, double)
+ {
+ throw uhd::runtime_error(
+ "uhd::device::recv_async_msg() cannot be called on this device type!");
+ return false;
+ }
+
+ uhd::property_tree::sptr get_tree(void) const
+ {
+ return _musrp->get_tree();
+ }
+
+ device_filter_t get_device_type() const
+ {
+ return USRP;
+ }
+
+private:
+ multi_usrp* _musrp;
+};
+
/*! Make sure the stream args are valid and can be used by get_tx_stream()
* and get_rx_stream().
*
@@ -94,7 +138,10 @@ public:
* Structors
*************************************************************************/
multi_usrp_rfnoc(rfnoc_graph::sptr graph, const device_addr_t& addr)
- : _args(addr), _graph(graph), _tree(_graph->get_tree())
+ : _args(addr)
+ , _graph(graph)
+ , _tree(_graph->get_tree())
+ , _device(std::make_shared<redirector_device>(this))
{
// Discover all of the radios on our devices and create a mapping between
// radio chains and channel numbers. The result is sorted.
@@ -155,10 +202,9 @@ public:
// nop
}
- // Direct device access makes no sense with RFNoC
device::sptr get_device(void)
{
- return nullptr;
+ return _device;
}
uhd::property_tree::sptr get_tree() const
@@ -2275,6 +2321,8 @@ private:
std::unordered_map<size_t, double> _tx_rates;
std::recursive_mutex _graph_mutex;
+
+ std::shared_ptr<redirector_device> _device;
};
/******************************************************************************