diff options
| author | Ben Hilburn <ben.hilburn@ettus.com> | 2014-04-28 17:43:23 -0700 | 
|---|---|---|
| committer | Ben Hilburn <ben.hilburn@ettus.com> | 2014-04-28 17:43:23 -0700 | 
| commit | a5d18ee206bebf66952f697c5387c0d1555fd2f3 (patch) | |
| tree | b009792be56a3eee1ca63c217c3d4d56bf1aa468 | |
| parent | 8f46b048818ba107126910159c76453cfb2025e2 (diff) | |
| parent | f018fa068f863d7f01887137b4bc935984430f3f (diff) | |
| download | uhd-a5d18ee206bebf66952f697c5387c0d1555fd2f3.tar.gz uhd-a5d18ee206bebf66952f697c5387c0d1555fd2f3.tar.bz2 uhd-a5d18ee206bebf66952f697c5387c0d1555fd2f3.zip  | |
Merge branch 'ashish/fpga-busy-bugfix' into maint
| -rw-r--r-- | firmware/x300/x300/x300_defs.h | 10 | ||||
| -rw-r--r-- | host/include/uhd/transport/nirio/niriok_proxy.h | 2 | ||||
| -rw-r--r-- | host/include/uhd/transport/nirio/niusrprio_session.h | 71 | ||||
| -rw-r--r-- | host/lib/transport/nirio/niriok_proxy.cpp | 10 | ||||
| -rw-r--r-- | host/lib/transport/nirio/niusrprio_session.cpp | 57 | ||||
| -rw-r--r-- | host/lib/transport/nirio_zero_copy.cpp | 64 | ||||
| -rw-r--r-- | host/lib/usrp/x300/x300_fw_common.h | 2 | ||||
| -rw-r--r-- | host/lib/usrp/x300/x300_impl.cpp | 54 | ||||
| -rw-r--r-- | host/lib/usrp/x300/x300_impl.hpp | 3 | ||||
| -rw-r--r-- | host/lib/usrp/x300/x300_regs.hpp | 10 | 
10 files changed, 220 insertions, 63 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/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<typename data_t> -	nirio_status create_tx_fifo( -		const char* fifo_name, -		boost::shared_ptr< nirio_fifo<data_t> >& fifo) -	{ +    template<typename data_t> +    nirio_status create_tx_fifo( +        const char* fifo_name, +        boost::shared_ptr< nirio_fifo<data_t> >& fifo) +    {          if (!_session_open) return NiRio_Status_ResourceNotInitialized;          return _resource_manager.create_tx_fifo(fifo_name, fifo); -	} +    }      template<typename data_t>      nirio_status create_tx_fifo( @@ -73,13 +73,13 @@ public:      }      template<typename data_t> -	nirio_status create_rx_fifo( -		const char* fifo_name, -		boost::shared_ptr< nirio_fifo<data_t> >& fifo) -	{ +    nirio_status create_rx_fifo( +        const char* fifo_name, +        boost::shared_ptr< nirio_fifo<data_t> >& fifo) +    {          if (!_session_open) return NiRio_Status_ResourceNotInitialized;          return _resource_manager.create_rx_fifo(fifo_name, fifo); -	} +    }      template<typename data_t>      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..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_zero_copy.cpp b/host/lib/transport/nirio_zero_copy.cpp index c3c8a9368..3bb822720 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,47 @@ private:          }      } +    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."); +        } +    } +      //memory management -> buffers and fifos      niusrprio::niusrprio_session::sptr _fpga_session;      uint32_t _fifo_instance; diff --git a/host/lib/usrp/x300/x300_fw_common.h b/host/lib/usrp/x300/x300_fw_common.h index 632391644..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 4 +#define X300_FPGA_COMPAT_MAJOR 6  //shared memory sections - in between the stack and the program space  #define X300_FW_SHMEM_BASE 0x6000 diff --git a/host/lib/usrp/x300/x300_impl.cpp b/host/lib/usrp/x300/x300_impl.cpp index 6a9de1f30..e931b7983 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<wb_iface> > 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<wb_iface>(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))); @@ -834,8 +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); +            {   //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(...) @@ -1461,13 +1492,18 @@ 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)  { -    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 +    {   //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  }  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..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 @@ -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 { 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)  | 
