From 37f1f1451f65aace9ca978ac3edcaa31d16e8c0d Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Fri, 8 Oct 2010 18:04:37 -0700 Subject: usrp2: add fc control registers, use small timeout for control packets again --- host/lib/usrp/usrp2/usrp2_regs.hpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'host/lib/usrp/usrp2/usrp2_regs.hpp') diff --git a/host/lib/usrp/usrp2/usrp2_regs.hpp b/host/lib/usrp/usrp2/usrp2_regs.hpp index 064ad4e95..bdd5194f9 100644 --- a/host/lib/usrp/usrp2/usrp2_regs.hpp +++ b/host/lib/usrp/usrp2/usrp2_regs.hpp @@ -193,9 +193,14 @@ #define U2_REG_TX_CTRL_CLEAR_STATE _SR_ADDR(SR_TX_CTRL + 1) #define U2_REG_TX_CTRL_REPORT_SID _SR_ADDR(SR_TX_CTRL + 2) #define U2_REG_TX_CTRL_POLICY _SR_ADDR(SR_TX_CTRL + 3) +#define U2_REG_TX_CTRL_CYCLES_PER_ACK _SR_ADDR(SR_TX_CTRL + 4) +#define U2_REG_TX_CTRL_PACKETS_PER_ACK _SR_ADDR(SR_TX_CTRL + 5) #define U2_FLAG_TX_CTRL_POLICY_WAIT (0x1 << 0) #define U2_FLAG_TX_CTRL_POLICY_NEXT_PACKET (0x1 << 1) #define U2_FLAG_TX_CTRL_POLICY_NEXT_BURST (0x1 << 2) +//enable flag for registers: cycles and packets per ack +#define U2_FLAG_TX_CTRL_ACK_ENB (1ul << 31) + #endif /* INCLUDED_USRP2_REGS_HPP */ -- cgit v1.2.3 From c6042a0b317a6f74d2b74b259f14431f5c8246d4 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 13 Oct 2010 14:28:52 -0700 Subject: usrp2: added docs on flow control ricer args and using usrp2 with a switch implemented flow control param hints in the mboard impl --- host/docs/transport.rst | 11 +++++++++++ host/docs/usrp2.rst | 15 +++++++-------- host/lib/usrp/usrp2/mboard_impl.cpp | 22 ++++++++++++++-------- host/lib/usrp/usrp2/usrp2_impl.cpp | 8 +++++--- host/lib/usrp/usrp2/usrp2_impl.hpp | 7 +++++-- host/lib/usrp/usrp2/usrp2_regs.hpp | 8 ++++---- 6 files changed, 46 insertions(+), 25 deletions(-) (limited to 'host/lib/usrp/usrp2/usrp2_regs.hpp') diff --git a/host/docs/transport.rst b/host/docs/transport.rst index 432db4bb5..2f730f8e4 100644 --- a/host/docs/transport.rst +++ b/host/docs/transport.rst @@ -39,6 +39,17 @@ The following parameters can be used to alter the transport's default behavior: **Note:** num_send_frames and concurrency_hint will not have an effect as the asynchronous send implementation is currently disabled. +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Flow control parameters +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +The host-based flow control expects periodic update packets from the device. +These update packets inform the host of the last packet consumed by the device, +which allows the host to determine throttling conditions for the transmission of packets. +The following mechanisms affect the transmission of periodic update packets: + +* **ups_per_fifo:** The number of update packets for each FIFO's worth of bytes sent into the device +* **ups_per_sec:** The number of update packets per second + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Resize socket buffers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/host/docs/usrp2.rst b/host/docs/usrp2.rst index 1ebab388a..8fa666a49 100644 --- a/host/docs/usrp2.rst +++ b/host/docs/usrp2.rst @@ -39,12 +39,10 @@ Use the card burner tool (windows) ------------------------------------------------------------------------ Setup networking ------------------------------------------------------------------------ -The USRP2 only supports gigabit ethernet, and -will not work with a 10/100 Mbps interface. -Because the USRP2 uses gigabit ethernet pause frames for flow control, -you cannot use multiple USRP2s with a switch or a hub. -It is recommended that each USRP2 be plugged directly into its own -dedicated gigabit ethernet interface on the host computer. +The USRP2 only supports gigabit ethernet, +and will not work with a 10/100 Mbps interface. +However, a 10/100 Mbps interface can be connected indirectly +to a USRP2 through a gigabit ethernet switch. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Setup the host interface @@ -63,8 +61,9 @@ It is recommended that you change or disable your firewall settings. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Multiple device configuration ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -As described above, you will need one ethernet interface per USRP2. -Each ethernet interface should have its own subnet, +For maximum throughput, one ethernet interface per USRP2 is recommended, +although multiple devices may be connected via a gigabit ethernet switch. +In any case, each ethernet interface should have its own subnet, and the corresponding USRP2 device should be assigned an address in that subnet. Example: diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp index 65066f125..5210eee94 100644 --- a/host/lib/usrp/usrp2/mboard_impl.cpp +++ b/host/lib/usrp/usrp2/mboard_impl.cpp @@ -39,7 +39,8 @@ usrp2_mboard_impl::usrp2_mboard_impl( size_t index, transport::udp_simple::sptr ctrl_transport, size_t recv_samps_per_packet, - size_t send_bytes_per_packet + size_t send_bytes_per_packet, + const device_addr_t &flow_control_hints ): _index(index), _recv_samps_per_packet(recv_samps_per_packet) @@ -89,11 +90,16 @@ usrp2_mboard_impl::usrp2_mboard_impl( _iface->poke32(U2_REG_TX_CTRL_CLEAR_STATE, 1); //reset _iface->poke32(U2_REG_TX_CTRL_REPORT_SID, 1); //sid 1 (different from rx) _iface->poke32(U2_REG_TX_CTRL_POLICY, U2_FLAG_TX_CTRL_POLICY_NEXT_PACKET); - const size_t cycles_per_ack = size_t(_clock_ctrl->get_master_clock_rate()/100); //100 aps - _iface->poke32(U2_REG_TX_CTRL_CYCLES_PER_ACK, U2_FLAG_TX_CTRL_ACK_ENB | cycles_per_ack); - static const double sram_frac = 1.0/8.0; //fraction of sram to fill before ack - const size_t packets_per_ack = size_t(usrp2_impl::sram_bytes*sram_frac/send_bytes_per_packet); - _iface->poke32(U2_REG_TX_CTRL_PACKETS_PER_ACK, U2_FLAG_TX_CTRL_ACK_ENB | packets_per_ack); + + //setting the cycles per update + const double ups_per_sec = flow_control_hints.cast("ups_per_sec", 100); + const size_t cycles_per_up = size_t(_clock_ctrl->get_master_clock_rate()/ups_per_sec); + _iface->poke32(U2_REG_TX_CTRL_CYCLES_PER_UP, U2_FLAG_TX_CTRL_UP_ENB | cycles_per_up); + + //setting the packets per update + const double ups_per_fifo = flow_control_hints.cast("ups_per_fifo", 8); + const size_t packets_per_up = size_t(usrp2_impl::sram_bytes/ups_per_fifo/send_bytes_per_packet); + _iface->poke32(U2_REG_TX_CTRL_PACKETS_PER_UP, U2_FLAG_TX_CTRL_UP_ENB | packets_per_up); //init the ddc init_ddc_config(); @@ -116,8 +122,8 @@ usrp2_mboard_impl::usrp2_mboard_impl( } usrp2_mboard_impl::~usrp2_mboard_impl(void){ - _iface->poke32(U2_REG_TX_CTRL_CYCLES_PER_ACK, 0); - _iface->poke32(U2_REG_TX_CTRL_PACKETS_PER_ACK, 0); + _iface->poke32(U2_REG_TX_CTRL_CYCLES_PER_UP, 0); + _iface->poke32(U2_REG_TX_CTRL_PACKETS_PER_UP, 0); } /*********************************************************************** diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp index 1d9f25019..e271f839c 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.cpp +++ b/host/lib/usrp/usrp2/usrp2_impl.cpp @@ -138,7 +138,7 @@ static device::sptr usrp2_make(const device_addr_t &device_addr){ //create the usrp2 implementation guts return device::sptr( - new usrp2_impl(ctrl_transports, data_transports) + new usrp2_impl(ctrl_transports, data_transports, device_addr) ); } @@ -151,7 +151,8 @@ UHD_STATIC_BLOCK(register_usrp2_device){ **********************************************************************/ usrp2_impl::usrp2_impl( std::vector ctrl_transports, - std::vector data_transports + std::vector data_transports, + const device_addr_t &flow_control_hints ): _data_transports(data_transports) { @@ -172,7 +173,8 @@ usrp2_impl::usrp2_impl( _mboards.push_back(usrp2_mboard_impl::sptr(new usrp2_mboard_impl( i, ctrl_transports[i], this->get_max_recv_samps_per_packet(), - _data_transports[i]->get_send_frame_size() + _data_transports[i]->get_send_frame_size(), + flow_control_hints ))); //use an empty name when there is only one mboard std::string name = (ctrl_transports.size() > 1)? boost::lexical_cast(i) : ""; diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp index 2077b0a50..3aa6e9cd5 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -85,7 +85,8 @@ public: size_t index, uhd::transport::udp_simple::sptr, size_t recv_samps_per_packet, - size_t send_bytes_per_packet + size_t send_bytes_per_packet, + const uhd::device_addr_t &flow_control_hints ); ~usrp2_mboard_impl(void); @@ -178,10 +179,12 @@ public: * Create a new usrp2 impl base. * \param ctrl_transports the udp transports for control * \param data_transports the udp transports for data + * \param flow_control_hints optional flow control params */ usrp2_impl( std::vector ctrl_transports, - std::vector data_transports + std::vector data_transports, + const uhd::device_addr_t &flow_control_hints ); ~usrp2_impl(void); diff --git a/host/lib/usrp/usrp2/usrp2_regs.hpp b/host/lib/usrp/usrp2/usrp2_regs.hpp index bdd5194f9..c3a4d22de 100644 --- a/host/lib/usrp/usrp2/usrp2_regs.hpp +++ b/host/lib/usrp/usrp2/usrp2_regs.hpp @@ -193,14 +193,14 @@ #define U2_REG_TX_CTRL_CLEAR_STATE _SR_ADDR(SR_TX_CTRL + 1) #define U2_REG_TX_CTRL_REPORT_SID _SR_ADDR(SR_TX_CTRL + 2) #define U2_REG_TX_CTRL_POLICY _SR_ADDR(SR_TX_CTRL + 3) -#define U2_REG_TX_CTRL_CYCLES_PER_ACK _SR_ADDR(SR_TX_CTRL + 4) -#define U2_REG_TX_CTRL_PACKETS_PER_ACK _SR_ADDR(SR_TX_CTRL + 5) +#define U2_REG_TX_CTRL_CYCLES_PER_UP _SR_ADDR(SR_TX_CTRL + 4) +#define U2_REG_TX_CTRL_PACKETS_PER_UP _SR_ADDR(SR_TX_CTRL + 5) #define U2_FLAG_TX_CTRL_POLICY_WAIT (0x1 << 0) #define U2_FLAG_TX_CTRL_POLICY_NEXT_PACKET (0x1 << 1) #define U2_FLAG_TX_CTRL_POLICY_NEXT_BURST (0x1 << 2) -//enable flag for registers: cycles and packets per ack -#define U2_FLAG_TX_CTRL_ACK_ENB (1ul << 31) +//enable flag for registers: cycles and packets per update packet +#define U2_FLAG_TX_CTRL_UP_ENB (1ul << 31) #endif /* INCLUDED_USRP2_REGS_HPP */ -- cgit v1.2.3 From 81c9f77306dc82f250bfb2871b8bd7db67a40085 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 8 Nov 2010 17:22:37 -0800 Subject: usrp2: implemented clear state for RX and TX control, and zero sample command support --- firmware/microblaze/lib/net_common.c | 2 +- host/include/uhd/usrp/dsp_utils.hpp | 5 +---- host/lib/usrp/dsp_utils.cpp | 6 ++---- host/lib/usrp/usrp2/io_impl.cpp | 25 ------------------------- host/lib/usrp/usrp2/mboard_impl.cpp | 13 +++++-------- host/lib/usrp/usrp2/usrp2_impl.hpp | 1 - host/lib/usrp/usrp2/usrp2_regs.hpp | 2 +- 7 files changed, 10 insertions(+), 44 deletions(-) (limited to 'host/lib/usrp/usrp2/usrp2_regs.hpp') diff --git a/firmware/microblaze/lib/net_common.c b/firmware/microblaze/lib/net_common.c index 0a085db3a..6305408d6 100644 --- a/firmware/microblaze/lib/net_common.c +++ b/firmware/microblaze/lib/net_common.c @@ -298,7 +298,7 @@ handle_icmp_packet(struct ip_addr src, struct ip_addr dst, sr_tx_ctrl->cyc_per_up = 0; //the end continuous streaming command - sr_rx_ctrl->cmd = (1 << 31) | 1; //one sample, asap + sr_rx_ctrl->cmd = 1 << 31; //no samples now sr_rx_ctrl->time_secs = 0; sr_rx_ctrl->time_ticks = 0; //latch the command diff --git a/host/include/uhd/usrp/dsp_utils.hpp b/host/include/uhd/usrp/dsp_utils.hpp index 8ec04dd2f..5b81ce322 100644 --- a/host/include/uhd/usrp/dsp_utils.hpp +++ b/host/include/uhd/usrp/dsp_utils.hpp @@ -85,12 +85,9 @@ namespace dsp_type1{ /*! * Calculate the stream command word from the stream command struct. * \param stream_cmd the requested stream command with mode, flags, timestamp - * \param num_samps_continuous number of samples to request in continuous mode * \return the 32-bit stream command word */ - UHD_API boost::uint32_t calc_stream_cmd_word( - const stream_cmd_t &stream_cmd, size_t num_samps_continuous - ); + UHD_API boost::uint32_t calc_stream_cmd_word(const stream_cmd_t &stream_cmd); } //namespace dsp_type1 diff --git a/host/lib/usrp/dsp_utils.cpp b/host/lib/usrp/dsp_utils.cpp index 10ae9a086..2553e4a25 100644 --- a/host/lib/usrp/dsp_utils.cpp +++ b/host/lib/usrp/dsp_utils.cpp @@ -109,9 +109,7 @@ boost::uint32_t dsp_type1::calc_iq_scale_word(unsigned rate){ return calc_iq_scale_word(scale, scale); } -boost::uint32_t dsp_type1::calc_stream_cmd_word( - const stream_cmd_t &stream_cmd, size_t num_samps_continuous -){ +boost::uint32_t dsp_type1::calc_stream_cmd_word(const stream_cmd_t &stream_cmd){ UHD_ASSERT_THROW(stream_cmd.num_samps <= 0x3fffffff); //setup the mode to instruction flags @@ -133,6 +131,6 @@ boost::uint32_t dsp_type1::calc_stream_cmd_word( word |= boost::uint32_t((stream_cmd.stream_now)? 1 : 0) << 31; word |= boost::uint32_t((inst_chain)? 1 : 0) << 30; word |= boost::uint32_t((inst_reload)? 1 : 0) << 29; - word |= (inst_samps)? stream_cmd.num_samps : ((inst_chain)? num_samps_continuous : 1); + word |= (inst_samps)? stream_cmd.num_samps : ((inst_chain)? 1 : 0); return word; } diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index 39e6c167f..844df603c 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -241,8 +241,6 @@ void usrp2_impl::io_impl::recv_pirate_loop( /*********************************************************************** * Helper Functions **********************************************************************/ -#include //TODO remove when hack below is fixed - void usrp2_impl::io_init(void){ //the assumption is that all data transports should be identical @@ -252,29 +250,6 @@ void usrp2_impl::io_init(void){ //create new io impl _io_impl = UHD_PIMPL_MAKE(io_impl, (num_recv_frames, send_frame_size, _data_transports.size())); - //TODO temporary fix for weird power up state, remove when FPGA fixed - { - //send an initial packet to all transports - tx_metadata_t md; md.end_of_burst = true; - this->send( - std::vector(_data_transports.size(), NULL), 0, md, - io_type_t::COMPLEX_FLOAT32, device::SEND_MODE_ONE_PACKET, 0 - ); - - //issue a stream command to each motherboard - BOOST_FOREACH(usrp2_mboard_impl::sptr mboard, _mboards){ - (*mboard)[MBOARD_PROP_STREAM_CMD] = stream_cmd_t(stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS); - } - - //wait - boost::this_thread::sleep(boost::posix_time::milliseconds(100)); - - //flush all transport receive queues (no timeout) - BOOST_FOREACH(zero_copy_if::sptr xport, _data_transports){ - while(xport->get_recv_buff(0).get() != NULL){}; - } - } - //create a new pirate thread for each zc if (yarr!!) for (size_t i = 0; i < _data_transports.size(); i++){ _io_impl->recv_pirate_crew.create_thread(boost::bind( diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp index bb9b6d1a9..d4dc8a4bd 100644 --- a/host/lib/usrp/usrp2/mboard_impl.cpp +++ b/host/lib/usrp/usrp2/mboard_impl.cpp @@ -40,7 +40,6 @@ usrp2_mboard_impl::usrp2_mboard_impl( const device_addr_t &flow_control_hints ): _index(index), - _recv_samps_per_packet(recv_samps_per_packet), _iface(usrp2_iface::make(ctrl_transport)) { //Send a small data packet so the usrp2 knows the udp source port. @@ -74,9 +73,9 @@ usrp2_mboard_impl::usrp2_mboard_impl( } //init the rx control registers - _iface->poke32(U2_REG_RX_CTRL_NSAMPS_PER_PKT, _recv_samps_per_packet); + _iface->poke32(U2_REG_TX_CTRL_CLEAR_STATE, 1); //reset + _iface->poke32(U2_REG_RX_CTRL_NSAMPS_PER_PKT, recv_samps_per_packet); _iface->poke32(U2_REG_RX_CTRL_NCHANNELS, 1); - _iface->poke32(U2_REG_RX_CTRL_CLEAR_OVERRUN, 1); //reset _iface->poke32(U2_REG_RX_CTRL_VRT_HEADER, 0 | (0x1 << 28) //if data with stream id | (0x1 << 26) //has trailer @@ -88,8 +87,8 @@ usrp2_mboard_impl::usrp2_mboard_impl( _iface->poke32(U2_REG_TIME64_TPS, size_t(get_master_clock_freq())); //init the tx control registers - _iface->poke32(U2_REG_TX_CTRL_NUM_CHAN, 0); //1 channel _iface->poke32(U2_REG_TX_CTRL_CLEAR_STATE, 1); //reset + _iface->poke32(U2_REG_TX_CTRL_NUM_CHAN, 0); //1 channel _iface->poke32(U2_REG_TX_CTRL_REPORT_SID, 1); //sid 1 (different from rx) _iface->poke32(U2_REG_TX_CTRL_POLICY, U2_FLAG_TX_CTRL_POLICY_NEXT_PACKET); @@ -97,6 +96,7 @@ usrp2_mboard_impl::usrp2_mboard_impl( const double ups_per_sec = flow_control_hints.cast("ups_per_sec", 100); const size_t cycles_per_up = size_t(_clock_ctrl->get_master_clock_rate()/ups_per_sec); _iface->poke32(U2_REG_TX_CTRL_CYCLES_PER_UP, U2_FLAG_TX_CTRL_UP_ENB | cycles_per_up); + _iface->poke32(U2_REG_TX_CTRL_CYCLES_PER_UP, 0); //cycles per update is disabled //setting the packets per update const double ups_per_fifo = flow_control_hints.cast("ups_per_fifo", 8); @@ -187,7 +187,6 @@ void usrp2_mboard_impl::set_time_spec(const time_spec_t &time_spec, bool now){ } void usrp2_mboard_impl::handle_overflow(void){ - _iface->poke32(U2_REG_RX_CTRL_CLEAR_OVERRUN, 1); if (_continuous_streaming){ //re-issue the stream command if already continuous this->issue_ddc_stream_cmd(stream_cmd_t::STREAM_MODE_START_CONTINUOUS); } @@ -195,9 +194,7 @@ void usrp2_mboard_impl::handle_overflow(void){ void usrp2_mboard_impl::issue_ddc_stream_cmd(const stream_cmd_t &stream_cmd){ _continuous_streaming = stream_cmd.stream_mode == stream_cmd_t::STREAM_MODE_START_CONTINUOUS; - _iface->poke32(U2_REG_RX_CTRL_STREAM_CMD, dsp_type1::calc_stream_cmd_word( - stream_cmd, _recv_samps_per_packet - )); + _iface->poke32(U2_REG_RX_CTRL_STREAM_CMD, dsp_type1::calc_stream_cmd_word(stream_cmd)); _iface->poke32(U2_REG_RX_CTRL_TIME_SECS, boost::uint32_t(stream_cmd.time_spec.get_full_secs())); _iface->poke32(U2_REG_RX_CTRL_TIME_TICKS, stream_cmd.time_spec.get_tick_count(get_master_clock_freq())); } diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp index e4980a539..e41cefc10 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -98,7 +98,6 @@ public: private: size_t _index; - const size_t _recv_samps_per_packet; bool _continuous_streaming; //interfaces diff --git a/host/lib/usrp/usrp2/usrp2_regs.hpp b/host/lib/usrp/usrp2/usrp2_regs.hpp index c3a4d22de..cef7cf2e6 100644 --- a/host/lib/usrp/usrp2/usrp2_regs.hpp +++ b/host/lib/usrp/usrp2/usrp2_regs.hpp @@ -179,7 +179,7 @@ #define U2_REG_RX_CTRL_TIME_SECS _SR_ADDR(SR_RX_CTRL + 1) #define U2_REG_RX_CTRL_TIME_TICKS _SR_ADDR(SR_RX_CTRL + 2) -#define U2_REG_RX_CTRL_CLEAR_OVERRUN _SR_ADDR(SR_RX_CTRL + 3) // write anything to clear overrun +#define U2_REG_RX_CTRL_CLEAR_STATE _SR_ADDR(SR_RX_CTRL + 3) #define U2_REG_RX_CTRL_VRT_HEADER _SR_ADDR(SR_RX_CTRL + 4) // word 0 of packet. FPGA fills in packet counter #define U2_REG_RX_CTRL_VRT_STREAM_ID _SR_ADDR(SR_RX_CTRL + 5) // word 1 of packet. #define U2_REG_RX_CTRL_VRT_TRAILER _SR_ADDR(SR_RX_CTRL + 6) -- cgit v1.2.3