diff options
Diffstat (limited to 'host')
32 files changed, 4 insertions, 4663 deletions
diff --git a/host/docs/configuration.dox b/host/docs/configuration.dox index d37943324..4ebc2cf9e 100644 --- a/host/docs/configuration.dox +++ b/host/docs/configuration.dox @@ -34,7 +34,7 @@ and possible more options. system_ref_rate | Reference Clock Rate in Hz | X3x0 | system_ref_rate=10e6 self_cal_adc_delay | Run ADC transfer delay self-calibration. | X3x0 | self_cal_adc_delay=1 ext_adc_self_test | Run an extended ADC self test (more than the usual) | X3x0 | ext_adc_self_test=1 - recover_mb_eeprom | Disable version checks. Can damage hardware. Only recommended for recovering devices with corrupted EEPROMs. | X3x0, N230 | recover_mb_eeprom=1 + recover_mb_eeprom | Disable version checks. Can damage hardware. Only recommended for recovering devices with corrupted EEPROMs. | X3x0 | recover_mb_eeprom=1 skip_dram | Ignore DRAM FIFO block. Connect TX streamers straight into DUC or radio. | X3x0, N3xx | skip_dram=1 skip_ddc | Ignore DDC block. Connect Rx streamers straight into radio. | X3x0, N3xx, E3xx | skip_ddc=1 skip_duc | Ignore DUC block. Connect Rx streamers or DRAM straight into radio. | X3x0, N3xx, E3xx | skip_duc=1 diff --git a/host/include/uhd/usrp/multi_usrp.hpp b/host/include/uhd/usrp/multi_usrp.hpp index 0abb9186d..6ea711be2 100644 --- a/host/include/uhd/usrp/multi_usrp.hpp +++ b/host/include/uhd/usrp/multi_usrp.hpp @@ -574,7 +574,7 @@ public: /*! Return a user settings interface object * - * This is only supported by some USRPs (B2xx series, N230). It will return + * This is only supported by the B2xx series. It will return * an object that will allow to peek and poke user settings, which typically * are implemented by custom FPGA images. * If the device does not support such an interface, it will return a null diff --git a/host/lib/CMakeLists.txt b/host/lib/CMakeLists.txt index a156a2eed..2ca216341 100644 --- a/host/lib/CMakeLists.txt +++ b/host/lib/CMakeLists.txt @@ -70,7 +70,6 @@ LIBUHD_REGISTER_COMPONENT("B200" ENABLE_B200 ON "ENABLE_LIBUHD;ENABLE_USB" OFF O LIBUHD_REGISTER_COMPONENT("USRP1" ENABLE_USRP1 ON "ENABLE_LIBUHD;ENABLE_USB" OFF OFF) LIBUHD_REGISTER_COMPONENT("USRP2" ENABLE_USRP2 ON "ENABLE_LIBUHD" OFF OFF) LIBUHD_REGISTER_COMPONENT("X300" ENABLE_X300 ON "ENABLE_LIBUHD" OFF OFF) -LIBUHD_REGISTER_COMPONENT("N230" ENABLE_N230 ON "ENABLE_LIBUHD" OFF OFF) LIBUHD_REGISTER_COMPONENT("MPMD" ENABLE_MPMD ON "ENABLE_LIBUHD" OFF OFF) LIBUHD_REGISTER_COMPONENT("N300" ENABLE_N300 ON "ENABLE_LIBUHD;ENABLE_MPMD" OFF OFF) LIBUHD_REGISTER_COMPONENT("N320" ENABLE_N320 ON "ENABLE_LIBUHD;ENABLE_MPMD" OFF OFF) diff --git a/host/lib/usrp/CMakeLists.txt b/host/lib/usrp/CMakeLists.txt index b62493595..8f3ccc9ff 100644 --- a/host/lib/usrp/CMakeLists.txt +++ b/host/lib/usrp/CMakeLists.txt @@ -41,4 +41,3 @@ INCLUDE_SUBDIRECTORY(usrp2) INCLUDE_SUBDIRECTORY(b100) INCLUDE_SUBDIRECTORY(x300) INCLUDE_SUBDIRECTORY(b200) -INCLUDE_SUBDIRECTORY(n230) diff --git a/host/lib/usrp/common/CMakeLists.txt b/host/lib/usrp/common/CMakeLists.txt index df0b550bf..bdc8a5977 100644 --- a/host/lib/usrp/common/CMakeLists.txt +++ b/host/lib/usrp/common/CMakeLists.txt @@ -14,14 +14,14 @@ if(ENABLE_USB) ) endif(ENABLE_USB) -if(ENABLE_E300 OR ENABLE_B200 OR ENABLE_N230 OR ENABLE_E320) +if(ENABLE_E300 OR ENABLE_B200 OR ENABLE_E320) include_directories("${CMAKE_CURRENT_SOURCE_DIR}/ad9361_driver") LIBUHD_APPEND_SOURCES( ${CMAKE_CURRENT_SOURCE_DIR}/ad9361_ctrl.cpp ${CMAKE_CURRENT_SOURCE_DIR}/ad936x_manager.cpp ${CMAKE_CURRENT_SOURCE_DIR}/ad9361_driver/ad9361_device.cpp ) -endif(ENABLE_E300 OR ENABLE_B200 OR ENABLE_N230 OR ENABLE_E320) +endif(ENABLE_E300 OR ENABLE_B200 OR ENABLE_E320) include_directories(${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/host/lib/usrp/n230/CMakeLists.txt b/host/lib/usrp/n230/CMakeLists.txt deleted file mode 100644 index 5bc9c815f..000000000 --- a/host/lib/usrp/n230/CMakeLists.txt +++ /dev/null @@ -1,28 +0,0 @@ -# -# Copyright 2013 Ettus Research LLC -# Copyright 2018 Ettus Research, a National Instruments Company -# -# SPDX-License-Identifier: GPL-3.0-or-later -# - -######################################################################## -# This file included, use CMake directory variables -######################################################################## - -######################################################################## -# Conditionally configure the N230 support -######################################################################## -if(ENABLE_N230) - LIBUHD_APPEND_SOURCES( - ${CMAKE_CURRENT_SOURCE_DIR}/n230_cores.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/n230_impl.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/n230_resource_manager.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/n230_eeprom_manager.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/n230_stream_manager.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/n230_clk_pps_ctrl.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/n230_frontend_ctrl.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/n230_uart.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/n230_image_loader.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/n230_fw_ctrl_iface.cpp - ) -endif(ENABLE_N230) diff --git a/host/lib/usrp/n230/n230_clk_pps_ctrl.cpp b/host/lib/usrp/n230/n230_clk_pps_ctrl.cpp deleted file mode 100644 index 749f3777a..000000000 --- a/host/lib/usrp/n230/n230_clk_pps_ctrl.cpp +++ /dev/null @@ -1,147 +0,0 @@ -// -// Copyright 2013-2014 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#include "n230_clk_pps_ctrl.hpp" - -#include <uhd/utils/log.hpp> -#include <uhd/utils/safe_call.hpp> -#include <stdint.h> -#include <boost/format.hpp> -#include <stdexcept> -#include <cmath> -#include <cstdlib> - -namespace uhd { namespace usrp { namespace n230 { - -class n230_clk_pps_ctrl_impl : public n230_clk_pps_ctrl -{ -public: - n230_clk_pps_ctrl_impl( - ad9361_ctrl::sptr codec_ctrl, - n230_ref_pll_ctrl::sptr ref_pll_ctrl, - fpga::core_misc_reg_t& core_misc_reg, - fpga::core_pps_sel_reg_t& core_pps_sel, - fpga::core_status_reg_t& core_status_reg, - const std::vector<time_core_3000::sptr>& time_cores - ): _codec_ctrl(codec_ctrl), - _ref_pll_ctrl(ref_pll_ctrl), - _core_misc_reg(core_misc_reg), - _core_pps_sel_reg(core_pps_sel), - _core_status_reg(core_status_reg), - _time_cores(time_cores), - _tick_rate(0.0), - _clock_source("<undefined>"), - _time_source("<undefined>") - { - } - - virtual ~n230_clk_pps_ctrl_impl() - { - } - - double set_tick_rate(const double rate) - { - UHD_LOGGER_INFO("N230") << "Configuring a tick rate of " << rate/1e6 << " MHz... "; - _tick_rate = _codec_ctrl->set_clock_rate(rate); - UHD_LOGGER_INFO("N230") << "got " << _tick_rate/1e6 << " MHz\n"; - - for(time_core_3000::sptr& time_core: _time_cores) { - time_core->set_tick_rate(_tick_rate); - time_core->self_test(); - } - - return _tick_rate; - } - - double get_tick_rate() - { - return _tick_rate; - } - - void set_clock_source(const std::string &source) - { - if (_clock_source == source) return; - - if (source == "internal") { - _ref_pll_ctrl->set_lock_to_ext_ref(false); - } else if (source == "external" || source == "gpsdo") { - _ref_pll_ctrl->set_lock_to_ext_ref(true); - } else { - throw uhd::key_error("set_clock_source: unknown source: " + source); - } - _core_misc_reg.write(fpga::core_misc_reg_t::REF_SEL, (source == "gpsdo") ? 1 : 0); - - _clock_source = source; - } - - const std::string& get_clock_source() - { - return _clock_source; - } - - uhd::sensor_value_t get_ref_locked() - { - bool locked = false; - if (_clock_source == "external" || _clock_source == "gpsdo") { - locked = (_core_status_reg.read(fpga::core_status_reg_t::REF_LOCKED) == 1); - } else { - //If the source is internal, the charge pump on the ADF4001 is tristated which - //means that the 40MHz VCTXXO is free running i.e. always "locked" - locked = true; - } - return sensor_value_t("Ref", locked, "locked", "unlocked"); - } - - void set_pps_source(const std::string &source) - { - if (_time_source == source) return; - - if (source == "none" or source == "gpsdo") { - _core_pps_sel_reg.write(fpga::core_pps_sel_reg_t::EXT_PPS_EN, 0); - } else if (source == "external") { - _core_pps_sel_reg.write(fpga::core_pps_sel_reg_t::EXT_PPS_EN, 1); - } else { - throw uhd::key_error("update_time_source: unknown source: " + source); - } - - _time_source = source; - } - - const std::string& get_pps_source() - { - return _time_source; - } - -private: - ad9361_ctrl::sptr _codec_ctrl; - n230_ref_pll_ctrl::sptr _ref_pll_ctrl; - fpga::core_misc_reg_t& _core_misc_reg; - fpga::core_pps_sel_reg_t& _core_pps_sel_reg; - fpga::core_status_reg_t& _core_status_reg; - std::vector<time_core_3000::sptr> _time_cores; - double _tick_rate; - std::string _clock_source; - std::string _time_source; -}; - -}}} //namespace - -using namespace uhd::usrp::n230; -using namespace uhd::usrp; - -n230_clk_pps_ctrl::sptr n230_clk_pps_ctrl::make( - ad9361_ctrl::sptr codec_ctrl, - n230_ref_pll_ctrl::sptr ref_pll_ctrl, - fpga::core_misc_reg_t& core_misc_reg, - fpga::core_pps_sel_reg_t& core_pps_sel_reg, - fpga::core_status_reg_t& core_status_reg, - const std::vector<time_core_3000::sptr>& time_cores) -{ - return sptr(new n230_clk_pps_ctrl_impl( - codec_ctrl, ref_pll_ctrl, core_misc_reg, core_pps_sel_reg, core_status_reg, time_cores)); -} - diff --git a/host/lib/usrp/n230/n230_clk_pps_ctrl.hpp b/host/lib/usrp/n230/n230_clk_pps_ctrl.hpp deleted file mode 100644 index f0ed316cf..000000000 --- a/host/lib/usrp/n230/n230_clk_pps_ctrl.hpp +++ /dev/null @@ -1,79 +0,0 @@ -// -// Copyright 2013-2014 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#ifndef INCLUDED_N230_CLK_PPS_CTRL_HPP -#define INCLUDED_N230_CLK_PPS_CTRL_HPP - -#include "n230_cores.hpp" -#include "n230_fpga_defs.h" -#include <uhd/types/sensors.hpp> -#include <uhdlib/usrp/cores/time_core_3000.hpp> -#include <uhdlib/usrp/common/ad9361_ctrl.hpp> -#include <boost/shared_ptr.hpp> -#include <uhd/utils/noncopyable.hpp> -#include <vector> - -namespace uhd { namespace usrp { namespace n230 { - -class n230_clk_pps_ctrl : uhd::noncopyable -{ -public: - typedef boost::shared_ptr<n230_clk_pps_ctrl> sptr; - - static sptr make( - ad9361_ctrl::sptr codec_ctrl, - n230_ref_pll_ctrl::sptr ref_pll_ctrl, - fpga::core_misc_reg_t& core_misc_reg, - fpga::core_pps_sel_reg_t& core_pps_sel_reg, - fpga::core_status_reg_t& core_status_reg, - const std::vector<time_core_3000::sptr>& time_cores); - - virtual ~n230_clk_pps_ctrl() {} - - /*********************************************************************** - * Tick Rate - **********************************************************************/ - /*! Set the master clock rate of the device. - * \return the clock frequency in Hz - */ - virtual double set_tick_rate(const double rate) = 0; - - /*! Get the master clock rate of the device. - * \return the clock frequency in Hz - */ - virtual double get_tick_rate() = 0; - - /*********************************************************************** - * Reference clock - **********************************************************************/ - /*! Set the reference clock source of the device. - */ - virtual void set_clock_source(const std::string &source) = 0; - - /*! Get the reference clock source of the device. - */ - virtual const std::string& get_clock_source() = 0; - - /*! Get the reference clock lock status. - */ - virtual uhd::sensor_value_t get_ref_locked() = 0; - - /*********************************************************************** - * Time source - **********************************************************************/ - /*! Set the time source of the device. - */ - virtual void set_pps_source(const std::string &source) = 0; - - /*! Get the reference clock source of the device. - */ - virtual const std::string& get_pps_source() = 0; -}; - -}}} //namespace - -#endif /* INCLUDED_N230_CLK_PPS_CTRL_HPP */ diff --git a/host/lib/usrp/n230/n230_cores.cpp b/host/lib/usrp/n230/n230_cores.cpp deleted file mode 100644 index 8e0132abd..000000000 --- a/host/lib/usrp/n230/n230_cores.cpp +++ /dev/null @@ -1,81 +0,0 @@ -// -// Copyright 2013-2014 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#include "n230_cores.hpp" -#include "n230_fpga_defs.h" -#include "n230_fw_defs.h" - -namespace uhd { namespace usrp { namespace n230 { - -n230_core_spi_core::n230_core_spi_core( - uhd::wb_iface::sptr iface, - perif_t default_perif) : - _spi_core(spi_core_3000::make(iface, - fpga::sr_addr(fpga::SR_CORE_SPI), - fpga::rb_addr(fpga::RB_CORE_SPI))), - _current_perif(default_perif), - _last_perif(default_perif) -{ - change_perif(default_perif); -} - -uint32_t n230_core_spi_core::transact_spi( - int which_slave, - const spi_config_t &config, - uint32_t data, - size_t num_bits, - bool readback) -{ - boost::mutex::scoped_lock lock(_mutex); - return _spi_core->transact_spi(which_slave, config, data, num_bits, readback); -} - -void n230_core_spi_core::change_perif(perif_t perif) -{ - boost::mutex::scoped_lock lock(_mutex); - _last_perif = _current_perif; - _current_perif = perif; - - switch (_current_perif) { - case CODEC: - _spi_core->set_divider(fw::CPU_CLOCK_FREQ/fw::CODEC_SPI_CLOCK_FREQ); - break; - case PLL: - _spi_core->set_divider(fw::CPU_CLOCK_FREQ/fw::ADF4001_SPI_CLOCK_FREQ); - break; - } -} - -void n230_core_spi_core::restore_perif() -{ - change_perif(_last_perif); -} - -n230_ref_pll_ctrl::n230_ref_pll_ctrl(n230_core_spi_core::sptr spi) : - adf4001_ctrl(spi, fpga::ADF4001_SPI_SLAVE_NUM), - _spi(spi) -{ -} - -void n230_ref_pll_ctrl::set_lock_to_ext_ref(bool external) -{ - _spi->change_perif(n230_core_spi_core::PLL); - adf4001_ctrl::set_lock_to_ext_ref(external); - _spi->restore_perif(); -} - -}}} //namespace - -using namespace uhd::usrp::n230; -using namespace uhd::usrp; - -n230_core_spi_core::sptr n230_core_spi_core::make( - uhd::wb_iface::sptr iface, n230_core_spi_core::perif_t default_perif) -{ - return sptr(new n230_core_spi_core(iface, default_perif)); -} - diff --git a/host/lib/usrp/n230/n230_cores.hpp b/host/lib/usrp/n230/n230_cores.hpp deleted file mode 100644 index b37a6c1ef..000000000 --- a/host/lib/usrp/n230/n230_cores.hpp +++ /dev/null @@ -1,61 +0,0 @@ -// -// Copyright 2013-2014 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#ifndef INCLUDED_N230_CORES_HPP -#define INCLUDED_N230_CORES_HPP - -#include <uhdlib/usrp/cores/spi_core_3000.hpp> -#include <uhdlib/usrp/common/adf4001_ctrl.hpp> -#include <boost/thread/mutex.hpp> - -namespace uhd { namespace usrp { namespace n230 { - -class n230_core_spi_core : uhd::noncopyable, public uhd::spi_iface { - -public: - typedef boost::shared_ptr<n230_core_spi_core> sptr; - - enum perif_t { - CODEC, PLL - }; - - n230_core_spi_core(uhd::wb_iface::sptr iface, perif_t default_perif); - - virtual uint32_t transact_spi( - int which_slave, - const spi_config_t &config, - uint32_t data, - size_t num_bits, - bool readback); - - void change_perif(perif_t perif); - void restore_perif(); - - static sptr make(uhd::wb_iface::sptr iface, perif_t default_perif = CODEC); - -private: - spi_core_3000::sptr _spi_core; - perif_t _current_perif; - perif_t _last_perif; - boost::mutex _mutex; -}; - -class n230_ref_pll_ctrl : public adf4001_ctrl { -public: - typedef boost::shared_ptr<n230_ref_pll_ctrl> sptr; - - n230_ref_pll_ctrl(n230_core_spi_core::sptr spi); - void set_lock_to_ext_ref(bool external); - -private: - n230_core_spi_core::sptr _spi; -}; - - -}}} //namespace - -#endif /* INCLUDED_N230_CORES_HPP */ diff --git a/host/lib/usrp/n230/n230_defaults.h b/host/lib/usrp/n230/n230_defaults.h deleted file mode 100644 index e224ab6f9..000000000 --- a/host/lib/usrp/n230/n230_defaults.h +++ /dev/null @@ -1,55 +0,0 @@ -// -// Copyright 2014 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#ifndef INCLUDED_N230_DEFAULTS_H -#define INCLUDED_N230_DEFAULTS_H - -#include <stdint.h> -#ifndef __cplusplus -#include <stdbool.h> -#endif -#include <uhd/transport/udp_constants.hpp> - -namespace uhd { -namespace usrp { -namespace n230 { - -static const double DEFAULT_TICK_RATE = 46.08e6; -static const double MAX_TICK_RATE = 50e6; -static const double MIN_TICK_RATE = 1e6; - -static const double DEFAULT_TX_SAMP_RATE = 1.0e6; -static const double DEFAULT_RX_SAMP_RATE = 1.0e6; -static const double DEFAULT_DDC_FREQ = 0.0; -static const double DEFAULT_DUC_FREQ = 0.0; - -static const double DEFAULT_FE_GAIN = 0.0; -static const double DEFAULT_FE_FREQ = 1.0e9; -static const double DEFAULT_FE_BW = 56e6; - -static const std::string DEFAULT_TIME_SRC = "none"; -static const std::string DEFAULT_CLOCK_SRC = "internal"; - -static const size_t DEFAULT_FRAME_SIZE = 1500 - 20 - 8; //default ipv4 mtu - ipv4 header - udp header -static const size_t MAX_FRAME_SIZE = 8000; -static const size_t MIN_FRAME_SIZE = IP_PROTOCOL_MIN_MTU_SIZE; - -static const size_t DEFAULT_NUM_FRAMES = 32; - -//A 1MiB SRAM is shared between two radios so we allocate each -//radio 0.5MiB minus 8 packets worth of buffering to ensure -//that the FIFO does not overflow -static const size_t DEFAULT_SEND_BUFF_SIZE = 500*1024; -#if defined(UHD_PLATFORM_MACOS) || defined(UHD_PLATFORM_BSD) -static const size_t DEFAULT_RECV_BUFF_SIZE = 0x100000; //1Mib -#elif defined(UHD_PLATFORM_LINUX) || defined(UHD_PLATFORM_WIN32) -static const size_t DEFAULT_RECV_BUFF_SIZE = 0x2000000;//32MiB -#endif - -}}} //namespace - -#endif /* INCLUDED_N230_DEFAULTS_H */ diff --git a/host/lib/usrp/n230/n230_device_args.hpp b/host/lib/usrp/n230/n230_device_args.hpp deleted file mode 100644 index 0e7b5dfe2..000000000 --- a/host/lib/usrp/n230/n230_device_args.hpp +++ /dev/null @@ -1,120 +0,0 @@ -// -// Copyright 2014 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#ifndef INCLUDED_N230_DEV_ARGS_HPP -#define INCLUDED_N230_DEV_ARGS_HPP - -#include <uhd/types/wb_iface.hpp> -#include <uhd/transport/udp_simple.hpp> -#include <uhdlib/usrp/constrained_device_args.hpp> -#include "n230_defaults.h" -#include <boost/thread/mutex.hpp> - -namespace uhd { namespace usrp { namespace n230 { - -class n230_device_args_t : public constrained_device_args_t -{ -public: - enum loopback_mode_t { LOOPBACK_OFF=0, LOOPBACK_RADIO=1, LOOPBACK_CODEC=2 }; - - n230_device_args_t(): - _master_clock_rate("master_clock_rate", n230::DEFAULT_TICK_RATE), - _send_frame_size("send_frame_size", n230::DEFAULT_FRAME_SIZE), - _recv_frame_size("recv_frame_size", n230::DEFAULT_FRAME_SIZE), - _num_send_frames("num_send_frames", n230::DEFAULT_NUM_FRAMES), - _num_recv_frames("num_recv_frames", n230::DEFAULT_NUM_FRAMES), - _send_buff_size("send_buff_size", n230::DEFAULT_SEND_BUFF_SIZE), - _recv_buff_size("recv_buff_size", n230::DEFAULT_RECV_BUFF_SIZE), - _safe_mode("safe_mode", false), - _loopback_mode("loopback_mode", - LOOPBACK_OFF, - {{"off", LOOPBACK_OFF}, {"radio", LOOPBACK_RADIO}, {"codec", LOOPBACK_CODEC}}) - {} - - double get_master_clock_rate() const { - return _master_clock_rate.get(); - } - size_t get_send_frame_size() const { - return _send_frame_size.get(); - } - size_t get_recv_frame_size() const { - return _recv_frame_size.get(); - } - size_t get_num_send_frames() const { - return _num_send_frames.get(); - } - size_t get_num_recv_frames() const { - return _num_recv_frames.get(); - } - size_t get_send_buff_size() const { - return _send_buff_size.get(); - } - size_t get_recv_buff_size() const { - return _recv_buff_size.get(); - } - bool get_safe_mode() const { - return _safe_mode.get(); - } - loopback_mode_t get_loopback_mode() const { - return _loopback_mode.get(); - } - - inline virtual std::string to_string() const { - return _master_clock_rate.to_string() + ", " + - _send_frame_size.to_string() + ", " + - _recv_frame_size.to_string() + ", " + - _num_send_frames.to_string() + ", " + - _num_recv_frames.to_string() + ", " + - _send_buff_size.to_string() + ", " + - _recv_buff_size.to_string() + ", " + - _safe_mode.to_string() + ", " + - _loopback_mode.to_string(); - } -private: - virtual void _parse(const device_addr_t& dev_args) { - //Extract parameters from dev_args - if (dev_args.has_key(_master_clock_rate.key())) - _master_clock_rate.parse(dev_args[_master_clock_rate.key()]); - if (dev_args.has_key(_send_frame_size.key())) - _send_frame_size.parse(dev_args[_send_frame_size.key()]); - if (dev_args.has_key(_recv_frame_size.key())) - _recv_frame_size.parse(dev_args[_recv_frame_size.key()]); - if (dev_args.has_key(_num_send_frames.key())) - _num_send_frames.parse(dev_args[_num_send_frames.key()]); - if (dev_args.has_key(_num_recv_frames.key())) - _num_recv_frames.parse(dev_args[_num_recv_frames.key()]); - if (dev_args.has_key(_send_buff_size.key())) - _send_buff_size.parse(dev_args[_send_buff_size.key()]); - if (dev_args.has_key(_recv_buff_size.key())) - _recv_buff_size.parse(dev_args[_recv_buff_size.key()]); - if (dev_args.has_key(_safe_mode.key())) - _safe_mode.parse(dev_args[_safe_mode.key()]); - if (dev_args.has_key(_loopback_mode.key())) - _loopback_mode.parse(dev_args[_loopback_mode.key()], false /* assert invalid */); - - //Sanity check params - _enforce_range(_master_clock_rate, MIN_TICK_RATE, MAX_TICK_RATE); - _enforce_range(_send_frame_size, MIN_FRAME_SIZE, MAX_FRAME_SIZE); - _enforce_range(_recv_frame_size, MIN_FRAME_SIZE, MAX_FRAME_SIZE); - _enforce_range(_num_send_frames, (size_t)2, (size_t)UINT_MAX); - _enforce_range(_num_recv_frames, (size_t)2, (size_t)UINT_MAX); - } - - constrained_device_args_t::num_arg<double> _master_clock_rate; - constrained_device_args_t::num_arg<size_t> _send_frame_size; - constrained_device_args_t::num_arg<size_t> _recv_frame_size; - constrained_device_args_t::num_arg<size_t> _num_send_frames; - constrained_device_args_t::num_arg<size_t> _num_recv_frames; - constrained_device_args_t::num_arg<size_t> _send_buff_size; - constrained_device_args_t::num_arg<size_t> _recv_buff_size; - constrained_device_args_t::bool_arg _safe_mode; - constrained_device_args_t::enum_arg<loopback_mode_t> _loopback_mode; -}; - -}}} //namespace - -#endif //INCLUDED_N230_DEV_ARGS_HPP diff --git a/host/lib/usrp/n230/n230_eeprom.h b/host/lib/usrp/n230/n230_eeprom.h deleted file mode 100644 index fdc942af5..000000000 --- a/host/lib/usrp/n230/n230_eeprom.h +++ /dev/null @@ -1,114 +0,0 @@ -// -// Copyright 2014 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#ifndef INCLUDED_N230_EEPROM_H -#define INCLUDED_N230_EEPROM_H - -#include <stdint.h> -#ifndef __cplusplus -#include <stdbool.h> -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -#define N230_NUM_ETH_PORTS 2 -#define N230_MAX_NUM_ETH_PORTS 2 - -#if (N230_NUM_ETH_PORTS > N230_MAX_NUM_ETH_PORTS) -#error -#endif - -#define N230_EEPROM_VER_MAJOR 1 -#define N230_EEPROM_VER_MINOR 1 -#define N230_EEPROM_SERIAL_LEN 9 -#define N230_EEPROM_NAME_LEN 32 - -typedef struct -{ - uint8_t mac_addr[6]; - uint8_t _pad[2]; - uint32_t subnet; - uint32_t ip_addr; -} n230_eth_eeprom_map_t; - -typedef struct -{ - //Data format version - uint16_t data_version_major; - uint16_t data_version_minor; - - //HW identification info - uint16_t hw_revision; - uint16_t hw_product; - uint8_t serial[N230_EEPROM_SERIAL_LEN]; - uint8_t _pad_serial; - uint16_t hw_revision_compat; - uint8_t _pad0[18 - (N230_EEPROM_SERIAL_LEN + 1)]; - - //Ethernet specific - uint32_t gateway; - n230_eth_eeprom_map_t eth_info[N230_MAX_NUM_ETH_PORTS]; - - //User specific - uint8_t user_name[N230_EEPROM_NAME_LEN]; -} n230_eeprom_map_t; - -#ifdef __cplusplus -} //extern "C" -#endif - -// The following definitions are only useful in firmware. Exclude in host code. -#ifndef __cplusplus - -/*! - * Read the eeprom and update caches. - * Returns true if read was successful. - * If the read was not successful then the cache is initialized with - * default values and marked as dirty. - */ -bool read_n230_eeprom(); - -/*! - * Write the contents of the cache to the eeprom. - * Returns true if write was successful. - */ -bool write_n230_eeprom(); - -/*! - * Returns the dirty state of the cache. - */ -bool is_n230_eeprom_cache_dirty(); - -/*! - * Returns a const pointer to the EEPROM map. - */ -const n230_eeprom_map_t* get_n230_const_eeprom_map(); - -/*! - * Returns the settings for the the 'iface'th ethernet interface - */ -const n230_eth_eeprom_map_t* get_n230_ethernet_info(uint32_t iface); - -/*! - * Returns a non-const pointer to the EEPROM map. Will mark the cache as dirty. - */ -n230_eeprom_map_t* get_n230_eeprom_map(); - -/*! - * FPGA Image operations - */ -inline void read_n230_fpga_image_page(uint32_t offset, void *buf, uint32_t num_bytes); - -inline bool write_n230_fpga_image_page(uint32_t offset, const void *buf, uint32_t num_bytes); - -inline bool erase_n230_fpga_image_sector(uint32_t offset); - -#endif //ifdef __cplusplus - -#endif /* INCLUDED_N230_EEPROM_H */ diff --git a/host/lib/usrp/n230/n230_eeprom_manager.cpp b/host/lib/usrp/n230/n230_eeprom_manager.cpp deleted file mode 100644 index f5fda3c2f..000000000 --- a/host/lib/usrp/n230/n230_eeprom_manager.cpp +++ /dev/null @@ -1,197 +0,0 @@ -// -// Copyright 2013-2014,2016 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#include "n230_eeprom.h" -#include <uhd/utils/byteswap.hpp> -#include <uhd/utils/log.hpp> -#include <uhd/exception.hpp> -#include <uhd/types/mac_addr.hpp> -#include <boost/format.hpp> -#include <boost/asio.hpp> //used for htonl and ntohl -#include "n230_eeprom_manager.hpp" - -namespace uhd { namespace usrp { namespace n230 { - -const double n230_eeprom_manager::UDP_TIMEOUT_IN_SEC = 2.0; - -n230_eeprom_manager::n230_eeprom_manager(const std::string& addr): - _seq_num(0) -{ - _udp_xport = transport::udp_simple::make_connected( - addr, BOOST_STRINGIZE(N230_FW_COMMS_FLASH_PROG_PORT)); - read_mb_eeprom(); -} - -static const std::string _bytes_to_string(const uint8_t* bytes, size_t max_len) -{ - std::string out; - for (size_t i = 0; i < max_len; i++) { - if (bytes[i] < 32 or bytes[i] > 127) return out; - out += bytes[i]; - } - return out; -} - -static void _string_to_bytes(const std::string &string, size_t max_len, uint8_t* buffer) -{ - byte_vector_t bytes; - const size_t len = std::min(string.size(), max_len); - for (size_t i = 0; i < len; i++){ - buffer[i] = string[i]; - } - if (len < max_len - 1) buffer[len] = '\0'; -} - -const mboard_eeprom_t& n230_eeprom_manager::read_mb_eeprom() -{ - boost::mutex::scoped_lock lock(_mutex); - - //Read EEPROM from device - _transact(N230_FLASH_COMM_CMD_READ_NV_DATA); - const n230_eeprom_map_t* map_ptr = reinterpret_cast<const n230_eeprom_map_t*>(_response.data); - const n230_eeprom_map_t& map = *map_ptr; - - uint16_t ver_major = uhd::htonx<uint16_t>(map.data_version_major); - uint16_t ver_minor = uhd::htonx<uint16_t>(map.data_version_minor); - - _mb_eeprom["product"] = std::to_string( - uhd::htonx<uint16_t>(map.hw_product)); - _mb_eeprom["revision"] = std::to_string( - uhd::htonx<uint16_t>(map.hw_revision)); - //The revision_compat field does not exist in version 1.0 - //EEPROM version 1.0 will only exist on HW revision 1 so it is safe to set - //revision_compat = revision - if (ver_major == 1 and ver_minor == 0) { - _mb_eeprom["revision_compat"] = _mb_eeprom["revision"]; - } else { - _mb_eeprom["revision_compat"] = std::to_string( - uhd::htonx<uint16_t>(map.hw_revision_compat)); - } - _mb_eeprom["serial"] = _bytes_to_string( - map.serial, N230_EEPROM_SERIAL_LEN); - - //Extract ethernet info - _mb_eeprom["gateway"] = boost::asio::ip::address_v4( - uhd::htonx<uint32_t>(map.gateway)).to_string(); - for (size_t i = 0; i < N230_MAX_NUM_ETH_PORTS; i++) { - const std::string n(1, i+'0'); - _mb_eeprom["ip-addr"+n] = boost::asio::ip::address_v4( - uhd::htonx<uint32_t>(map.eth_info[i].ip_addr)).to_string(); - _mb_eeprom["subnet"+n] = boost::asio::ip::address_v4( - uhd::htonx<uint32_t>(map.eth_info[i].subnet)).to_string(); - byte_vector_t mac_addr(map.eth_info[i].mac_addr, map.eth_info[i].mac_addr + 6); - _mb_eeprom["mac-addr"+n] = mac_addr_t::from_bytes(mac_addr).to_string(); - } - - _mb_eeprom["name"] = _bytes_to_string( - map.user_name, N230_EEPROM_NAME_LEN); - - return _mb_eeprom; -} - -void n230_eeprom_manager::write_mb_eeprom(const mboard_eeprom_t& eeprom) -{ - boost::mutex::scoped_lock lock(_mutex); - - _mb_eeprom = eeprom; - - n230_eeprom_map_t* map_ptr = reinterpret_cast<n230_eeprom_map_t*>(_request.data); - memset(map_ptr, 0xff, sizeof(n230_eeprom_map_t)); //Initialize to erased state - //Read EEPROM from device - _transact(N230_FLASH_COMM_CMD_READ_NV_DATA); - memcpy(map_ptr, _response.data, sizeof(n230_eeprom_map_t)); - n230_eeprom_map_t& map = *map_ptr; - - // Automatic version upgrade handling - uint16_t old_ver_major = uhd::htonx<uint16_t>(map.data_version_major); - uint16_t old_ver_minor = uhd::htonx<uint16_t>(map.data_version_minor); - - //The revision_compat field does not exist for version 1.0 so force write it - //EEPROM version 1.0 will only exist on HW revision 1 so it is safe to set - //revision_compat = revision for the upgrade - bool force_write_version_compat = (old_ver_major == 1 and old_ver_minor == 0); - - map.data_version_major = uhd::htonx<uint16_t>(N230_EEPROM_VER_MAJOR); - map.data_version_minor = uhd::htonx<uint16_t>(N230_EEPROM_VER_MINOR); - - if (_mb_eeprom.has_key("product")) { - map.hw_product = uhd::htonx<uint16_t>( - boost::lexical_cast<uint16_t>(_mb_eeprom["product"])); - } - if (_mb_eeprom.has_key("revision")) { - map.hw_revision = uhd::htonx<uint16_t>( - boost::lexical_cast<uint16_t>(_mb_eeprom["revision"])); - } - if (_mb_eeprom.has_key("revision_compat")) { - map.hw_revision_compat = uhd::htonx<uint16_t>( - boost::lexical_cast<uint16_t>(_mb_eeprom["revision_compat"])); - } else if (force_write_version_compat) { - map.hw_revision_compat = map.hw_revision; - } - if (_mb_eeprom.has_key("serial")) { - _string_to_bytes(_mb_eeprom["serial"], N230_EEPROM_SERIAL_LEN, map.serial); - } - - //Push ethernet info - if (_mb_eeprom.has_key("gateway")){ - map.gateway = uhd::htonx<uint32_t>( - boost::asio::ip::address_v4::from_string(_mb_eeprom["gateway"]).to_ulong()); - } - for (size_t i = 0; i < N230_MAX_NUM_ETH_PORTS; i++) { - const std::string n(1, i+'0'); - if (_mb_eeprom.has_key("ip-addr"+n)){ - map.eth_info[i].ip_addr = uhd::htonx<uint32_t>( - boost::asio::ip::address_v4::from_string(_mb_eeprom["ip-addr"+n]).to_ulong()); - } - if (_mb_eeprom.has_key("subnet"+n)){ - map.eth_info[i].subnet = uhd::htonx<uint32_t>( - boost::asio::ip::address_v4::from_string(_mb_eeprom["subnet"+n]).to_ulong()); - } - if (_mb_eeprom.has_key("mac-addr"+n)) { - byte_vector_t mac_addr = mac_addr_t::from_string(_mb_eeprom["mac-addr"+n]).to_bytes(); - std::copy(mac_addr.begin(), mac_addr.end(), map.eth_info[i].mac_addr); - } - } - //store the name - if (_mb_eeprom.has_key("name")) { - _string_to_bytes(_mb_eeprom["name"], N230_EEPROM_NAME_LEN, map.user_name); - } - - //Write EEPROM to device - _transact(N230_FLASH_COMM_CMD_WRITE_NV_DATA); -} - -void n230_eeprom_manager::_transact(const uint32_t command) -{ - //Load request struct - _request.flags = uhd::htonx<uint32_t>(N230_FLASH_COMM_FLAGS_ACK | command); - _request.seq = uhd::htonx<uint32_t>(_seq_num++); - - //Send request - _flush_xport(); - _udp_xport->send(boost::asio::buffer(&_request, sizeof(_request))); - - //Recv reply - const size_t nbytes = _udp_xport->recv(boost::asio::buffer(&_response, sizeof(_response)), UDP_TIMEOUT_IN_SEC); - if (nbytes == 0) throw uhd::io_error("n230_eeprom_manager::_transact failure"); - - //Sanity checks - const size_t flags = uhd::ntohx<uint32_t>(_response.flags); - UHD_ASSERT_THROW(nbytes == sizeof(_response)); - UHD_ASSERT_THROW(_response.seq == _request.seq); - UHD_ASSERT_THROW(flags & command); -} - -void n230_eeprom_manager::_flush_xport() -{ - char buff[sizeof(n230_flash_prog_t)] = {}; - while (_udp_xport->recv(boost::asio::buffer(buff), 0.0)) { - /*NOP*/ - } -} - -}}}; //namespace diff --git a/host/lib/usrp/n230/n230_eeprom_manager.hpp b/host/lib/usrp/n230/n230_eeprom_manager.hpp deleted file mode 100644 index 72735916f..000000000 --- a/host/lib/usrp/n230/n230_eeprom_manager.hpp +++ /dev/null @@ -1,48 +0,0 @@ -// -// Copyright 2013-2014 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#ifndef INCLUDED_N230_EEPROM_MANAGER_HPP -#define INCLUDED_N230_EEPROM_MANAGER_HPP - -#include <boost/thread/mutex.hpp> -#include <uhd/transport/udp_simple.hpp> -#include <uhd/types/dict.hpp> -#include <uhd/usrp/mboard_eeprom.hpp> -#include "n230_fw_host_iface.h" - -namespace uhd { namespace usrp { namespace n230 { - -class n230_eeprom_manager : uhd::noncopyable -{ -public: - n230_eeprom_manager(const std::string& addr); - - const mboard_eeprom_t& read_mb_eeprom(); - void write_mb_eeprom(const mboard_eeprom_t& eeprom); - - inline const mboard_eeprom_t& get_mb_eeprom() { - return _mb_eeprom; - } - -private: //Functions - void _transact(const uint32_t command); - void _flush_xport(); - -private: //Members - mboard_eeprom_t _mb_eeprom; - transport::udp_simple::sptr _udp_xport; - n230_flash_prog_t _request; - n230_flash_prog_t _response; - uint32_t _seq_num; - boost::mutex _mutex; - - static const double UDP_TIMEOUT_IN_SEC; -}; - -}}} //namespace - -#endif /* INCLUDED_N230_EEPROM_MANAGER_HPP */ diff --git a/host/lib/usrp/n230/n230_fpga_defs.h b/host/lib/usrp/n230/n230_fpga_defs.h deleted file mode 100644 index e3efff7af..000000000 --- a/host/lib/usrp/n230/n230_fpga_defs.h +++ /dev/null @@ -1,197 +0,0 @@ -// -// Copyright 2014 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#ifndef INCLUDED_N230_FPGA_DEFS_H -#define INCLUDED_N230_FPGA_DEFS_H - -#include <stdint.h> -#ifndef __cplusplus -#include <stdbool.h> -#endif -#include <uhd/utils/soft_register.hpp> - -namespace uhd { -namespace usrp { -namespace n230 { -namespace fpga { - -static inline uint32_t sr_addr(uint32_t offset) { - return (offset*4); -} - -static inline uint32_t rb_addr(uint32_t offset) { - return (offset*8); -} - -static const size_t NUM_RADIOS = 2; -static const double BUS_CLK_RATE = 80e6; - -/******************************************************************* - * CVITA Routing - *******************************************************************/ -static const uint32_t CVITA_UDP_PORT = 49153; -static const bool CVITA_BIG_ENDIAN = true; - -enum xb_endpoint_t { - N230_XB_DST_E0 = 0, - N230_XB_DST_E1 = 1, - N230_XB_DST_R0 = 2, - N230_XB_DST_R1 = 3, - N230_XB_DST_GCTRL = 4, - N230_XB_DST_UART = 5 -}; - -static const uint8_t RADIO_CTRL_SUFFIX = 0x00; -static const uint8_t RADIO_FC_SUFFIX = 0x01; -static const uint8_t RADIO_DATA_SUFFIX = 0x02; - -/******************************************************************* - * Seting Register Base addresses - *******************************************************************/ -static const uint32_t SR_CORE_RADIO_CONTROL = 3; -static const uint32_t SR_CORE_LOOPBACK = 4; -static const uint32_t SR_CORE_BIST1 = 5; -static const uint32_t SR_CORE_BIST2 = 6; -static const uint32_t SR_CORE_SPI = 8; -static const uint32_t SR_CORE_MISC = 16; -static const uint32_t SR_CORE_DATA_DELAY = 17; -static const uint32_t SR_CORE_CLK_DELAY = 18; -static const uint32_t SR_CORE_COMPAT = 24; -static const uint32_t SR_CORE_READBACK = 32; -static const uint32_t SR_CORE_GPSDO_ST = 40; -static const uint32_t SR_CORE_PPS_SEL = 48; -static const uint32_t SR_CORE_MS0_GPIO = 50; -static const uint32_t SR_CORE_MS1_GPIO = 58; - -static const uint32_t RB_CORE_SIGNATUE = 0; -static const uint32_t RB_CORE_SPI = 1; -static const uint32_t RB_CORE_STATUS = 2; -static const uint32_t RB_CORE_BIST = 3; -static const uint32_t RB_CORE_VERSION_HASH = 4; -static const uint32_t RB_CORE_MS0_GPIO = 5; -static const uint32_t RB_CORE_MS1_GPIO = 6; - -/******************************************************************* - * Seting Register Base addresses - *******************************************************************/ -static const uint32_t SR_RADIO_SPI = 8; -static const uint32_t SR_RADIO_ATR = 12; -static const uint32_t SR_RADIO_SW_RST = 20; -static const uint32_t SR_RADIO_TEST = 21; -static const uint32_t SR_RADIO_CODEC_IDLE = 22; -static const uint32_t SR_RADIO_READBACK = 32; -static const uint32_t SR_RADIO_TX_CTRL = 64; -static const uint32_t SR_RADIO_RX_CTRL = 96; -static const uint32_t SR_RADIO_RX_DSP = 144; -static const uint32_t SR_RADIO_TX_DSP = 184; -static const uint32_t SR_RADIO_TIME = 128; -static const uint32_t SR_RADIO_RX_FMT = 136; -static const uint32_t SR_RADIO_TX_FMT = 138; -static const uint32_t SR_RADIO_USER_SR = 253; - -static const uint32_t RB_RADIO_TEST = 0; -static const uint32_t RB_RADIO_TIME_NOW = 1; -static const uint32_t RB_RADIO_TIME_PPS = 2; -static const uint32_t RB_RADIO_CODEC_DATA = 3; -static const uint32_t RB_RADIO_DEBUG = 4; -static const uint32_t RB_RADIO_FRAMER = 5; -static const uint32_t SR_RADIO_USER_RB = 7; - -static const uint32_t AD9361_SPI_SLAVE_NUM = 0x1; -static const uint32_t ADF4001_SPI_SLAVE_NUM = 0x2; - -static const uint32_t RB_N230_PRODUCT_ID = 1; -static const uint32_t RB_N230_COMPAT_MAJOR = 0x21; -static const uint32_t RB_N230_COMPAT_SAFE = 0xC0; - -/******************************************************************* - * Codec Interface Specific - *******************************************************************/ - -// Matches delay setting of 0x00 in AD9361 register 0x006 -static const uint32_t CODEC_DATA_DELAY = 0; -static const uint32_t CODEC_CLK_DELAY = 16; - -//This number must be < 46.08MHz to make sure we don't -//violate timing for radio_clk. It is only used during -//initialization so the exact value does not matter. -static const double CODEC_DEFAULT_CLK_RATE = 40e6; - -/******************************************************************* - * Link Specific - *******************************************************************/ -static const double N230_LINK_RATE_BPS = 1e9/8; - -/******************************************************************* - * GPSDO - *******************************************************************/ -static const uint32_t GPSDO_UART_BAUDRATE = 115200; -static const uint32_t GPSDO_ST_ABSENT = 0x83; -/******************************************************************* - * Register Objects - *******************************************************************/ -class core_radio_ctrl_reg_t : public soft_reg32_wo_t { -public: - UHD_DEFINE_SOFT_REG_FIELD(MIMO, /*width*/ 1, /*shift*/ 0); //[0] - UHD_DEFINE_SOFT_REG_FIELD(CODEC_ARST, /*width*/ 1, /*shift*/ 1); //[1] - - core_radio_ctrl_reg_t(): - soft_reg32_wo_t(fpga::sr_addr(fpga::SR_CORE_RADIO_CONTROL)) - { - //Initial values - set(CODEC_ARST, 0); - set(MIMO, 1); //MIMO always ON for now - } -}; - -class core_misc_reg_t : public soft_reg32_wo_t { -public: - UHD_DEFINE_SOFT_REG_FIELD(REF_SEL, /*width*/ 1, /*shift*/ 0); //[0] - UHD_DEFINE_SOFT_REG_FIELD(RX_BANDSEL_C, /*width*/ 1, /*shift*/ 1); //[1] - UHD_DEFINE_SOFT_REG_FIELD(RX_BANDSEL_B, /*width*/ 1, /*shift*/ 2); //[2] - UHD_DEFINE_SOFT_REG_FIELD(RX_BANDSEL_A, /*width*/ 1, /*shift*/ 3); //[3] - UHD_DEFINE_SOFT_REG_FIELD(TX_BANDSEL_B, /*width*/ 1, /*shift*/ 4); //[4] - UHD_DEFINE_SOFT_REG_FIELD(TX_BANDSEL_A, /*width*/ 1, /*shift*/ 5); //[5] - - core_misc_reg_t(): - soft_reg32_wo_t(fpga::sr_addr(fpga::SR_CORE_MISC)) - { - //Initial values - set(REF_SEL, 0); - set(RX_BANDSEL_C, 0); - set(RX_BANDSEL_B, 0); - set(RX_BANDSEL_A, 0); - set(TX_BANDSEL_B, 0); - set(TX_BANDSEL_A, 0); - } -}; - -class core_pps_sel_reg_t : public soft_reg32_wo_t { -public: - UHD_DEFINE_SOFT_REG_FIELD(EXT_PPS_EN, /*width*/ 1, /*shift*/ 0); //[0] - - core_pps_sel_reg_t(): - soft_reg32_wo_t(fpga::sr_addr(fpga::SR_CORE_PPS_SEL)) - { - //Initial values - set(EXT_PPS_EN, 0); - } -}; - -class core_status_reg_t : public soft_reg64_ro_t { -public: - UHD_DEFINE_SOFT_REG_FIELD(REF_LOCKED, /*width*/ 1, /*shift*/ 0); //[0] - UHD_DEFINE_SOFT_REG_FIELD(GPSDO_STATUS, /*width*/ 8, /*shift*/ 32); //[32:39] - - core_status_reg_t(): - soft_reg64_ro_t(fpga::rb_addr(fpga::RB_CORE_STATUS)) - { } -}; - -}}}} //namespace - -#endif /* INCLUDED_N230_FPGA_DEFS_H */ diff --git a/host/lib/usrp/n230/n230_frontend_ctrl.cpp b/host/lib/usrp/n230/n230_frontend_ctrl.cpp deleted file mode 100644 index 7cbe578eb..000000000 --- a/host/lib/usrp/n230/n230_frontend_ctrl.cpp +++ /dev/null @@ -1,233 +0,0 @@ -// -// Copyright 2013-2014,2016 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#include "n230_frontend_ctrl.hpp" - -#include <uhd/utils/log.hpp> -#include <uhd/exception.hpp> -#include <uhd/types/dict.hpp> -#include <boost/format.hpp> -#include <boost/thread.hpp> -#include "n230_fpga_defs.h" - -namespace uhd { namespace usrp { namespace n230 { - -/* ATR Control Bits */ -static const uint32_t TX_ENABLE = (1 << 7); -static const uint32_t SFDX_RX = (1 << 6); -static const uint32_t SFDX_TX = (1 << 5); -static const uint32_t SRX_RX = (1 << 4); -static const uint32_t SRX_TX = (1 << 3); -static const uint32_t LED_RX = (1 << 2); -static const uint32_t LED_TXRX_RX = (1 << 1); -static const uint32_t LED_TXRX_TX = (1 << 0); - -/* ATR State Definitions. */ -static const uint32_t STATE_OFF = 0x00; -static const uint32_t STATE_RX_RX2 = (SFDX_RX - | SFDX_TX - | LED_RX); -static const uint32_t STATE_RX_TXRX = (SRX_RX - | SRX_TX - | LED_TXRX_RX); -static const uint32_t STATE_FDX_TXRX = (TX_ENABLE - | SFDX_RX - | SFDX_TX - | LED_TXRX_TX - | LED_RX); -static const uint32_t STATE_TX_TXRX = (TX_ENABLE - | SFDX_RX - | SFDX_TX - | LED_TXRX_TX); - -using namespace uhd::usrp; - -class n230_frontend_ctrl_impl : public n230_frontend_ctrl -{ -public: - n230_frontend_ctrl_impl( - radio_ctrl_core_3000::sptr core_ctrl, - fpga::core_misc_reg_t& core_misc_reg, - ad9361_ctrl::sptr codec_ctrl, - const std::vector<gpio_atr::gpio_atr_3000::sptr>& gpio_cores - ): _core_ctrl(core_ctrl), - _codec_ctrl(codec_ctrl), - _gpio_cores(gpio_cores), - _core_misc_reg(core_misc_reg) - { - } - - virtual ~n230_frontend_ctrl_impl() - { - } - - void set_antenna_sel(const size_t which, const std::string &ant) - { - if (ant != "TX/RX" and ant != "RX2") - throw uhd::value_error("n230: unknown RX antenna option: " + ant); - - _fe_states[which].rx_ant = ant; - _flush_atr_state(); - } - - void set_stream_state(const fe_state_t fe0_state_, const fe_state_t fe1_state_) - { - //Update soft-state - _fe_states[0].state = fe0_state_; - _fe_states[1].state = fe1_state_; - - const fe_state_t fe0_state = _fe_states[0].state; - const fe_state_t fe1_state = (_gpio_cores.size() > 1) ? _fe_states[1].state : NONE_STREAMING; - - const size_t num_tx = (_is_tx(fe0_state) ? 1 : 0) + (_is_tx(fe1_state) ? 1 : 0); - const size_t num_rx = (_is_rx(fe0_state) ? 1 : 0) + (_is_rx(fe1_state) ? 1 : 0); - - //setup the active chains in the codec - if ((num_rx + num_tx) == 0) { - _codec_ctrl->set_active_chains( - true, false, - true, false); //enable something - } else { - _codec_ctrl->set_active_chains( - _is_tx(fe0_state), _is_tx(fe1_state), - _is_rx(fe0_state), _is_rx(fe1_state)); - } - - _core_misc_reg.flush(); - //atrs change based on enables - _flush_atr_state(); - } - - - void set_stream_state(const size_t which, const fe_state_t state) - { - if (which == 0) { - set_stream_state(state, _fe_states[1].state); - } else if (which == 1) { - set_stream_state(_fe_states[0].state, state); - } else { - throw uhd::value_error( - str(boost::format("n230: unknown stream index option: %d") % which) - ); - } - } - - void set_bandsel(const std::string& which, double freq) - { - using namespace n230::fpga; - - if(which[0] == 'R') { - if(freq < 2.2e9) { - _core_misc_reg.set(core_misc_reg_t::RX_BANDSEL_A, 0); - _core_misc_reg.set(core_misc_reg_t::RX_BANDSEL_B, 0); - _core_misc_reg.set(core_misc_reg_t::RX_BANDSEL_C, 1); - } else if((freq >= 2.2e9) && (freq < 4e9)) { - _core_misc_reg.set(core_misc_reg_t::RX_BANDSEL_A, 0); - _core_misc_reg.set(core_misc_reg_t::RX_BANDSEL_B, 1); - _core_misc_reg.set(core_misc_reg_t::RX_BANDSEL_C, 0); - } else if((freq >= 4e9) && (freq <= 6e9)) { - _core_misc_reg.set(core_misc_reg_t::RX_BANDSEL_A, 1); - _core_misc_reg.set(core_misc_reg_t::RX_BANDSEL_B, 0); - _core_misc_reg.set(core_misc_reg_t::RX_BANDSEL_C, 0); - } else { - UHD_THROW_INVALID_CODE_PATH(); - } - } else if(which[0] == 'T') { - if(freq < 2.5e9) { - _core_misc_reg.set(core_misc_reg_t::TX_BANDSEL_A, 0); - _core_misc_reg.set(core_misc_reg_t::TX_BANDSEL_B, 1); - } else if((freq >= 2.5e9) && (freq <= 6e9)) { - _core_misc_reg.set(core_misc_reg_t::TX_BANDSEL_A, 1); - _core_misc_reg.set(core_misc_reg_t::TX_BANDSEL_B, 0); - } else { - UHD_THROW_INVALID_CODE_PATH(); - } - } else { - UHD_THROW_INVALID_CODE_PATH(); - } - - _core_misc_reg.flush(); - } - - void set_self_test_mode(self_test_mode_t mode) - { - switch (mode) { - case LOOPBACK_RADIO: { - _core_ctrl->poke32(fpga::sr_addr(fpga::SR_CORE_LOOPBACK), 0x1); - } break; - case LOOPBACK_CODEC: { - _core_ctrl->poke32(fpga::sr_addr(fpga::SR_CORE_LOOPBACK), 0x0); - _codec_ctrl->data_port_loopback(true); - } break; - //Default = disable - default: - case LOOPBACK_DISABLED: { - _core_ctrl->poke32(fpga::sr_addr(fpga::SR_CORE_LOOPBACK), 0x0); - _codec_ctrl->data_port_loopback(false); - } break; - } - } - -private: - void _flush_atr_state() - { - for (size_t i = 0; i < _gpio_cores.size(); i++) { - const fe_state_cache_t& fe_state_cache = _fe_states[i]; - const bool enb_rx = _is_rx(fe_state_cache.state); - const bool enb_tx = _is_tx(fe_state_cache.state); - const bool is_rx2 = (fe_state_cache.rx_ant == "RX2"); - const size_t rxonly = (enb_rx)? ((is_rx2)? STATE_RX_RX2 : STATE_RX_TXRX) : STATE_OFF; - const size_t txonly = (enb_tx)? (STATE_TX_TXRX) : STATE_OFF; - size_t fd = STATE_OFF; - if (enb_rx and enb_tx) fd = STATE_FDX_TXRX; - if (enb_rx and not enb_tx) fd = rxonly; - if (not enb_rx and enb_tx) fd = txonly; - _gpio_cores[i]->set_atr_reg(gpio_atr::ATR_REG_IDLE, STATE_OFF); - _gpio_cores[i]->set_atr_reg(gpio_atr::ATR_REG_RX_ONLY, rxonly); - _gpio_cores[i]->set_atr_reg(gpio_atr::ATR_REG_TX_ONLY, txonly); - _gpio_cores[i]->set_atr_reg(gpio_atr::ATR_REG_FULL_DUPLEX, fd); - } - } - - inline static bool _is_tx(const fe_state_t state) - { - return state == TX_STREAMING || state == TXRX_STREAMING; - } - - inline static bool _is_rx(const fe_state_t state) - { - return state == RX_STREAMING || state == TXRX_STREAMING; - } - -private: - struct fe_state_cache_t { - fe_state_cache_t() : state(NONE_STREAMING), rx_ant("RX2") - {} - fe_state_t state; - std::string rx_ant; - }; - - radio_ctrl_core_3000::sptr _core_ctrl; - ad9361_ctrl::sptr _codec_ctrl; - std::vector<gpio_atr::gpio_atr_3000::sptr> _gpio_cores; - fpga::core_misc_reg_t& _core_misc_reg; - uhd::dict<size_t, fe_state_cache_t> _fe_states; -}; - -}}} //namespace - -using namespace uhd::usrp::n230; - -n230_frontend_ctrl::sptr n230_frontend_ctrl::make( - radio_ctrl_core_3000::sptr core_ctrl, - fpga::core_misc_reg_t& core_misc_reg, - ad9361_ctrl::sptr codec_ctrl, - const std::vector<gpio_atr::gpio_atr_3000::sptr>& gpio_cores) -{ - return sptr(new n230_frontend_ctrl_impl(core_ctrl, core_misc_reg, codec_ctrl, gpio_cores)); -} - diff --git a/host/lib/usrp/n230/n230_frontend_ctrl.hpp b/host/lib/usrp/n230/n230_frontend_ctrl.hpp deleted file mode 100644 index d8b376831..000000000 --- a/host/lib/usrp/n230/n230_frontend_ctrl.hpp +++ /dev/null @@ -1,66 +0,0 @@ -// -// Copyright 2013-2014 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#ifndef INCLUDED_N230_FRONTEND_CTRL_HPP -#define INCLUDED_N230_FRONTEND_CTRL_HPP - -#include "n230_fpga_defs.h" -#include <uhdlib/usrp/cores/radio_ctrl_core_3000.hpp> -#include <uhdlib/usrp/cores/gpio_atr_3000.hpp> -#include <uhdlib/usrp/common/ad9361_ctrl.hpp> -#include <uhd/types/sensors.hpp> -#include <boost/shared_ptr.hpp> -#include <uhd/utils/noncopyable.hpp> -#include <vector> - -namespace uhd { namespace usrp { namespace n230 { - -enum fe_state_t { - NONE_STREAMING, TX_STREAMING, RX_STREAMING, TXRX_STREAMING -}; - -enum self_test_mode_t { - LOOPBACK_DISABLED, LOOPBACK_RADIO, LOOPBACK_CODEC -}; - - -class n230_frontend_ctrl : uhd::noncopyable -{ -public: - typedef boost::shared_ptr<n230_frontend_ctrl> sptr; - - static sptr make( - radio_ctrl_core_3000::sptr core_ctrl, - fpga::core_misc_reg_t& core_misc_reg, - ad9361_ctrl::sptr codec_ctrl, - const std::vector<gpio_atr::gpio_atr_3000::sptr>& gpio_cores); - - virtual ~n230_frontend_ctrl() {} - - virtual void set_antenna_sel( - const size_t which, - const std::string &ant) = 0; - - virtual void set_stream_state( - const size_t which, - const fe_state_t state) = 0; - - virtual void set_stream_state( - const fe_state_t fe0_state, - const fe_state_t fe1_state) = 0; - - virtual void set_bandsel( - const std::string& which, - double freq) = 0; - - virtual void set_self_test_mode( - self_test_mode_t mode) = 0; -}; - -}}} //namespace - -#endif /* INCLUDED_N230_FRONTEND_CTRL_HPP */ diff --git a/host/lib/usrp/n230/n230_fw_comm_protocol.h b/host/lib/usrp/n230/n230_fw_comm_protocol.h deleted file mode 100644 index 77d8bd7bf..000000000 --- a/host/lib/usrp/n230/n230_fw_comm_protocol.h +++ /dev/null @@ -1,92 +0,0 @@ -// -// Copyright 2014 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#ifndef INCLUDED_N230_FW_COMM_PROTOCOL -#define INCLUDED_N230_FW_COMM_PROTOCOL - -#include <stdint.h> -#ifndef __cplusplus -#include <stdbool.h> -#endif - -/*! - * Structs and constants for communication between firmware and host. - * This header is shared by the firmware and host code. - * Therefore, this header may only contain valid C code. - */ -#ifdef __cplusplus -extern "C" { -#endif - -#define FW_COMM_PROTOCOL_SIGNATURE 0xACE3 -#define FW_COMM_PROTOCOL_VERSION 0 -#define FW_COMM_MAX_DATA_WORDS 16 -#define FW_COMM_PROTOCOL_MTU 256 - -#define FW_COMM_FLAGS_ACK 0x00000001 -#define FW_COMM_FLAGS_CMD_MASK 0x00000FF0 -#define FW_COMM_FLAGS_ERROR_MASK 0xFF000000 - -#define FW_COMM_CMD_ECHO 0x00000000 -#define FW_COMM_CMD_POKE32 0x00000010 -#define FW_COMM_CMD_PEEK32 0x00000020 -#define FW_COMM_CMD_BLOCK_POKE32 0x00000030 -#define FW_COMM_CMD_BLOCK_PEEK32 0x00000040 - -#define FW_COMM_ERR_PKT_ERROR 0x80000000 -#define FW_COMM_ERR_CMD_ERROR 0x40000000 -#define FW_COMM_ERR_SIZE_ERROR 0x20000000 - -#define FW_COMM_GENERATE_ID(prod) ((((uint32_t) FW_COMM_PROTOCOL_SIGNATURE) << 0) | \ - (((uint32_t) prod) << 16) | \ - (((uint32_t) FW_COMM_PROTOCOL_VERSION) << 24)) - -#define FW_COMM_GET_PROTOCOL_SIG(id) ((uint16_t)(id & 0xFFFF)) -#define FW_COMM_GET_PRODUCT_ID(id) ((uint8_t)(id >> 16)) -#define FW_COMM_GET_PROTOCOL_VER(id) ((uint8_t)(id >> 24)) - -typedef struct -{ - uint32_t id; //Protocol and device identifier - uint32_t flags; //Holds commands and ack messages - uint32_t sequence; //Sequence number (specific to FW communication transactions) - uint32_t data_words; //Number of data words in payload - uint32_t addr; //Address field for the command in flags - uint32_t data[FW_COMM_MAX_DATA_WORDS]; //Data field for the command in flags -} fw_comm_pkt_t; - -#ifdef __cplusplus -} //extern "C" -#endif - -// The following definitions are only useful in firmware. Exclude in host code. -#ifndef __cplusplus - -typedef void (*poke32_func)(const uint32_t addr, const uint32_t data); -typedef uint32_t (*peek32_func)(const uint32_t addr); - -/*! - * Process a firmware communication packet and compute a response. - * Args: - * - (in) request: Pointer to the request struct - * - (out) response: Pointer to the response struct - * - (in) product_id: The 8-bit usrp3 specific product ID (for request filtering) - * - (func) poke_callback, peek_callback: Callback functions for a single peek/poke - * - return value: Send a response packet - */ -bool process_fw_comm_protocol_pkt( - const fw_comm_pkt_t* request, - fw_comm_pkt_t* response, - uint8_t product_id, - uint32_t iface_id, - poke32_func poke_callback, - peek32_func peek_callback -); - -#endif //ifdef __cplusplus - -#endif /* INCLUDED_N230_FW_COMM_PROTOCOL */ diff --git a/host/lib/usrp/n230/n230_fw_ctrl_iface.cpp b/host/lib/usrp/n230/n230_fw_ctrl_iface.cpp deleted file mode 100644 index 17fc46d68..000000000 --- a/host/lib/usrp/n230/n230_fw_ctrl_iface.cpp +++ /dev/null @@ -1,237 +0,0 @@ -// -// Copyright 2013 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#include "n230_fw_ctrl_iface.hpp" - -#include <uhd/utils/byteswap.hpp> -#include <uhd/utils/log.hpp> -#include <uhd/exception.hpp> -#include <boost/format.hpp> -#include <boost/asio.hpp> //used for htonl and ntohl -#include "n230_fw_comm_protocol.h" -#include <cstring> - -namespace uhd { namespace usrp { namespace n230 { - -//---------------------------------------------------------- -// Factory method -//---------------------------------------------------------- -uhd::wb_iface::sptr n230_fw_ctrl_iface::make( - uhd::transport::udp_simple::sptr udp_xport, - const uint16_t product_id, - const bool verbose) -{ - return wb_iface::sptr(new n230_fw_ctrl_iface(udp_xport, product_id, verbose)); -} - -//---------------------------------------------------------- -// udp_fw_ctrl_iface -//---------------------------------------------------------- - -n230_fw_ctrl_iface::n230_fw_ctrl_iface( - uhd::transport::udp_simple::sptr udp_xport, - const uint16_t product_id, - const bool verbose) : - _product_id(product_id), _verbose(verbose), _udp_xport(udp_xport), - _seq_num(0) -{ - flush(); - peek32(0); -} - -n230_fw_ctrl_iface::~n230_fw_ctrl_iface() -{ - flush(); -} - -void n230_fw_ctrl_iface::flush() -{ - boost::mutex::scoped_lock lock(_mutex); - _flush(); -} - -void n230_fw_ctrl_iface::poke32(const wb_addr_type addr, const uint32_t data) -{ - boost::mutex::scoped_lock lock(_mutex); - - for (size_t i = 1; i <= NUM_RETRIES; i++) { - try { - _poke32(addr, data); - return; - } catch(const std::exception &ex) { - const std::string error_msg = str(boost::format( - "udp fw poke32 failure #%u\n%s") % i % ex.what()); - if (_verbose) UHD_LOGGER_WARNING("N230") << error_msg ; - if (i == NUM_RETRIES) throw uhd::io_error(error_msg); - } - } -} - -uint32_t n230_fw_ctrl_iface::peek32(const wb_addr_type addr) -{ - boost::mutex::scoped_lock lock(_mutex); - - for (size_t i = 1; i <= NUM_RETRIES; i++) { - try { - return _peek32(addr); - } catch(const std::exception &ex) { - const std::string error_msg = str(boost::format( - "udp fw peek32 failure #%u\n%s") % i % ex.what()); - if (_verbose) UHD_LOGGER_WARNING("N230") << error_msg ; - if (i == NUM_RETRIES) throw uhd::io_error(error_msg); - } - } - return 0; -} - -void n230_fw_ctrl_iface::_poke32(const wb_addr_type addr, const uint32_t data) -{ - //Load request struct - fw_comm_pkt_t request; - request.id = uhd::htonx<uint32_t>(FW_COMM_GENERATE_ID(_product_id)); - request.flags = uhd::htonx<uint32_t>(FW_COMM_FLAGS_ACK | FW_COMM_CMD_POKE32); - request.sequence = uhd::htonx<uint32_t>(_seq_num++); - request.addr = uhd::htonx(addr); - request.data_words = 1; - request.data[0] = uhd::htonx(data); - - //Send request - _flush(); - _udp_xport->send(boost::asio::buffer(&request, sizeof(request))); - - //Recv reply - fw_comm_pkt_t reply; - const size_t nbytes = _udp_xport->recv(boost::asio::buffer(&reply, sizeof(reply)), 1.0); - if (nbytes == 0) throw uhd::io_error("udp fw poke32 - reply timed out"); - - //Sanity checks - const size_t flags = uhd::ntohx<uint32_t>(reply.flags); - UHD_ASSERT_THROW(nbytes == sizeof(reply)); - UHD_ASSERT_THROW(not (flags & FW_COMM_FLAGS_ERROR_MASK)); - UHD_ASSERT_THROW(flags & FW_COMM_CMD_POKE32); - UHD_ASSERT_THROW(flags & FW_COMM_FLAGS_ACK); - UHD_ASSERT_THROW(reply.sequence == request.sequence); - UHD_ASSERT_THROW(reply.addr == request.addr); - UHD_ASSERT_THROW(reply.data[0] == request.data[0]); -} - -uint32_t n230_fw_ctrl_iface::_peek32(const wb_addr_type addr) -{ - //Load request struct - fw_comm_pkt_t request; - request.id = uhd::htonx<uint32_t>(FW_COMM_GENERATE_ID(_product_id)); - request.flags = uhd::htonx<uint32_t>(FW_COMM_FLAGS_ACK | FW_COMM_CMD_PEEK32); - request.sequence = uhd::htonx<uint32_t>(_seq_num++); - request.addr = uhd::htonx(addr); - request.data_words = 1; - request.data[0] = 0; - - //Send request - _flush(); - _udp_xport->send(boost::asio::buffer(&request, sizeof(request))); - - //Recv reply - fw_comm_pkt_t reply; - const size_t nbytes = _udp_xport->recv(boost::asio::buffer(&reply, sizeof(reply)), 1.0); - if (nbytes == 0) throw uhd::io_error("udp fw peek32 - reply timed out"); - - //Sanity checks - const size_t flags = uhd::ntohx<uint32_t>(reply.flags); - UHD_ASSERT_THROW(nbytes == sizeof(reply)); - UHD_ASSERT_THROW(not (flags & FW_COMM_FLAGS_ERROR_MASK)); - UHD_ASSERT_THROW(flags & FW_COMM_CMD_PEEK32); - UHD_ASSERT_THROW(flags & FW_COMM_FLAGS_ACK); - UHD_ASSERT_THROW(reply.sequence == request.sequence); - UHD_ASSERT_THROW(reply.addr == request.addr); - - //return result! - return uhd::ntohx<uint32_t>(reply.data[0]); -} - -void n230_fw_ctrl_iface::_flush(void) -{ - char buff[FW_COMM_PROTOCOL_MTU] = {}; - while (_udp_xport->recv(boost::asio::buffer(buff), 0.0)) { - /*NOP*/ - } -} - -std::vector<std::string> n230_fw_ctrl_iface::discover_devices( - const std::string& addr_hint, const std::string& port, - uint16_t product_id) -{ - std::vector<std::string> addrs; - - //Create a UDP transport to communicate: - //Some devices will cause a throw when opened for a broadcast address. - //We print and recover so the caller can loop through all bcast addrs. - uhd::transport::udp_simple::sptr udp_bcast_xport; - try { - udp_bcast_xport = uhd::transport::udp_simple::make_broadcast(addr_hint, port); - } catch(const std::exception &e) { - UHD_LOGGER_ERROR("N230") << boost::format("Cannot open UDP transport on %s for discovery\n%s") - % addr_hint % e.what() ; - return addrs; - } - - //Send dummy request - fw_comm_pkt_t request; - std::memset(&request, 0, sizeof(request)); - request.id = uhd::htonx<uint32_t>(FW_COMM_GENERATE_ID(product_id)); - request.flags = uhd::htonx<uint32_t>(FW_COMM_FLAGS_ACK|FW_COMM_CMD_ECHO); - request.sequence = uhd::htonx<uint32_t>(std::rand()); - udp_bcast_xport->send(boost::asio::buffer(&request, sizeof(request))); - - //loop for replies until timeout - while (true) { - char buff[FW_COMM_PROTOCOL_MTU] = {}; - const size_t nbytes = udp_bcast_xport->recv(boost::asio::buffer(buff), 0.050); - if (nbytes != sizeof(fw_comm_pkt_t)) break; //No more responses or responses are invalid - - const fw_comm_pkt_t *reply = (const fw_comm_pkt_t *)buff; - if (request.id == reply->id && - request.flags == reply->flags && - request.sequence == reply->sequence) - { - addrs.push_back(udp_bcast_xport->get_recv_addr()); - } - } - - return addrs; -} - -uint32_t n230_fw_ctrl_iface::get_iface_id( - const std::string& addr, const std::string& port, - uint16_t product_id) -{ - uhd::transport::udp_simple::sptr udp_xport = - uhd::transport::udp_simple::make_connected(addr, port); - - //Send dummy request - fw_comm_pkt_t request; - request.id = uhd::htonx<uint32_t>(FW_COMM_GENERATE_ID(product_id)); - request.flags = uhd::htonx<uint32_t>(FW_COMM_FLAGS_ACK|FW_COMM_CMD_ECHO); - request.sequence = uhd::htonx<uint32_t>(std::rand()); - udp_xport->send(boost::asio::buffer(&request, sizeof(request))); - - //loop for replies until timeout - char buff[FW_COMM_PROTOCOL_MTU] = {}; - const size_t nbytes = udp_xport->recv(boost::asio::buffer(buff), 1.0); - - const fw_comm_pkt_t *reply = (const fw_comm_pkt_t *)buff; - if (nbytes > 0 && - request.id == reply->id && - request.flags == reply->flags && - request.sequence == reply->sequence) - { - return uhd::ntohx<uint32_t>(reply->data[0]); - } else { - throw uhd::io_error("udp get_iface_id - bad response"); - } -} - -}}} //namespace diff --git a/host/lib/usrp/n230/n230_fw_ctrl_iface.hpp b/host/lib/usrp/n230/n230_fw_ctrl_iface.hpp deleted file mode 100644 index 942640332..000000000 --- a/host/lib/usrp/n230/n230_fw_ctrl_iface.hpp +++ /dev/null @@ -1,62 +0,0 @@ -// -// Copyright 2014 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#ifndef INCLUDED_LIBUHD_USRP_N230_UDP_FW_CTRL_IFACE_HPP -#define INCLUDED_LIBUHD_USRP_N230_UDP_FW_CTRL_IFACE_HPP - -#include <uhd/types/wb_iface.hpp> -#include <uhd/transport/udp_simple.hpp> -#include <boost/thread/mutex.hpp> -#include <vector> - -namespace uhd { namespace usrp { namespace n230 { - -class n230_fw_ctrl_iface : public uhd::wb_iface -{ -public: - n230_fw_ctrl_iface( - uhd::transport::udp_simple::sptr udp_xport, - const uint16_t product_id, - const bool verbose); - virtual ~n230_fw_ctrl_iface(); - - // -- uhd::wb_iface -- - void poke32(const wb_addr_type addr, const uint32_t data); - uint32_t peek32(const wb_addr_type addr); - void flush(); - - static uhd::wb_iface::sptr make( - uhd::transport::udp_simple::sptr udp_xport, - const uint16_t product_id, - const bool verbose = true); - // -- uhd::wb_iface -- - - static std::vector<std::string> discover_devices( - const std::string& addr_hint, const std::string& port, - uint16_t product_id); - - static uint32_t get_iface_id( - const std::string& addr, const std::string& port, - uint16_t product_id); - -private: - void _poke32(const wb_addr_type addr, const uint32_t data); - uint32_t _peek32(const wb_addr_type addr); - void _flush(void); - - const uint16_t _product_id; - const bool _verbose; - uhd::transport::udp_simple::sptr _udp_xport; - uint32_t _seq_num; - boost::mutex _mutex; - - static const size_t NUM_RETRIES = 3; -}; - -}}} //namespace - -#endif // INCLUDED_LIBUHD_USRP_N230_UDP_FW_CTRL_IFACE_HPP diff --git a/host/lib/usrp/n230/n230_fw_defs.h b/host/lib/usrp/n230/n230_fw_defs.h deleted file mode 100644 index a9e4f9274..000000000 --- a/host/lib/usrp/n230/n230_fw_defs.h +++ /dev/null @@ -1,127 +0,0 @@ -// -// Copyright 2014 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#ifndef INCLUDED_N230_FW_DEFS_H -#define INCLUDED_N230_FW_DEFS_H - -#include <stdint.h> - -/*! - * Constants specific to N230 firmware. - * This header is shared by the firmware and host code. - * Therefore, this header may only contain valid C code. - * However, if it is included from within the host code, - * it will be namespaced appropriately - */ -#ifdef __cplusplus -namespace uhd { -namespace usrp { -namespace n230 { -namespace fw { -#endif - -static inline uint32_t reg_addr(uint32_t base, uint32_t offset) { - return ((base) + (offset)*4); -} - -/******************************************************************* - * Global - *******************************************************************/ -static const uint32_t CPU_CLOCK_FREQ = 80000000; -static const uint32_t PER_MILLISEC_CRON_JOBID = 0; -static const uint32_t PER_SECOND_CRON_JOBID = 1; - -/******************************************************************* - * Wishbone slave addresses - *******************************************************************/ -static const uint32_t WB_MAIN_RAM_BASE = 0x0000; -static const uint32_t WB_PKT_RAM_BASE = 0x8000; -static const uint32_t WB_SBRB_BASE = 0xa000; -static const uint32_t WB_SPI_FLASH_BASE = 0xb000; -static const uint32_t WB_ETH0_MAC_BASE = 0xc000; -static const uint32_t WB_ETH1_MAC_BASE = 0xd000; -static const uint32_t WB_XB_SBRB_BASE = 0xe000; -static const uint32_t WB_ETH0_I2C_BASE = 0xf600; -static const uint32_t WB_ETH1_I2C_BASE = 0xf700; -static const uint32_t WB_DBG_UART_BASE = 0xf900; - -/******************************************************************* - * Seting Register Base addresses - *******************************************************************/ -static const uint32_t SR_ZPU_SW_RST = 0; -static const uint32_t SR_ZPU_BOOT_DONE = 1; -static const uint32_t SR_ZPU_LEDS = 2; -static const uint32_t SR_ZPU_XB_LOCAL = 4; -static const uint32_t SR_ZPU_SFP_CTRL0 = 16; -static const uint32_t SR_ZPU_SFP_CTRL1 = 17; -static const uint32_t SR_ZPU_ETHINT0 = 64; -static const uint32_t SR_ZPU_ETHINT1 = 80; - -static const uint32_t SR_ZPU_SW_RST_NONE = 0x0; -static const uint32_t SR_ZPU_SW_RST_PHY = 0x1; -static const uint32_t SR_ZPU_SW_RST_RADIO = 0x2; - -/******************************************************************* - * Readback addresses - *******************************************************************/ -static const uint32_t RB_ZPU_COMPAT = 0; -static const uint32_t RB_ZPU_COUNTER = 1; -static const uint32_t RB_ZPU_SFP_STATUS0 = 2; -static const uint32_t RB_ZPU_SFP_STATUS1 = 3; -static const uint32_t RB_ZPU_ETH0_PKT_CNT = 6; -static const uint32_t RB_ZPU_ETH1_PKT_CNT = 7; - -/******************************************************************* - * Ethernet - *******************************************************************/ -static const uint32_t WB_PKT_RAM_CTRL_OFFSET = 0x1FFC; - -static const uint32_t SR_ZPU_ETHINT_FRAMER_BASE = 0; -static const uint32_t SR_ZPU_ETHINT_DISPATCHER_BASE = 8; - -//Eth framer constants -static const uint32_t ETH_FRAMER_SRC_MAC_HI = 0; -static const uint32_t ETH_FRAMER_SRC_MAC_LO = 1; -static const uint32_t ETH_FRAMER_SRC_IP_ADDR = 2; -static const uint32_t ETH_FRAMER_SRC_UDP_PORT = 3; -static const uint32_t ETH_FRAMER_DST_RAM_ADDR = 4; -static const uint32_t ETH_FRAMER_DST_IP_ADDR = 5; -static const uint32_t ETH_FRAMER_DST_UDP_MAC = 6; -static const uint32_t ETH_FRAMER_DST_MAC_LO = 7; - -/******************************************************************* - * CODEC - *******************************************************************/ -static const uint32_t CODEC_SPI_CLOCK_FREQ = 4000000; //4MHz -static const uint32_t ADF4001_SPI_CLOCK_FREQ = 200000; //200kHz - -/******************************************************************* - * UART - *******************************************************************/ -static const uint32_t DBG_UART_BAUD = 115200; - -/******************************************************************* - * Build Compatability Numbers - *******************************************************************/ -static const uint8_t PRODUCT_NUM = 0x01; -static const uint8_t COMPAT_MAJOR = 0x00; -static const uint16_t COMPAT_MINOR = 0x0000; - -static inline uint8_t get_prod_num(uint32_t compat_reg) { - return (compat_reg >> 24) & 0xFF; -} -static inline uint8_t get_compat_major(uint32_t compat_reg) { - return (compat_reg >> 16) & 0xFF; -} -static inline uint8_t get_compat_minor(uint32_t compat_reg) { - return compat_reg & 0xFFFF; -} - -#ifdef __cplusplus -}}}} //namespace -#endif -#endif /* INCLUDED_N230_FW_DEFS_H */ diff --git a/host/lib/usrp/n230/n230_fw_host_iface.h b/host/lib/usrp/n230/n230_fw_host_iface.h deleted file mode 100644 index 552049ccd..000000000 --- a/host/lib/usrp/n230/n230_fw_host_iface.h +++ /dev/null @@ -1,118 +0,0 @@ -// -// Copyright 2014 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#ifndef INCLUDED_N230_FW_HOST_IFACE_H -#define INCLUDED_N230_FW_HOST_IFACE_H - -#include <stdint.h> - -/*! - * Structs and constants for N230 communication between firmware and host. - * This header is shared by the firmware and host code. - * Therefore, this header may only contain valid C code. - */ -#ifdef __cplusplus -extern "C" { -#endif - -//-------------------------------------------------- -// Ethernet related -// -#define N230_DEFAULT_ETH0_MAC {0x00, 0x50, 0xC2, 0x85, 0x3f, 0xff} -#define N230_DEFAULT_ETH1_MAC {0x00, 0x50, 0xC2, 0x85, 0x3f, 0x33} -#define N230_DEFAULT_ETH0_IP (192 << 24 | 168 << 16 | 10 << 8 | 2 << 0) -#define N230_DEFAULT_ETH1_IP (192 << 24 | 168 << 16 | 20 << 8 | 2 << 0) -#define N230_DEFAULT_ETH0_MASK (255 << 24 | 255 << 16 | 255 << 8 | 0 << 0) -#define N230_DEFAULT_ETH1_MASK (255 << 24 | 255 << 16 | 255 << 8 | 0 << 0) -#define N230_DEFAULT_GATEWAY (192 << 24 | 168 << 16 | 10 << 8 | 1 << 0) - -#define N230_FW_COMMS_UDP_PORT 49152 -#define N230_FW_COMMS_CVITA_PORT 49153 -#define N230_FW_COMMS_FLASH_PROG_PORT 49154 -// -//-------------------------------------------------- - -//-------------------------------------------------- -// Memory shared with host -// -#define N230_FW_HOST_SHMEM_BASE_ADDR 0x10000 -#define N230_FW_HOST_SHMEM_RW_BASE_ADDR 0x1000C -#define N230_FW_HOST_SHMEM_NUM_WORDS (sizeof(n230_host_shared_mem_data_t)/sizeof(uint32_t)) - -#define N230_FW_HOST_SHMEM_MAX_ADDR \ - (N230_FW_HOST_SHMEM_BASE_ADDR + ((N230_FW_HOST_SHMEM_NUM_WORDS - 1) * sizeof(uint32_t))) - -#define N230_FW_HOST_SHMEM_OFFSET(member) \ - (N230_FW_HOST_SHMEM_BASE_ADDR + ((uint32_t)offsetof(n230_host_shared_mem_data_t, member))) - -//The shared memory block can only be accessed on 32-bit boundaries -typedef struct { //All fields must be 32-bit wide to avoid packing directives - //Read-Only fields (N230_FW_HOST_SHMEM_BASE_ADDR) - uint32_t fw_compat_num; //Compat number must be at offset 0 - uint32_t fw_version_hash; - uint32_t claim_status; - - //Read-Write fields (N230_FW_HOST_SHMEM_RW_BASE_ADDR) - uint32_t scratch; - uint32_t claim_time; - uint32_t claim_src; -} n230_host_shared_mem_data_t; - -typedef union -{ - uint32_t buff[N230_FW_HOST_SHMEM_NUM_WORDS]; - n230_host_shared_mem_data_t data; -} n230_host_shared_mem_t; - -#define N230_FW_PRODUCT_ID 1 -#define N230_FW_COMPAT_NUM_MAJOR 32 -#define N230_FW_COMPAT_NUM_MINOR 0 -#define N230_FW_COMPAT_NUM (((N230_FW_COMPAT_NUM_MAJOR & 0xFF) << 16) | (N230_FW_COMPAT_NUM_MINOR & 0xFFFF)) -// -//-------------------------------------------------- - -//-------------------------------------------------- -// Flash read-write interface for host -// -#define N230_FLASH_COMM_FLAGS_ACK 0x00000001 -#define N230_FLASH_COMM_FLAGS_CMD_MASK 0x00000FF0 -#define N230_FLASH_COMM_FLAGS_ERROR_MASK 0xFF000000 - -#define N230_FLASH_COMM_CMD_READ_NV_DATA 0x00000010 -#define N230_FLASH_COMM_CMD_WRITE_NV_DATA 0x00000020 -#define N230_FLASH_COMM_CMD_READ_FPGA 0x00000030 -#define N230_FLASH_COMM_CMD_WRITE_FPGA 0x00000040 -#define N230_FLASH_COMM_CMD_ERASE_FPGA 0x00000050 - -#define N230_FLASH_COMM_ERR_PKT_ERROR 0x80000000 -#define N230_FLASH_COMM_ERR_CMD_ERROR 0x40000000 -#define N230_FLASH_COMM_ERR_SIZE_ERROR 0x20000000 - -#define N230_FLASH_COMM_MAX_PAYLOAD_SIZE 128 - -typedef struct -{ - uint32_t flags; - uint32_t seq; - uint32_t offset; - uint32_t size; - uint8_t data[N230_FLASH_COMM_MAX_PAYLOAD_SIZE]; -} n230_flash_prog_t; -// -//-------------------------------------------------- - -#define N230_HW_REVISION_COMPAT 1 -#define N230_HW_REVISION_MIN 1 - - -#define N230_CLAIMER_TIMEOUT_IN_MS 2000 - -#ifdef __cplusplus -} -#endif - -#endif /* INCLUDED_N230_FW_HOST_IFACE_H */ diff --git a/host/lib/usrp/n230/n230_image_loader.cpp b/host/lib/usrp/n230/n230_image_loader.cpp deleted file mode 100644 index ac0daa770..000000000 --- a/host/lib/usrp/n230/n230_image_loader.cpp +++ /dev/null @@ -1,199 +0,0 @@ -// -// Copyright 2016 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#include <fstream> -#include <algorithm> -#include <uhd/image_loader.hpp> -#include <uhd/exception.hpp> -#include <uhd/utils/static.hpp> -#include <uhd/utils/byteswap.hpp> -#include <uhd/utils/paths.hpp> -#include <uhd/transport/udp_simple.hpp> -#include <boost/algorithm/string.hpp> -#include <boost/filesystem.hpp> -#include <boost/format.hpp> -#include "n230_fw_host_iface.h" -#include "n230_impl.hpp" - -using namespace uhd; -using namespace uhd::usrp; -using namespace uhd::transport; - -struct xil_bitfile_hdr_t { - xil_bitfile_hdr_t(): - valid(false), userid(0), product(""), - fpga(""), timestamp(""), filesize(0) - {} - - bool valid; - uint32_t userid; - std::string product; - std::string fpga; - std::string timestamp; - uint32_t filesize; -}; - -static inline uint16_t _to_uint16(uint8_t* buf) { - return (static_cast<uint16_t>(buf[0]) << 8) | - (static_cast<uint16_t>(buf[1]) << 0); -} - -static inline uint32_t _to_uint32(uint8_t* buf) { - return (static_cast<uint32_t>(buf[0]) << 24) | - (static_cast<uint32_t>(buf[1]) << 16) | - (static_cast<uint32_t>(buf[2]) << 8) | - (static_cast<uint32_t>(buf[3]) << 0); -} - -static void _parse_bitfile_header(const std::string& filepath, xil_bitfile_hdr_t& hdr) { - // Read header into memory - std::ifstream img_file(filepath.c_str(), std::ios::binary); - static const size_t MAX_HDR_SIZE = 1024; - boost::scoped_array<char> hdr_buf(new char[MAX_HDR_SIZE]); - img_file.seekg(0, std::ios::beg); - img_file.read(hdr_buf.get(), MAX_HDR_SIZE); - img_file.close(); - - //Parse header - size_t ptr = 0; - uint8_t* buf = reinterpret_cast<uint8_t*>(hdr_buf.get()); //Shortcut - - uint8_t signature[10] = {0x00, 0x09, 0x0f, 0xf0, 0x0f, 0xf0, 0x0f, 0xf0, 0x0f, 0xf0}; - if (memcmp(buf, signature, 10) == 0) { //Validate signature - ptr += _to_uint16(buf + ptr) + 2; - ptr += _to_uint16(buf + ptr) + 1; - - std::string fields[4]; - for (size_t i = 0; i < 4; i++) { - size_t key = buf[ptr++] - 'a'; - uint16_t len = _to_uint16(buf + ptr); ptr += 2; - fields[key] = std::string(reinterpret_cast<char*>(buf + ptr), size_t(len)); ptr += len; - } - - hdr.filesize = _to_uint32(buf + ++ptr); - hdr.fpga = fields[1]; - hdr.timestamp = fields[2] + std::string(" ") + fields[3]; - - std::vector<std::string> tokens; - boost::split(tokens, fields[0], boost::is_any_of(";")); - if (tokens.size() == 3) { - hdr.product = tokens[0]; - std::vector<std::string> uidtokens; - boost::split(uidtokens, tokens[1], boost::is_any_of("=")); - if (uidtokens.size() == 2 and uidtokens[0] == "UserID") { - std::stringstream stream; - stream << uidtokens[1]; - stream >> std::hex >> hdr.userid; - hdr.valid = true; - } - } - } -} - -static size_t _send_and_recv( - udp_simple::sptr xport, - n230_flash_prog_t& out, n230_flash_prog_t& in) -{ - static uint32_t seqno = 0; - out.seq = htonx<uint32_t>(++seqno); - xport->send(boost::asio::buffer(&out, sizeof(n230_flash_prog_t))); - size_t len = xport->recv(boost::asio::buffer(&in, udp_simple::mtu), 0.5); - if (len != sizeof(n230_flash_prog_t) or ntohx<uint32_t>(in.seq) != seqno) { - throw uhd::io_error("Error communicating with the device."); - } - return len; -} - - -static bool n230_image_loader(const image_loader::image_loader_args_t &loader_args){ - // Run discovery routine and ensure that exactly one N230 is specified - device_addrs_t devs = usrp::n230::n230_impl::n230_find(loader_args.args); - if (devs.size() == 0 or !loader_args.load_fpga) return false; - if (devs.size() > 1) { - throw uhd::runtime_error("Multiple devices match the specified args. To avoid accidentally updating the " - "wrong device, please narrow the search by specifying a unique \"addr\" argument."); - } - device_addr_t dev = devs[0]; - - // Sanity check the specified bitfile - std::string fpga_img_path = loader_args.fpga_path; - bool fpga_path_specified = !loader_args.fpga_path.empty(); - if (not fpga_path_specified) { - fpga_img_path = ( - fs::path(uhd::get_pkg_path()) / "share" / "uhd" / "images" / "usrp_n230_fpga.bit" - ).string(); - } - - if (not boost::filesystem::exists(fpga_img_path)) { - if (fpga_path_specified) { - throw uhd::runtime_error(str(boost::format("The file \"%s\" does not exist.") % fpga_img_path)); - } else { - throw uhd::runtime_error(str(boost::format( - "Could not find the default FPGA image: %s.\n" - "Either specify the --fpga-path argument or download the latest prebuilt images:\n" - "%s\n") - % fpga_img_path % print_utility_error("uhd_images_downloader.py"))); - } - } - xil_bitfile_hdr_t hdr; - _parse_bitfile_header(fpga_img_path, hdr); - - // Create a UDP communication link - udp_simple::sptr udp_xport = - udp_simple::make_connected(dev["addr"],BOOST_STRINGIZE(N230_FW_COMMS_FLASH_PROG_PORT)); - - if (hdr.valid and hdr.product == "n230") { - if (hdr.userid != 0x5AFE0000) { - std::cout << boost::format("Unit: USRP N230 (%s, %s)\n-- FPGA Image: %s\n") - % dev["addr"] % dev["serial"] % fpga_img_path; - - // Write image - std::ifstream image(fpga_img_path.c_str(), std::ios::binary); - size_t image_size = boost::filesystem::file_size(fpga_img_path); - - static const size_t SECTOR_SIZE = 65536; - static const size_t IMAGE_BASE = 0x400000; - - n230_flash_prog_t out, in; - size_t bytes_written = 0; - while (bytes_written < image_size) { - size_t payload_size = std::min<size_t>(image_size - bytes_written, N230_FLASH_COMM_MAX_PAYLOAD_SIZE); - if (bytes_written % SECTOR_SIZE == 0) { - out.flags = htonx<uint32_t>(N230_FLASH_COMM_FLAGS_ACK|N230_FLASH_COMM_CMD_ERASE_FPGA); - out.offset = htonx<uint32_t>(bytes_written + IMAGE_BASE); - out.size = htonx<uint32_t>(payload_size); - _send_and_recv(udp_xport, out, in); - } - out.flags = htonx<uint32_t>(N230_FLASH_COMM_FLAGS_ACK|N230_FLASH_COMM_CMD_WRITE_FPGA); - out.offset = htonx<uint32_t>(bytes_written + IMAGE_BASE); - out.size = htonx<uint32_t>(payload_size); - image.read((char*)out.data, payload_size); - _send_and_recv(udp_xport, out, in); - bytes_written += ntohx<uint32_t>(in.size); - std::cout << boost::format("\r-- Loading FPGA image: %d%%") - % (int(double(bytes_written) / double(image_size) * 100.0)) - << std::flush; - } - std::cout << std::endl << "FPGA image loaded successfully." << std::endl; - std::cout << std::endl << "Power-cycle the device to run the image." << std::endl; - return true; - } else { - throw uhd::runtime_error("This utility cannot burn a failsafe image!"); - } - } else { - throw uhd::runtime_error(str(boost::format("The file at path \"%s\" is not a valid USRP N230 FPGA image.") - % fpga_img_path)); - } -} - -UHD_STATIC_BLOCK(register_n230_image_loader){ - std::string recovery_instructions = "Aborting. Your USRP N230 device will likely boot in safe mode.\n" - "Please re-run this command with the additional \"safe_mode\" device argument\n" - "to recover your device."; - - image_loader::register_image_loader("n230", n230_image_loader, recovery_instructions); -} diff --git a/host/lib/usrp/n230/n230_impl.cpp b/host/lib/usrp/n230/n230_impl.cpp deleted file mode 100644 index 854585ae2..000000000 --- a/host/lib/usrp/n230/n230_impl.cpp +++ /dev/null @@ -1,613 +0,0 @@ -// -// Copyright 2014 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#include "n230_impl.hpp" -#include "n230_fw_ctrl_iface.hpp" -#include "n230_defaults.h" -#include "n230_fpga_defs.h" -#include "n230_fw_defs.h" -#include "n230_fw_host_iface.h" - -#include <uhdlib/usrp/common/validate_subdev_spec.hpp> - -#include <uhd/utils/static.hpp> -#include <uhd/transport/if_addrs.hpp> -#include <uhd/transport/udp_zero_copy.hpp> -#include <uhd/usrp/subdev_spec.hpp> -#include <uhd/utils/byteswap.hpp> -#include <uhd/utils/log.hpp> - -#include <uhd/types/sensors.hpp> -#include <uhd/types/ranges.hpp> -#include <uhd/types/direction.hpp> -#include <uhd/usrp/mboard_eeprom.hpp> -#include <uhd/usrp/dboard_eeprom.hpp> -#include <uhd/usrp/gps_ctrl.hpp> - -#include <boost/format.hpp> -#include <boost/lexical_cast.hpp> -#include <boost/bind.hpp> -#include <boost/algorithm/string.hpp> -#include <boost/asio/ip/address_v4.hpp> -#include <boost/asio.hpp> //used for htonl and ntohl -#include <boost/make_shared.hpp> - -#include <chrono> -#include <thread> - -namespace uhd { namespace usrp { namespace n230 { - -using namespace uhd::transport; -namespace asio = boost::asio; - -//---------------------------------------------------------- -// Static device registration with framework -//---------------------------------------------------------- -UHD_STATIC_BLOCK(register_n230_device) -{ - device::register_device(&n230_impl::n230_find, &n230_impl::n230_make, device::USRP); -} - -//---------------------------------------------------------- -// Device discovery -//---------------------------------------------------------- -uhd::device_addrs_t n230_impl::n230_find(const uhd::device_addr_t &multi_dev_hint) -{ - //handle the multi-device discovery - device_addrs_t hints = separate_device_addr(multi_dev_hint); - if (hints.size() > 1){ - device_addrs_t found_devices; - std::string error_msg; - for(const device_addr_t &hint_i: hints){ - device_addrs_t found_devices_i = n230_find(hint_i); - if (found_devices_i.size() != 1) error_msg += str(boost::format( - "Could not resolve device hint \"%s\" to a single device." - ) % hint_i.to_string()); - else found_devices.push_back(found_devices_i[0]); - } - if (found_devices.empty()) return device_addrs_t(); - if (not error_msg.empty()) throw uhd::value_error(error_msg); - return device_addrs_t(1, combine_device_addrs(found_devices)); - } - - //initialize the hint for a single device case - UHD_ASSERT_THROW(hints.size() <= 1); - hints.resize(1); //in case it was empty - device_addr_t hint = hints[0]; - device_addrs_t n230_addrs; - - //return an empty list of addresses when type is set to non-n230 - if (hint.has_key("type") and hint["type"] != "n230") return n230_addrs; - - //Return an empty list of addresses when a resource is specified, - //since a resource is intended for a different, non-networked, device. - if (hint.has_key("resource")) return n230_addrs; - - //if no address was specified, send a broadcast on each interface - if (not hint.has_key("addr")) { - for(const if_addrs_t &if_addrs: get_if_addrs()) { - //avoid the loopback device - if (if_addrs.inet == asio::ip::address_v4::loopback().to_string()) continue; - - //create a new hint with this broadcast address - device_addr_t new_hint = hint; - new_hint["addr"] = if_addrs.bcast; - - //call discover with the new hint and append results - device_addrs_t new_n230_addrs = n230_find(new_hint); - n230_addrs.insert(n230_addrs.begin(), - new_n230_addrs.begin(), new_n230_addrs.end() - ); - } - return n230_addrs; - } - - std::vector<std::string> discovered_addrs = - n230_fw_ctrl_iface::discover_devices( - hint["addr"], BOOST_STRINGIZE(N230_FW_COMMS_UDP_PORT), N230_FW_PRODUCT_ID); - - for(const std::string& addr: discovered_addrs) - { - device_addr_t new_addr; - new_addr["type"] = "n230"; - new_addr["addr"] = addr; - - //Attempt a simple 2-way communication with a connected socket. - //Reason: Although the USRP will respond the broadcast above, - //we may not be able to communicate directly (non-broadcast). - udp_simple::sptr ctrl_xport = udp_simple::make_connected(new_addr["addr"], BOOST_STRINGIZE(N230_FW_COMMS_UDP_PORT)); - - //Corner case: If two devices have the same IP but different MAC - //addresses and are used back-to-back it takes a while for ARP tables - //on the host to update in which period brodcasts will respond but - //connected communication can fail. Retry the following call to allow - //the stack to update - size_t first_conn_retries = 10; - n230_fw_ctrl_iface::sptr fw_ctrl; - while (first_conn_retries > 0) { - try { - fw_ctrl = n230_fw_ctrl_iface::make(ctrl_xport, N230_FW_PRODUCT_ID, false /*verbose*/); - break; - } catch (uhd::io_error& ex) { - std::this_thread::sleep_for(std::chrono::milliseconds(500)); - first_conn_retries--; - } - } - if (first_conn_retries > 0) { - uint32_t compat_reg = fw_ctrl->peek32(fw::reg_addr(fw::WB_SBRB_BASE, fw::RB_ZPU_COMPAT)); - if (fw::get_prod_num(compat_reg) == fw::PRODUCT_NUM) { - if (!n230_resource_manager::is_device_claimed(fw_ctrl)) { - //Not claimed by another process or host - try { - //Try to read the EEPROM to get the name and serial - n230_eeprom_manager eeprom_mgr(new_addr["addr"]); - const mboard_eeprom_t& eeprom = eeprom_mgr.get_mb_eeprom(); - new_addr["name"] = eeprom["name"]; - new_addr["serial"] = eeprom["serial"]; - } - catch(const std::exception &) - { - //set these values as empty string so the device may still be found - //and the filter's below can still operate on the discovered device - new_addr["name"] = ""; - new_addr["serial"] = ""; - } - //filter the discovered device below by matching optional keys - if ((not hint.has_key("name") or hint["name"] == new_addr["name"]) and - (not hint.has_key("serial") or hint["serial"] == new_addr["serial"])) - { - n230_addrs.push_back(new_addr); - } - } - } - } - } - - return n230_addrs; -} - -/*********************************************************************** - * Make - **********************************************************************/ -device::sptr n230_impl::n230_make(const device_addr_t &device_addr) -{ - return device::sptr(new n230_impl(device_addr)); -} - -/*********************************************************************** - * n230_impl::ctor - **********************************************************************/ -n230_impl::n230_impl(const uhd::device_addr_t& dev_addr) -{ - UHD_LOGGER_INFO("N230") << "N230 initialization sequence..."; - _dev_args.parse(dev_addr); - _tree = uhd::property_tree::make(); - - //TODO: Only supports one motherboard per device class. - const fs_path mb_path = "/mboards/0"; - - //Initialize addresses - std::vector<std::string> ip_addrs(1, dev_addr["addr"]); - if (dev_addr.has_key("second_addr")) { - ip_addrs.push_back(dev_addr["second_addr"]); - } - - //Read EEPROM and perform version checks before talking to HW - _eeprom_mgr = boost::make_shared<n230_eeprom_manager>(ip_addrs[0]); - const mboard_eeprom_t& mb_eeprom = _eeprom_mgr->get_mb_eeprom(); - bool recover_mb_eeprom = dev_addr.has_key("recover_mb_eeprom"); - if (recover_mb_eeprom) { - UHD_LOGGER_WARNING("N230") << "UHD is operating in EEPROM Recovery Mode which disables hardware version " - "checks.\nOperating in this mode may cause hardware damage and unstable " - "radio performance!"; - } - uint16_t hw_rev = boost::lexical_cast<uint16_t>(mb_eeprom["revision"]); - uint16_t hw_rev_compat = boost::lexical_cast<uint16_t>(mb_eeprom["revision_compat"]); - if (not recover_mb_eeprom) { - if (hw_rev_compat > N230_HW_REVISION_COMPAT) { - throw uhd::runtime_error(str(boost::format( - "Hardware is too new for this software. Please upgrade to a driver that supports hardware revision %d.") - % hw_rev)); - } - } - - //Initialize all subsystems - _resource_mgr = boost::make_shared<n230_resource_manager>(ip_addrs, _dev_args.get_safe_mode()); - _stream_mgr = boost::make_shared<n230_stream_manager>(_dev_args, _resource_mgr, _tree); - - //Build property tree - _initialize_property_tree(mb_path); - - //Debug loopback mode - switch(_dev_args.get_loopback_mode()) { - case n230_device_args_t::LOOPBACK_RADIO: - UHD_LOGGER_INFO("N230") << "DEBUG: Running in TX->RX Radio loopback mode."; - _resource_mgr->get_frontend_ctrl().set_self_test_mode(LOOPBACK_RADIO); - break; - case n230_device_args_t::LOOPBACK_CODEC: - UHD_LOGGER_INFO("N230") << "DEBUG: Running in TX->RX CODEC loopback mode."; - _resource_mgr->get_frontend_ctrl().set_self_test_mode(LOOPBACK_CODEC); - break; - default: - _resource_mgr->get_frontend_ctrl().set_self_test_mode(LOOPBACK_DISABLED); - break; - } -} - -/*********************************************************************** - * n230_impl::dtor - **********************************************************************/ -n230_impl::~n230_impl() -{ - _stream_mgr.reset(); - _eeprom_mgr.reset(); - _resource_mgr.reset(); - _tree.reset(); -} - -/*********************************************************************** - * n230_impl::get_rx_stream - **********************************************************************/ -rx_streamer::sptr n230_impl::get_rx_stream(const uhd::stream_args_t &args) -{ - return _stream_mgr->get_rx_stream(args); -} - -/*********************************************************************** - * n230_impl::get_tx_stream - **********************************************************************/ -tx_streamer::sptr n230_impl::get_tx_stream(const uhd::stream_args_t &args) -{ - return _stream_mgr->get_tx_stream(args); -} - -/*********************************************************************** - * n230_impl::recv_async_msg - **********************************************************************/ -bool n230_impl::recv_async_msg(uhd::async_metadata_t &async_metadata, double timeout) -{ - return _stream_mgr->recv_async_msg(async_metadata, timeout); -} - -/*********************************************************************** - * _initialize_property_tree - **********************************************************************/ -void n230_impl::_initialize_property_tree(const fs_path& mb_path) -{ - //------------------------------------------------------------------ - // General info - //------------------------------------------------------------------ - _tree->create<std::string>("/name").set("N230 Device"); - - _tree->create<std::string>(mb_path / "name").set("N230"); - _tree->create<std::string>(mb_path / "codename").set("N230"); - _tree->create<std::string>(mb_path / "dboards").set("none"); //No dboards. - - _tree->create<std::string>(mb_path / "fw_version").set(str(boost::format("%u.%u") - % _resource_mgr->get_version(FIRMWARE, COMPAT_MAJOR) - % _resource_mgr->get_version(FIRMWARE, COMPAT_MINOR))); - _tree->create<std::string>(mb_path / "fw_version_hash").set(str(boost::format("%s") - % _resource_mgr->get_version_hash(FIRMWARE))); - _tree->create<std::string>(mb_path / "fpga_version").set(str(boost::format("%u.%u") - % _resource_mgr->get_version(FPGA, COMPAT_MAJOR) - % _resource_mgr->get_version(FPGA, COMPAT_MINOR))); - _tree->create<std::string>(mb_path / "fpga_version_hash").set(str(boost::format("%s") - % _resource_mgr->get_version_hash(FPGA))); - - _tree->create<double>(mb_path / "link_max_rate").set(_resource_mgr->get_max_link_rate()); - - //------------------------------------------------------------------ - // EEPROM - //------------------------------------------------------------------ - _tree->create<mboard_eeprom_t>(mb_path / "eeprom") - .set(_eeprom_mgr->get_mb_eeprom()) //Set first... - .add_coerced_subscriber(boost::bind(&n230_eeprom_manager::write_mb_eeprom, _eeprom_mgr, _1)); //..then enable writer - - //------------------------------------------------------------------ - // Create codec nodes - //------------------------------------------------------------------ - const fs_path rx_codec_path = mb_path / ("rx_codecs") / "A"; - _tree->create<std::string>(rx_codec_path / "name") - .set("N230 RX dual ADC"); - _tree->create<int>(rx_codec_path / "gains"); //Empty because gains are in frontend - - const fs_path tx_codec_path = mb_path / ("tx_codecs") / "A"; - _tree->create<std::string>(tx_codec_path / "name") - .set("N230 TX dual DAC"); - _tree->create<int>(tx_codec_path / "gains"); //Empty because gains are in frontend - - //------------------------------------------------------------------ - // Create clock and time control nodes - //------------------------------------------------------------------ - _tree->create<double>(mb_path / "tick_rate") - .set_coercer(boost::bind(&n230_clk_pps_ctrl::set_tick_rate, _resource_mgr->get_clk_pps_ctrl_sptr(), _1)) - .set_publisher(boost::bind(&n230_clk_pps_ctrl::get_tick_rate, _resource_mgr->get_clk_pps_ctrl_sptr())) - .add_coerced_subscriber(boost::bind(&n230_stream_manager::update_tick_rate, _stream_mgr, _1)); - - //Register time now and pps onto available radio cores - //radio0 is the master - _tree->create<time_spec_t>(mb_path / "time" / "cmd"); - _tree->create<time_spec_t>(mb_path / "time" / "now") - .set_publisher(boost::bind(&time_core_3000::get_time_now, _resource_mgr->get_radio(0).time)); - _tree->create<time_spec_t>(mb_path / "time" / "pps") - .set_publisher(boost::bind(&time_core_3000::get_time_last_pps, _resource_mgr->get_radio(0).time)); - - //Setup time source props - _tree->create<std::string>(mb_path / "time_source" / "value") - .add_coerced_subscriber(boost::bind(&n230_impl::_check_time_source, this, _1)) - .add_coerced_subscriber(boost::bind(&n230_clk_pps_ctrl::set_pps_source, _resource_mgr->get_clk_pps_ctrl_sptr(), _1)) - .set(n230::DEFAULT_TIME_SRC); - const std::vector<std::string> time_sources{"none", "external", "gpsdo"}; - _tree->create<std::vector<std::string> >(mb_path / "time_source" / "options") - .set(time_sources); - - //Setup reference source props - _tree->create<std::string>(mb_path / "clock_source" / "value") - .add_coerced_subscriber(boost::bind(&n230_impl::_check_clock_source, this, _1)) - .add_coerced_subscriber(boost::bind(&n230_clk_pps_ctrl::set_clock_source, _resource_mgr->get_clk_pps_ctrl_sptr(), _1)) - .set(n230::DEFAULT_CLOCK_SRC); - const std::vector<std::string> clock_sources{"internal", "external", "gpsdo"}; - _tree->create<std::vector<std::string> >(mb_path / "clock_source" / "options") - .set(clock_sources); - _tree->create<sensor_value_t>(mb_path / "sensors" / "ref_locked") - .set_publisher(boost::bind(&n230_clk_pps_ctrl::get_ref_locked, _resource_mgr->get_clk_pps_ctrl_sptr())); - - //------------------------------------------------------------------ - // Create frontend mapping - //------------------------------------------------------------------ - _tree->create<subdev_spec_t>(mb_path / "rx_subdev_spec") - .set(subdev_spec_t()) - .add_coerced_subscriber(boost::bind(&n230_impl::_update_rx_subdev_spec, this, _1)); - _tree->create<subdev_spec_t>(mb_path / "tx_subdev_spec") - .set(subdev_spec_t()) - .add_coerced_subscriber(boost::bind(&n230_impl::_update_tx_subdev_spec, this, _1)); - - //------------------------------------------------------------------ - // Create a fake dboard to put frontends in - //------------------------------------------------------------------ - //For completeness we give it a fake EEPROM as well - dboard_eeprom_t db_eeprom; //Default state: ID is 0xffff, Version and serial empty - _tree->create<dboard_eeprom_t>(mb_path / "dboards" / "A" / "rx_eeprom").set(db_eeprom); - _tree->create<dboard_eeprom_t>(mb_path / "dboards" / "A" / "tx_eeprom").set(db_eeprom); - _tree->create<dboard_eeprom_t>(mb_path / "dboards" / "A" / "gdb_eeprom").set(db_eeprom); - - //------------------------------------------------------------------ - // Create radio specific nodes - //------------------------------------------------------------------ - for (size_t radio_instance = 0; radio_instance < fpga::NUM_RADIOS; radio_instance++) { - _initialize_radio_properties(mb_path, radio_instance); - } - //Update tick rate on newly created radio objects - _tree->access<double>(mb_path / "tick_rate").set(_dev_args.get_master_clock_rate()); - - //------------------------------------------------------------------ - // Initialize subdev specs - //------------------------------------------------------------------ - subdev_spec_t rx_spec, tx_spec; - for(const std::string &fe: _tree->list(mb_path / "dboards" / "A" / "rx_frontends")) - { - rx_spec.push_back(subdev_spec_pair_t("A", fe)); - } - for(const std::string &fe: _tree->list(mb_path / "dboards" / "A" / "tx_frontends")) - { - tx_spec.push_back(subdev_spec_pair_t("A", fe)); - } - _tree->access<subdev_spec_t>(mb_path / "rx_subdev_spec").set(rx_spec); - _tree->access<subdev_spec_t>(mb_path / "tx_subdev_spec").set(tx_spec); - - //------------------------------------------------------------------ - // MiniSAS GPIO - //------------------------------------------------------------------ - for(const usrp::gpio_atr::gpio_attr_map_t::value_type attr: usrp::gpio_atr::gpio_attr_map) { - switch (attr.first){ - case usrp::gpio_atr::GPIO_SRC: - case usrp::gpio_atr::GPIO_CTRL: - _tree->create<std::vector<std::string>>(mb_path / "gpio" / "FP0" / attr.second) - .set(std::vector<std::string>(32, usrp::gpio_atr::default_attr_value_map.at(attr.first))); - _tree->create<std::vector<std::string>>(mb_path / "gpio" / "FP1" / attr.second) - .set(std::vector<std::string>(32, usrp::gpio_atr::default_attr_value_map.at(attr.first))); - break; - case usrp::gpio_atr::GPIO_DDR: - _tree->create<std::vector<std::string>>(mb_path / "gpio" / "FP0" / attr.second) - .set(std::vector<std::string>(32, usrp::gpio_atr::default_attr_value_map.at(attr.first))) - .add_coerced_subscriber([this, attr](const std::vector<std::string> str_val){ - uint32_t val = 0; - for(size_t i = 0 ; i < str_val.size() ; i++){ - val += usrp::gpio_atr::gpio_attr_value_pair.at(attr.second).at(str_val[i])<<i; - } - _resource_mgr->get_minisas_gpio_ctrl_sptr(0)->set_gpio_attr(attr.first, val); - }); - _tree->create<std::vector<std::string>>(mb_path / "gpio" / "FP1" / attr.second) - .set(std::vector<std::string>(32, usrp::gpio_atr::default_attr_value_map.at(attr.first))) - .add_coerced_subscriber([this, attr](const std::vector<std::string> str_val){ - uint32_t val = 0; - for(size_t i = 0 ; i < str_val.size() ; i++){ - val += usrp::gpio_atr::gpio_attr_value_pair.at(attr.second).at(str_val[i])<<i; - } - _resource_mgr->get_minisas_gpio_ctrl_sptr(1)->set_gpio_attr(attr.first, val); - }); - break; - case usrp::gpio_atr::GPIO_OUT: - _tree->create<uint32_t>(mb_path / "gpio" / "FP0" / attr.second) - .set(0) - .add_coerced_subscriber([this, attr](const uint32_t val){ - _resource_mgr->get_minisas_gpio_ctrl_sptr(0)->set_gpio_attr(attr.first, val); - }); - _tree->create<uint32_t>(mb_path / "gpio" / "FP1" / attr.second) - .set(0) - .add_coerced_subscriber([this, attr](const uint32_t val){ - _resource_mgr->get_minisas_gpio_ctrl_sptr(1)->set_gpio_attr(attr.first, val); - }); - break; - case usrp::gpio_atr::GPIO_READBACK: - _tree->create<uint32_t>(mb_path / "gpio" / "FP0" / "READBACK") - .set_publisher(boost::bind(&gpio_atr::gpio_atr_3000::read_gpio, _resource_mgr->get_minisas_gpio_ctrl_sptr(0))); - _tree->create<uint32_t>(mb_path / "gpio" / "FP1" / "READBACK") - .set_publisher(boost::bind(&gpio_atr::gpio_atr_3000::read_gpio, _resource_mgr->get_minisas_gpio_ctrl_sptr(1))); - break; - default: - _tree->create<uint32_t>(mb_path / "gpio" / "FP0" / attr.second) - .set(0); - _tree->create<uint32_t>(mb_path / "gpio" / "FP1" / attr.second) - .set(0); - break; - } - } - //------------------------------------------------------------------ - // GPSDO sensors - //------------------------------------------------------------------ - if (_resource_mgr->is_gpsdo_present()) { - uhd::gps_ctrl::sptr gps_ctrl = _resource_mgr->get_gps_ctrl(); - for(const std::string &name: gps_ctrl->get_sensors()) - { - _tree->create<sensor_value_t>(mb_path / "sensors" / name) - .set_publisher(boost::bind(&gps_ctrl::get_sensor, gps_ctrl, name)); - } - } -} - -/*********************************************************************** - * _initialize_radio_properties - **********************************************************************/ -void n230_impl::_initialize_radio_properties(const fs_path& mb_path, size_t instance) -{ - radio_resource_t& perif = _resource_mgr->get_radio(instance); - - //Time - _tree->access<time_spec_t>(mb_path / "time" / "cmd") - .add_coerced_subscriber(boost::bind(&radio_ctrl_core_3000::set_time, perif.ctrl, _1)); - _tree->access<double>(mb_path / "tick_rate") - .add_coerced_subscriber(boost::bind(&radio_ctrl_core_3000::set_tick_rate, perif.ctrl, _1)); - _tree->access<time_spec_t>(mb_path / "time" / "now") - .add_coerced_subscriber(boost::bind(&time_core_3000::set_time_now, perif.time, _1)); - _tree->access<time_spec_t>(mb_path / "time" / "pps") - .add_coerced_subscriber(boost::bind(&time_core_3000::set_time_next_pps, perif.time, _1)); - - //RX DSP - _tree->access<double>(mb_path / "tick_rate") - .add_coerced_subscriber(boost::bind(&rx_vita_core_3000::set_tick_rate, perif.framer, _1)) - .add_coerced_subscriber(boost::bind(&rx_dsp_core_3000::set_tick_rate, perif.ddc, _1)); - const fs_path rx_dsp_path = mb_path / "rx_dsps" / str(boost::format("%u") % instance); - _tree->create<meta_range_t>(rx_dsp_path / "rate" / "range") - .set_publisher(boost::bind(&rx_dsp_core_3000::get_host_rates, perif.ddc)); - _tree->create<double>(rx_dsp_path / "rate" / "value") - .set_coercer(boost::bind(&rx_dsp_core_3000::set_host_rate, perif.ddc, _1)) - .add_coerced_subscriber(boost::bind(&n230_stream_manager::update_rx_samp_rate, _stream_mgr, instance, _1)) - .set(n230::DEFAULT_RX_SAMP_RATE); - _tree->create<double>(rx_dsp_path / "freq" / "value") - .set_coercer(boost::bind(&rx_dsp_core_3000::set_freq, perif.ddc, _1)) - .set(n230::DEFAULT_DDC_FREQ); - _tree->create<meta_range_t>(rx_dsp_path / "freq" / "range") - .set_publisher(boost::bind(&rx_dsp_core_3000::get_freq_range, perif.ddc)); - _tree->create<stream_cmd_t>(rx_dsp_path / "stream_cmd") - .add_coerced_subscriber(boost::bind(&rx_vita_core_3000::issue_stream_command, perif.framer, _1)); - - //TX DSP - _tree->access<double>(mb_path / "tick_rate") - .add_coerced_subscriber(boost::bind(&tx_dsp_core_3000::set_tick_rate, perif.duc, _1)); - const fs_path tx_dsp_path = mb_path / "tx_dsps" / str(boost::format("%u") % instance); - _tree->create<meta_range_t>(tx_dsp_path / "rate" / "range") - .set_publisher(boost::bind(&tx_dsp_core_3000::get_host_rates, perif.duc)); - _tree->create<double>(tx_dsp_path / "rate" / "value") - .set_coercer(boost::bind(&tx_dsp_core_3000::set_host_rate, perif.duc, _1)) - .add_coerced_subscriber(boost::bind(&n230_stream_manager::update_tx_samp_rate, _stream_mgr, instance, _1)) - .set(n230::DEFAULT_TX_SAMP_RATE); - _tree->create<double>(tx_dsp_path / "freq" / "value") - .set_coercer(boost::bind(&tx_dsp_core_3000::set_freq, perif.duc, _1)) - .set(n230::DEFAULT_DUC_FREQ); - _tree->create<meta_range_t>(tx_dsp_path / "freq" / "range") - .set_publisher(boost::bind(&tx_dsp_core_3000::get_freq_range, perif.duc)); - - //RF Frontend Interfacing - for (direction_t direction : std::vector<direction_t>{RX_DIRECTION, TX_DIRECTION}) { - const std::string dir_str = (direction == RX_DIRECTION) ? "rx" : "tx"; - const std::string key = boost::to_upper_copy(dir_str) + str(boost::format("%u") % (instance + 1)); - const fs_path rf_fe_path = mb_path / "dboards" / "A" / (dir_str + "_frontends") / ((instance==0)?"A":"B"); - - //CODEC subtree - _resource_mgr->get_codec_mgr().populate_frontend_subtree(_tree->subtree(rf_fe_path), key, direction); - - //User settings - _tree->create<uhd::wb_iface::sptr>(rf_fe_path / "user_settings" / "iface") - .set(perif.user_settings); - - //Setup antenna stuff - if (key[0] == 'R') { - _tree->create<std::vector<std::string> >(rf_fe_path / "antenna" / "options") - .set({"TX/RX", "RX2"}); - _tree->create<std::string>(rf_fe_path / "antenna" / "value") - .add_coerced_subscriber(boost::bind(&n230_frontend_ctrl::set_antenna_sel, _resource_mgr->get_frontend_ctrl_sptr(), instance, _1)) - .set("RX2"); - } - if (key[0] == 'T') { - _tree->create<std::vector<std::string> >(rf_fe_path / "antenna" / "options") - .set({"TX/RX"}); - _tree->create<std::string>(rf_fe_path / "antenna" / "value") - .set("TX/RX"); - } - } -} - -void n230_impl::_update_rx_subdev_spec(const uhd::usrp::subdev_spec_t &spec) -{ - //sanity checking - if (spec.size()) validate_subdev_spec(_tree, spec, "rx"); - UHD_ASSERT_THROW(spec.size() <= fpga::NUM_RADIOS); - - if (spec.size() > 0) { - UHD_ASSERT_THROW(spec[0].db_name == "A"); - UHD_ASSERT_THROW(spec[0].sd_name == "A"); - } - if (spec.size() > 1) { - //TODO we can support swapping at a later date, only this combo is supported - UHD_ASSERT_THROW(spec[1].db_name == "A"); - UHD_ASSERT_THROW(spec[1].sd_name == "B"); - } - - _stream_mgr->update_stream_states(); -} - -void n230_impl::_update_tx_subdev_spec(const uhd::usrp::subdev_spec_t &spec) -{ - //sanity checking - if (spec.size()) validate_subdev_spec(_tree, spec, "tx"); - UHD_ASSERT_THROW(spec.size() <= fpga::NUM_RADIOS); - - if (spec.size() > 0) { - UHD_ASSERT_THROW(spec[0].db_name == "A"); - UHD_ASSERT_THROW(spec[0].sd_name == "A"); - } - if (spec.size() > 1) { - //TODO we can support swapping at a later date, only this combo is supported - UHD_ASSERT_THROW(spec[1].db_name == "A"); - UHD_ASSERT_THROW(spec[1].sd_name == "B"); - } - - _stream_mgr->update_stream_states(); -} - -void n230_impl::_check_time_source(std::string source) -{ - if (source == "gpsdo") - { - uhd::gps_ctrl::sptr gps_ctrl = _resource_mgr->get_gps_ctrl(); - if (not (gps_ctrl and gps_ctrl->gps_detected())) - throw uhd::runtime_error("GPSDO time source not available"); - } -} - -void n230_impl::_check_clock_source(std::string source) -{ - if (source == "gpsdo") - { - uhd::gps_ctrl::sptr gps_ctrl = _resource_mgr->get_gps_ctrl(); - if (not (gps_ctrl and gps_ctrl->gps_detected())) - throw uhd::runtime_error("GPSDO clock source not available"); - } -} - -}}} //namespace diff --git a/host/lib/usrp/n230/n230_impl.hpp b/host/lib/usrp/n230/n230_impl.hpp deleted file mode 100644 index 213f0f61e..000000000 --- a/host/lib/usrp/n230/n230_impl.hpp +++ /dev/null @@ -1,71 +0,0 @@ -// -// Copyright 2014 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#ifndef INCLUDED_N230_IMPL_HPP -#define INCLUDED_N230_IMPL_HPP - -#include <uhd/property_tree.hpp> -#include <uhd/device.hpp> -#include <uhd/usrp/subdev_spec.hpp> - -#include "n230_device_args.hpp" -#include "n230_eeprom_manager.hpp" -#include "n230_resource_manager.hpp" -#include "n230_stream_manager.hpp" -#include <uhdlib/usrp/common/recv_packet_demuxer_3000.hpp> - -namespace uhd { namespace usrp { namespace n230 { - -class n230_impl : public uhd::device -{ -public: //Functions - // ctor and dtor - n230_impl(const uhd::device_addr_t& device_addr); - virtual ~n230_impl(void); - - //--------------------------------------------------------------------- - // uhd::device interface - // - static sptr make(const uhd::device_addr_t &hint, size_t which = 0); - - //! Make a new receive streamer from the streamer arguments - virtual uhd::rx_streamer::sptr get_rx_stream(const uhd::stream_args_t &args); - - //! Make a new transmit streamer from the streamer arguments - virtual uhd::tx_streamer::sptr get_tx_stream(const uhd::stream_args_t &args); - - //!Receive and asynchronous message from the device. - virtual bool recv_async_msg(uhd::async_metadata_t &async_metadata, double timeout = 0.1); - - //!Registration methods the discovery and factory system. - //[static void register_device(const find_t &find, const make_t &make)] - static uhd::device_addrs_t n230_find(const uhd::device_addr_t &hint); - static uhd::device::sptr n230_make(const uhd::device_addr_t &device_addr); - // - //--------------------------------------------------------------------- - - typedef uhd::transport::bounded_buffer<uhd::async_metadata_t> async_md_type; - -private: //Functions - void _initialize_property_tree(const fs_path& mb_path); - void _initialize_radio_properties(const fs_path& mb_path, size_t instance); - - void _update_rx_subdev_spec(const uhd::usrp::subdev_spec_t &); - void _update_tx_subdev_spec(const uhd::usrp::subdev_spec_t &); - void _check_time_source(std::string); - void _check_clock_source(std::string); - -private: //Classes and Members - n230_device_args_t _dev_args; - boost::shared_ptr<n230_resource_manager> _resource_mgr; - boost::shared_ptr<n230_eeprom_manager> _eeprom_mgr; - boost::shared_ptr<n230_stream_manager> _stream_mgr; -}; - -}}} //namespace - -#endif /* INCLUDED_N230_IMPL_HPP */ diff --git a/host/lib/usrp/n230/n230_resource_manager.cpp b/host/lib/usrp/n230/n230_resource_manager.cpp deleted file mode 100644 index 22f8ddedb..000000000 --- a/host/lib/usrp/n230/n230_resource_manager.cpp +++ /dev/null @@ -1,561 +0,0 @@ -// -// Copyright 2013 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#include "n230_resource_manager.hpp" - -#include "n230_fw_ctrl_iface.hpp" -#include <uhd/transport/if_addrs.hpp> -#include <uhd/transport/udp_zero_copy.hpp> -#include <uhd/utils/byteswap.hpp> -#include <uhd/utils/log.hpp> -#include <uhd/utils/platform.hpp> -#include <uhd/utils/paths.hpp> -#include <boost/format.hpp> -#include <boost/functional/hash.hpp> -#include <boost/make_shared.hpp> -#include "n230_fw_defs.h" -#include "n230_fw_host_iface.h" -#include <chrono> -#include <thread> - -#define IF_DATA_I_MASK 0xFFF00000 -#define IF_DATA_Q_MASK 0x0000FFF0 - -namespace uhd { namespace usrp { namespace n230 { - -//Constants -static const uint8_t N230_HOST_SRC_ADDR_ETH0 = 0; -static const uint8_t N230_HOST_SRC_ADDR_ETH1 = 1; -static const uint8_t N230_HOST_DEST_ADDR = 2; - -static const uint8_t N230_ETH0_IFACE_ID = 0; -static const uint8_t N230_ETH1_IFACE_ID = 1; - -boost::mutex n230_resource_manager::_claimer_mutex; - -class n230_ad9361_client_t : public ad9361_params { -public: - ~n230_ad9361_client_t() {} - double get_band_edge(frequency_band_t band) { - switch (band) { - case AD9361_RX_BAND0: return 2.2e9; - case AD9361_RX_BAND1: return 4.0e9; - case AD9361_TX_BAND0: return 2.5e9; - default: return 0; - } - } - clocking_mode_t get_clocking_mode() { - return clocking_mode_t::AD9361_XTAL_N_CLK_PATH; - } - digital_interface_mode_t get_digital_interface_mode() { - return AD9361_DDR_FDD_LVDS; - } - digital_interface_delays_t get_digital_interface_timing() { - digital_interface_delays_t delays; - delays.rx_clk_delay = 0; - delays.rx_data_delay = 0; - delays.tx_clk_delay = 0; - delays.tx_data_delay = 2; - return delays; - } -}; - -n230_resource_manager::n230_resource_manager( - const std::vector<std::string> ip_addrs, - const bool safe_mode -) : - _safe_mode(safe_mode), - _last_host_enpoint(0) -{ - if (_safe_mode) UHD_LOGGER_WARNING("N230") << "Initializing device in safe mode\n"; - UHD_LOGGER_INFO("N230") << "Setup basic communication..."; - - //Discover ethernet interfaces - bool dual_eth_expected = (ip_addrs.size() > 1); - for(const std::string& addr: ip_addrs) { - n230_eth_conn_t conn_iface; - conn_iface.ip_addr = addr; - - uint32_t iface_id = 0xFFFFFFFF; - try { - iface_id = n230::n230_fw_ctrl_iface::get_iface_id( - conn_iface.ip_addr, BOOST_STRINGIZE(N230_FW_COMMS_UDP_PORT), N230_FW_PRODUCT_ID); - } catch (uhd::io_error&) { - throw uhd::io_error(str(boost::format( - "Could not communicate with the device over address %s") % - conn_iface.ip_addr)); - } - switch (iface_id) { - case N230_ETH0_IFACE_ID: conn_iface.type = ETH0; break; - case N230_ETH1_IFACE_ID: conn_iface.type = ETH1; break; - default: { - if (dual_eth_expected) { - throw uhd::runtime_error("N230 Initialization Error: Could not detect ethernet port number."); - } else { - //For backwards compatibility, if only one port is specified, assume that a detection - //failure means that the device does not support dual-ethernet behavior. - conn_iface.type = ETH0; break; - } - } - } - _eth_conns.push_back(conn_iface); - } - if (_eth_conns.size() < 1) { - throw uhd::runtime_error("N230 Initialization Error: No eth interfaces specified.)"); - } - - //Create firmware communication interface - _fw_ctrl = n230::n230_fw_ctrl_iface::make( - transport::udp_simple::make_connected( - _get_conn(PRI_ETH).ip_addr, BOOST_STRINGIZE(N230_FW_COMMS_UDP_PORT)), N230_FW_PRODUCT_ID); - if (_fw_ctrl.get() == NULL) { - throw uhd::runtime_error("N230 Initialization Error: Could not create n230_ctrl_iface.)"); - } - _check_fw_compat(); - - //Start the device claimer - _claimer_task = uhd::task::make(boost::bind(&n230_resource_manager::_claimer_loop, this)); - - //Create common settings interface - const sid_t core_sid = _generate_sid(CORE, _get_conn(PRI_ETH).type); - - transport::udp_zero_copy::buff_params dummy_out_params; - transport::zero_copy_if::sptr core_xport = - _create_transport(_get_conn(PRI_ETH), core_sid, device_addr_t(), dummy_out_params); - if (core_xport.get() == NULL) { - throw uhd::runtime_error("N230 Initialization Error: Could not create settings transport.)"); - } - _core_ctrl = radio_ctrl_core_3000::make( - fpga::CVITA_BIG_ENDIAN, core_xport, core_xport, core_sid.get()); - if (_core_ctrl.get() == NULL) { - throw uhd::runtime_error("N230 Initialization Error: Could not create settings ctrl.)"); - } - _check_fpga_compat(); - - UHD_LOGGER_INFO("N230") << boost::format("Version signatures... Firmware:%s FPGA:%s...") - % _fw_version.get_hash_str() % _fpga_version.get_hash_str(); - - _core_radio_ctrl_reg.initialize(*_core_ctrl, true /*flush*/); - _core_misc_reg.initialize(*_core_ctrl, true /*flush*/); - _core_pps_sel_reg.initialize(*_core_ctrl, true /*flush*/); - _core_status_reg.initialize(*_core_ctrl); - - //Create common SPI interface - _core_spi_ctrl = n230_core_spi_core::make(_core_ctrl); - if (_core_spi_ctrl.get() == NULL) { - throw uhd::runtime_error("N230 Initialization Error: Could not create SPI ctrl.)"); - } - - //Create AD9361 interface - UHD_LOGGER_INFO("N230") << "Initializing CODEC..."; - _codec_ctrl = ad9361_ctrl::make_spi( - boost::make_shared<n230_ad9361_client_t>(), _core_spi_ctrl, fpga::AD9361_SPI_SLAVE_NUM); - if (_codec_ctrl.get() == NULL) { - throw uhd::runtime_error("N230 Initialization Error: Could not create Catalina ctrl.)"); - } - _codec_ctrl->set_clock_rate(fpga::CODEC_DEFAULT_CLK_RATE); - _codec_mgr = ad936x_manager::make(_codec_ctrl, fpga::NUM_RADIOS); - _codec_mgr->init_codec(); - - //Create AD4001 interface - _ref_pll_ctrl = boost::make_shared<n230_ref_pll_ctrl>(_core_spi_ctrl); - if (_ref_pll_ctrl.get() == NULL) { - throw uhd::runtime_error("N230 Initialization Error: Could not create ADF4001 ctrl.)"); - } - - //Reset SERDES interface and synchronize to frame sync from AD9361 - _reset_codec_digital_interface(); - - std::vector<time_core_3000::sptr> time_cores; - std::vector<gpio_atr::gpio_atr_3000::sptr> gpio_cores; - for (size_t i = 0; i < fpga::NUM_RADIOS; i++) { - _initialize_radio(i); - time_cores.push_back(_radios[i].time); - gpio_cores.push_back(_radios[i].gpio_atr); - } - - //Create clock and PPS control interface - _clk_pps_ctrl = n230_clk_pps_ctrl::make( - _codec_ctrl, _ref_pll_ctrl, _core_misc_reg, _core_pps_sel_reg, _core_status_reg, time_cores); - if (_clk_pps_ctrl.get() == NULL) { - throw uhd::runtime_error("N230 Initialization Error: Could not create clock and PPS ctrl.)"); - } - - //Create front-end control interface - _frontend_ctrl = n230_frontend_ctrl::make(_core_ctrl, _core_misc_reg, _codec_ctrl, gpio_cores); - if (_frontend_ctrl.get() == NULL) { - throw uhd::runtime_error("N230 Initialization Error: Could not create front-end ctrl.)"); - } - - //Create miniSAS GPIO interfaces - _ms0_gpio = gpio_atr::gpio_atr_3000::make( - _core_ctrl, fpga::sr_addr(fpga::SR_CORE_MS0_GPIO), fpga::rb_addr(fpga::RB_CORE_MS0_GPIO)); - _ms0_gpio->set_atr_mode(gpio_atr::MODE_GPIO,gpio_atr::gpio_atr_3000::MASK_SET_ALL); - _ms1_gpio = gpio_atr::gpio_atr_3000::make( - _core_ctrl, fpga::sr_addr(fpga::SR_CORE_MS1_GPIO), fpga::rb_addr(fpga::RB_CORE_MS1_GPIO)); - _ms1_gpio->set_atr_mode(gpio_atr::MODE_GPIO,gpio_atr::gpio_atr_3000::MASK_SET_ALL); - - //Create GPSDO interface - if (_core_status_reg.read(fpga::core_status_reg_t::GPSDO_STATUS) != fpga::GPSDO_ST_ABSENT) { - UHD_LOGGER_INFO("N230") << "Detecting GPSDO.... "; - try { - const sid_t gps_uart_sid = _generate_sid(GPS_UART, _get_conn(PRI_ETH).type); - transport::zero_copy_if::sptr gps_uart_xport = - _create_transport(_get_conn(PRI_ETH), gps_uart_sid, device_addr_t(), dummy_out_params); - _gps_uart = n230_uart::make(gps_uart_xport, uhd::htonx(gps_uart_sid.get())); - _gps_uart->set_baud_divider(fpga::BUS_CLK_RATE/fpga::GPSDO_UART_BAUDRATE); - _gps_uart->write_uart("\n"); //cause the baud and response to be setup - std::this_thread::sleep_for(std::chrono::seconds(1)); //allow for a little propagation - _gps_ctrl = gps_ctrl::make(_gps_uart); - } catch(std::exception &e) { - UHD_LOGGER_ERROR("N230") << "An error occurred making GPSDO control: " << e.what() ; - } - if (not is_gpsdo_present()) { - _core_ctrl->poke32(fpga::sr_addr(fpga::SR_CORE_GPSDO_ST), fpga::GPSDO_ST_ABSENT); - } - } - - //Perform data self-tests - _frontend_ctrl->set_stream_state(TXRX_STREAMING, TXRX_STREAMING); - for (size_t i = 0; i < fpga::NUM_RADIOS; i++) { - _frontend_ctrl->set_self_test_mode(LOOPBACK_RADIO); - bool radio_selftest_pass = _radio_data_loopback_self_test(_radios[i].ctrl); - if (!radio_selftest_pass) { - throw uhd::runtime_error("N230 Initialization Error: Data loopback test failed.)"); - } - - _frontend_ctrl->set_self_test_mode(LOOPBACK_CODEC); - bool codec_selftest_pass = _radio_data_loopback_self_test(_radios[i].ctrl); - if (!codec_selftest_pass) { - throw uhd::runtime_error("N230 Initialization Error: Codec loopback test failed.)"); - } - } - _frontend_ctrl->set_self_test_mode(LOOPBACK_DISABLED); - _frontend_ctrl->set_stream_state(NONE_STREAMING, NONE_STREAMING); -} - -n230_resource_manager::~n230_resource_manager() -{ - _claimer_task.reset(); - { //Critical section - boost::mutex::scoped_lock lock(_claimer_mutex); - _fw_ctrl->poke32(N230_FW_HOST_SHMEM_OFFSET(claim_time), 0); - _fw_ctrl->poke32(N230_FW_HOST_SHMEM_OFFSET(claim_src), 0); - } -} - -transport::zero_copy_if::sptr n230_resource_manager::create_transport( - n230_data_dir_t direction, - size_t radio_instance, - const device_addr_t ¶ms, - sid_t& sid_pair, - transport::udp_zero_copy::buff_params& buff_out_params) -{ - const n230_eth_conn_t& conn = _get_conn((radio_instance==1)?SEC_ETH:PRI_ETH); - const sid_t temp_sid_pair = - _generate_sid(direction==RX_DATA?RADIO_RX_DATA:RADIO_TX_DATA, conn.type, radio_instance); - transport::zero_copy_if::sptr xport = _create_transport(conn, temp_sid_pair, params, buff_out_params); - if (xport.get() == NULL) { - throw uhd::runtime_error("N230 Create Data Transport: Could not create data transport.)"); - } else { - sid_pair = temp_sid_pair; - } - return xport; -} - -bool n230_resource_manager::is_device_claimed(n230_fw_ctrl_iface::sptr fw_ctrl) -{ - boost::mutex::scoped_lock lock(_claimer_mutex); - - //If timed out then device is definitely unclaimed - if (fw_ctrl->peek32(N230_FW_HOST_SHMEM_OFFSET(claim_status)) == 0) - return false; - - //otherwise check claim src to determine if another thread with the same src has claimed the device - return fw_ctrl->peek32(N230_FW_HOST_SHMEM_OFFSET(claim_src)) != get_process_hash(); -} - -void n230_resource_manager::_claimer_loop() -{ - { //Critical section - boost::mutex::scoped_lock lock(_claimer_mutex); - _fw_ctrl->poke32(N230_FW_HOST_SHMEM_OFFSET(claim_time), time(NULL)); - _fw_ctrl->poke32(N230_FW_HOST_SHMEM_OFFSET(claim_src), get_process_hash()); - } - std::this_thread::sleep_for(std::chrono::milliseconds(N230_CLAIMER_TIMEOUT_IN_MS / 2)); -} - -void n230_resource_manager::_initialize_radio(size_t instance) -{ - radio_resource_t& radio = _radios[instance]; - - //Create common settings interface - const sid_t ctrl_sid = _generate_sid(RADIO_CONTROL, _get_conn(PRI_ETH).type, instance); - transport::udp_zero_copy::buff_params buff_out_params; - transport::zero_copy_if::sptr ctrl_xport = - _create_transport(_get_conn(PRI_ETH), ctrl_sid, device_addr_t(), buff_out_params); - if (ctrl_xport.get() == NULL) { - throw uhd::runtime_error("N230 Initialization Error: Could not create radio transport.)"); - } - radio.ctrl = radio_ctrl_core_3000::make( - fpga::CVITA_BIG_ENDIAN, ctrl_xport, ctrl_xport, ctrl_sid.get()); - if (radio.ctrl.get() == NULL) { - throw uhd::runtime_error("N230 Initialization Error: Could not create radio ctrl.)"); - } - - //Perform register loopback test to verify the radio clock - bool reg_selftest_pass = _radio_register_loopback_self_test(radio.ctrl); - if (!reg_selftest_pass) { - throw uhd::runtime_error("N230 Initialization Error: Register loopback test failed.)"); - } - - //Write-only ATR interface - radio.gpio_atr = gpio_atr::gpio_atr_3000::make_write_only(radio.ctrl, fpga::sr_addr(fpga::SR_RADIO_ATR)); - radio.gpio_atr->set_atr_mode(gpio_atr::MODE_ATR,gpio_atr::gpio_atr_3000::MASK_SET_ALL); - - //Core VITA time interface - time_core_3000::readback_bases_type time_bases; - time_bases.rb_now = fpga::rb_addr(fpga::RB_RADIO_TIME_NOW); - time_bases.rb_pps = fpga::rb_addr(fpga::RB_RADIO_TIME_PPS); - radio.time = time_core_3000::make(radio.ctrl, fpga::sr_addr(fpga::SR_RADIO_TIME), time_bases); - if (radio.time.get() == NULL) { - throw uhd::runtime_error("N230 Initialization Error: Could not create time core.)"); - } - - //RX DSP - radio.framer = rx_vita_core_3000::make( - radio.ctrl, fpga::sr_addr(fpga::SR_RADIO_RX_CTRL)); - radio.ddc = rx_dsp_core_3000::make(radio.ctrl, fpga::sr_addr(fpga::SR_RADIO_RX_DSP), true /*old DDC?*/); - if (radio.framer.get() == NULL || radio.ddc.get() == NULL) { - throw uhd::runtime_error("N230 Initialization Error: Could not create RX DSP interface.)"); - } - radio.ddc->set_link_rate(fpga::N230_LINK_RATE_BPS); - - //TX DSP - radio.deframer = tx_vita_core_3000::make(radio.ctrl, fpga::sr_addr(fpga::SR_RADIO_TX_CTRL)); - radio.duc = tx_dsp_core_3000::make(radio.ctrl, fpga::sr_addr(fpga::SR_RADIO_TX_DSP)); - if (radio.deframer.get() == NULL || radio.duc.get() == NULL) { - throw uhd::runtime_error("N230 Initialization Error: Could not create RX DSP interface.)"); - } - radio.duc->set_link_rate(fpga::N230_LINK_RATE_BPS); - - //User settings - radio.user_settings = user_settings_core_3000::make(radio.ctrl, - fpga::sr_addr(fpga::SR_RADIO_USER_SR), fpga::rb_addr(fpga::SR_RADIO_USER_RB)); - if (radio.user_settings.get() == NULL) { - throw uhd::runtime_error("N230 Initialization Error: Could not create user settings bus.)"); - } -} - -uint8_t xb_ep_to_sid(fpga::xb_endpoint_t ep) { - return static_cast<uint8_t>(ep) << 4; -} - -const sid_t n230_resource_manager::_generate_sid(const n230_endpoint_t type, const n230_eth_port_t xport, size_t instance) -{ - fpga::xb_endpoint_t xb_dest_ep; - uint8_t sid_dest_ep = 0; - fpga::xb_endpoint_t xb_ret_ep = (xport == ETH1) ? fpga::N230_XB_DST_E1 : fpga::N230_XB_DST_E0; - uint8_t sid_ret_addr = (xport == ETH1) ? N230_HOST_SRC_ADDR_ETH1 : N230_HOST_SRC_ADDR_ETH0; - - if (type == CORE or type == GPS_UART) { - //Non-radio endpoints - xb_dest_ep = (type == CORE) ? fpga::N230_XB_DST_GCTRL : fpga::N230_XB_DST_UART; - sid_dest_ep = xb_ep_to_sid(xb_dest_ep); - } else { - //Radio endpoints - xb_dest_ep = (instance == 1) ? fpga::N230_XB_DST_R1 : fpga::N230_XB_DST_R0; - sid_dest_ep = xb_ep_to_sid(xb_dest_ep); - switch (type) { - case RADIO_TX_DATA: - sid_dest_ep |= fpga::RADIO_DATA_SUFFIX; - break; - case RADIO_RX_DATA: - sid_dest_ep |= fpga::RADIO_FC_SUFFIX; - break; - default: - sid_dest_ep |= fpga::RADIO_CTRL_SUFFIX; - break; - } - } - - //Increment last host logical endpoint - sid_t sid(sid_ret_addr, ++_last_host_enpoint, N230_HOST_DEST_ADDR, sid_dest_ep); - - //Program the crossbar addr - _fw_ctrl->poke32(fw::reg_addr(fw::WB_SBRB_BASE, fw::SR_ZPU_XB_LOCAL), sid.get_dst_addr()); - // Program CAM entry for returning packets to us - // This type of packet does not match the XB_LOCAL address and is looked up in the lower half of the CAM - _fw_ctrl->poke32(fw::reg_addr(fw::WB_XB_SBRB_BASE, sid.get_src_addr()), static_cast<uint32_t>(xb_ret_ep)); - // Program CAM entry for outgoing packets matching a N230 resource (for example a Radio) - // This type of packet does matches the XB_LOCAL address and is looked up in the upper half of the CAM - _fw_ctrl->poke32(fw::reg_addr(fw::WB_XB_SBRB_BASE, 256 + sid.get_dst_endpoint()), static_cast<uint32_t>(xb_dest_ep)); - - return sid; -} - -transport::zero_copy_if::sptr n230_resource_manager::_create_transport( - const n230_eth_conn_t& eth_conn, - const sid_t& sid, const device_addr_t &buff_params, - transport::udp_zero_copy::buff_params& buff_params_out) -{ - transport::zero_copy_xport_params default_buff_args; - default_buff_args.recv_frame_size = transport::udp_simple::mtu; - default_buff_args.send_frame_size = transport::udp_simple::mtu; - default_buff_args.num_recv_frames = 32; - default_buff_args.num_send_frames = 32; - - transport::zero_copy_if::sptr xport = transport::udp_zero_copy::make( - eth_conn.ip_addr, std::to_string(fpga::CVITA_UDP_PORT), - default_buff_args, buff_params_out, buff_params); - - if (xport.get()) { - _program_dispatcher(*xport, eth_conn.type, sid); - } - return xport; -} - -void n230_resource_manager::_program_dispatcher( - transport::zero_copy_if& xport, const n230_eth_port_t port, const sid_t& sid) -{ - //Send a mini packet with SID into the ZPU - //ZPU will reprogram the ethernet framer - transport::managed_send_buffer::sptr buff = xport.get_send_buff(); - buff->cast<uint32_t *>()[0] = 0; //eth dispatch looks for != 0 - buff->cast<uint32_t *>()[1] = uhd::htonx(sid.get()); - buff->commit(8); - buff.reset(); - - //reprogram the ethernet dispatcher's udp port (should be safe to always set) - uint32_t disp_base_offset = - ((port == ETH1) ? fw::SR_ZPU_ETHINT1 : fw::SR_ZPU_ETHINT0) + fw::SR_ZPU_ETHINT_DISPATCHER_BASE; - _fw_ctrl->poke32(fw::reg_addr(fw::WB_SBRB_BASE, disp_base_offset + fw::ETH_FRAMER_SRC_UDP_PORT), fpga::CVITA_UDP_PORT); - - //Do a peek to an arbitrary address to guarantee that the - //ethernet framer has been programmed before we return. - _fw_ctrl->peek32(0); -} - -void n230_resource_manager::_reset_codec_digital_interface() -{ - //Set timing registers - _core_ctrl->poke32(fpga::sr_addr(fpga::SR_CORE_DATA_DELAY), fpga::CODEC_DATA_DELAY); - _core_ctrl->poke32(fpga::sr_addr(fpga::SR_CORE_CLK_DELAY), fpga::CODEC_CLK_DELAY); - - _core_radio_ctrl_reg.write(fpga::core_radio_ctrl_reg_t::CODEC_ARST, 1); - std::this_thread::sleep_for(std::chrono::milliseconds(10)); - _core_radio_ctrl_reg.write(fpga::core_radio_ctrl_reg_t::CODEC_ARST, 0); -} - -bool n230_resource_manager::_radio_register_loopback_self_test(wb_iface::sptr iface) -{ - bool test_fail = false; - size_t hash = static_cast<size_t>(time(NULL)); - for (size_t i = 0; i < 100; i++) { - boost::hash_combine(hash, i); - iface->poke32(fpga::sr_addr(fpga::SR_RADIO_TEST), uint32_t(hash)); - test_fail = iface->peek32(fpga::rb_addr(fpga::RB_RADIO_TEST)) != uint32_t(hash); - if (test_fail) break; //exit loop on any failure - } - return !test_fail; -} - -bool n230_resource_manager::_radio_data_loopback_self_test(wb_iface::sptr iface) -{ - bool test_fail = false; - size_t hash = size_t(time(NULL)); - for (size_t i = 0; i < 100; i++) { - boost::hash_combine(hash, i); - const uint32_t word32 = uint32_t(hash) & (IF_DATA_I_MASK | IF_DATA_Q_MASK); - iface->poke32(fpga::sr_addr(fpga::SR_RADIO_CODEC_IDLE), word32); - iface->peek64(fpga::rb_addr(fpga::RB_RADIO_CODEC_DATA)); //block until request completes - std::this_thread::sleep_for(std::chrono::microseconds(100)); //wait for loopback to propagate through codec - const uint64_t rb_word64 = iface->peek64(fpga::rb_addr(fpga::RB_RADIO_CODEC_DATA)); - const uint32_t rb_tx = uint32_t(rb_word64 >> 32); - const uint32_t rb_rx = uint32_t(rb_word64 & 0xffffffff); - test_fail = word32 != rb_tx or word32 != rb_rx; - if (test_fail){ - UHD_LOG_ERROR("N230", str(boost::format("mismatch (exp:%x, got:%x and %x)... ") % word32 % rb_tx % rb_rx)); - break; //exit loop on any failure - } - } - - /* Zero out the idle data. */ - iface->poke32(fpga::sr_addr(fpga::SR_RADIO_CODEC_IDLE), 0); - return !test_fail; -} - -std::string n230_resource_manager::_get_fpga_upgrade_msg() { - std::string img_loader_path = - (fs::path(uhd::get_pkg_path()) / "bin" / "uhd_image_loader").string(); - - return str(boost::format( - "\nDownload the appropriate FPGA images for this version of UHD.\n" - "%s\n\n" - "Then burn a new image to the on-board flash storage of your\n" - "USRP N230 device using the image loader utility. Use this command:\n" - "\n \"%s\" --args=\"type=n230,addr=%s\"\n") - % print_utility_error("uhd_images_downloader.py") - % img_loader_path % _get_conn(PRI_ETH).ip_addr); - -} - -void n230_resource_manager::_check_fw_compat() -{ - uint32_t compat_num = _fw_ctrl->peek32(N230_FW_HOST_SHMEM_OFFSET(fw_compat_num)); - _fw_version.compat_major = compat_num >> 16; - _fw_version.compat_minor = compat_num; - _fw_version.version_hash = _fw_ctrl->peek32(N230_FW_HOST_SHMEM_OFFSET(fw_version_hash)); - - if (_fw_version.compat_major != N230_FW_COMPAT_NUM_MAJOR){ - throw uhd::runtime_error(str(boost::format( - "Expected firmware compatibility number %d.x, but got %d.%d\n" - "The firmware build is not compatible with the host code build.\n" - "%s" - ) % static_cast<uint32_t>(N230_FW_COMPAT_NUM_MAJOR) - % static_cast<uint32_t>(_fw_version.compat_major) - % static_cast<uint32_t>(_fw_version.compat_minor) - % _get_fpga_upgrade_msg())); - } -} - -void n230_resource_manager::_check_fpga_compat() -{ - const uint64_t compat = _core_ctrl->peek64(fpga::rb_addr(fpga::RB_CORE_SIGNATUE)); - const uint32_t signature = uint32_t(compat >> 32); - const uint16_t product_id = uint8_t(compat >> 24); - _fpga_version.compat_major = static_cast<uint8_t>(compat >> 16); - _fpga_version.compat_minor = static_cast<uint16_t>(compat); - - const uint64_t version_hash = _core_ctrl->peek64(fpga::rb_addr(fpga::RB_CORE_VERSION_HASH)); - _fpga_version.version_hash = uint32_t(version_hash); - - if (signature != 0x0ACE0BA5E || product_id != fpga::RB_N230_PRODUCT_ID) - throw uhd::runtime_error("Signature check failed. Please contact support."); - - bool is_safe_image = (_fpga_version.compat_major > fpga::RB_N230_COMPAT_SAFE); - - if (is_safe_image && !_safe_mode) { - throw uhd::runtime_error( - "The device appears to have the failsafe FPGA image loaded\n" - "This could have happened because the production FPGA image in the flash was either corrupt or non-existent\n" - "To remedy this error, please burn a valid FPGA image to the flash.\n" - "To continue using the failsafe image with UHD, create the UHD device with the \"safe_mode\" device arg.\n" - "Radio functionality/performance not guaranteed when operating in safe mode.\n"); - } else if (_fpga_version.compat_major != fpga::RB_N230_COMPAT_MAJOR && !is_safe_image) { - throw uhd::runtime_error(str(boost::format( - "Expected FPGA compatibility number %d.x, but got %d.%d:\n" - "The FPGA build is not compatible with the host code build.\n" - "%s" - ) % static_cast<uint32_t>(fpga::RB_N230_COMPAT_MAJOR) - % static_cast<uint32_t>(_fpga_version.compat_major) - % static_cast<uint32_t>(_fpga_version.compat_minor) - % _get_fpga_upgrade_msg())); - } -} - -}}} //namespace diff --git a/host/lib/usrp/n230/n230_resource_manager.hpp b/host/lib/usrp/n230/n230_resource_manager.hpp deleted file mode 100644 index ed3bbcb0c..000000000 --- a/host/lib/usrp/n230/n230_resource_manager.hpp +++ /dev/null @@ -1,309 +0,0 @@ -// -// Copyright 2014 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#ifndef INCLUDED_N230_RESOURCE_MANAGER_HPP -#define INCLUDED_N230_RESOURCE_MANAGER_HPP - -#include "n230_fw_ctrl_iface.hpp" -#include "n230_clk_pps_ctrl.hpp" -#include "n230_cores.hpp" -#include "n230_fpga_defs.h" -#include "n230_frontend_ctrl.hpp" -#include "n230_uart.hpp" - -#include <uhdlib/usrp/cores/radio_ctrl_core_3000.hpp> -#include <uhdlib/usrp/cores/spi_core_3000.hpp> -#include <uhdlib/usrp/cores/gpio_atr_3000.hpp> -#include <uhdlib/usrp/cores/rx_vita_core_3000.hpp> -#include <uhdlib/usrp/cores/tx_vita_core_3000.hpp> -#include <uhdlib/usrp/cores/time_core_3000.hpp> -#include <uhdlib/usrp/cores/rx_dsp_core_3000.hpp> -#include <uhdlib/usrp/cores/tx_dsp_core_3000.hpp> -#include <uhdlib/usrp/cores/user_settings_core_3000.hpp> -#include <uhdlib/usrp/common/ad9361_ctrl.hpp> -#include <uhdlib/usrp/common/ad936x_manager.hpp> - -#include <uhd/utils/tasks.hpp> -#include <uhd/types/sid.hpp> -#include <uhd/types/device_addr.hpp> -#include <uhd/utils/soft_register.hpp> -#include <uhd/transport/udp_zero_copy.hpp> -#include <uhd/transport/bounded_buffer.hpp> -#include <uhd/usrp/gps_ctrl.hpp> - -namespace uhd { namespace usrp { namespace n230 { - -enum n230_eth_port_t { - ETH0, - ETH1 -}; - -enum n230_eth_pref_t { - PRI_ETH, - SEC_ETH -}; - -enum n230_endpoint_t { - RADIO_TX_DATA, - RADIO_RX_DATA, - RADIO_CONTROL, - CORE, - GPS_UART -}; - -enum n230_ver_src_t { - SOFTWARE, - FIRMWARE, - FPGA -}; - -enum n230_version_t { - COMPAT_MAJOR, - COMPAT_MINOR -}; - -enum n230_data_dir_t { - RX_DATA, TX_DATA -}; - -//Radio resources -class radio_resource_t : public uhd::noncopyable { -public: - radio_ctrl_core_3000::sptr ctrl; - gpio_atr::gpio_atr_3000::sptr gpio_atr; - time_core_3000::sptr time; - rx_vita_core_3000::sptr framer; - rx_dsp_core_3000::sptr ddc; - tx_vita_core_3000::sptr deframer; - tx_dsp_core_3000::sptr duc; - user_settings_core_3000::sptr user_settings; -}; - -class n230_resource_manager : public uhd::noncopyable -{ -public: //Methods - n230_resource_manager(const std::vector<std::string> ip_addrs, const bool safe_mode); - virtual ~n230_resource_manager(); - - static bool is_device_claimed(n230_fw_ctrl_iface::sptr fw_ctrl); - - inline bool is_device_claimed() { - if (_fw_ctrl.get()) { - return is_device_claimed(_fw_ctrl); - } else { - return false; - } - } - - inline uint32_t get_version(n230_ver_src_t src, n230_version_t type) { - switch (src) { - case FPGA: return _fpga_version.get(type); - case FIRMWARE: return _fw_version.get(type); - default: return 0; - } - } - - inline const std::string get_version_hash(n230_ver_src_t src) { - switch (src) { - case FPGA: return _fpga_version.get_hash_str(); - case FIRMWARE: return _fw_version.get_hash_str(); - default: return ""; - } - } - - //Firmware control interface - inline wb_iface& get_fw_ctrl() const { - return *_fw_ctrl; - } - inline wb_iface::sptr get_fw_ctrl_sptr() { - return _fw_ctrl; - } - - //Core settings control interface - inline radio_ctrl_core_3000& get_core_ctrl() const { - return *_core_ctrl; - } - inline radio_ctrl_core_3000::sptr get_core_ctrl_sptr() { - return _core_ctrl; - } - - //AD931 control interface - inline ad9361_ctrl& get_codec_ctrl() const { - return *_codec_ctrl; - } - inline ad9361_ctrl::sptr get_codec_ctrl_sptr() { - return _codec_ctrl; - } - inline uhd::usrp::ad936x_manager& get_codec_mgr() const { - return *_codec_mgr; - } - - //Clock PPS controls - inline n230_ref_pll_ctrl& get_ref_pll_ctrl() const { - return *_ref_pll_ctrl; - } - inline n230_ref_pll_ctrl::sptr get_ref_pll_ctrl_sptr() { - return _ref_pll_ctrl; - } - - //Clock PPS controls - inline n230_clk_pps_ctrl& get_clk_pps_ctrl() const { - return *_clk_pps_ctrl; - } - inline n230_clk_pps_ctrl::sptr get_clk_pps_ctrl_sptr() { - return _clk_pps_ctrl; - } - - //Front-end control - inline n230_frontend_ctrl& get_frontend_ctrl() const { - return *_frontend_ctrl; - } - inline n230_frontend_ctrl::sptr get_frontend_ctrl_sptr() { - return _frontend_ctrl; - } - - //MiniSAS GPIO control - inline gpio_atr::gpio_atr_3000::sptr get_minisas_gpio_ctrl_sptr(size_t idx) { - return idx == 0 ? _ms0_gpio : _ms1_gpio; - } - - inline gpio_atr::gpio_atr_3000& get_minisas_gpio_ctrl(size_t idx) { - return *get_minisas_gpio_ctrl_sptr(idx); - } - - //GPSDO control - inline bool is_gpsdo_present() { - return _gps_ctrl.get() and _gps_ctrl->gps_detected(); - } - - inline uhd::gps_ctrl::sptr get_gps_ctrl(void) { - return _gps_ctrl; - } - - inline radio_resource_t& get_radio(size_t instance) { - return _radios[instance]; - } - - //Transport to stream data - transport::zero_copy_if::sptr create_transport( - n230_data_dir_t direction, size_t radio_instance, - const device_addr_t ¶ms, sid_t& sid, - transport::udp_zero_copy::buff_params& buff_out_params); - - //Misc - inline double get_max_link_rate() { - return fpga::N230_LINK_RATE_BPS * _eth_conns.size(); - } - -private: - struct ver_info_t { - uint8_t compat_major; - uint16_t compat_minor; - uint32_t version_hash; - - uint32_t get(n230_version_t type) { - switch (type) { - case COMPAT_MAJOR: return compat_major; - case COMPAT_MINOR: return compat_minor; - default: return 0; - } - } - - const std::string get_hash_str() { - return (str(boost::format("%07x%s") - % (version_hash & 0x0FFFFFFF) - % ((version_hash & 0xF0000000) ? "(modified)" : ""))); - } - }; - - struct n230_eth_conn_t { - std::string ip_addr; - n230_eth_port_t type; - }; - - //-- Functions -- - - void _claimer_loop(); - - void _initialize_radio(size_t instance); - - std::string _get_fpga_upgrade_msg(); - void _check_fw_compat(); - void _check_fpga_compat(); - - const sid_t _generate_sid( - const n230_endpoint_t type, const n230_eth_port_t xport, size_t instance = 0); - - transport::zero_copy_if::sptr _create_transport( - const n230_eth_conn_t& eth_conn, - const sid_t& sid, const device_addr_t &buff_params, - transport::udp_zero_copy::buff_params& buff_params_out); - - void _program_dispatcher( - transport::zero_copy_if& xport, const n230_eth_port_t port, const sid_t& sid); - - void _reset_codec_digital_interface(); - - bool _radio_register_loopback_self_test(wb_iface::sptr iface); - - bool _radio_data_loopback_self_test(wb_iface::sptr iface); - - inline const n230_eth_conn_t& _get_conn(const n230_eth_pref_t pref) { - if (_eth_conns.size() == 1) - return _eth_conns[0]; - else - return _eth_conns[(pref==PRI_ETH)?0:1]; - } - - //-- Members -- - - std::vector<n230_eth_conn_t> _eth_conns; - const bool _safe_mode; - ver_info_t _fw_version; - ver_info_t _fpga_version; - - //Firmware register interface - n230_fw_ctrl_iface::sptr _fw_ctrl; - uhd::task::sptr _claimer_task; - static boost::mutex _claimer_mutex; //All claims and checks in this process are serialized - - //Transport - uint8_t _last_host_enpoint; - - //Radio settings interface - radio_ctrl_core_3000::sptr _core_ctrl; - n230_core_spi_core::sptr _core_spi_ctrl; - ad9361_ctrl::sptr _codec_ctrl; - uhd::usrp::ad936x_manager::sptr _codec_mgr; - - //Core Registers - fpga::core_radio_ctrl_reg_t _core_radio_ctrl_reg; - fpga::core_misc_reg_t _core_misc_reg; - fpga::core_pps_sel_reg_t _core_pps_sel_reg; - fpga::core_status_reg_t _core_status_reg; - - //Radio peripherals - radio_resource_t _radios[fpga::NUM_RADIOS]; - - //Misc IO peripherals - n230_ref_pll_ctrl::sptr _ref_pll_ctrl; - n230_clk_pps_ctrl::sptr _clk_pps_ctrl; - n230_frontend_ctrl::sptr _frontend_ctrl; - - //miniSAS GPIO - gpio_atr::gpio_atr_3000::sptr _ms0_gpio; - gpio_atr::gpio_atr_3000::sptr _ms1_gpio; - - //GPSDO - n230_uart::sptr _gps_uart; - uhd::gps_ctrl::sptr _gps_ctrl; - -}; - -}}} //namespace - -#endif //INCLUDED_N230_RESOURCE_MANAGER_HPP diff --git a/host/lib/usrp/n230/n230_stream_manager.cpp b/host/lib/usrp/n230/n230_stream_manager.cpp deleted file mode 100644 index 5c44992ca..000000000 --- a/host/lib/usrp/n230/n230_stream_manager.cpp +++ /dev/null @@ -1,551 +0,0 @@ -// -// Copyright 2013 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#include "n230_stream_manager.hpp" - -#include "../../transport/super_recv_packet_handler.hpp" -#include "../../transport/super_send_packet_handler.hpp" -#include <uhdlib/usrp/common/async_packet_handler.hpp> -#include <uhd/transport/bounded_buffer.hpp> -#include <uhd/utils/tasks.hpp> -#include <uhd/utils/log.hpp> -#include <boost/bind.hpp> -#include <boost/make_shared.hpp> - -static const double N230_RX_SW_BUFF_FULL_FACTOR = 0.90; //Buffer should ideally be 90% full. -static const size_t N230_RX_FC_REQUEST_FREQ = 32; //per flow-control window -static const size_t N230_TX_MAX_ASYNC_MESSAGES = 1000; -static const size_t N230_TX_MAX_SPP = 4092; -static const size_t N230_TX_FC_RESPONSE_FREQ = 10; //per flow-control window - -static const uint32_t N230_EVENT_CODE_FLOW_CTRL = 0; - -namespace uhd { namespace usrp { namespace n230 { - -using namespace uhd::transport; - -n230_stream_manager::~n230_stream_manager() -{ -} - -/*********************************************************************** - * Receive streamer - **********************************************************************/ -n230_stream_manager::n230_stream_manager( - const n230_device_args_t& dev_args, - boost::shared_ptr<n230_resource_manager> resource_mgr, - boost::weak_ptr<property_tree> prop_tree -) : - _dev_args(dev_args), - _resource_mgr(resource_mgr), - _tree(prop_tree) -{ - _async_md_queue.reset(new async_md_queue_t(N230_TX_MAX_ASYNC_MESSAGES)); -} - -/*********************************************************************** - * Receive streamer - **********************************************************************/ -rx_streamer::sptr n230_stream_manager::get_rx_stream(const uhd::stream_args_t &args_) -{ - boost::mutex::scoped_lock lock(_stream_setup_mutex); - - stream_args_t args = args_; - - //setup defaults for unspecified values - if (args.otw_format.empty()) args.otw_format = "sc16"; - args.channels = args.channels.empty()? std::vector<size_t>(1, 0) : args.channels; - - boost::shared_ptr<sph::recv_packet_streamer> my_streamer; - for (size_t stream_i = 0; stream_i < args.channels.size(); stream_i++) - { - const size_t chan = args.channels[stream_i]; - radio_resource_t& perif = _resource_mgr->get_radio(chan); - - //setup transport hints (default to a large recv buff) - //TODO: Propagate the device_args class into streamer in the future - device_addr_t device_addr = args.args; - if (not device_addr.has_key("recv_buff_size")) { - device_addr["recv_buff_size"] = std::to_string(_dev_args.get_recv_buff_size()); - } - if (not device_addr.has_key("recv_frame_size")) { - device_addr["recv_frame_size"] = std::to_string(_dev_args.get_recv_frame_size()); - } - if (not device_addr.has_key("num_recv_frames")) { - device_addr["num_recv_frames"] = std::to_string(_dev_args.get_num_recv_frames()); - } - - transport::udp_zero_copy::buff_params buff_params_out; - sid_t sid; - zero_copy_if::sptr xport = _resource_mgr->create_transport( - RX_DATA, chan, device_addr, sid, buff_params_out); - - //calculate packet size - static const size_t hdr_size = 0 - + vrt::max_if_hdr_words32*sizeof(uint32_t) - //+ sizeof(vrt::if_packet_info_t().tlr) //no longer using trailer - - sizeof(vrt::if_packet_info_t().cid) //no class id ever used - - sizeof(vrt::if_packet_info_t().tsi) //no int time ever used - ; - const size_t bpp = xport->get_recv_frame_size() - hdr_size; - const size_t bpi = convert::get_bytes_per_item(args.otw_format); - size_t spp = unsigned(args.args.cast<double>("spp", bpp/bpi)); - spp = std::min<size_t>(N230_TX_MAX_SPP, spp); //FPGA FIFO maximum for framing at full rate - - //make the new streamer given the samples per packet - if (not my_streamer) my_streamer = boost::make_shared<sph::recv_packet_streamer>(spp); - my_streamer->resize(args.channels.size()); - - //init some streamer stuff - my_streamer->set_vrt_unpacker(&n230_stream_manager::_cvita_hdr_unpack); - - //set the converter - uhd::convert::id_type id; - id.input_format = args.otw_format + "_item32_be"; - id.num_inputs = 1; - id.output_format = args.cpu_format; - id.num_outputs = 1; - my_streamer->set_converter(id); - - perif.framer->clear(); - perif.framer->set_nsamps_per_packet(spp); - perif.framer->set_sid(sid.reversed().get()); - perif.framer->setup(args); - perif.ddc->setup(args); - - //Give the streamer a functor to get the recv_buffer - //bind requires a zero_copy_if::sptr to add a streamer->xport lifetime dependency - my_streamer->set_xport_chan_get_buff( - stream_i, - boost::bind(&zero_copy_if::get_recv_buff, xport, _1), - true /*flush*/ - ); - - my_streamer->set_overflow_handler(stream_i, boost::bind( - &n230_stream_manager::_handle_overflow, this, chan - )); - - my_streamer->set_issue_stream_cmd(stream_i, boost::bind( - &rx_vita_core_3000::issue_stream_command, perif.framer, _1 - )); - - const size_t fc_window = _get_rx_flow_control_window( - xport->get_recv_frame_size(), buff_params_out.recv_buff_size); - const size_t fc_handle_window = std::max<size_t>(1, fc_window / N230_RX_FC_REQUEST_FREQ); - - perif.framer->configure_flow_control(fc_window); - - //Give the streamer a functor to send flow control messages - //handle_rx_flowctrl is static and has no lifetime issues - boost::shared_ptr<rx_fc_cache_t> fc_cache(new rx_fc_cache_t()); - my_streamer->set_xport_handle_flowctrl( - stream_i, boost::bind(&n230_stream_manager::_handle_rx_flowctrl, sid.get(), xport, fc_cache, _1), - fc_handle_window, - true/*init*/ - ); - - //Store a weak pointer to prevent a streamer->manager->streamer circular dependency - _rx_streamers[chan] = my_streamer; //store weak pointer - _rx_stream_cached_args[chan] = args; - - //Sets tick and samp rates on all streamer - update_tick_rate(_get_tick_rate()); - - //TODO: Find a way to remove this dependency - property_tree::sptr prop_tree = _tree.lock(); - if (prop_tree) { - //TODO: Update this to support multiple motherboards - const fs_path mb_path = "/mboards/0"; - prop_tree->access<double>(mb_path / "rx_dsps" / std::to_string(chan) / "rate" / "value").update(); - } - } - update_stream_states(); - - return my_streamer; -} - -/*********************************************************************** - * Transmit streamer - **********************************************************************/ -tx_streamer::sptr n230_stream_manager::get_tx_stream(const uhd::stream_args_t &args_) -{ - boost::mutex::scoped_lock lock(_stream_setup_mutex); - - uhd::stream_args_t args = args_; - - //setup defaults for unspecified values - if (not args.otw_format.empty() and args.otw_format != "sc16") { - throw uhd::value_error("n230_impl::get_tx_stream only supports otw_format sc16"); - } - args.otw_format = "sc16"; - args.channels = args.channels.empty()? std::vector<size_t>(1, 0) : args.channels; - - //shared async queue for all channels in streamer - boost::shared_ptr<async_md_queue_t> async_md(new async_md_queue_t(N230_TX_MAX_ASYNC_MESSAGES)); - - boost::shared_ptr<sph::send_packet_streamer> my_streamer; - for (size_t stream_i = 0; stream_i < args.channels.size(); stream_i++) - { - const size_t chan = args.channels[stream_i]; - radio_resource_t& perif = _resource_mgr->get_radio(chan); - - //setup transport hints (default to a large recv buff) - //TODO: Propagate the device_args class into streamer in the future - device_addr_t device_addr = args.args; - if (not device_addr.has_key("send_buff_size")) { - device_addr["send_buff_size"] = std::to_string(_dev_args.get_send_buff_size()); - } - if (not device_addr.has_key("send_frame_size")) { - device_addr["send_frame_size"] = std::to_string(_dev_args.get_send_frame_size()); - } - if (not device_addr.has_key("num_send_frames")) { - device_addr["num_send_frames"] = std::to_string(_dev_args.get_num_send_frames()); - } - - transport::udp_zero_copy::buff_params buff_params_out; - sid_t sid; - zero_copy_if::sptr xport = _resource_mgr->create_transport( - TX_DATA, chan, device_addr, sid, buff_params_out); - - //calculate packet size - static const size_t hdr_size = 0 - + vrt::num_vrl_words32*sizeof(uint32_t) - + vrt::max_if_hdr_words32*sizeof(uint32_t) - //+ sizeof(vrt::if_packet_info_t().tlr) //forced to have trailer - - sizeof(vrt::if_packet_info_t().cid) //no class id ever used - - sizeof(vrt::if_packet_info_t().tsi) //no int time ever used - ; - const size_t bpp = xport->get_send_frame_size() - hdr_size; - const size_t bpi = convert::get_bytes_per_item(args.otw_format); - const size_t spp = unsigned(args.args.cast<double>("spp", bpp/bpi)); - - //make the new streamer given the samples per packet - if (not my_streamer) my_streamer = boost::make_shared<sph::send_packet_streamer>(spp); - my_streamer->resize(args.channels.size()); - my_streamer->set_vrt_packer(&n230_stream_manager::_cvita_hdr_pack); - - //set the converter - uhd::convert::id_type id; - id.input_format = args.cpu_format; - id.num_inputs = 1; - id.output_format = args.otw_format + "_item32_be"; - id.num_outputs = 1; - my_streamer->set_converter(id); - - perif.deframer->clear(); - perif.deframer->setup(args); - perif.duc->setup(args); - - //flow control setup - size_t fc_window = _get_tx_flow_control_window( - bpp, device_addr.cast<size_t>("send_buff_size", _dev_args.get_send_buff_size())); - //In packets - const size_t fc_handle_window = (fc_window / N230_TX_FC_RESPONSE_FREQ); - - perif.deframer->configure_flow_control(0/*cycs off*/, fc_handle_window); - boost::shared_ptr<tx_fc_cache_t> fc_cache(new tx_fc_cache_t()); - fc_cache->stream_channel = stream_i; - fc_cache->device_channel = chan; - fc_cache->async_queue = async_md; - fc_cache->old_async_queue = _async_md_queue; - - tick_rate_retriever_t get_tick_rate_fn = boost::bind(&n230_stream_manager::_get_tick_rate, this); - task::sptr task = task::make( - boost::bind(&n230_stream_manager::_handle_tx_async_msgs, - fc_cache, xport, get_tick_rate_fn)); - - //Give the streamer a functor to get the send buffer - //get_tx_buff_with_flowctrl is static so bind has no lifetime issues - //xport.send (sptr) is required to add streamer->data-transport lifetime dependency - //task (sptr) is required to add a streamer->async-handler lifetime dependency - my_streamer->set_xport_chan_get_buff( - stream_i, - boost::bind(&n230_stream_manager::_get_tx_buff_with_flowctrl, task, fc_cache, xport, fc_window, _1) - ); - //Give the streamer a functor handled received async messages - my_streamer->set_async_receiver( - boost::bind(&async_md_queue_t::pop_with_timed_wait, async_md, _1, _2) - ); - my_streamer->set_xport_chan_sid(stream_i, true, sid.get()); - my_streamer->set_enable_trailer(false); //TODO not implemented trailer support yet - - //Store a weak pointer to prevent a streamer->manager->streamer circular dependency - _tx_streamers[chan] = boost::weak_ptr<sph::send_packet_streamer>(my_streamer); - _tx_stream_cached_args[chan] = args; - - //Sets tick and samp rates on all streamer - update_tick_rate(_get_tick_rate()); - - //TODO: Find a way to remove this dependency - property_tree::sptr prop_tree = _tree.lock(); - if (prop_tree) { - //TODO: Update this to support multiple motherboards - const fs_path mb_path = "/mboards/0"; - prop_tree->access<double>(mb_path / "tx_dsps" / std::to_string(chan) / "rate" / "value").update(); - } - } - update_stream_states(); - - return my_streamer; -} - -/*********************************************************************** - * Async Message Receiver - **********************************************************************/ -bool n230_stream_manager::recv_async_msg(async_metadata_t &async_metadata, double timeout) -{ - return _async_md_queue->pop_with_timed_wait(async_metadata, timeout); -} - -/*********************************************************************** - * Sample Rate Updaters - **********************************************************************/ -void n230_stream_manager::update_rx_samp_rate(const size_t dspno, const double rate) -{ - boost::shared_ptr<sph::recv_packet_streamer> my_streamer = - boost::dynamic_pointer_cast<sph::recv_packet_streamer>(_rx_streamers[dspno].lock()); - if (not my_streamer) return; - my_streamer->set_samp_rate(rate); - const double adj = _resource_mgr->get_radio(dspno).ddc->get_scaling_adjustment(); - my_streamer->set_scale_factor(adj); -} - -void n230_stream_manager::update_tx_samp_rate(const size_t dspno, const double rate) -{ - boost::shared_ptr<sph::send_packet_streamer> my_streamer = - boost::dynamic_pointer_cast<sph::send_packet_streamer>(_tx_streamers[dspno].lock()); - if (not my_streamer) return; - my_streamer->set_samp_rate(rate); - const double adj = _resource_mgr->get_radio(dspno).duc->get_scaling_adjustment(); - my_streamer->set_scale_factor(adj); -} - -/*********************************************************************** - * Tick Rate Updater - **********************************************************************/ -void n230_stream_manager::update_tick_rate(const double rate) -{ - for (size_t i = 0; i < fpga::NUM_RADIOS; i++) { - radio_resource_t& perif = _resource_mgr->get_radio(i); - - boost::shared_ptr<sph::recv_packet_streamer> my_rx_streamer = - boost::dynamic_pointer_cast<sph::recv_packet_streamer>(_rx_streamers[i].lock()); - if (my_rx_streamer) my_rx_streamer->set_tick_rate(rate); - perif.framer->set_tick_rate(rate); - - boost::shared_ptr<sph::send_packet_streamer> my_tx_streamer = - boost::dynamic_pointer_cast<sph::send_packet_streamer>(_tx_streamers[i].lock()); - if (my_tx_streamer) my_tx_streamer->set_tick_rate(rate); - } -} - -/*********************************************************************** - * Stream State Updater - **********************************************************************/ -void n230_stream_manager::update_stream_states() -{ - //extract settings from state variables - const bool enb_tx0 = bool(_tx_streamers[0].lock()); - const bool enb_rx0 = bool(_rx_streamers[0].lock()); - const bool enb_tx1 = bool(_tx_streamers[1].lock()); - const bool enb_rx1 = bool(_rx_streamers[1].lock()); - - fe_state_t fe0_state = NONE_STREAMING; - if (enb_tx0 && enb_rx0) fe0_state = TXRX_STREAMING; - else if (enb_tx0) fe0_state = TX_STREAMING; - else if (enb_rx0) fe0_state = RX_STREAMING; - - fe_state_t fe1_state = NONE_STREAMING; - if (enb_tx1 && enb_rx1) fe1_state = TXRX_STREAMING; - else if (enb_tx1) fe1_state = TX_STREAMING; - else if (enb_rx1) fe1_state = RX_STREAMING; - - _resource_mgr->get_frontend_ctrl().set_stream_state(fe0_state, fe1_state); -} - -size_t n230_stream_manager::_get_rx_flow_control_window(size_t frame_size, size_t sw_buff_size) -{ - double sw_buff_max = sw_buff_size * N230_RX_SW_BUFF_FULL_FACTOR; - size_t window_in_pkts = (static_cast<size_t>(sw_buff_max) / frame_size); - if (window_in_pkts == 0) { - throw uhd::value_error("recv_buff_size must be larger than the recv_frame_size."); - } - return window_in_pkts; -} - -void n230_stream_manager::_handle_overflow(const size_t i) -{ - boost::shared_ptr<sph::recv_packet_streamer> my_streamer = - boost::dynamic_pointer_cast<sph::recv_packet_streamer>(_rx_streamers[i].lock()); - if (my_streamer->get_num_channels() == 2) { - //MIMO - //find out if we were in continuous mode before stopping - const bool in_continuous_streaming_mode = _resource_mgr->get_radio(i).framer->in_continuous_streaming_mode(); - //stop streaming - my_streamer->issue_stream_cmd(stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS); - //restart streaming - if (in_continuous_streaming_mode) { - stream_cmd_t stream_cmd(stream_cmd_t::STREAM_MODE_START_CONTINUOUS); - stream_cmd.stream_now = false; - stream_cmd.time_spec = _resource_mgr->get_radio(i).time->get_time_now() + time_spec_t(0.01); - my_streamer->issue_stream_cmd(stream_cmd); - } - } else { - _resource_mgr->get_radio(i).framer->handle_overflow(); - } -} - -void n230_stream_manager::_handle_rx_flowctrl( - const sid_t& sid, - zero_copy_if::sptr xport, - boost::shared_ptr<rx_fc_cache_t> fc_cache, - const size_t last_seq) -{ - static const size_t RXFC_PACKET_LEN_IN_WORDS = 2; - static const size_t RXFC_CMD_CODE_OFFSET = 0; - static const size_t RXFC_SEQ_NUM_OFFSET = 1; - - managed_send_buffer::sptr buff = xport->get_send_buff(0.0); - if (not buff) { - throw uhd::runtime_error("handle_rx_flowctrl timed out getting a send buffer"); - } - uint32_t *pkt = buff->cast<uint32_t *>(); - - //recover seq32 - size_t& seq_sw = fc_cache->last_seq_in; - const size_t seq_hw = seq_sw & HW_SEQ_NUM_MASK; - if (last_seq < seq_hw) seq_sw += (HW_SEQ_NUM_MASK + 1); - seq_sw &= ~HW_SEQ_NUM_MASK; - seq_sw |= last_seq; - - //load packet info - vrt::if_packet_info_t packet_info; - packet_info.packet_type = vrt::if_packet_info_t::PACKET_TYPE_CONTEXT; - packet_info.num_payload_words32 = RXFC_PACKET_LEN_IN_WORDS; - packet_info.num_payload_bytes = packet_info.num_payload_words32*sizeof(uint32_t); - packet_info.packet_count = seq_sw; - packet_info.sob = false; - packet_info.eob = false; - packet_info.sid = sid.get(); - packet_info.has_sid = true; - packet_info.has_cid = false; - packet_info.has_tsi = false; - packet_info.has_tsf = false; - packet_info.has_tlr = false; - - //load header - _cvita_hdr_pack(pkt, packet_info); - - //load payload - pkt[packet_info.num_header_words32 + RXFC_CMD_CODE_OFFSET] = uhd::htonx<uint32_t>(N230_EVENT_CODE_FLOW_CTRL); - pkt[packet_info.num_header_words32 + RXFC_SEQ_NUM_OFFSET] = uhd::htonx<uint32_t>(seq_sw); - - //send the buffer over the interface - buff->commit(sizeof(uint32_t)*(packet_info.num_packet_words32)); -} - -void n230_stream_manager::_handle_tx_async_msgs( - boost::shared_ptr<tx_fc_cache_t> fc_cache, - zero_copy_if::sptr xport, - tick_rate_retriever_t get_tick_rate) -{ - managed_recv_buffer::sptr buff = xport->get_recv_buff(); - if (not buff) return; - - //extract packet info - vrt::if_packet_info_t if_packet_info; - if_packet_info.num_packet_words32 = buff->size()/sizeof(uint32_t); - const uint32_t *packet_buff = buff->cast<const uint32_t *>(); - - //unpacking can fail - uint32_t (*endian_conv)(uint32_t) = uhd::ntohx; - try { - _cvita_hdr_unpack(packet_buff, if_packet_info); - endian_conv = uhd::ntohx; - } catch(const std::exception &ex) { - UHD_LOGGER_ERROR("N230") << "Error parsing async message packet: " << ex.what() ; - return; - } - - //fill in the async metadata - async_metadata_t metadata; - load_metadata_from_buff( - endian_conv, metadata, if_packet_info, packet_buff, - get_tick_rate(), fc_cache->stream_channel); - - //The FC response and the burst ack are two indicators that the radio - //consumed packets. Use them to update the FC metadata - if (metadata.event_code == N230_EVENT_CODE_FLOW_CTRL or - metadata.event_code == async_metadata_t::EVENT_CODE_BURST_ACK - ) { - const size_t seq = metadata.user_payload[0]; - fc_cache->seq_queue.push_with_pop_on_full(seq); - } - - //FC responses don't propagate up to the user so filter them here - if (metadata.event_code != N230_EVENT_CODE_FLOW_CTRL) { - fc_cache->async_queue->push_with_pop_on_full(metadata); - metadata.channel = fc_cache->device_channel; - fc_cache->old_async_queue->push_with_pop_on_full(metadata); - standard_async_msg_prints(metadata); - } -} - -managed_send_buffer::sptr n230_stream_manager::_get_tx_buff_with_flowctrl( - task::sptr /*holds ref*/, - boost::shared_ptr<tx_fc_cache_t> fc_cache, - zero_copy_if::sptr xport, - size_t fc_pkt_window, - const double timeout) -{ - while (true) - { - const size_t delta = (fc_cache->last_seq_out & HW_SEQ_NUM_MASK) - (fc_cache->last_seq_ack & HW_SEQ_NUM_MASK); - if ((delta & HW_SEQ_NUM_MASK) <= fc_pkt_window) break; - - const bool ok = fc_cache->seq_queue.pop_with_timed_wait(fc_cache->last_seq_ack, timeout); - if (not ok) return managed_send_buffer::sptr(); //timeout waiting for flow control - } - - managed_send_buffer::sptr buff = xport->get_send_buff(timeout); - if (buff) fc_cache->last_seq_out++; //update seq, this will actually be a send - return buff; -} - -size_t n230_stream_manager::_get_tx_flow_control_window( - size_t payload_size, - size_t hw_buff_size) -{ - size_t window_in_pkts = hw_buff_size / payload_size; - if (window_in_pkts == 0) { - throw uhd::value_error("send_buff_size must be larger than the send_frame_size."); - } - return window_in_pkts; -} - -double n230_stream_manager::_get_tick_rate() -{ - return _resource_mgr->get_clk_pps_ctrl().get_tick_rate(); -} - -void n230_stream_manager::_cvita_hdr_unpack( - const uint32_t *packet_buff, - vrt::if_packet_info_t &if_packet_info) -{ - if_packet_info.link_type = vrt::if_packet_info_t::LINK_TYPE_CHDR; - return vrt::if_hdr_unpack_be(packet_buff, if_packet_info); -} - -void n230_stream_manager::_cvita_hdr_pack( - uint32_t *packet_buff, - vrt::if_packet_info_t &if_packet_info) -{ - if_packet_info.link_type = vrt::if_packet_info_t::LINK_TYPE_CHDR; - return vrt::if_hdr_pack_be(packet_buff, if_packet_info); -} - -}}} //namespace diff --git a/host/lib/usrp/n230/n230_stream_manager.hpp b/host/lib/usrp/n230/n230_stream_manager.hpp deleted file mode 100644 index fcb00bd51..000000000 --- a/host/lib/usrp/n230/n230_stream_manager.hpp +++ /dev/null @@ -1,142 +0,0 @@ -// -// Copyright 2014 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#ifndef INCLUDED_N230_STREAM_MANAGER_HPP -#define INCLUDED_N230_STREAM_MANAGER_HPP - -#include "n230_device_args.hpp" -#include "n230_resource_manager.hpp" - -#include <uhdlib/usrp/cores/time_core_3000.hpp> -#include <uhdlib/usrp/cores/rx_vita_core_3000.hpp> -#include <uhd/types/sid.hpp> -#include <uhd/types/device_addr.hpp> -#include <uhd/types/metadata.hpp> -#include <uhd/transport/zero_copy.hpp> -#include <uhd/transport/bounded_buffer.hpp> -#include <uhd/transport/vrt_if_packet.hpp> -#include <uhd/property_tree.hpp> -#include <uhd/utils/tasks.hpp> -#include <boost/smart_ptr.hpp> - -namespace uhd { namespace usrp { namespace n230 { - -class n230_stream_manager : public uhd::noncopyable -{ -public: //Methods - n230_stream_manager( - const n230_device_args_t& dev_args, - boost::shared_ptr<n230_resource_manager> resource_mgr, - boost::weak_ptr<property_tree> prop_tree); - virtual ~n230_stream_manager(); - - rx_streamer::sptr get_rx_stream( - const uhd::stream_args_t &args); - - tx_streamer::sptr get_tx_stream( - const uhd::stream_args_t &args_); - - bool recv_async_msg( - async_metadata_t &async_metadata, - double timeout); - - void update_stream_states(); - - void update_rx_samp_rate( - const size_t dspno, const double rate); - - void update_tx_samp_rate( - const size_t dspno, const double rate); - - void update_tick_rate( - const double rate); - -private: - typedef transport::bounded_buffer<async_metadata_t> async_md_queue_t; - - struct rx_fc_cache_t - { - rx_fc_cache_t(): - last_seq_in(0){} - size_t last_seq_in; - }; - - struct tx_fc_cache_t - { - tx_fc_cache_t(): - stream_channel(0), - device_channel(0), - last_seq_out(0), - last_seq_ack(0), - seq_queue(1){} - size_t stream_channel; - size_t device_channel; - size_t last_seq_out; - size_t last_seq_ack; - transport::bounded_buffer<size_t> seq_queue; - boost::shared_ptr<async_md_queue_t> async_queue; - boost::shared_ptr<async_md_queue_t> old_async_queue; - }; - - typedef boost::function<double(void)> tick_rate_retriever_t; - - void _handle_overflow(const size_t i); - - double _get_tick_rate(); - - static size_t _get_rx_flow_control_window( - size_t frame_size, size_t sw_buff_size); - - static void _handle_rx_flowctrl( - const sid_t& sid, - transport::zero_copy_if::sptr xport, - boost::shared_ptr<rx_fc_cache_t> fc_cache, - const size_t last_seq); - - static void _handle_tx_async_msgs( - boost::shared_ptr<tx_fc_cache_t> guts, - transport::zero_copy_if::sptr xport, - tick_rate_retriever_t get_tick_rate); - - static transport::managed_send_buffer::sptr _get_tx_buff_with_flowctrl( - task::sptr /*holds ref*/, - boost::shared_ptr<tx_fc_cache_t> guts, - transport::zero_copy_if::sptr xport, - size_t fc_pkt_window, - const double timeout); - - static size_t _get_tx_flow_control_window( - size_t payload_size, - size_t hw_buff_size); - - static void _cvita_hdr_unpack( - const uint32_t *packet_buff, - transport::vrt::if_packet_info_t &if_packet_info); - - static void _cvita_hdr_pack( - uint32_t *packet_buff, - transport::vrt::if_packet_info_t &if_packet_info); - - const n230_device_args_t _dev_args; - boost::shared_ptr<n230_resource_manager> _resource_mgr; - //TODO: Find a way to remove this dependency - boost::weak_ptr<property_tree> _tree; - - boost::mutex _stream_setup_mutex; - uhd::msg_task::sptr _async_task; - boost::shared_ptr<async_md_queue_t> _async_md_queue; - boost::weak_ptr<uhd::tx_streamer> _tx_streamers[fpga::NUM_RADIOS]; - boost::weak_ptr<uhd::rx_streamer> _rx_streamers[fpga::NUM_RADIOS]; - stream_args_t _tx_stream_cached_args[fpga::NUM_RADIOS]; - stream_args_t _rx_stream_cached_args[fpga::NUM_RADIOS]; - - static const uint32_t HW_SEQ_NUM_MASK = 0xFFF; -}; - -}}} //namespace - -#endif //INCLUDED_N230_STREAM_MANAGER_HPP diff --git a/host/lib/usrp/n230/n230_uart.cpp b/host/lib/usrp/n230/n230_uart.cpp deleted file mode 100644 index 8689335c8..000000000 --- a/host/lib/usrp/n230/n230_uart.cpp +++ /dev/null @@ -1,121 +0,0 @@ -// -// Copyright 2013 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#include "n230_uart.hpp" - -#include <uhd/transport/bounded_buffer.hpp> -#include <uhd/transport/vrt_if_packet.hpp> -#include <uhd/utils/byteswap.hpp> -#include <uhd/utils/log.hpp> -#include <uhd/types/time_spec.hpp> -#include <uhd/exception.hpp> - -using namespace uhd; -using namespace uhd::transport; - -namespace uhd { namespace usrp { namespace n230 { - -struct n230_uart_impl : n230_uart -{ - n230_uart_impl(zero_copy_if::sptr xport, const uint32_t sid): - _xport(xport), - _sid(sid), - _count(0), - _char_queue(4096) - { - //this default baud divider is over 9000 - this->set_baud_divider(9001); - - //create a task to handle incoming packets - _recv_task = uhd::task::make(boost::bind(&n230_uart_impl::handle_recv, this)); - } - - void send_char(const char ch) - { - managed_send_buffer::sptr buff = _xport->get_send_buff(); - UHD_ASSERT_THROW(bool(buff)); - - vrt::if_packet_info_t packet_info; - packet_info.link_type = vrt::if_packet_info_t::LINK_TYPE_CHDR; - packet_info.packet_type = vrt::if_packet_info_t::PACKET_TYPE_CONTEXT; - packet_info.num_payload_words32 = 2; - packet_info.num_payload_bytes = packet_info.num_payload_words32*sizeof(uint32_t); - packet_info.packet_count = _count++; - packet_info.sob = false; - packet_info.eob = false; - packet_info.sid = _sid; - packet_info.has_sid = true; - packet_info.has_cid = false; - packet_info.has_tsi = false; - packet_info.has_tsf = false; - packet_info.has_tlr = false; - - uint32_t *packet_buff = buff->cast<uint32_t *>(); - vrt::if_hdr_pack_le(packet_buff, packet_info); - packet_buff[packet_info.num_header_words32+0] = uhd::htonx(uint32_t(_baud_div)); - packet_buff[packet_info.num_header_words32+1] = uhd::htonx(uint32_t(ch)); - buff->commit(packet_info.num_packet_words32*sizeof(uint32_t)); - } - - void write_uart(const std::string &buff) - { - static bool r_sent = false; - for (size_t i = 0; i < buff.size(); i++) - { - if (buff[i] == '\n' and not r_sent) this->send_char('\r'); - this->send_char(buff[i]); - r_sent = (buff[i] == '\r'); - } - } - - std::string read_uart(double timeout) - { - std::string line; - char ch = '\0'; - while (_char_queue.pop_with_timed_wait(ch, timeout)) - { - if (ch == '\r') continue; - line += std::string(&ch, 1); - if (ch == '\n') return line; - } - return line; - } - - void handle_recv(void) - { - managed_recv_buffer::sptr buff = _xport->get_recv_buff(); - if (not buff) - return; - const uint32_t *packet_buff = buff->cast<const uint32_t *>(); - vrt::if_packet_info_t packet_info; - packet_info.link_type = vrt::if_packet_info_t::LINK_TYPE_CHDR; - packet_info.num_packet_words32 = buff->size()/sizeof(uint32_t); - vrt::if_hdr_unpack_be(packet_buff, packet_info); - const char ch = char(uhd::ntohx(packet_buff[packet_info.num_header_words32+1])); - _char_queue.push_with_pop_on_full(ch); - } - - void set_baud_divider(const double baud_div) - { - _baud_div = size_t(baud_div + 0.5); - } - - const zero_copy_if::sptr _xport; - const uint32_t _sid; - size_t _count; - size_t _baud_div; - bounded_buffer<char> _char_queue; - uhd::task::sptr _recv_task; -}; - - -n230_uart::sptr n230_uart::make(zero_copy_if::sptr xport, const uint32_t sid) -{ - return n230_uart::sptr(new n230_uart_impl(xport, sid)); -} - -}}} //namespace diff --git a/host/lib/usrp/n230/n230_uart.hpp b/host/lib/usrp/n230/n230_uart.hpp deleted file mode 100644 index b1b60a21d..000000000 --- a/host/lib/usrp/n230/n230_uart.hpp +++ /dev/null @@ -1,28 +0,0 @@ -// -// Copyright 2013 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#ifndef INCLUDED_N230_UART_HPP -#define INCLUDED_N230_UART_HPP - -#include <uhd/transport/zero_copy.hpp> -#include <uhd/types/serial.hpp> //uart iface -#include <uhd/utils/tasks.hpp> -#include <boost/shared_ptr.hpp> -#include <uhd/utils/noncopyable.hpp> -namespace uhd { namespace usrp { namespace n230 { - -class n230_uart: uhd::noncopyable, public uhd::uart_iface -{ -public: - typedef boost::shared_ptr<n230_uart> sptr; - static sptr make(uhd::transport::zero_copy_if::sptr, const uint32_t sid); - virtual void set_baud_divider(const double baud_div) = 0; -}; - -}}} //namespace - -#endif /* INCLUDED_N230_UART_HPP */ |