From 4b4e493f976094115dad7809121a092e2ac31668 Mon Sep 17 00:00:00 2001 From: Ashish Chaudhari Date: Thu, 24 Apr 2014 12:40:58 -0700 Subject: 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 --- host/include/uhd/transport/nirio/niriok_proxy.h | 2 + .../uhd/transport/nirio/niusrprio_session.h | 71 +++++++++++----------- host/lib/transport/nirio/niriok_proxy.cpp | 10 +++ host/lib/transport/nirio/niusrprio_session.cpp | 58 ++++++++++++++++++ host/lib/transport/nirio_zero_copy.cpp | 58 +++++++++++++++--- host/lib/usrp/x300/x300_regs.hpp | 10 ++- 6 files changed, 162 insertions(+), 47 deletions(-) diff --git a/host/include/uhd/transport/nirio/niriok_proxy.h b/host/include/uhd/transport/nirio/niriok_proxy.h index a6b6183d1..ca6a4ba02 100644 --- a/host/include/uhd/transport/nirio/niriok_proxy.h +++ b/host/include/uhd/transport/nirio/niriok_proxy.h @@ -126,6 +126,8 @@ namespace uhd { namespace niusrprio nirio_status unmap_fifo_memory( nirio_driver_iface::rio_mmap_t& map); + nirio_status stop_all_fifos(); + nirio_quirks& get_rio_quirks() { return _rio_quirks; } diff --git a/host/include/uhd/transport/nirio/niusrprio_session.h b/host/include/uhd/transport/nirio/niusrprio_session.h index c9a61ae76..c84bc75d0 100644 --- a/host/include/uhd/transport/nirio/niusrprio_session.h +++ b/host/include/uhd/transport/nirio/niusrprio_session.h @@ -37,31 +37,31 @@ public: typedef uhd::usrprio_rpc::usrprio_device_info device_info; typedef uhd::usrprio_rpc::usrprio_device_info_vtr device_info_vtr; - static nirio_status enumerate( + static nirio_status enumerate( const std::string& rpc_port_name, device_info_vtr& device_info_vtr); - niusrprio_session( + niusrprio_session( const std::string& resource_name, const std::string& port_name); - virtual ~niusrprio_session(); + virtual ~niusrprio_session(); - nirio_status open( + nirio_status open( nifpga_lvbitx::sptr lvbitx, bool force_download = false); - void close(bool skip_reset = false); + void close(bool skip_reset = false); - nirio_status reset(); + nirio_status reset(); - template - nirio_status create_tx_fifo( - const char* fifo_name, - boost::shared_ptr< nirio_fifo >& fifo) - { + template + nirio_status create_tx_fifo( + const char* fifo_name, + boost::shared_ptr< nirio_fifo >& fifo) + { if (!_session_open) return NiRio_Status_ResourceNotInitialized; return _resource_manager.create_tx_fifo(fifo_name, fifo); - } + } template nirio_status create_tx_fifo( @@ -73,13 +73,13 @@ public: } template - nirio_status create_rx_fifo( - const char* fifo_name, - boost::shared_ptr< nirio_fifo >& fifo) - { + nirio_status create_rx_fifo( + const char* fifo_name, + boost::shared_ptr< nirio_fifo >& fifo) + { if (!_session_open) return NiRio_Status_ResourceNotInitialized; return _resource_manager.create_rx_fifo(fifo_name, fifo); - } + } template nirio_status create_rx_fifo( @@ -90,9 +90,9 @@ public: return create_rx_fifo(_lvbitx->get_input_fifo_names()[fifo_instance], fifo); } - niriok_proxy& get_kernel_proxy() { - return _riok_proxy; - } + niriok_proxy& get_kernel_proxy() { + return _riok_proxy; + } nirio_status download_bitstream_to_flash(const std::string& bitstream_path); @@ -102,21 +102,22 @@ public: const std::string& rpc_port_name); private: - nirio_status _verify_signature(); - std::string _read_bitstream_checksum(); - nirio_status _write_bitstream_checksum(const std::string& checksum); - nirio_status _wait_for_device_available(); - - std::string _resource_name; - nifpga_lvbitx::sptr _lvbitx; - std::string _interface_path; - bool _session_open; - niriok_proxy _riok_proxy; - nirio_resource_manager _resource_manager; - usrprio_rpc::usrprio_rpc_client _rpc_client; - boost::recursive_mutex _session_mutex; - - static const uint32_t SESSION_LOCK_TIMEOUT_IN_MS = 3000; + nirio_status _verify_signature(); + std::string _read_bitstream_checksum(); + nirio_status _write_bitstream_checksum(const std::string& checksum); + nirio_status _ensure_fpga_ready(); + + std::string _resource_name; + nifpga_lvbitx::sptr _lvbitx; + std::string _interface_path; + bool _session_open; + niriok_proxy _riok_proxy; + nirio_resource_manager _resource_manager; + usrprio_rpc::usrprio_rpc_client _rpc_client; + boost::recursive_mutex _session_mutex; + + static const uint32_t FPGA_READY_TIMEOUT_IN_MS = 1000; + static const uint32_t SESSION_LOCK_TIMEOUT_IN_MS = 3000; static const uint32_t SESSION_LOCK_RETRY_INT_IN_MS = 500; }; 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..dd9cc2f8b 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); @@ -93,6 +95,7 @@ nirio_status niusrprio_session::open( } } + nirio_status_chain(_riok_proxy.set_attribute(ADDRESS_SPACE, BUS_INTERFACE), status); return status; } @@ -196,4 +199,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 (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::microsec(1000)); //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_FpgaBusy; + } + + return status; +} + }} 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 #include #include +#include #include //sleep #include #include // 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(_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(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; diff --git a/host/lib/usrp/x300/x300_regs.hpp b/host/lib/usrp/x300/x300_regs.hpp index fb1786deb..cf1e33695 100644 --- a/host/lib/usrp/x300/x300_regs.hpp +++ b/host/lib/usrp/x300/x300_regs.hpp @@ -124,9 +124,12 @@ static const uint32_t FPGA_PCIE_SIG_REG = PCIE_FPGA_REG(0x0000); static const uint32_t FPGA_CNTR_LO_REG = PCIE_FPGA_REG(0x0004); static const uint32_t FPGA_CNTR_HI_REG = PCIE_FPGA_REG(0x0008); static const uint32_t FPGA_CNTR_FREQ_REG = PCIE_FPGA_REG(0x000C); +static const uint32_t FPGA_STATUS_REG = PCIE_FPGA_REG(0x0020); static const uint32_t FPGA_USR_SIG_REG_BASE = PCIE_FPGA_REG(0x0030); static const uint32_t FPGA_USR_SIG_REG_SIZE = 16; +static const uint32_t FPGA_STATUS_DMA_ACTIVE_MASK = 0x3F3F0000; + static const uint32_t PCIE_TX_DMA_REG_BASE = PCIE_FPGA_REG(0x0200); static const uint32_t PCIE_RX_DMA_REG_BASE = PCIE_FPGA_REG(0x0400); @@ -139,12 +142,15 @@ static const uint32_t DMA_PKT_COUNT_REG = 0xC; #define PCIE_TX_DMA_REG(REG, CHAN) (PCIE_TX_DMA_REG_BASE + (CHAN*DMA_REG_GRP_SIZE) + REG) #define PCIE_RX_DMA_REG(REG, CHAN) (PCIE_RX_DMA_REG_BASE + (CHAN*DMA_REG_GRP_SIZE) + REG) -static const uint32_t DMA_CTRL_RESET = 1; +static const uint32_t DMA_CTRL_DISABLED = 0x00000000; +static const uint32_t DMA_CTRL_ENABLED = 0x00000002; +static const uint32_t DMA_CTRL_CLEAR_STB = 0x00000001; static const uint32_t DMA_CTRL_SW_BUF_U64 = (3 << 4); static const uint32_t DMA_CTRL_SW_BUF_U32 = (2 << 4); static const uint32_t DMA_CTRL_SW_BUF_U16 = (1 << 4); static const uint32_t DMA_CTRL_SW_BUF_U8 = (0 << 4); -static const uint32_t DMA_STATUS_ERROR = 1; +static const uint32_t DMA_STATUS_ERROR = 0x00000001; +static const uint32_t DMA_STATUS_BUSY = 0x00000002; static const uint32_t PCIE_ROUTER_REG_BASE = PCIE_FPGA_REG(0x0500); #define PCIE_ROUTER_REG(X) (PCIE_ROUTER_REG_BASE + X) -- cgit v1.2.3 From 8e5fe11b6015c3456261d7b7b2ef6918fefa1ee8 Mon Sep 17 00:00:00 2001 From: Ashish Chaudhari Date: Thu, 24 Apr 2014 13:01:37 -0700 Subject: x300: Cleanup for PCIe flushing --- host/lib/transport/nirio/niusrprio_session.cpp | 28 ++++++------- host/lib/transport/nirio_zero_copy.cpp | 54 ++++++++++++++------------ 2 files changed, 44 insertions(+), 38 deletions(-) diff --git a/host/lib/transport/nirio/niusrprio_session.cpp b/host/lib/transport/nirio/niusrprio_session.cpp index dd9cc2f8b..094009ae9 100644 --- a/host/lib/transport/nirio/niusrprio_session.cpp +++ b/host/lib/transport/nirio/niusrprio_session.cpp @@ -233,22 +233,22 @@ nirio_status niusrprio_session::_ensure_fpga_ready() //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::microsec(1000)); //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); + 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_FpgaBusy; + 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_zero_copy.cpp b/host/lib/transport/nirio_zero_copy.cpp index 87739b9c6..a739c01f1 100644 --- a/host/lib/transport/nirio_zero_copy.cpp +++ b/host/lib/transport/nirio_zero_copy.cpp @@ -292,34 +292,40 @@ private: 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; - 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."); + 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."); + } } //memory management -> buffers and fifos -- cgit v1.2.3 From 09ca0f535ee953939a8317e2f685ae282d7fa9c6 Mon Sep 17 00:00:00 2001 From: Ashish Chaudhari Date: Thu, 24 Apr 2014 13:58:54 -0700 Subject: x300: Added synchronization between device claiming and checking. - We now maintain a registry of pcie ZPU transports - Added static mutex for claimer --- host/lib/usrp/x300/x300_impl.cpp | 44 +++++++++++++++++++++++++++++++++++----- host/lib/usrp/x300/x300_impl.hpp | 1 + 2 files changed, 40 insertions(+), 5 deletions(-) diff --git a/host/lib/usrp/x300/x300_impl.cpp b/host/lib/usrp/x300/x300_impl.cpp index 6a9de1f30..7cb5d9ad8 100644 --- a/host/lib/usrp/x300/x300_impl.cpp +++ b/host/lib/usrp/x300/x300_impl.cpp @@ -135,6 +135,12 @@ static device_addrs_t x300_find_with_addr(const device_addr_t &hint) return addrs; } +//We need a zpu xport registry to ensure synchronization between the static finder method +//and the instances of the x300_impl class. +typedef uhd::dict< std::string, boost::weak_ptr > pcie_zpu_iface_registry_t; +UHD_SINGLETON_FCN(pcie_zpu_iface_registry_t, get_pcie_zpu_iface_registry) +static boost::mutex pcie_zpu_iface_registry_mutex; + static device_addrs_t x300_find_pcie(const device_addr_t &hint, bool explicit_query) { std::string rpc_port_name(NIUSRPRIO_DEFAULT_RPC_PORT); @@ -167,17 +173,30 @@ static device_addrs_t x300_find_pcie(const device_addr_t &hint, bool explicit_qu } niriok_proxy kernel_proxy; - kernel_proxy.open(dev_info.interface_path); //Attempt to read the name from the EEPROM and perform filtering. //This operation can throw due to compatibility mismatch. try { - //This call could throw an exception if the user is switching to using UHD + //This block could throw an exception if the user is switching to using UHD //after LabVIEW FPGA. In that case, skip reading the name and serial and pick //a default FPGA flavor. During make, a new image will be loaded and everything //will be OK - wb_iface::sptr zpu_ctrl = x300_make_ctrl_iface_pcie(kernel_proxy); + + wb_iface::sptr zpu_ctrl; + + //Hold on to the registry mutex as long as zpu_ctrl is alive + //to prevent any use by different threads while enumerating + boost::mutex::scoped_lock(pcie_zpu_iface_registry_mutex); + + if (get_pcie_zpu_iface_registry().has_key(resource_d)) { + zpu_ctrl = get_pcie_zpu_iface_registry()[resource_d].lock(); + } else { + kernel_proxy.open(dev_info.interface_path); + zpu_ctrl = x300_make_ctrl_iface_pcie(kernel_proxy); + //We don't put this zpu_ctrl in the registry because we need + //a persistent niriok_proxy associated with the object + } if (x300_impl::is_claimed(zpu_ctrl)) continue; //claimed by another process //Attempt to autodetect the FPGA type @@ -465,7 +484,13 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr) //create basic communication UHD_MSG(status) << "Setup basic communication..." << std::endl; if (mb.xport_path == "nirio") { - mb.zpu_ctrl = x300_make_ctrl_iface_pcie(mb.rio_fpga_interface->get_kernel_proxy()); + boost::mutex::scoped_lock(pcie_zpu_iface_registry_mutex); + if (get_pcie_zpu_iface_registry().has_key(mb.addr)) { + throw uhd::assertion_error("Someone else has a ZPU transport to the device open. Internal error!"); + } else { + mb.zpu_ctrl = x300_make_ctrl_iface_pcie(mb.rio_fpga_interface->get_kernel_proxy()); + get_pcie_zpu_iface_registry()[mb.addr] = boost::weak_ptr(mb.zpu_ctrl); + } } else { mb.zpu_ctrl = x300_make_ctrl_iface_enet(udp_simple::make_connected(mb.addr, BOOST_STRINGIZE(X300_FW_COMMS_UDP_PORT))); @@ -836,6 +861,11 @@ x300_impl::~x300_impl(void) mb.claimer_task.reset(); mb.zpu_ctrl->poke32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_CLAIM_TIME), 0); mb.zpu_ctrl->poke32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_CLAIM_SRC), 0); + + boost::mutex::scoped_lock(pcie_zpu_iface_registry_mutex); + //If the process is killed, the entire registry will disappear so we + //don't need to worry about unclean shutdowns here. + get_pcie_zpu_iface_registry().pop(mb.addr); } } catch(...) @@ -1461,13 +1491,17 @@ void x300_impl::set_fp_gpio(gpio_core_200::sptr gpio, const std::string &attr, c void x300_impl::claimer_loop(wb_iface::sptr iface) { + boost::mutex::scoped_lock(claimer_mutex); + iface->poke32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_CLAIM_TIME), time(NULL)); iface->poke32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_CLAIM_SRC), get_process_hash()); - boost::this_thread::sleep(boost::posix_time::milliseconds(1500)); //1.5 seconds + boost::this_thread::sleep(boost::posix_time::milliseconds(1000)); //1 second } bool x300_impl::is_claimed(wb_iface::sptr iface) { + boost::mutex::scoped_lock(claimer_mutex); + //If timed out then device is definitely unclaimed if (iface->peek32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_CLAIM_STATUS)) == 0) return false; diff --git a/host/lib/usrp/x300/x300_impl.hpp b/host/lib/usrp/x300/x300_impl.hpp index 4b3efc845..9645fe4af 100644 --- a/host/lib/usrp/x300/x300_impl.hpp +++ b/host/lib/usrp/x300/x300_impl.hpp @@ -152,6 +152,7 @@ public: bool recv_async_msg(uhd::async_metadata_t &, double); // used by x300_find_with_addr to find X300 devices. + static boost::mutex claimer_mutex; //All claims and checks in this process are serialized static bool is_claimed(uhd::wb_iface::sptr); enum x300_mboard_t { -- cgit v1.2.3 From e85062880b02db9527f6aa0a86299c7bc95a731d Mon Sep 17 00:00:00 2001 From: Ashish Chaudhari Date: Fri, 25 Apr 2014 09:52:23 -0700 Subject: x300: Addressed review feedback - Fixed synchronization for unclaim - Removed stray RIO addr space set --- host/lib/transport/nirio/niusrprio_session.cpp | 1 - host/lib/usrp/x300/x300_impl.cpp | 24 +++++++++++++----------- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/host/lib/transport/nirio/niusrprio_session.cpp b/host/lib/transport/nirio/niusrprio_session.cpp index 094009ae9..3afe61eae 100644 --- a/host/lib/transport/nirio/niusrprio_session.cpp +++ b/host/lib/transport/nirio/niusrprio_session.cpp @@ -95,7 +95,6 @@ nirio_status niusrprio_session::open( } } - nirio_status_chain(_riok_proxy.set_attribute(ADDRESS_SPACE, BUS_INTERFACE), status); return status; } diff --git a/host/lib/usrp/x300/x300_impl.cpp b/host/lib/usrp/x300/x300_impl.cpp index 7cb5d9ad8..e931b7983 100644 --- a/host/lib/usrp/x300/x300_impl.cpp +++ b/host/lib/usrp/x300/x300_impl.cpp @@ -859,13 +859,14 @@ x300_impl::~x300_impl(void) //kill the claimer task and unclaim the device mb.claimer_task.reset(); - mb.zpu_ctrl->poke32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_CLAIM_TIME), 0); - mb.zpu_ctrl->poke32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_CLAIM_SRC), 0); - - boost::mutex::scoped_lock(pcie_zpu_iface_registry_mutex); - //If the process is killed, the entire registry will disappear so we - //don't need to worry about unclean shutdowns here. - get_pcie_zpu_iface_registry().pop(mb.addr); + { //Critical section + boost::mutex::scoped_lock(pcie_zpu_iface_registry_mutex); + mb.zpu_ctrl->poke32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_CLAIM_TIME), 0); + mb.zpu_ctrl->poke32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_CLAIM_SRC), 0); + //If the process is killed, the entire registry will disappear so we + //don't need to worry about unclean shutdowns here. + get_pcie_zpu_iface_registry().pop(mb.addr); + } } } catch(...) @@ -1491,10 +1492,11 @@ void x300_impl::set_fp_gpio(gpio_core_200::sptr gpio, const std::string &attr, c void x300_impl::claimer_loop(wb_iface::sptr iface) { - boost::mutex::scoped_lock(claimer_mutex); - - iface->poke32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_CLAIM_TIME), time(NULL)); - iface->poke32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_CLAIM_SRC), get_process_hash()); + { //Critical section + boost::mutex::scoped_lock(claimer_mutex); + iface->poke32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_CLAIM_TIME), time(NULL)); + iface->poke32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_CLAIM_SRC), get_process_hash()); + } boost::this_thread::sleep(boost::posix_time::milliseconds(1000)); //1 second } -- cgit v1.2.3 From 72f11b3ecb233b8ce214ba7814dbb036575e3f4f Mon Sep 17 00:00:00 2001 From: Ashish Chaudhari Date: Fri, 25 Apr 2014 12:24:52 -0700 Subject: x300: Bumped FPGA compat number to 5. --- host/lib/usrp/x300/x300_fw_common.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/host/lib/usrp/x300/x300_fw_common.h b/host/lib/usrp/x300/x300_fw_common.h index 632391644..1edb8b296 100644 --- a/host/lib/usrp/x300/x300_fw_common.h +++ b/host/lib/usrp/x300/x300_fw_common.h @@ -31,7 +31,7 @@ extern "C" { #define X300_FW_COMPAT_MAJOR 3 #define X300_FW_COMPAT_MINOR 0 -#define X300_FPGA_COMPAT_MAJOR 4 +#define X300_FPGA_COMPAT_MAJOR 5 //shared memory sections - in between the stack and the program space #define X300_FW_SHMEM_BASE 0x6000 -- cgit v1.2.3 From 623f5295d8297794d85894ed174221b6d18e75c0 Mon Sep 17 00:00:00 2001 From: Ashish Chaudhari Date: Mon, 28 Apr 2014 13:08:39 -0700 Subject: x300: Changed bus_clk frequency to 166.67MHz. --- firmware/x300/x300/x300_defs.h | 10 +++++----- host/lib/usrp/x300/x300_impl.hpp | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/firmware/x300/x300/x300_defs.h b/firmware/x300/x300/x300_defs.h index 02c3d4808..65c5d5a23 100644 --- a/firmware/x300/x300/x300_defs.h +++ b/firmware/x300/x300/x300_defs.h @@ -1,10 +1,10 @@ -// Copyright 2012 Ettus Research LLC +// Copyright 2014 Ettus Research LLC -#ifndef INCLUDED_B250_DEFS_H -#define INCLUDED_B250_DEFS_H +#ifndef INCLUDED_X300_DEFS_H +#define INCLUDED_X300_DEFS_H -#define CPU_CLOCK 175000000 +#define CPU_CLOCK 166666667 #define MAIN_RAM_BASE 0x0000 #define PKT_RAM0_BASE 0x8000 #define XGE0_BASE 0xC000 @@ -72,4 +72,4 @@ static const int BL_DATA = 1; #define ETH_FRAMER_DST_UDP_MAC 6 #define ETH_FRAMER_DST_MAC_LO 7 -#endif /* INCLUDED_B250_DEFS_H */ +#endif /* INCLUDED_X300_DEFS_H */ diff --git a/host/lib/usrp/x300/x300_impl.hpp b/host/lib/usrp/x300/x300_impl.hpp index 9645fe4af..90aed2fdb 100644 --- a/host/lib/usrp/x300/x300_impl.hpp +++ b/host/lib/usrp/x300/x300_impl.hpp @@ -53,7 +53,7 @@ static const std::string X300_FW_FILE_NAME = "usrp_x300_fw.bin"; static const double X300_DEFAULT_TICK_RATE = 200e6; //Hz -static const double X300_BUS_CLOCK_RATE = 175e6; //Hz +static const double X300_BUS_CLOCK_RATE = 166.666667e6; //Hz static const size_t X300_TX_HW_BUFF_SIZE = 0x90000; //576KiB static const size_t X300_TX_FC_RESPONSE_FREQ = 8; //per flow-control window -- cgit v1.2.3 From 7fad62620d75a56f35fb12d3a74ca5b157e01514 Mon Sep 17 00:00:00 2001 From: Ashish Chaudhari Date: Mon, 28 Apr 2014 15:22:47 -0700 Subject: x300: Fixed DMA busy logic after review feedback. --- host/lib/transport/nirio/niusrprio_session.cpp | 2 +- host/lib/transport/nirio_zero_copy.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/host/lib/transport/nirio/niusrprio_session.cpp b/host/lib/transport/nirio/niusrprio_session.cpp index 3afe61eae..97d764736 100644 --- a/host/lib/transport/nirio/niusrprio_session.cpp +++ b/host/lib/transport/nirio/niusrprio_session.cpp @@ -214,7 +214,7 @@ nirio_status niusrprio_session::_ensure_fpga_ready() boost::uint32_t reg_data = 0xffffffff; nirio_status_chain(_riok_proxy.peek(FPGA_STATUS_REG, reg_data), status); - if (reg_data & FPGA_STATUS_DMA_ACTIVE_MASK) + 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 diff --git a/host/lib/transport/nirio_zero_copy.cpp b/host/lib/transport/nirio_zero_copy.cpp index a739c01f1..3bb822720 100644 --- a/host/lib/transport/nirio_zero_copy.cpp +++ b/host/lib/transport/nirio_zero_copy.cpp @@ -304,7 +304,7 @@ private: 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) { + 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 -- cgit v1.2.3 From f018fa068f863d7f01887137b4bc935984430f3f Mon Sep 17 00:00:00 2001 From: Ashish Chaudhari Date: Mon, 28 Apr 2014 15:29:49 -0700 Subject: x300: Bumped FPGA compat number to 6. --- host/lib/usrp/x300/x300_fw_common.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/host/lib/usrp/x300/x300_fw_common.h b/host/lib/usrp/x300/x300_fw_common.h index 1edb8b296..0bbaee319 100644 --- a/host/lib/usrp/x300/x300_fw_common.h +++ b/host/lib/usrp/x300/x300_fw_common.h @@ -31,7 +31,7 @@ extern "C" { #define X300_FW_COMPAT_MAJOR 3 #define X300_FW_COMPAT_MINOR 0 -#define X300_FPGA_COMPAT_MAJOR 5 +#define X300_FPGA_COMPAT_MAJOR 6 //shared memory sections - in between the stack and the program space #define X300_FW_SHMEM_BASE 0x6000 -- cgit v1.2.3