aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib/usrp
diff options
context:
space:
mode:
Diffstat (limited to 'host/lib/usrp')
-rw-r--r--host/lib/usrp/x300/x300_fw_common.h2
-rw-r--r--host/lib/usrp/x300/x300_impl.cpp54
-rw-r--r--host/lib/usrp/x300/x300_impl.hpp3
-rw-r--r--host/lib/usrp/x300/x300_regs.hpp10
4 files changed, 56 insertions, 13 deletions
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)