mirror of
https://github.com/EttusResearch/uhd.git
synced 2026-10-25 17:36:10 +00:00
- boost::optional is replaced by std::optional - In public APIs, boost::optional is still usable, but it is declared deprecated. That means this is no API break (but it is an ABI break). - Within the library portion (host/lib/**) there is no more usage of boost::optional. Some backward-compatibility code (in actions.cpp and ctrlport_endpoint.cpp) was moved out to the header. Note: The most difficult replacement was that for parse_log_level_from_string(), where boost::optional is the return value. To retain API compatibility, we had to create a helper function.
306 lines
11 KiB
C++
306 lines
11 KiB
C++
//
|
|
// Copyright 2017 Ettus Research, a National Instruments Company
|
|
//
|
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
//
|
|
|
|
#ifndef INCLUDED_MPMD_IMPL_HPP
|
|
#define INCLUDED_MPMD_IMPL_HPP
|
|
|
|
#include <uhd/property_tree.hpp>
|
|
#include <uhd/stream.hpp>
|
|
#include <uhd/types/device_addr.hpp>
|
|
#include <uhd/types/dict.hpp>
|
|
#include <uhd/utils/tasks.hpp>
|
|
#include <uhdlib/rfnoc/clock_iface.hpp>
|
|
#include <uhdlib/rfnoc/rfnoc_device.hpp>
|
|
#include <uhdlib/usrp/common/mpmd_mb_controller.hpp>
|
|
#include <uhdlib/utils/rpc.hpp>
|
|
#include <map>
|
|
#include <memory>
|
|
#include <optional>
|
|
|
|
/*************************************************************************
|
|
* RPC timeout constants for MPMD
|
|
************************************************************************/
|
|
//! Time between reclaims (ms)
|
|
static constexpr size_t MPMD_RECLAIM_INTERVAL_MS = 1000;
|
|
//! Default timeout value for the init() RPC call (ms)
|
|
static constexpr size_t MPMD_DEFAULT_INIT_TIMEOUT = 120000;
|
|
//! Default timeout value for the reset_timer_and_mgr() RPC call (ms)
|
|
static constexpr size_t MPMD_DEFAULT_REBOOT_TIMEOUT = 200000;
|
|
//! Default timeout value for RPC calls (ms)
|
|
static constexpr size_t MPMD_DEFAULT_RPC_TIMEOUT = 2000;
|
|
//! Short timeout value for RPC calls (ms), used for calls that shouldn't
|
|
// take long. This value can be used to quickly determine a link status.
|
|
static constexpr size_t MPMD_SHORT_RPC_TIMEOUT = 2000;
|
|
//! Claimer loop timeout value for RPC calls (ms).
|
|
static constexpr size_t MPMD_CLAIMER_RPC_TIMEOUT = 10000;
|
|
//! Ethernet address for management and RPC communication
|
|
static const std::string MGMT_ADDR_KEY = "mgmt_addr";
|
|
//! RPC version
|
|
static const std::string RPC_VERSION_KEY = "rpc_version";
|
|
static const std::string RPC_VERSION = "1";
|
|
// Older devices did not provide an RPC version, but they were all using
|
|
// mprpc, aka version 1.
|
|
static const std::string DEFAULT_RPC_VERSION = "1";
|
|
|
|
namespace uhd { namespace mpmd {
|
|
|
|
/*! Stores all attributes specific to a single MPM device
|
|
*/
|
|
class mpmd_mboard_impl
|
|
{
|
|
public:
|
|
/*** Types ***************************************************************/
|
|
using uptr = std::unique_ptr<mpmd_mboard_impl>;
|
|
using dev_info = std::map<std::string, std::string>;
|
|
|
|
//! MPMD-specific implementation of the mb_iface
|
|
//
|
|
// This handles the transport management
|
|
class mpmd_mb_iface;
|
|
|
|
/*** Static helper *******************************************************/
|
|
/*! Will run some checks to determine if this device can be reached from
|
|
* the current UHD session
|
|
*
|
|
* \param device_addr Device args. Must contain an mgmt_addr.
|
|
*/
|
|
static std::optional<device_addr_t> is_device_reachable(
|
|
const device_addr_t& device_addr);
|
|
|
|
/*** Structors ***********************************************************/
|
|
/*! Ctor: Claim device or throw an exception on failure.
|
|
*
|
|
* Does not initialize the device.
|
|
*
|
|
* \param mb_args Device args that pertain to this motherboard
|
|
* \param ip_addr RPC client will attempt to connect to this IP address
|
|
*/
|
|
mpmd_mboard_impl(const uhd::device_addr_t& mb_args, const std::string& ip_addr);
|
|
~mpmd_mboard_impl();
|
|
|
|
/*** Factory *************************************************************/
|
|
/*!
|
|
* \param mb_args Device args that pertain to this motherboard
|
|
* \param ip_addr RPC client will attempt to connect to this IP address
|
|
*/
|
|
static uptr make(const uhd::device_addr_t& mb_args, const std::string& addr);
|
|
|
|
/*** API *****************************************************************/
|
|
void init();
|
|
|
|
uhd::rfnoc::mb_iface& get_mb_iface();
|
|
|
|
/*** Public attributes ***************************************************/
|
|
//! These are the args given by the user, with some filtering/preprocessing
|
|
uhd::device_addr_t mb_args;
|
|
|
|
//! Device information is read back via MPM and stored here.
|
|
uhd::device_addr_t device_info;
|
|
|
|
//! Dboard info is read back via MPM and stored here. There will be one
|
|
// dictionary per dboard; but there's no requirement for the dictionary
|
|
// to be populated at all.
|
|
std::vector<uhd::device_addr_t> dboard_info;
|
|
|
|
//! Reference to this motherboards mb_iface
|
|
std::unique_ptr<mpmd_mb_iface> mb_iface;
|
|
|
|
//! Reference to this motherboards mb_controller
|
|
uhd::rfnoc::mpmd_mb_controller::sptr mb_ctrl;
|
|
|
|
/*! Reference to the RPC client for this motherboard
|
|
*
|
|
* We store a shared ptr, because we might share it with some of the RFNoC
|
|
* blocks.
|
|
*/
|
|
uhd::rpc_client::sptr rpc;
|
|
|
|
/*************************************************************************
|
|
* API
|
|
************************************************************************/
|
|
/*! Setting this flag will enable a mode where a reclaim failure is
|
|
* acceptable.
|
|
*
|
|
* The only legitimate time to do this is when a procedure is called that
|
|
* can cause communication with the RPC server to be interrupted
|
|
* legitimately, but non-critically. For example, when updating the FPGA
|
|
* image, the RPC server gets rebooted, but the claim loop is running in a
|
|
* separate thread, and needs some kind of flag to be notified that
|
|
* something is up.
|
|
*/
|
|
void allow_claim_failure(const bool allow)
|
|
{
|
|
if (allow) {
|
|
_allow_claim_failure_latch = true;
|
|
}
|
|
_allow_claim_failure_flag = allow;
|
|
}
|
|
|
|
//! Read the device access token
|
|
std::string get_token()
|
|
{
|
|
return _token;
|
|
}
|
|
|
|
private:
|
|
/*! Reference to the RPC client that handles claiming
|
|
*/
|
|
uhd::rpc_client::sptr _claim_rpc;
|
|
/*************************************************************************
|
|
* Private methods
|
|
************************************************************************/
|
|
/*! Renew the claim onto the device.
|
|
*
|
|
* This is meant to be called repeatedly, e.g., using a UHD task. See also
|
|
* _claimer_task.
|
|
*/
|
|
bool claim();
|
|
|
|
/*! Set RPC client timeout value
|
|
*
|
|
* \param timeout_ms time limit (in ms) that a rpc client waits for a single call
|
|
*/
|
|
void set_rpcc_timeout(const uint64_t timeout_ms);
|
|
|
|
uhd::task::sptr make_claim_loop_task();
|
|
|
|
uhd::task::sptr claim_device_and_make_task();
|
|
|
|
//! Reset the _claim_rpc and _claimer_task
|
|
void reset_claim_loop();
|
|
|
|
/*! Read out the log buffer from the MPM device and send it to native
|
|
* logging system.
|
|
*/
|
|
void dump_logs(const bool dump_to_null = false);
|
|
|
|
/*************************************************************************
|
|
* Private attributes
|
|
************************************************************************/
|
|
/*! Continuously reclaims the device.
|
|
*/
|
|
uhd::task::sptr _claimer_task;
|
|
|
|
/*! A copy of the device access token
|
|
*/
|
|
std::string _token;
|
|
|
|
/*! A copy of the device access token
|
|
*/
|
|
std::string _rpc_server_addr;
|
|
|
|
/*! This flag is only used within the claim() function. Go look there if you
|
|
* really need to know what it does.
|
|
*/
|
|
std::atomic<bool> _allow_claim_failure_flag{false};
|
|
|
|
/*! This flag is only used within the claim() function. Go look there if you
|
|
* really need to know what it does.
|
|
*/
|
|
std::atomic<bool> _allow_claim_failure_latch{false};
|
|
};
|
|
|
|
|
|
/*! Parent class of an MPM device
|
|
*
|
|
* An MPM device is a USRP running MPM. Because most of the hardware controls
|
|
* are taken care of by MPM itself, it is not necessary to write a specific
|
|
* derived class for every single type of MPM device.
|
|
*/
|
|
class mpmd_impl : public uhd::rfnoc::detail::rfnoc_device
|
|
{
|
|
public:
|
|
//! Device arg key which will allow finding all devices, even those not
|
|
// reachable via CHDR.
|
|
static const std::string MPM_FINDALL_KEY;
|
|
//! Port on which the discovery process is listening (default value, it is
|
|
// user-overridable)
|
|
static const size_t MPM_DISCOVERY_PORT;
|
|
//! Device arg key to override the discovery port
|
|
static const std::string MPM_DISCOVERY_PORT_KEY;
|
|
//! Port on which the RPC process is listening (default value, it is user-
|
|
// overridable)
|
|
static const size_t MPM_RPC_PORT;
|
|
//! Device arg key to override the RPC port
|
|
static const std::string MPM_RPC_PORT_KEY;
|
|
//! This is the command that needs to be sent to the discovery port to
|
|
// trigger a response.
|
|
static const std::string MPM_DISCOVERY_CMD;
|
|
//! This is the command that will let you measure ping responses from the
|
|
// device via the discovery process. Useful for MTU discovery.
|
|
static const std::string MPM_ECHO_CMD;
|
|
//! This is the RPC command that will return the last known error from MPM.
|
|
static const std::string MPM_RPC_GET_LAST_ERROR_CMD;
|
|
|
|
/**************************************************************************
|
|
* Structors
|
|
************************************************************************/
|
|
mpmd_impl(const uhd::device_addr_t& device_addr);
|
|
~mpmd_impl() override;
|
|
|
|
/**************************************************************************
|
|
* API
|
|
************************************************************************/
|
|
uhd::rfnoc::mb_iface& get_mb_iface(const size_t mb_idx) override
|
|
{
|
|
if (mb_idx >= _mb.size()) {
|
|
throw uhd::index_error(
|
|
std::string("Cannot get mb_iface, invalid motherboard index: ")
|
|
+ std::to_string(mb_idx));
|
|
}
|
|
return _mb.at(mb_idx)->get_mb_iface();
|
|
}
|
|
|
|
protected:
|
|
//! Destroys the mboard_impls and the device_tree
|
|
void _deinit();
|
|
|
|
private:
|
|
/*************************************************************************
|
|
* Private methods/helpers
|
|
************************************************************************/
|
|
/*! Claim a device and create a reference to the mpmd_mboard_impl object.
|
|
*
|
|
* Does not initialize the device (see setup_mb() for that).
|
|
*/
|
|
mpmd_mboard_impl::uptr claim_and_make(const uhd::device_addr_t& dev_args);
|
|
|
|
/*! Initialize a single motherboard
|
|
*
|
|
* This is where mpmd_mboard_impl::init() is called.
|
|
* Also assigns the local crossbar addresses.
|
|
*
|
|
* \param mb Reference to the mboard class
|
|
* \param mb_index Index number of the mboard that's being initialized
|
|
* \param device_args Device args
|
|
*
|
|
*/
|
|
void setup_mb(mpmd_mboard_impl* mb, const size_t mb_index);
|
|
|
|
/*! Initialize property tree for a single device.
|
|
*
|
|
* \param tree Property tree reference (to the whole tree)
|
|
* \param mb_path Subtree path for this device
|
|
* \param mb Reference to the actual device
|
|
*/
|
|
static void init_property_tree(
|
|
uhd::property_tree::sptr tree, fs_path mb_path, mpmd_mboard_impl* mb);
|
|
|
|
/*************************************************************************
|
|
* Private attributes
|
|
************************************************************************/
|
|
//! Stores the args with which the device was originally initialized
|
|
uhd::device_addr_t _device_args;
|
|
//! Stores a list of mboard references
|
|
std::vector<mpmd_mboard_impl::uptr> _mb;
|
|
};
|
|
|
|
}} /* namespace uhd::mpmd */
|
|
|
|
uhd::device_addrs_t mpmd_find(const uhd::device_addr_t& hint_);
|
|
|
|
#endif /* INCLUDED_MPMD_IMPL_HPP */
|