uhd/host/lib/usrp/mpmd/mpmd_impl.hpp
Martin Braun 3eb6fe492a uhd: Remove usage of boost::optional
- 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.
2026-05-05 14:41:39 +02:00

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 */