aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib/transport
diff options
context:
space:
mode:
Diffstat (limited to 'host/lib/transport')
-rw-r--r--host/lib/transport/nirio/CMakeLists.txt10
-rw-r--r--host/lib/transport/nirio/nifpga_lvbitx.cpp16
-rw-r--r--host/lib/transport/nirio/nirio_driver_iface_unsupported.cpp (renamed from host/lib/transport/nirio/nirio_driver_iface_macos.cpp)0
-rw-r--r--host/lib/transport/nirio/niriok_proxy.cpp10
-rw-r--r--host/lib/transport/nirio/niusrprio_session.cpp57
-rw-r--r--host/lib/transport/nirio/rpc/rpc_client.cpp5
-rw-r--r--host/lib/transport/nirio_zero_copy.cpp97
7 files changed, 166 insertions, 29 deletions
diff --git a/host/lib/transport/nirio/CMakeLists.txt b/host/lib/transport/nirio/CMakeLists.txt
index 6a33da6c5..5f12e91df 100644
--- a/host/lib/transport/nirio/CMakeLists.txt
+++ b/host/lib/transport/nirio/CMakeLists.txt
@@ -39,10 +39,8 @@ LIBUHD_APPEND_SOURCES(
IF(WIN32)
LIBUHD_APPEND_SOURCES(${CMAKE_CURRENT_SOURCE_DIR}/nirio_driver_iface_win.cpp)
-ELSE(WIN32)
- IF(APPLE)
- LIBUHD_APPEND_SOURCES(${CMAKE_CURRENT_SOURCE_DIR}/nirio_driver_iface_macos.cpp)
- ELSE(APPLE)
- LIBUHD_APPEND_SOURCES(${CMAKE_CURRENT_SOURCE_DIR}/nirio_driver_iface_linux.cpp)
- ENDIF(APPLE)
+ELSEIF(${CMAKE_SYSTEM_NAME} STREQUAL "Linux") #Built-in variable encompasses all UNIX-like systems
+ LIBUHD_APPEND_SOURCES(${CMAKE_CURRENT_SOURCE_DIR}/nirio_driver_iface_linux.cpp)
+ELSE()
+ LIBUHD_APPEND_SOURCES(${CMAKE_CURRENT_SOURCE_DIR}/nirio_driver_iface_unsupported.cpp)
ENDIF(WIN32)
diff --git a/host/lib/transport/nirio/nifpga_lvbitx.cpp b/host/lib/transport/nirio/nifpga_lvbitx.cpp
index 289a44d4a..b87d87a8d 100644
--- a/host/lib/transport/nirio/nifpga_lvbitx.cpp
+++ b/host/lib/transport/nirio/nifpga_lvbitx.cpp
@@ -16,6 +16,7 @@
//
#include <uhd/transport/nirio/nifpga_lvbitx.h>
+#include <cstdlib>
#include <string>
#include <iostream>
#include <fstream>
@@ -109,6 +110,21 @@ std::string nifpga_lvbitx::_get_fpga_images_dir(const std::string search_paths)
std::vector<std::string> search_path_vtr;
boost::split(search_path_vtr, search_paths, boost::is_any_of(","));
+ //
+ // Add the value of the UHD_IMAGES_DIR environment variable to the list of
+ // directories searched for a LVBITX image.
+ //
+ char* uhd_images_dir;
+#ifdef UHD_PLATFORM_WIN32
+ size_t len;
+ errno_t err = _dupenv_s(&uhd_images_dir, &len, "UHD_IMAGES_DIR");
+ if(not err and uhd_images_dir != NULL) search_path_vtr.push_back(std::string(uhd_images_dir));
+ free(uhd_images_dir);
+#else
+ uhd_images_dir = getenv("UHD_IMAGES_DIR");
+ if(uhd_images_dir != NULL) search_path_vtr.push_back(std::string(uhd_images_dir));
+#endif
+
std::string lvbitx_dir;
//Traverse through the list of search paths. Priority: lexical
BOOST_FOREACH(std::string& search_path, search_path_vtr) {
diff --git a/host/lib/transport/nirio/nirio_driver_iface_macos.cpp b/host/lib/transport/nirio/nirio_driver_iface_unsupported.cpp
index 1a1142525..1a1142525 100644
--- a/host/lib/transport/nirio/nirio_driver_iface_macos.cpp
+++ b/host/lib/transport/nirio/nirio_driver_iface_unsupported.cpp
diff --git a/host/lib/transport/nirio/niriok_proxy.cpp b/host/lib/transport/nirio/niriok_proxy.cpp
index 031623c9a..ac8faf0a4 100644
--- a/host/lib/transport/nirio/niriok_proxy.cpp
+++ b/host/lib/transport/nirio/niriok_proxy.cpp
@@ -293,6 +293,16 @@ namespace uhd { namespace niusrprio
{
return nirio_driver_iface::rio_munmap(map);
}
+
+ nirio_status niriok_proxy::stop_all_fifos()
+ {
+ nirio_driver_iface::nirio_syncop_in_params_t in = {};
+ nirio_driver_iface::nirio_syncop_out_params_t out = {};
+
+ in.function = nirio_driver_iface::NIRIO_FUNC::FIFO_STOP_ALL;
+
+ return sync_operation(&in, sizeof(in), &out, sizeof(out));
+ }
}}
#ifdef __GNUC__
diff --git a/host/lib/transport/nirio/niusrprio_session.cpp b/host/lib/transport/nirio/niusrprio_session.cpp
index a07bc4fdf..97d764736 100644
--- a/host/lib/transport/nirio/niusrprio_session.cpp
+++ b/host/lib/transport/nirio/niusrprio_session.cpp
@@ -77,6 +77,8 @@ nirio_status niusrprio_session::open(
std::string lvbitx_checksum(_lvbitx->get_bitstream_checksum());
boost::uint16_t download_fpga = (force_download || (_read_bitstream_checksum() != lvbitx_checksum)) ? 1 : 0;
+ nirio_status_chain(_ensure_fpga_ready(), status);
+
nirio_status_chain(_rpc_client.niusrprio_open_session(
_resource_name, bitfile_path, signature, download_fpga), status);
_session_open = nirio_status_not_fatal(status);
@@ -196,4 +198,59 @@ nirio_status niusrprio_session::_write_bitstream_checksum(const std::string& che
return status;
}
+nirio_status niusrprio_session::_ensure_fpga_ready()
+{
+ nirio_status status = NiRio_Status_Success;
+ niriok_scoped_addr_space(_riok_proxy, BUS_INTERFACE, status);
+
+ //Verify that the Ettus FPGA loaded in the device. This may not be true if the
+ //user is switching to UHD after using LabVIEW FPGA. In that case skip this check.
+ boost::uint32_t pcie_fpga_signature = 0;
+ nirio_status_chain(_riok_proxy.peek(FPGA_PCIE_SIG_REG, pcie_fpga_signature), status);
+ //@TODO: Remove X300 specific constants for future products
+ if (pcie_fpga_signature != FPGA_X3xx_SIG_VALUE) {
+ return status;
+ }
+
+ boost::uint32_t reg_data = 0xffffffff;
+ nirio_status_chain(_riok_proxy.peek(FPGA_STATUS_REG, reg_data), status);
+ if (nirio_status_not_fatal(status) && (reg_data & FPGA_STATUS_DMA_ACTIVE_MASK))
+ {
+ //In case this session was re-initialized *immediately* after the previous
+ //there is a small chance that the server is still finishing up cleaning up
+ //the DMA FIFOs. We currently don't have any feedback from the driver regarding
+ //this state so just wait.
+ boost::this_thread::sleep(boost::posix_time::milliseconds(FPGA_READY_TIMEOUT_IN_MS));
+
+ //Disable all FIFOs in the FPGA
+ for (size_t i = 0; i < _lvbitx->get_input_fifo_count(); i++) {
+ _riok_proxy.poke(PCIE_RX_DMA_REG(DMA_CTRL_STATUS_REG, i), DMA_CTRL_DISABLED);
+ }
+ for (size_t i = 0; i < _lvbitx->get_output_fifo_count(); i++) {
+ _riok_proxy.poke(PCIE_TX_DMA_REG(DMA_CTRL_STATUS_REG, i), DMA_CTRL_DISABLED);
+ }
+
+ //Disable all FIFOs in the kernel driver
+ _riok_proxy.stop_all_fifos();
+
+ boost::posix_time::ptime start_time = boost::posix_time::microsec_clock::local_time();
+ boost::posix_time::time_duration elapsed;
+ do {
+ boost::this_thread::sleep(boost::posix_time::milliseconds(10)); //Avoid flooding the bus
+ elapsed = boost::posix_time::microsec_clock::local_time() - start_time;
+ nirio_status_chain(_riok_proxy.peek(FPGA_STATUS_REG, reg_data), status);
+ } while (
+ nirio_status_not_fatal(status) &&
+ (reg_data & FPGA_STATUS_DMA_ACTIVE_MASK) &&
+ elapsed.total_milliseconds() < FPGA_READY_TIMEOUT_IN_MS);
+
+ nirio_status_chain(_riok_proxy.peek(FPGA_STATUS_REG, reg_data), status);
+ if (nirio_status_not_fatal(status) && (reg_data & FPGA_STATUS_DMA_ACTIVE_MASK)) {
+ return NiRio_Status_FifoReserved;
+ }
+ }
+
+ return status;
+}
+
}}
diff --git a/host/lib/transport/nirio/rpc/rpc_client.cpp b/host/lib/transport/nirio/rpc/rpc_client.cpp
index f8dc26b50..0c4b8fe3c 100644
--- a/host/lib/transport/nirio/rpc/rpc_client.cpp
+++ b/host/lib/transport/nirio/rpc/rpc_client.cpp
@@ -104,6 +104,11 @@ rpc_client::rpc_client (
} catch (boost::exception&) {
UHD_LOG << "rpc_client connection request cancelled/aborted." << std::endl;
_exec_err.assign(boost::asio::error::connection_aborted, boost::asio::error::get_system_category());
+#if BOOST_VERSION < 104700
+ } catch (std::exception& e) {
+ UHD_LOG << "rpc_client connection error: " << e.what() << std::endl;
+ _exec_err.assign(boost::asio::error::connection_aborted, boost::asio::error::get_system_category());
+#endif
}
}
diff --git a/host/lib/transport/nirio_zero_copy.cpp b/host/lib/transport/nirio_zero_copy.cpp
index 7b1e32fe0..3bb822720 100644
--- a/host/lib/transport/nirio_zero_copy.cpp
+++ b/host/lib/transport/nirio_zero_copy.cpp
@@ -18,13 +18,13 @@
#include <uhd/transport/nirio_zero_copy.hpp>
#include <stdio.h>
#include <uhd/transport/nirio/nirio_fifo.h>
-#include <uhd/transport/nirio/nirio_fifo.h>
#include <uhd/transport/buffer_pool.hpp>
#include <uhd/utils/msg.hpp>
#include <uhd/utils/log.hpp>
#include <uhd/utils/atomic.hpp>
#include <boost/format.hpp>
#include <boost/make_shared.hpp>
+#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/thread/thread.hpp> //sleep
#include <vector>
#include <algorithm> // std::max
@@ -144,6 +144,12 @@ public:
nirio_status status = 0;
size_t actual_depth = 0, actual_size = 0;
+ //Disable DMA streams in case last shutdown was unclean (cleanup, so don't status chain)
+ _proxy().poke(PCIE_TX_DMA_REG(DMA_CTRL_STATUS_REG, _fifo_instance), DMA_CTRL_DISABLED);
+ _proxy().poke(PCIE_RX_DMA_REG(DMA_CTRL_STATUS_REG, _fifo_instance), DMA_CTRL_DISABLED);
+
+ _wait_until_stream_ready();
+
//Configure frame width
nirio_status_chain(
_proxy().poke(PCIE_TX_DMA_REG(DMA_FRAME_SIZE_REG, _fifo_instance),
@@ -153,14 +159,14 @@ public:
_proxy().poke(PCIE_RX_DMA_REG(DMA_FRAME_SIZE_REG, _fifo_instance),
static_cast<uint32_t>(_xport_params.recv_frame_size/sizeof(fifo_data_t))),
status);
- //Config 32-bit word flipping and Reset DMA streams
+ //Config 32-bit word flipping and enable DMA streams
nirio_status_chain(
_proxy().poke(PCIE_TX_DMA_REG(DMA_CTRL_STATUS_REG, _fifo_instance),
- DMA_CTRL_SW_BUF_U32 | DMA_CTRL_RESET),
+ DMA_CTRL_SW_BUF_U32 | DMA_CTRL_ENABLED),
status);
nirio_status_chain(
_proxy().poke(PCIE_RX_DMA_REG(DMA_CTRL_STATUS_REG, _fifo_instance),
- DMA_CTRL_SW_BUF_U32 | DMA_CTRL_RESET),
+ DMA_CTRL_SW_BUF_U32 | DMA_CTRL_ENABLED),
status);
//Create FIFOs
@@ -190,10 +196,6 @@ public:
nirio_status_chain(_send_fifo->start(), status);
if (nirio_status_not_fatal(status)) {
- //Flush RX kernel buffers in case some cruft was
- //left behind from the last run
- _flush_rx_buff();
-
//allocate re-usable managed receive buffers
for (size_t i = 0; i < get_num_recv_frames(); i++){
_mrb_pool.push_back(boost::shared_ptr<nirio_zero_copy_mrb>(new nirio_zero_copy_mrb(
@@ -217,9 +219,9 @@ public:
{
_proxy().get_rio_quirks().remove_tx_fifo(_fifo_instance);
- //Reset DMA streams (Teardown, so don't status chain)
- _proxy().poke(PCIE_TX_DMA_REG(DMA_CTRL_STATUS_REG, _fifo_instance), DMA_CTRL_RESET);
- _proxy().poke(PCIE_RX_DMA_REG(DMA_CTRL_STATUS_REG, _fifo_instance), DMA_CTRL_RESET);
+ //Disable DMA streams (cleanup, so don't status chain)
+ _proxy().poke(PCIE_TX_DMA_REG(DMA_CTRL_STATUS_REG, _fifo_instance), DMA_CTRL_DISABLED);
+ _proxy().poke(PCIE_RX_DMA_REG(DMA_CTRL_STATUS_REG, _fifo_instance), DMA_CTRL_DISABLED);
_flush_rx_buff();
@@ -261,19 +263,68 @@ private:
UHD_INLINE void _flush_rx_buff()
{
- nirio_status flush_status = 0;
- while (nirio_status_not_fatal(flush_status)) {
- static const size_t NUM_ELEMS_TO_FLUSH = 1;
- static const uint32_t FLUSH_TIMEOUT_IN_MS = 0;
-
- fifo_data_t* flush_data_ptr = NULL;
- size_t flush_elems_acquired = 0, flush_elems_remaining = 0;
- flush_status = _recv_fifo->acquire(
- flush_data_ptr, NUM_ELEMS_TO_FLUSH, FLUSH_TIMEOUT_IN_MS,
- flush_elems_acquired, flush_elems_remaining);
- if (nirio_status_not_fatal(flush_status)) {
- _recv_fifo->release(flush_elems_acquired);
+ // acquire is called with 0 elements requested first to
+ // get the number of elements in the buffer and then
+ // repeatedly with the number of remaining elements
+ // until the buffer is empty
+ fifo_data_t* elems_buffer;
+ for (size_t num_elems_requested = 0,
+ num_elems_acquired = 0,
+ num_elems_remaining = 1;
+ num_elems_remaining;
+ num_elems_requested = num_elems_remaining)
+ {
+ nirio_status status = _recv_fifo->acquire(
+ elems_buffer,
+ num_elems_requested,
+ 0, // timeout
+ num_elems_acquired,
+ num_elems_remaining);
+ // throw excetption if status is fatal
+ nirio_status_to_exception(status,
+ "NI-RIO PCIe data transfer failed during flush.");
+ _recv_fifo->release(num_elems_acquired);
+ }
+ }
+
+ UHD_INLINE void _wait_until_stream_ready()
+ {
+ static const uint32_t TIMEOUT_IN_MS = 100;
+
+ uint32_t reg_data = 0xffffffff;
+ bool tx_busy = true, rx_busy = true;
+ boost::posix_time::ptime start_time;
+ boost::posix_time::time_duration elapsed;
+ nirio_status status = NiRio_Status_Success;
+
+ nirio_status_chain(_proxy().peek(
+ PCIE_TX_DMA_REG(DMA_CTRL_STATUS_REG, _fifo_instance), reg_data), status);
+ tx_busy = (reg_data & DMA_STATUS_BUSY);
+ nirio_status_chain(_proxy().peek(
+ PCIE_RX_DMA_REG(DMA_CTRL_STATUS_REG, _fifo_instance), reg_data), status);
+ rx_busy = (reg_data & DMA_STATUS_BUSY);
+
+ if (nirio_status_not_fatal(status) && (tx_busy || rx_busy)) {
+ start_time = boost::posix_time::microsec_clock::local_time();
+ do {
+ boost::this_thread::sleep(boost::posix_time::microsec(50)); //Avoid flooding the bus
+ elapsed = boost::posix_time::microsec_clock::local_time() - start_time;
+ nirio_status_chain(_proxy().peek(
+ PCIE_TX_DMA_REG(DMA_CTRL_STATUS_REG, _fifo_instance), reg_data), status);
+ tx_busy = (reg_data & DMA_STATUS_BUSY);
+ nirio_status_chain(_proxy().peek(
+ PCIE_RX_DMA_REG(DMA_CTRL_STATUS_REG, _fifo_instance), reg_data), status);
+ rx_busy = (reg_data & DMA_STATUS_BUSY);
+ } while (
+ nirio_status_not_fatal(status) &&
+ (tx_busy || rx_busy) &&
+ elapsed.total_milliseconds() < TIMEOUT_IN_MS);
+
+ if (tx_busy || rx_busy) {
+ nirio_status_chain(NiRio_Status_FpgaBusy, status);
}
+
+ nirio_status_to_exception(status, "Could not create nirio_zero_copy transport.");
}
}