aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib/usrp/n230/n230_resource_manager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'host/lib/usrp/n230/n230_resource_manager.cpp')
-rw-r--r--host/lib/usrp/n230/n230_resource_manager.cpp561
1 files changed, 0 insertions, 561 deletions
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 &params,
- 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