aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib/transport/nirio_zero_copy.cpp
diff options
context:
space:
mode:
authorAshish Chaudhari <ashish@ettus.com>2014-04-24 12:40:58 -0700
committerAshish Chaudhari <ashish@ettus.com>2014-04-24 12:40:58 -0700
commit4b4e493f976094115dad7809121a092e2ac31668 (patch)
tree9eef93cca3bda2183059d2812f36c6c061c32958 /host/lib/transport/nirio_zero_copy.cpp
parent8f46b048818ba107126910159c76453cfb2025e2 (diff)
downloaduhd-4b4e493f976094115dad7809121a092e2ac31668.tar.gz
uhd-4b4e493f976094115dad7809121a092e2ac31668.tar.bz2
uhd-4b4e493f976094115dad7809121a092e2ac31668.zip
x300: Added hardware flush mechanism to PCIe logic.
- Added DMA enabled states to DMA logic to allow for hardware data flushing during init. - niusrprio_session will now check for FPGA busy before downloading
Diffstat (limited to 'host/lib/transport/nirio_zero_copy.cpp')
-rw-r--r--host/lib/transport/nirio_zero_copy.cpp58
1 files changed, 48 insertions, 10 deletions
diff --git a/host/lib/transport/nirio_zero_copy.cpp b/host/lib/transport/nirio_zero_copy.cpp
index c3c8a9368..87739b9c6 100644
--- a/host/lib/transport/nirio_zero_copy.cpp
+++ b/host/lib/transport/nirio_zero_copy.cpp
@@ -24,6 +24,7 @@
#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
@@ -143,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),
@@ -152,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
@@ -189,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(
@@ -216,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();
@@ -284,6 +287,41 @@ private:
}
}
+ UHD_INLINE void _wait_until_stream_ready()
+ {
+ static const uint32_t TIMEOUT_IN_MS = 100;
+
+ uint32_t reg_data = 0xffffffff;
+ boost::posix_time::ptime start_time;
+ boost::posix_time::time_duration elapsed;
+ nirio_status status = NiRio_Status_Success;
+
+ 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);
+ } while (
+ nirio_status_not_fatal(status) &&
+ (reg_data & DMA_STATUS_BUSY) &&
+ elapsed.total_milliseconds() < TIMEOUT_IN_MS);
+
+ 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_RX_DMA_REG(DMA_CTRL_STATUS_REG, _fifo_instance), reg_data), status);
+ } while (
+ nirio_status_not_fatal(status) &&
+ (reg_data & DMA_STATUS_BUSY) &&
+ elapsed.total_milliseconds() < TIMEOUT_IN_MS);
+
+ nirio_status_to_exception(status,
+ "Could not create nirio_zero_copy transport because the FPGA is busy. Try re-downloading the LVBITX.");
+ }
+
//memory management -> buffers and fifos
niusrprio::niusrprio_session::sptr _fpga_session;
uint32_t _fifo_instance;