aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib/usrp/x300
diff options
context:
space:
mode:
Diffstat (limited to 'host/lib/usrp/x300')
-rw-r--r--host/lib/usrp/x300/x300_adc_dac_utils.cpp47
-rw-r--r--host/lib/usrp/x300/x300_impl.cpp63
-rw-r--r--host/lib/usrp/x300/x300_impl.hpp7
-rw-r--r--host/lib/usrp/x300/x300_radio_ctrl_impl.cpp20
4 files changed, 68 insertions, 69 deletions
diff --git a/host/lib/usrp/x300/x300_adc_dac_utils.cpp b/host/lib/usrp/x300/x300_adc_dac_utils.cpp
index fda0bb6c9..05228a309 100644
--- a/host/lib/usrp/x300/x300_adc_dac_utils.cpp
+++ b/host/lib/usrp/x300/x300_adc_dac_utils.cpp
@@ -21,53 +21,6 @@
using namespace uhd::usrp::x300;
/***********************************************************************
- * DAC: Reset and synchronization operations
- **********************************************************************/
-
-void x300_impl::synchronize_dacs(const std::vector<radio_perifs_t*>& radios)
-{
- if (radios.size() < 2) return; //Nothing to synchronize
-
- //**PRECONDITION**
- //This function assumes that all the VITA times in "radios" are synchronized
- //to a common reference. Currently, this function is called in get_tx_stream
- //which also has the same precondition.
-
- //Reinitialize and resync all DACs
- for (size_t i = 0; i < radios.size(); i++) {
- radios[i]->dac->reset();
- }
-
- //Get a rough estimate of the cumulative command latency
- boost::posix_time::ptime t_start = boost::posix_time::microsec_clock::local_time();
- for (size_t i = 0; i < radios.size(); i++) {
- radios[i]->ctrl->peek64(uhd::usrp::radio::RB64_TIME_NOW); //Discard value. We are just timing the call
- }
- boost::posix_time::time_duration t_elapsed =
- boost::posix_time::microsec_clock::local_time() - t_start;
-
- //Add 100% of headroom + uncertaintly to the command time
- uint64_t t_sync_us = (t_elapsed.total_microseconds() * 2) + 13000 /*Scheduler latency*/;
-
- //Pick radios[0] as the time reference.
- uhd::time_spec_t sync_time =
- radios[0]->time64->get_time_now() + uhd::time_spec_t(((double)t_sync_us)/1e6);
-
- //Send the sync command
- for (size_t i = 0; i < radios.size(); i++) {
- radios[i]->ctrl->set_time(sync_time);
- radios[i]->ctrl->poke32(uhd::usrp::radio::sr_addr(uhd::usrp::radio::DACSYNC), 0x1); //Arm FRAMEP/N sync pulse
- radios[i]->ctrl->set_time(uhd::time_spec_t(0.0)); //Clear command time
- }
-
- //Wait and check status
- boost::this_thread::sleep(boost::posix_time::microseconds(t_sync_us));
- for (size_t i = 0; i < radios.size(); i++) {
- radios[i]->dac->verify_sync();
- }
-}
-
-/***********************************************************************
* ADC: Self-test operations
**********************************************************************/
diff --git a/host/lib/usrp/x300/x300_impl.cpp b/host/lib/usrp/x300/x300_impl.cpp
index 08865f9a6..4601b2789 100644
--- a/host/lib/usrp/x300/x300_impl.cpp
+++ b/host/lib/usrp/x300/x300_impl.cpp
@@ -542,6 +542,8 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr)
eth_addrs.push_back(eth0_addr);
mb.next_src_addr = 0; //Host source address for blocks
+ mb.next_tx_src_addr = 0;
+ mb.next_rx_src_addr = 0;
if (dev_addr.has_key("second_addr")) {
std::string eth1_addr = dev_addr["second_addr"];
@@ -1057,9 +1059,12 @@ x300_impl::~x300_impl(void)
uint32_t x300_impl::mboard_members_t::allocate_pcie_dma_chan(const uhd::sid_t &tx_sid, const xport_type_t xport_type)
{
static const uint32_t CTRL_CHANNEL = 0;
- static const uint32_t FIRST_DATA_CHANNEL = 1;
+ static const uint32_t ASYNC_MSG_CHANNEL = 1;
+ static const uint32_t FIRST_DATA_CHANNEL = 2;
if (xport_type == CTRL) {
return CTRL_CHANNEL;
+ } else if (xport_type == ASYNC_MSG) {
+ return ASYNC_MSG_CHANNEL;
} else {
// sid_t has no comparison defined, so we need to convert it uint32_t
uint32_t raw_sid = tx_sid.get();
@@ -1081,6 +1086,24 @@ static uint32_t extract_sid_from_pkt(void* pkt, size_t) {
return uhd::sid_t(uhd::wtohx(static_cast<const uint32_t*>(pkt)[1])).get_dst();
}
+static uhd::transport::muxed_zero_copy_if::sptr make_muxed_pcie_msg_xport
+(
+ uhd::niusrprio::niusrprio_session::sptr rio_fpga_interface,
+ uint32_t dma_channel_num,
+ size_t max_muxed_ports
+) {
+ zero_copy_xport_params buff_args;
+ buff_args.send_frame_size = X300_PCIE_MSG_FRAME_SIZE;
+ buff_args.recv_frame_size = X300_PCIE_MSG_FRAME_SIZE;
+ buff_args.num_send_frames = X300_PCIE_MSG_NUM_FRAMES * max_muxed_ports;
+ buff_args.num_recv_frames = X300_PCIE_MSG_NUM_FRAMES * max_muxed_ports;
+
+ zero_copy_if::sptr base_xport = nirio_zero_copy::make(
+ rio_fpga_interface, dma_channel_num,
+ buff_args, uhd::device_addr_t());
+ return muxed_zero_copy_if::make(base_xport, extract_sid_from_pkt, max_muxed_ports);
+}
+
uhd::both_xports_t x300_impl::make_transport(
const uhd::sid_t &address,
const xport_type_t xport_type,
@@ -1103,19 +1126,25 @@ uhd::both_xports_t x300_impl::make_transport(
if (not mb.ctrl_dma_xport) {
//One underlying DMA channel will handle
//all control traffic
- zero_copy_xport_params ctrl_buff_args;
- ctrl_buff_args.send_frame_size = X300_PCIE_MSG_FRAME_SIZE;
- ctrl_buff_args.recv_frame_size = X300_PCIE_MSG_FRAME_SIZE;
- ctrl_buff_args.num_send_frames = X300_PCIE_MSG_NUM_FRAMES * X300_PCIE_MAX_MUXED_XPORTS;
- ctrl_buff_args.num_recv_frames = X300_PCIE_MSG_NUM_FRAMES * X300_PCIE_MAX_MUXED_XPORTS;
-
- zero_copy_if::sptr base_xport = nirio_zero_copy::make(
- mb.rio_fpga_interface, dma_channel_num,
- ctrl_buff_args, uhd::device_addr_t());
- mb.ctrl_dma_xport = muxed_zero_copy_if::make(base_xport, extract_sid_from_pkt, X300_PCIE_MAX_MUXED_XPORTS);
+ mb.ctrl_dma_xport = make_muxed_pcie_msg_xport(
+ mb.rio_fpga_interface,
+ dma_channel_num,
+ X300_PCIE_MAX_MUXED_CTRL_XPORTS);
}
//Create a virtual control transport
xports.recv = mb.ctrl_dma_xport->make_stream(xports.recv_sid.get_dst());
+ } else if (xport_type == ASYNC_MSG) {
+ //Transport for async message stream
+ if (not mb.async_msg_dma_xport) {
+ //One underlying DMA channel will handle
+ //all async message traffic
+ mb.async_msg_dma_xport = make_muxed_pcie_msg_xport(
+ mb.rio_fpga_interface,
+ dma_channel_num,
+ X300_PCIE_MAX_MUXED_ASYNC_XPORTS);
+ }
+ //Create a virtual async message transport
+ xports.recv = mb.async_msg_dma_xport->make_stream(xports.recv_sid.get_dst());
} else {
//Transport for data stream
default_buff_args.send_frame_size =
@@ -1157,12 +1186,16 @@ uhd::both_xports_t x300_impl::make_transport(
} else if (mb.xport_path == "eth") {
// Decide on the IP/Interface pair based on the endpoint index
- std::string interface_addr = mb.eth_conns[mb.next_src_addr].addr;
+ size_t &next_src_addr =
+ xport_type == TX_DATA ? mb.next_tx_src_addr :
+ xport_type == RX_DATA ? mb.next_rx_src_addr :
+ mb.next_src_addr;
+ std::string interface_addr = mb.eth_conns[next_src_addr].addr;
const uint32_t xbar_src_addr =
- mb.next_src_addr==0 ? X300_SRC_ADDR0 : X300_SRC_ADDR1;
+ next_src_addr==0 ? X300_SRC_ADDR0 : X300_SRC_ADDR1;
const uint32_t xbar_src_dst =
- mb.eth_conns[mb.next_src_addr].type==X300_IFACE_ETH0 ? X300_XB_DST_E0 : X300_XB_DST_E1;
- mb.next_src_addr = (mb.next_src_addr + 1) % mb.eth_conns.size();
+ mb.eth_conns[next_src_addr].type==X300_IFACE_ETH0 ? X300_XB_DST_E0 : X300_XB_DST_E1;
+ next_src_addr = (next_src_addr + 1) % mb.eth_conns.size();
xports.send_sid = this->allocate_sid(mb, address, xbar_src_addr, xbar_src_dst);
xports.recv_sid = xports.send_sid.reversed();
diff --git a/host/lib/usrp/x300/x300_impl.hpp b/host/lib/usrp/x300/x300_impl.hpp
index 27f3f130e..7186e5f4f 100644
--- a/host/lib/usrp/x300/x300_impl.hpp
+++ b/host/lib/usrp/x300/x300_impl.hpp
@@ -63,7 +63,8 @@ static const size_t X300_PCIE_TX_DATA_NUM_FRAMES = 4096;
static const size_t X300_PCIE_MSG_FRAME_SIZE = 256; //bytes
static const size_t X300_PCIE_MSG_NUM_FRAMES = 64;
static const size_t X300_PCIE_MAX_CHANNELS = 6;
-static const size_t X300_PCIE_MAX_MUXED_XPORTS = 32;
+static const size_t X300_PCIE_MAX_MUXED_CTRL_XPORTS = 32;
+static const size_t X300_PCIE_MAX_MUXED_ASYNC_XPORTS = 4;
static const size_t X300_10GE_DATA_FRAME_MAX_SIZE = 8000; // CHDR packet size in bytes
static const size_t X300_1GE_DATA_FRAME_MAX_SIZE = 1472; // CHDR packet size in bytes
@@ -166,6 +167,8 @@ private:
std::vector<x300_eth_conn_t> eth_conns;
size_t next_src_addr;
+ size_t next_tx_src_addr;
+ size_t next_rx_src_addr;
// Discover the ethernet connections per motherboard
void discover_eth(const uhd::usrp::mboard_eeprom_t mb_eeprom,
@@ -207,6 +210,8 @@ private:
std::map<uint32_t, uint32_t> _dma_chan_pool;
//! Control transport for one PCIe connection
uhd::transport::muxed_zero_copy_if::sptr ctrl_dma_xport;
+ //! Async message transport
+ uhd::transport::muxed_zero_copy_if::sptr async_msg_dma_xport;
/*! Allocate or return a previously allocated PCIe channel pair
*
diff --git a/host/lib/usrp/x300/x300_radio_ctrl_impl.cpp b/host/lib/usrp/x300/x300_radio_ctrl_impl.cpp
index daae309c3..1a37cbdd1 100644
--- a/host/lib/usrp/x300/x300_radio_ctrl_impl.cpp
+++ b/host/lib/usrp/x300/x300_radio_ctrl_impl.cpp
@@ -870,8 +870,14 @@ void x300_radio_ctrl_impl::synchronize_dacs(const std::vector<x300_radio_ctrl_im
boost::posix_time::time_duration t_elapsed =
boost::posix_time::microsec_clock::local_time() - t_start;
- //Add 100% of headroom + uncertaintly to the command time
- uint64_t t_sync_us = (t_elapsed.total_microseconds() * 2) + 13000 /*Scheduler latency*/;
+ //Set tick rate and make sure FRAMEP/N is 0
+ for (size_t i = 0; i < radios.size(); i++) {
+ radios[i]->set_command_tick_rate(radios[i]->_radio_clk_rate, IO_MASTER_RADIO);
+ radios[i]->_regs->misc_outs_reg.write(radio_regmap_t::misc_outs_reg_t::DAC_SYNC, 0);
+ }
+
+ //Add 100% of headroom + uncertainty to the command time
+ uint64_t t_sync_us = (t_elapsed.total_microseconds() * 2) + 16000 /*Scheduler latency*/;
//Pick radios[0] as the time reference.
uhd::time_spec_t sync_time =
@@ -879,15 +885,17 @@ void x300_radio_ctrl_impl::synchronize_dacs(const std::vector<x300_radio_ctrl_im
//Send the sync command
for (size_t i = 0; i < radios.size(); i++) {
- radios[i]->set_command_tick_rate(radios[i]->_radio_clk_rate, IO_MASTER_RADIO);
- radios[i]->_regs->misc_outs_reg.set(radio_regmap_t::misc_outs_reg_t::DAC_SYNC, 0);
radios[i]->set_command_time(sync_time, IO_MASTER_RADIO);
//Arm FRAMEP/N sync pulse by asserting a rising edge
- radios[i]->_regs->misc_outs_reg.set(radio_regmap_t::misc_outs_reg_t::DAC_SYNC, 1);
- radios[i]->_regs->misc_outs_reg.set(radio_regmap_t::misc_outs_reg_t::DAC_SYNC, 0);
+ radios[i]->_regs->misc_outs_reg.write(radio_regmap_t::misc_outs_reg_t::DAC_SYNC, 1);
radios[i]->set_command_time(uhd::time_spec_t(0.0), IO_MASTER_RADIO);
}
+ //Reset FRAMEP/N to 0
+ for (size_t i = 0; i < radios.size(); i++) {
+ radios[i]->_regs->misc_outs_reg.write(radio_regmap_t::misc_outs_reg_t::DAC_SYNC, 0);
+ }
+
//Wait and check status
boost::this_thread::sleep(boost::posix_time::microseconds(t_sync_us));
for (size_t i = 0; i < radios.size(); i++) {