From d6eae2063c33b05cece8293ed4391fa8619c2447 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 15 Dec 2010 23:51:29 -0800 Subject: usrp2: added support in fw for setting dsp0 and err0 ports with protocol framer changes --- firmware/microblaze/apps/txrx_uhd.c | 14 +++++++++++--- firmware/microblaze/usrp2/memory_map.h | 9 ++++++++- firmware/microblaze/usrp2p/memory_map.h | 9 ++++++++- host/lib/usrp/usrp2/fw_common.h | 1 + 4 files changed, 28 insertions(+), 5 deletions(-) diff --git a/firmware/microblaze/apps/txrx_uhd.c b/firmware/microblaze/apps/txrx_uhd.c index 9c1873e1c..06f94e108 100644 --- a/firmware/microblaze/apps/txrx_uhd.c +++ b/firmware/microblaze/apps/txrx_uhd.c @@ -141,15 +141,22 @@ static void print_ip_addr(const void *t){ printf("%d.%d.%d.%d", p[0], p[1], p[2], p[3]); } +void handle_udp_err0_packet( + struct socket_address src, struct socket_address dst, + unsigned char *payload, int payload_len +){ + sr_udp_sm->err0_port = src.port; +} + void handle_udp_data_packet( struct socket_address src, struct socket_address dst, unsigned char *payload, int payload_len ){ - //its a tiny payload, load the fast-path variables fp_mac_addr_src = *ethernet_mac_addr(); arp_cache_lookup_mac(&src.addr, &fp_mac_addr_dst); fp_socket_src = dst; fp_socket_dst = src; + sr_udp_sm->dsp0_port = src.port; printf("Storing for fast path:\n"); printf(" source mac addr: "); print_mac_addr(fp_mac_addr_src.addr); newline(); @@ -163,7 +170,7 @@ void handle_udp_data_packet( printf(" destination udp port: %d\n", fp_socket_dst.port); newline(); - //setup network and vrt + //setup network setup_network(); // kick off the state machine @@ -478,7 +485,7 @@ static void setup_network(void){ //setup the udp header machine sr_udp_sm->udp_hdr.src_port = fp_socket_src.port; - sr_udp_sm->udp_hdr.dst_port = fp_socket_dst.port; + sr_udp_sm->udp_hdr.dst_port = UDP_SM_INS_UDP_PORT; sr_udp_sm->udp_hdr.length = UDP_SM_INS_UDP_LEN; sr_udp_sm->udp_hdr.checksum = UDP_SM_LAST_WORD; // zero UDP checksum } @@ -521,6 +528,7 @@ main(void) //2) register callbacks for udp ports we service register_udp_listener(USRP2_UDP_CTRL_PORT, handle_udp_ctrl_packet); register_udp_listener(USRP2_UDP_DATA_PORT, handle_udp_data_packet); + register_udp_listener(USRP2_UDP_ERR0_PORT, handle_udp_err0_packet); register_udp_listener(USRP2_UDP_UPDATE_PORT, handle_udp_fw_update_packet); //3) setup ethernet hardware to bring the link up diff --git a/firmware/microblaze/usrp2/memory_map.h b/firmware/microblaze/usrp2/memory_map.h index eac0c217f..2b91063b2 100644 --- a/firmware/microblaze/usrp2/memory_map.h +++ b/firmware/microblaze/usrp2/memory_map.h @@ -435,11 +435,18 @@ typedef struct { uint32_t length; uint32_t checksum; //word 22 } udp_hdr; - volatile uint32_t _pad[32-23]; + volatile uint32_t _pad[2]; + volatile uint32_t dsp0_port; + volatile uint32_t err0_port; + volatile uint32_t dsp1_port; + volatile uint32_t err1_port; } sr_udp_sm_t; // control bits (all expect UDP_SM_LAST_WORD are mutually exclusive) +// Insert a UDP dest port from the table +#define UDP_SM_INS_UDP_PORT (1 << 20) + // This is the last word of the header #define UDP_SM_LAST_WORD (1 << 19) diff --git a/firmware/microblaze/usrp2p/memory_map.h b/firmware/microblaze/usrp2p/memory_map.h index 3b2dc0057..140ab0675 100644 --- a/firmware/microblaze/usrp2p/memory_map.h +++ b/firmware/microblaze/usrp2p/memory_map.h @@ -462,11 +462,18 @@ typedef struct { uint32_t length; uint32_t checksum; //word 22 } udp_hdr; - volatile uint32_t _pad[32-23]; + volatile uint32_t _pad[2]; + volatile uint32_t dsp0_port; + volatile uint32_t err0_port; + volatile uint32_t dsp1_port; + volatile uint32_t err1_port; } sr_udp_sm_t; // control bits (all expect UDP_SM_LAST_WORD are mutually exclusive) +// Insert a UDP dest port from the table +#define UDP_SM_INS_UDP_PORT (1 << 20) + // This is the last word of the header #define UDP_SM_LAST_WORD (1 << 19) diff --git a/host/lib/usrp/usrp2/fw_common.h b/host/lib/usrp/usrp2/fw_common.h index a9c39e650..a26f56e8b 100644 --- a/host/lib/usrp/usrp2/fw_common.h +++ b/host/lib/usrp/usrp2/fw_common.h @@ -43,6 +43,7 @@ extern "C" { // Dynamic and/or private ports: 49152-65535 #define USRP2_UDP_CTRL_PORT 49152 #define USRP2_UDP_DATA_PORT 49153 +#define USRP2_UDP_ERR0_PORT 49154 //////////////////////////////////////////////////////////////////////// // I2C addresses -- cgit v1.2.3 From fa7d4a2a15cf332085b218373e7746604285bf2c Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 15 Dec 2010 23:58:01 -0800 Subject: usrp2: pulled some changes from the next branch to make merging easier --- host/lib/usrp/usrp2/mboard_impl.cpp | 12 ++++-------- host/lib/usrp/usrp2/usrp2_impl.cpp | 14 +++++++------- host/lib/usrp/usrp2/usrp2_impl.hpp | 8 +++----- 3 files changed, 14 insertions(+), 20 deletions(-) diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp index 766ea993c..b64d4e3f6 100644 --- a/host/lib/usrp/usrp2/mboard_impl.cpp +++ b/host/lib/usrp/usrp2/mboard_impl.cpp @@ -38,8 +38,8 @@ usrp2_mboard_impl::usrp2_mboard_impl( size_t index, transport::udp_simple::sptr ctrl_transport, transport::zero_copy_if::sptr data_transport, - size_t recv_samps_per_packet, - const device_addr_t &flow_control_hints + const device_addr_t &device_args, + size_t recv_samps_per_packet ): _index(index), _iface(usrp2_iface::make(ctrl_transport)) @@ -58,7 +58,6 @@ usrp2_mboard_impl::usrp2_mboard_impl( //contruct the interfaces to mboard perifs _clock_ctrl = usrp2_clock_ctrl::make(_iface); _codec_ctrl = usrp2_codec_ctrl::make(_iface); - _serdes_ctrl = usrp2_serdes_ctrl::make(_iface); //_gps_ctrl = usrp2_gps_ctrl::make(_iface); //if(_gps_ctrl->gps_detected()) std::cout << "GPS time: " << _gps_ctrl->get_time() << std::endl; @@ -98,14 +97,14 @@ usrp2_mboard_impl::usrp2_mboard_impl( _iface->poke32(_iface->regs.tx_ctrl_policy, U2_FLAG_TX_CTRL_POLICY_NEXT_PACKET); //setting the cycles per update (disabled by default) - const double ups_per_sec = flow_control_hints.cast("ups_per_sec", 0.0); + const double ups_per_sec = device_args.cast("ups_per_sec", 0.0); if (ups_per_sec > 0.0){ const size_t cycles_per_up = size_t(_clock_ctrl->get_master_clock_rate()/ups_per_sec); _iface->poke32(_iface->regs.tx_ctrl_cycles_per_up, U2_FLAG_TX_CTRL_UP_ENB | cycles_per_up); } //setting the packets per update (enabled by default) - const double ups_per_fifo = flow_control_hints.cast("ups_per_fifo", 8.0); + const double ups_per_fifo = device_args.cast("ups_per_fifo", 8.0); if (ups_per_fifo > 0.0){ const size_t packets_per_up = size_t(usrp2_impl::sram_bytes/ups_per_fifo/data_transport->get_send_frame_size()); _iface->poke32(_iface->regs.tx_ctrl_packets_per_up, U2_FLAG_TX_CTRL_UP_ENB | packets_per_up); @@ -155,7 +154,6 @@ void usrp2_mboard_impl::update_clock_config(void){ //translate pps source enums switch(_clock_config.pps_source){ case clock_config_t::PPS_SMA: pps_flags |= U2_FLAG_TIME64_PPS_SMA; break; - case clock_config_t::PPS_MIMO: pps_flags |= U2_FLAG_TIME64_PPS_MIMO; break; default: throw std::runtime_error("unhandled clock configuration pps source"); } @@ -176,7 +174,6 @@ void usrp2_mboard_impl::update_clock_config(void){ switch(_clock_config.ref_source){ case clock_config_t::REF_INT : _iface->poke32(_iface->regs.misc_ctrl_clock, 0x12); break; case clock_config_t::REF_SMA : _iface->poke32(_iface->regs.misc_ctrl_clock, 0x1C); break; - case clock_config_t::REF_MIMO: _iface->poke32(_iface->regs.misc_ctrl_clock, 0x15); break; default: throw std::runtime_error("unhandled clock configuration reference source"); } _clock_ctrl->enable_external_ref(true); //USRP2P has an internal 10MHz TCXO @@ -187,7 +184,6 @@ void usrp2_mboard_impl::update_clock_config(void){ switch(_clock_config.ref_source){ case clock_config_t::REF_INT : _iface->poke32(_iface->regs.misc_ctrl_clock, 0x10); break; case clock_config_t::REF_SMA : _iface->poke32(_iface->regs.misc_ctrl_clock, 0x1C); break; - case clock_config_t::REF_MIMO: _iface->poke32(_iface->regs.misc_ctrl_clock, 0x15); break; default: throw std::runtime_error("unhandled clock configuration reference source"); } _clock_ctrl->enable_external_ref(_clock_config.ref_source != clock_config_t::REF_INT); diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp index c3bbe4d65..133c39a35 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.cpp +++ b/host/lib/usrp/usrp2/usrp2_impl.cpp @@ -201,8 +201,9 @@ sep_indexed_dev_addrs(device_addr); //create a ctrl and data transport for each address std::vector ctrl_transports; std::vector data_transports; + const device_addrs_t device_addrs = sep_indexed_dev_addrs(device_addr); - BOOST_FOREACH(const device_addr_t &dev_addr_i, sep_indexed_dev_addrs(device_addr)){ + BOOST_FOREACH(const device_addr_t &dev_addr_i, device_addrs){ ctrl_transports.push_back(udp_simple::make_connected( dev_addr_i["addr"], num2str(USRP2_UDP_CTRL_PORT) )); @@ -213,7 +214,7 @@ sep_indexed_dev_addrs(device_addr); //create the usrp2 implementation guts return device::sptr( - new usrp2_impl(ctrl_transports, data_transports, device_addr) + new usrp2_impl(ctrl_transports, data_transports, device_addrs) ); } @@ -227,7 +228,7 @@ UHD_STATIC_BLOCK(register_usrp2_device){ usrp2_impl::usrp2_impl( std::vector ctrl_transports, std::vector data_transports, - const device_addr_t &flow_control_hints + const device_addrs_t &device_args ): _data_transports(data_transports) { @@ -244,11 +245,10 @@ usrp2_impl::usrp2_impl( //!!!!! set the otw type here before continuing, its used below //create a new mboard handler for each control transport - for(size_t i = 0; i < ctrl_transports.size(); i++){ + for(size_t i = 0; i < device_args.size(); i++){ _mboards.push_back(usrp2_mboard_impl::sptr(new usrp2_mboard_impl( - i, ctrl_transports[i], data_transports[i], - this->get_max_recv_samps_per_packet(), - flow_control_hints + i, ctrl_transports[i], data_transports[i], device_args[i], + this->get_max_recv_samps_per_packet() ))); //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 aa8eb0155..16a7a0a7c 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -22,7 +22,6 @@ #include "clock_ctrl.hpp" #include "codec_ctrl.hpp" #include "gps_ctrl.hpp" -#include "serdes_ctrl.hpp" #include #include #include @@ -86,8 +85,8 @@ public: size_t index, uhd::transport::udp_simple::sptr, uhd::transport::zero_copy_if::sptr, - size_t recv_samps_per_packet, - const uhd::device_addr_t &flow_control_hints + const uhd::device_addr_t &device_args, + size_t recv_samps_per_packet ); ~usrp2_mboard_impl(void); @@ -105,7 +104,6 @@ private: usrp2_iface::sptr _iface; usrp2_clock_ctrl::sptr _clock_ctrl; usrp2_codec_ctrl::sptr _codec_ctrl; - usrp2_serdes_ctrl::sptr _serdes_ctrl; usrp2_gps_ctrl::sptr _gps_ctrl; //properties for this mboard @@ -192,7 +190,7 @@ public: usrp2_impl( std::vector ctrl_transports, std::vector data_transports, - const uhd::device_addr_t &flow_control_hints + const uhd::device_addrs_t &device_args ); ~usrp2_impl(void); -- cgit v1.2.3 From 28194df43e34b8f5c89d7a3f0fdea0be3a15b7b2 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 16 Dec 2010 00:07:19 -0800 Subject: usrp2: brought err0 transports into device and mboard constructors --- host/lib/usrp/usrp2/mboard_impl.cpp | 7 ++++++- host/lib/usrp/usrp2/usrp2_impl.cpp | 17 ++++++++++++----- host/lib/usrp/usrp2/usrp2_impl.hpp | 6 +++++- 3 files changed, 23 insertions(+), 7 deletions(-) diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp index b64d4e3f6..9afa6eda7 100644 --- a/host/lib/usrp/usrp2/mboard_impl.cpp +++ b/host/lib/usrp/usrp2/mboard_impl.cpp @@ -38,6 +38,7 @@ usrp2_mboard_impl::usrp2_mboard_impl( size_t index, transport::udp_simple::sptr ctrl_transport, transport::zero_copy_if::sptr data_transport, + transport::zero_copy_if::sptr err0_transport, const device_addr_t &device_args, size_t recv_samps_per_packet ): @@ -47,11 +48,15 @@ usrp2_mboard_impl::usrp2_mboard_impl( //Send a small data packet so the usrp2 knows the udp source port. //This setup must happen before further initialization occurs //or the async update packets will cause ICMP destination unreachable. - transport::managed_send_buffer::sptr send_buff = data_transport->get_send_buff(); + transport::managed_send_buffer::sptr send_buff; static const boost::uint32_t data[2] = { uhd::htonx(boost::uint32_t(0 /* don't care seq num */)), uhd::htonx(boost::uint32_t(USRP2_INVALID_VRT_HEADER)) }; + send_buff = data_transport->get_send_buff(); + std::memcpy(send_buff->cast(), &data, sizeof(data)); + send_buff->commit(sizeof(data)); + send_buff = err0_transport->get_send_buff(); std::memcpy(send_buff->cast(), &data, sizeof(data)); send_buff->commit(sizeof(data)); diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp index 133c39a35..ca4a463b7 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.cpp +++ b/host/lib/usrp/usrp2/usrp2_impl.cpp @@ -201,6 +201,7 @@ sep_indexed_dev_addrs(device_addr); //create a ctrl and data transport for each address std::vector ctrl_transports; std::vector data_transports; + std::vector err0_transports; const device_addrs_t device_addrs = sep_indexed_dev_addrs(device_addr); BOOST_FOREACH(const device_addr_t &dev_addr_i, device_addrs){ @@ -210,12 +211,15 @@ sep_indexed_dev_addrs(device_addr); data_transports.push_back(udp_zero_copy::make( dev_addr_i["addr"], num2str(USRP2_UDP_DATA_PORT), device_addr )); + err0_transports.push_back(udp_zero_copy::make( + dev_addr_i["addr"], num2str(USRP2_UDP_ERR0_PORT), device_addr + )); } //create the usrp2 implementation guts - return device::sptr( - new usrp2_impl(ctrl_transports, data_transports, device_addrs) - ); + return device::sptr(new usrp2_impl( + ctrl_transports, data_transports, err0_transports, device_addrs + )); } UHD_STATIC_BLOCK(register_usrp2_device){ @@ -228,9 +232,11 @@ UHD_STATIC_BLOCK(register_usrp2_device){ usrp2_impl::usrp2_impl( std::vector ctrl_transports, std::vector data_transports, + std::vector err0_transports, const device_addrs_t &device_args ): - _data_transports(data_transports) + _data_transports(data_transports), + _err0_transports(err0_transports) { //setup rx otw type _rx_otw_type.width = 16; @@ -247,7 +253,8 @@ usrp2_impl::usrp2_impl( //create a new mboard handler for each control transport for(size_t i = 0; i < device_args.size(); i++){ _mboards.push_back(usrp2_mboard_impl::sptr(new usrp2_mboard_impl( - i, ctrl_transports[i], data_transports[i], device_args[i], + i, ctrl_transports[i], data_transports[i], + err0_transports[i], device_args[i], this->get_max_recv_samps_per_packet() ))); //use an empty name when there is only one mboard diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp index 16a7a0a7c..be97e1121 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -85,6 +85,7 @@ public: size_t index, uhd::transport::udp_simple::sptr, uhd::transport::zero_copy_if::sptr, + uhd::transport::zero_copy_if::sptr, const uhd::device_addr_t &device_args, size_t recv_samps_per_packet ); @@ -185,11 +186,13 @@ 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 + * \param err0_transports the udp transports for error + * \param device_args optional misc device parameters */ usrp2_impl( std::vector ctrl_transports, std::vector data_transports, + std::vector err0_transports, const uhd::device_addrs_t &device_args ); @@ -221,6 +224,7 @@ private: //io impl methods and members std::vector _data_transports; + std::vector _err0_transports; uhd::otw_type_t _rx_otw_type, _tx_otw_type; UHD_PIMPL_DECL(io_impl) _io_impl; void io_init(void); -- cgit v1.2.3 From 72c7a0c9f0e41afe9713465eaa6ff2f189122753 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 16 Dec 2010 14:38:06 -0800 Subject: usrp2: removed alignment buffer and implemented event based recv + alignment, TODO test me --- host/include/uhd/transport/CMakeLists.txt | 2 - host/include/uhd/transport/alignment_buffer.hpp | 69 --------- host/include/uhd/transport/alignment_buffer.ipp | 144 ------------------ host/include/uhd/transport/bounded_buffer.ipp | 13 +- host/lib/usrp/usrp2/io_impl.cpp | 187 ++++++++++++++++++------ host/test/buffer_test.cpp | 51 ------- 6 files changed, 150 insertions(+), 316 deletions(-) delete mode 100644 host/include/uhd/transport/alignment_buffer.hpp delete mode 100644 host/include/uhd/transport/alignment_buffer.ipp diff --git a/host/include/uhd/transport/CMakeLists.txt b/host/include/uhd/transport/CMakeLists.txt index 2c84c0724..ec3b7b113 100644 --- a/host/include/uhd/transport/CMakeLists.txt +++ b/host/include/uhd/transport/CMakeLists.txt @@ -17,8 +17,6 @@ INSTALL(FILES - alignment_buffer.hpp - alignment_buffer.ipp bounded_buffer.hpp bounded_buffer.ipp convert_types.hpp diff --git a/host/include/uhd/transport/alignment_buffer.hpp b/host/include/uhd/transport/alignment_buffer.hpp deleted file mode 100644 index f44a037f8..000000000 --- a/host/include/uhd/transport/alignment_buffer.hpp +++ /dev/null @@ -1,69 +0,0 @@ -// -// Copyright 2010 Ettus Research LLC -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -#ifndef INCLUDED_UHD_TRANSPORT_ALIGNMENT_BUFFER_HPP -#define INCLUDED_UHD_TRANSPORT_ALIGNMENT_BUFFER_HPP - -#include -#include //time_duration_t -#include -#include - -namespace uhd{ namespace transport{ - - /*! - * Implement a templated alignment buffer: - * Used for aligning asynchronously pushed elements with matching ids. - */ - template class alignment_buffer{ - public: - typedef boost::shared_ptr > sptr; - - /*! - * Make a new alignment buffer object. - * \param capacity the maximum elements per index - * \param width the number of elements to align - */ - static sptr make(size_t capacity, size_t width); - - /*! - * Push an element with sequence id into the buffer at index. - * \param elem the element to push - * \param seq the sequence identifier - * \param index the buffer index - * \return true if the element fit without popping for space - */ - virtual bool push_with_pop_on_full( - const elem_type &elem, const seq_type &seq, size_t index - ) = 0; - - /*! - * Pop an aligned set of elements from this alignment buffer. - * \param elems a collection to store the aligned elements - * \param timeout the timeout in seconds - * \return false when the operation times out - */ - virtual bool pop_elems_with_timed_wait( - std::vector &elems, double timeout - ) = 0; - }; - -}} //namespace - -#include - -#endif /* INCLUDED_UHD_TRANSPORT_ALIGNMENT_BUFFER_HPP */ diff --git a/host/include/uhd/transport/alignment_buffer.ipp b/host/include/uhd/transport/alignment_buffer.ipp deleted file mode 100644 index 833b5d399..000000000 --- a/host/include/uhd/transport/alignment_buffer.ipp +++ /dev/null @@ -1,144 +0,0 @@ -// -// Copyright 2010 Ettus Research LLC -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -#ifndef INCLUDED_UHD_TRANSPORT_ALIGNMENT_BUFFER_IPP -#define INCLUDED_UHD_TRANSPORT_ALIGNMENT_BUFFER_IPP - -#include -#include -#include - -namespace uhd{ namespace transport{ namespace{ /*anon*/ - - /*! - * Imlement a templated alignment buffer: - * Used for aligning asynchronously pushed elements with matching ids. - */ - template - class alignment_buffer_impl : public alignment_buffer{ - public: - - alignment_buffer_impl(size_t capacity, size_t width) : _last_seqs(width){ - for (size_t i = 0; i < width; i++){ - _buffs.push_back(bounded_buffer::make(capacity)); - _all_indexes.push_back(i); - } - _there_was_a_clear = false; - } - - UHD_INLINE bool push_with_pop_on_full( - const elem_type &elem, const seq_type &seq, size_t index - ){ - //clear the buffer for this index if the seqs are mis-ordered - if (seq < _last_seqs[index]){ - _buffs[index]->clear(); - _there_was_a_clear = true; - } _last_seqs[index] = seq; - return _buffs[index]->push_with_pop_on_full(buff_contents_type(elem, seq)); - } - - UHD_INLINE bool pop_elems_with_timed_wait( - std::vector &elems, double timeout - ){ - boost::system_time exit_time = boost::get_system_time() + to_time_dur(timeout); - buff_contents_type buff_contents_tmp; - std::list indexes_to_do(_all_indexes); - - //do an initial pop to load an initial sequence id - size_t index = indexes_to_do.front(); - if (not _buffs[index]->pop_with_timed_wait( - buff_contents_tmp, from_time_dur(exit_time - boost::get_system_time()) - )) return false; - elems[index] = buff_contents_tmp.first; - seq_type expected_seq_id = buff_contents_tmp.second; - indexes_to_do.pop_front(); - - //get an aligned set of elements from the buffers: - while(indexes_to_do.size() != 0){ - - //respond to a clear by starting from scratch - if(_there_was_a_clear){ - _there_was_a_clear = false; - indexes_to_do = _all_indexes; - index = indexes_to_do.front(); - if (not _buffs[index]->pop_with_timed_wait( - buff_contents_tmp, from_time_dur(exit_time - boost::get_system_time()) - )) return false; - elems[index] = buff_contents_tmp.first; - expected_seq_id = buff_contents_tmp.second; - indexes_to_do.pop_front(); - } - - //pop an element off for this index - index = indexes_to_do.front(); - if (not _buffs[index]->pop_with_timed_wait( - buff_contents_tmp, from_time_dur(exit_time - boost::get_system_time()) - )) return false; - - //if the sequence id matches: - // store the popped element into the output, - // remove this index from the list and continue - if (buff_contents_tmp.second == expected_seq_id){ - elems[index] = buff_contents_tmp.first; - indexes_to_do.pop_front(); - continue; - } - - //if the sequence id is older: - // continue with the same index to try again - if (buff_contents_tmp.second < expected_seq_id){ - continue; - } - - //if the sequence id is newer: - // store the popped element into the output, - // add all other indexes back into the list - if (buff_contents_tmp.second > expected_seq_id){ - elems[index] = buff_contents_tmp.first; - expected_seq_id = buff_contents_tmp.second; - indexes_to_do = _all_indexes; - indexes_to_do.remove(index); - continue; - } - } - return true; - } - - private: - //a vector of bounded buffers for each index - typedef std::pair buff_contents_type; - std::vector::sptr> _buffs; - std::vector _last_seqs; - std::list _all_indexes; - bool _there_was_a_clear; - }; - -}}} //namespace - -namespace uhd{ namespace transport{ - - template - typename alignment_buffer::sptr - alignment_buffer::make(size_t capacity, size_t width){ - return typename alignment_buffer::sptr( - new alignment_buffer_impl(capacity, width) - ); - } - -}} //namespace - -#endif /* INCLUDED_UHD_TRANSPORT_ALIGNMENT_BUFFER_IPP */ diff --git a/host/include/uhd/transport/bounded_buffer.ipp b/host/include/uhd/transport/bounded_buffer.ipp index edc7faa06..f7915d866 100644 --- a/host/include/uhd/transport/bounded_buffer.ipp +++ b/host/include/uhd/transport/bounded_buffer.ipp @@ -26,14 +26,6 @@ namespace uhd{ namespace transport{ namespace{ /*anon*/ - static UHD_INLINE boost::posix_time::time_duration to_time_dur(double timeout){ - return boost::posix_time::microseconds(long(timeout*1e6)); - } - - static UHD_INLINE double from_time_dur(const boost::posix_time::time_duration &time_dur){ - return 1e-6*time_dur.total_microseconds(); - } - template class bounded_buffer_impl : public bounded_buffer{ public: @@ -127,6 +119,11 @@ namespace uhd{ namespace transport{ namespace{ /*anon*/ _buffer.pop_back(); return elem; } + + static UHD_INLINE boost::posix_time::time_duration to_time_dur(double timeout){ + return boost::posix_time::microseconds(long(timeout*1e6)); + } + }; }}} //namespace diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index cbc0a0817..c8e4b7096 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -21,11 +21,13 @@ #include #include #include -#include +#include #include #include #include +#include #include +#include using namespace uhd; using namespace uhd::usrp; @@ -108,16 +110,24 @@ private: * - vrt packet handler states **********************************************************************/ struct usrp2_impl::io_impl{ - typedef alignment_buffer alignment_buffer_type; - io_impl(size_t num_recv_frames, size_t send_frame_size, size_t width): + io_impl(size_t send_frame_size, size_t width): packet_handler_recv_state(width), - recv_pirate_booty(alignment_buffer_type::make(num_recv_frames-3, width)), async_msg_fifo(bounded_buffer::make(100/*messages deep*/)) { - for (size_t i = 0; i < width; i++) fc_mons.push_back( - flow_control_monitor::sptr(new flow_control_monitor(usrp2_impl::sram_bytes/send_frame_size)) - ); + for (size_t i = 0; i < width; i++){ + fc_mons.push_back(flow_control_monitor::sptr( + new flow_control_monitor(usrp2_impl::sram_bytes/send_frame_size) + )); + //init empty packet infos + vrt::if_packet_info_t packet_info; + packet_info.packet_count = 0; + packet_info.has_tsi = true; + packet_info.tsi = 0; + packet_info.has_tsf = true; + packet_info.tsf = 0; + prev_infos.push_back(packet_info); + } } ~io_impl(void){ @@ -126,11 +136,6 @@ struct usrp2_impl::io_impl{ recv_pirate_crew.join_all(); } - bool get_recv_buffs(vrt_packet_handler::managed_recv_buffs_t &buffs, double timeout){ - boost::this_thread::disable_interruption di; //disable because the wait can throw - return recv_pirate_booty->pop_elems_with_timed_wait(buffs, timeout); - } - bool get_send_buffs( const std::vector &trans, vrt_packet_handler::managed_send_buffs_t &buffs, @@ -151,6 +156,15 @@ struct usrp2_impl::io_impl{ return true; } + bool get_recv_buffs( + const std::vector xports, + vrt_packet_handler::managed_recv_buffs_t &buffs, + double timeout + ); + + //previous state for each buffer + std::vector prev_infos; + //flow control monitors std::vector fc_mons; @@ -162,29 +176,28 @@ struct usrp2_impl::io_impl{ void recv_pirate_loop(zero_copy_if::sptr, usrp2_mboard_impl::sptr, size_t); boost::thread_group recv_pirate_crew; bool recv_pirate_crew_raiding; - alignment_buffer_type::sptr recv_pirate_booty; bounded_buffer::sptr async_msg_fifo; boost::mutex spawn_mutex; }; /*********************************************************************** * Receive Pirate Loop - * - while raiding, loot for recv buffers - * - put booty into the alignment buffer + * - while raiding, loot for message packet + * - update flow control condition count + * - put async message packets into queue **********************************************************************/ void usrp2_impl::io_impl::recv_pirate_loop( - zero_copy_if::sptr zc_if, + zero_copy_if::sptr zc_if_err0, usrp2_mboard_impl::sptr mboard, size_t index ){ set_thread_priority_safe(); recv_pirate_crew_raiding = true; - size_t next_packet_seq = 0; spawn_mutex.unlock(); while(recv_pirate_crew_raiding){ - managed_recv_buffer::sptr buff = zc_if->get_recv_buff(); + managed_recv_buffer::sptr buff = zc_if_err0->get_recv_buff(); if (not buff.get()) continue; //ignore timeout/error buffers try{ @@ -194,26 +207,6 @@ void usrp2_impl::io_impl::recv_pirate_loop( const boost::uint32_t *vrt_hdr = buff->cast(); vrt::if_hdr_unpack_be(vrt_hdr, if_packet_info); - //handle the rx data stream - if (if_packet_info.sid == usrp2_impl::RECV_SID){ - //handle the packet count / sequence number - if (if_packet_info.packet_count != next_packet_seq){ - //std::cerr << "S" << (if_packet_info.packet_count - next_packet_seq)%16; - std::cerr << "O" << std::flush; //report overflow (drops in the kernel) - } - next_packet_seq = (if_packet_info.packet_count+1)%16; - - //extract the timespec and round to the nearest packet - UHD_ASSERT_THROW(if_packet_info.has_tsi and if_packet_info.has_tsf); - time_spec_t time( - time_t(if_packet_info.tsi), size_t(if_packet_info.tsf), mboard->get_master_clock_freq() - ); - - //push the packet into the buffer with the new time - recv_pirate_booty->push_with_pop_on_full(buff, time, index); - continue; - } - //handle a tx async report message if (if_packet_info.sid == usrp2_impl::ASYNC_SID and if_packet_info.packet_type != vrt::if_packet_info_t::PACKET_TYPE_DATA){ @@ -253,11 +246,10 @@ void usrp2_impl::io_impl::recv_pirate_loop( void usrp2_impl::io_init(void){ //the assumption is that all data transports should be identical - const size_t num_recv_frames = _data_transports.front()->get_num_recv_frames(); const size_t send_frame_size = _data_transports.front()->get_send_frame_size(); //create new io impl - _io_impl = UHD_PIMPL_MAKE(io_impl, (num_recv_frames, send_frame_size, _data_transports.size())); + _io_impl = UHD_PIMPL_MAKE(io_impl, (send_frame_size, _data_transports.size())); //TODO temporary fix for weird power up state, remove when FPGA fixed { @@ -276,7 +268,7 @@ void usrp2_impl::io_init(void){ //spawn a new pirate to plunder the recv booty _io_impl->recv_pirate_crew.create_thread(boost::bind( &usrp2_impl::io_impl::recv_pirate_loop, - _io_impl.get(), _data_transports.at(i), + _io_impl.get(), _err0_transports.at(i), _mboards.at(i), i )); //block here until the spawned thread unlocks @@ -327,6 +319,117 @@ size_t usrp2_impl::send( ); } +/*********************************************************************** + * Alignment logic on receive + **********************************************************************/ +static UHD_INLINE boost::posix_time::time_duration to_time_dur(double timeout){ + return boost::posix_time::microseconds(long(timeout*1e6)); +} + +static UHD_INLINE double from_time_dur(const boost::posix_time::time_duration &time_dur){ + return 1e-6*time_dur.total_microseconds(); +} + +static UHD_INLINE time_spec_t extract_time_spec(const vrt::if_packet_info_t &packet_info){ + return time_spec_t( //assumes has_tsi and has_tsf are true + time_t(packet_info.tsi), size_t(packet_info.tsf), + 100e6 //tick rate does not have to be correct for comparison purposes + ); +} + +static UHD_INLINE void extract_packet_info( + managed_recv_buffer::sptr buff, + vrt::if_packet_info_t &prev_info, + time_spec_t &time, bool &clear +){ + //extract packet info + vrt::if_packet_info_t next_info; + vrt::if_hdr_unpack_be(buff->cast(), next_info); + + //handle the packet count / sequence number + if ((prev_info.packet_count+1)%16 != next_info.packet_count){ + std::cerr << "O" << std::flush; //report overflow (drops in the kernel) + } + + time = extract_time_spec(next_info); + clear = extract_time_spec(prev_info) > time; + prev_info = next_info; +} + +UHD_INLINE bool usrp2_impl::io_impl::get_recv_buffs( + const std::vector xports, + vrt_packet_handler::managed_recv_buffs_t &buffs, + double timeout +){ + if (buffs.size() == 1){ + buffs[0] = xports[0]->get_recv_buff(timeout); + if (buffs[0].get() == NULL) return false; + bool clear; time_spec_t time; //unused variables + //call extract_packet_info to handle printing the overflows + extract_packet_info(buffs[0], this->prev_infos[0], time, clear); + return true; + } + //-------------------- begin alignment logic ---------------------// + boost::system_time exit_time = boost::get_system_time() + to_time_dur(timeout); + managed_recv_buffer::sptr buff_tmp; + std::list _all_indexes, indexes_to_do; + for (size_t i = 0; i < buffs.size(); i++) _all_indexes.push_back(i); + bool clear; + time_spec_t expected_time; + + //respond to a clear by starting from scratch + got_clear: + indexes_to_do = _all_indexes; + clear = false; + + //do an initial pop to load an initial sequence id + size_t index = indexes_to_do.front(); + buff_tmp = xports[index]->get_recv_buff(from_time_dur(exit_time - boost::get_system_time())); + if (buff_tmp.get() == NULL) return false; + extract_packet_info(buff_tmp, this->prev_infos[index], expected_time, clear); + if (clear) goto got_clear; + buffs[index] = buff_tmp; + indexes_to_do.pop_front(); + + //get an aligned set of elements from the buffers: + while(indexes_to_do.size() != 0){ + + //pop an element off for this index + index = indexes_to_do.front(); + buff_tmp = xports[index]->get_recv_buff(from_time_dur(exit_time - boost::get_system_time())); + if (buff_tmp.get() == NULL) return false; + time_spec_t this_time; + extract_packet_info(buff_tmp, this->prev_infos[index], this_time, clear); + if (clear) goto got_clear; + buffs[index] = buff_tmp; + + //if the sequence id matches: + // remove this index from the list and continue + if (this_time == expected_time){ + indexes_to_do.pop_front(); + continue; + } + + //if the sequence id is older: + // continue with the same index to try again + else if (this_time < expected_time){ + continue; + } + + //if the sequence id is newer: + // use the new expected time for comparison + // add all other indexes back into the list + else{ + expected_time = this_time; + indexes_to_do = _all_indexes; + indexes_to_do.remove(index); + continue; + } + } + return true; + //-------------------- end alignment logic -----------------------// +} + /*********************************************************************** * Receive Data **********************************************************************/ @@ -357,7 +460,7 @@ size_t usrp2_impl::recv( io_type, _rx_otw_type, //input and output types to convert _mboards.front()->get_master_clock_freq(), //master clock tick rate uhd::transport::vrt::if_hdr_unpack_be, - boost::bind(&usrp2_impl::io_impl::get_recv_buffs, _io_impl.get(), _1, timeout), + boost::bind(&usrp2_impl::io_impl::get_recv_buffs, _io_impl.get(), _data_transports, _1, timeout), boost::bind(&handle_overflow, _mboards, _1) ); } diff --git a/host/test/buffer_test.cpp b/host/test/buffer_test.cpp index 8445412e7..e7bc88699 100644 --- a/host/test/buffer_test.cpp +++ b/host/test/buffer_test.cpp @@ -17,7 +17,6 @@ #include #include -#include #include using namespace boost::assign; @@ -63,53 +62,3 @@ BOOST_AUTO_TEST_CASE(test_bounded_buffer_with_pop_on_full){ BOOST_CHECK(bb->pop_with_timed_wait(val, timeout)); BOOST_CHECK_EQUAL(val, 3); } - -BOOST_AUTO_TEST_CASE(test_alignment_buffer){ - alignment_buffer::sptr ab(alignment_buffer::make(7, 3)); - //load index 0 with all good seq numbers - BOOST_CHECK(ab->push_with_pop_on_full(0, 0, 0)); - BOOST_CHECK(ab->push_with_pop_on_full(1, 1, 0)); - BOOST_CHECK(ab->push_with_pop_on_full(2, 2, 0)); - BOOST_CHECK(ab->push_with_pop_on_full(3, 3, 0)); - BOOST_CHECK(ab->push_with_pop_on_full(4, 4, 0)); - - //load index 1 with some skipped seq numbers - BOOST_CHECK(ab->push_with_pop_on_full(10, 0, 1)); - BOOST_CHECK(ab->push_with_pop_on_full(11, 1, 1)); - BOOST_CHECK(ab->push_with_pop_on_full(14, 4, 1)); - BOOST_CHECK(ab->push_with_pop_on_full(15, 5, 1)); - BOOST_CHECK(ab->push_with_pop_on_full(16, 6, 1)); - - //load index 2 with all good seq numbers - BOOST_CHECK(ab->push_with_pop_on_full(20, 0, 2)); - BOOST_CHECK(ab->push_with_pop_on_full(21, 1, 2)); - BOOST_CHECK(ab->push_with_pop_on_full(22, 2, 2)); - BOOST_CHECK(ab->push_with_pop_on_full(23, 3, 2)); - BOOST_CHECK(ab->push_with_pop_on_full(24, 4, 2)); - - //readback aligned values - std::vector aligned_elems(3); - - static const std::vector expected_elems0 = list_of(0)(10)(20); - BOOST_CHECK(ab->pop_elems_with_timed_wait(aligned_elems, timeout)); - BOOST_CHECK_EQUAL_COLLECTIONS( - aligned_elems.begin(), aligned_elems.end(), - expected_elems0.begin(), expected_elems0.end() - ); - - static const std::vector expected_elems1 = list_of(1)(11)(21); - BOOST_CHECK(ab->pop_elems_with_timed_wait(aligned_elems, timeout)); - BOOST_CHECK_EQUAL_COLLECTIONS( - aligned_elems.begin(), aligned_elems.end(), - expected_elems1.begin(), expected_elems1.end() - ); - - //there was a skip now find 4 - - static const std::vector expected_elems4 = list_of(4)(14)(24); - BOOST_CHECK(ab->pop_elems_with_timed_wait(aligned_elems, timeout)); - BOOST_CHECK_EQUAL_COLLECTIONS( - aligned_elems.begin(), aligned_elems.end(), - expected_elems4.begin(), expected_elems4.end() - ); -} -- cgit v1.2.3 From 0e66165d43d896bbc263dcf3481b94450d7de89f Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Fri, 17 Dec 2010 13:45:57 -0800 Subject: udp_ports: set the source and destination ports --- firmware/microblaze/apps/txrx_uhd.c | 18 +++++++++++------- firmware/microblaze/usrp2/memory_map.h | 7 +++++-- firmware/microblaze/usrp2p/memory_map.h | 7 +++++-- 3 files changed, 21 insertions(+), 11 deletions(-) diff --git a/firmware/microblaze/apps/txrx_uhd.c b/firmware/microblaze/apps/txrx_uhd.c index 06f94e108..4f331718f 100644 --- a/firmware/microblaze/apps/txrx_uhd.c +++ b/firmware/microblaze/apps/txrx_uhd.c @@ -141,14 +141,18 @@ static void print_ip_addr(const void *t){ printf("%d.%d.%d.%d", p[0], p[1], p[2], p[3]); } -void handle_udp_err0_packet( +static void handle_udp_err0_packet( struct socket_address src, struct socket_address dst, unsigned char *payload, int payload_len ){ - sr_udp_sm->err0_port = src.port; + sr_udp_sm->err0_port = (((uint32_t)dst.port) << 16) | src.port; + printf("Storing for async error path:\n"); + printf(" source udp port: %d\n", dst.port); + printf(" destination udp port: %d\n", src.port); + newline(); } -void handle_udp_data_packet( +static void handle_udp_data_packet( struct socket_address src, struct socket_address dst, unsigned char *payload, int payload_len ){ @@ -156,7 +160,7 @@ void handle_udp_data_packet( arp_cache_lookup_mac(&src.addr, &fp_mac_addr_dst); fp_socket_src = dst; fp_socket_dst = src; - sr_udp_sm->dsp0_port = src.port; + sr_udp_sm->dsp0_port = (((uint32_t)dst.port) << 16) | src.port; printf("Storing for fast path:\n"); printf(" source mac addr: "); print_mac_addr(fp_mac_addr_src.addr); newline(); @@ -208,7 +212,7 @@ void get_spi_readback_data(void) { spi_register_callback(0); } -void handle_udp_ctrl_packet( +static void handle_udp_ctrl_packet( struct socket_address src, struct socket_address dst, unsigned char *payload, int payload_len ){ @@ -484,8 +488,8 @@ static void setup_network(void){ sr_udp_sm->ip_hdr.checksum = UDP_SM_INS_IP_HDR_CHKSUM | (chksum & 0xffff); //setup the udp header machine - sr_udp_sm->udp_hdr.src_port = fp_socket_src.port; - sr_udp_sm->udp_hdr.dst_port = UDP_SM_INS_UDP_PORT; + sr_udp_sm->udp_hdr.src_port = UDP_SM_INS_UDP_SRC_PORT; + sr_udp_sm->udp_hdr.dst_port = UDP_SM_INS_UDP_DST_PORT; sr_udp_sm->udp_hdr.length = UDP_SM_INS_UDP_LEN; sr_udp_sm->udp_hdr.checksum = UDP_SM_LAST_WORD; // zero UDP checksum } diff --git a/firmware/microblaze/usrp2/memory_map.h b/firmware/microblaze/usrp2/memory_map.h index 2b91063b2..b4e4077c2 100644 --- a/firmware/microblaze/usrp2/memory_map.h +++ b/firmware/microblaze/usrp2/memory_map.h @@ -435,7 +435,7 @@ typedef struct { uint32_t length; uint32_t checksum; //word 22 } udp_hdr; - volatile uint32_t _pad[2]; + volatile uint32_t _pad[1]; volatile uint32_t dsp0_port; volatile uint32_t err0_port; volatile uint32_t dsp1_port; @@ -444,8 +444,11 @@ typedef struct { // control bits (all expect UDP_SM_LAST_WORD are mutually exclusive) +// Insert a UDP source port from the table +#define UDP_SM_INS_UDP_SRC_PORT (1 << 21) + // Insert a UDP dest port from the table -#define UDP_SM_INS_UDP_PORT (1 << 20) +#define UDP_SM_INS_UDP_DST_PORT (1 << 20) // This is the last word of the header #define UDP_SM_LAST_WORD (1 << 19) diff --git a/firmware/microblaze/usrp2p/memory_map.h b/firmware/microblaze/usrp2p/memory_map.h index 140ab0675..db47d0b5f 100644 --- a/firmware/microblaze/usrp2p/memory_map.h +++ b/firmware/microblaze/usrp2p/memory_map.h @@ -462,7 +462,7 @@ typedef struct { uint32_t length; uint32_t checksum; //word 22 } udp_hdr; - volatile uint32_t _pad[2]; + volatile uint32_t _pad[1]; volatile uint32_t dsp0_port; volatile uint32_t err0_port; volatile uint32_t dsp1_port; @@ -471,8 +471,11 @@ typedef struct { // control bits (all expect UDP_SM_LAST_WORD are mutually exclusive) +// Insert a UDP source port from the table +#define UDP_SM_INS_UDP_SRC_PORT (1 << 21) + // Insert a UDP dest port from the table -#define UDP_SM_INS_UDP_PORT (1 << 20) +#define UDP_SM_INS_UDP_DST_PORT (1 << 20) // This is the last word of the header #define UDP_SM_LAST_WORD (1 << 19) -- cgit v1.2.3 From 37365d1c93ad330a71fa2f6640fe9ce9a7aedad8 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Fri, 17 Dec 2010 13:46:31 -0800 Subject: udp_ports: host code tweaks, seems to be closer to working --- host/lib/usrp/usrp2/fw_common.h | 5 +++-- host/lib/usrp/usrp2/io_impl.cpp | 13 ++++++++----- host/lib/usrp/usrp2/usrp2_impl.cpp | 2 +- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/host/lib/usrp/usrp2/fw_common.h b/host/lib/usrp/usrp2/fw_common.h index a26f56e8b..29c2a8484 100644 --- a/host/lib/usrp/usrp2/fw_common.h +++ b/host/lib/usrp/usrp2/fw_common.h @@ -42,8 +42,9 @@ extern "C" { // udp ports for the usrp2 communication // Dynamic and/or private ports: 49152-65535 #define USRP2_UDP_CTRL_PORT 49152 -#define USRP2_UDP_DATA_PORT 49153 -#define USRP2_UDP_ERR0_PORT 49154 +//#define USRP2_UDP_UPDATE_PORT 49154 +#define USRP2_UDP_DATA_PORT 49156 +#define USRP2_UDP_ERR0_PORT 49157 //////////////////////////////////////////////////////////////////////// // I2C addresses diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index c8e4b7096..fbab0202a 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -121,7 +121,7 @@ struct usrp2_impl::io_impl{ )); //init empty packet infos vrt::if_packet_info_t packet_info; - packet_info.packet_count = 0; + packet_info.packet_count = 0xf; packet_info.has_tsi = true; packet_info.tsi = 0; packet_info.has_tsf = true; @@ -157,7 +157,7 @@ struct usrp2_impl::io_impl{ } bool get_recv_buffs( - const std::vector xports, + const std::vector &xports, vrt_packet_handler::managed_recv_buffs_t &buffs, double timeout ); @@ -330,7 +330,9 @@ static UHD_INLINE double from_time_dur(const boost::posix_time::time_duration &t return 1e-6*time_dur.total_microseconds(); } -static UHD_INLINE time_spec_t extract_time_spec(const vrt::if_packet_info_t &packet_info){ +static UHD_INLINE time_spec_t extract_time_spec( + const vrt::if_packet_info_t &packet_info +){ return time_spec_t( //assumes has_tsi and has_tsf are true time_t(packet_info.tsi), size_t(packet_info.tsf), 100e6 //tick rate does not have to be correct for comparison purposes @@ -338,12 +340,13 @@ static UHD_INLINE time_spec_t extract_time_spec(const vrt::if_packet_info_t &pac } static UHD_INLINE void extract_packet_info( - managed_recv_buffer::sptr buff, + managed_recv_buffer::sptr &buff, vrt::if_packet_info_t &prev_info, time_spec_t &time, bool &clear ){ //extract packet info vrt::if_packet_info_t next_info; + next_info.num_packet_words32 = buff->size()/sizeof(boost::uint32_t); vrt::if_hdr_unpack_be(buff->cast(), next_info); //handle the packet count / sequence number @@ -357,7 +360,7 @@ static UHD_INLINE void extract_packet_info( } UHD_INLINE bool usrp2_impl::io_impl::get_recv_buffs( - const std::vector xports, + const std::vector &xports, vrt_packet_handler::managed_recv_buffs_t &buffs, double timeout ){ diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp index ca4a463b7..3f8da5fda 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.cpp +++ b/host/lib/usrp/usrp2/usrp2_impl.cpp @@ -212,7 +212,7 @@ sep_indexed_dev_addrs(device_addr); dev_addr_i["addr"], num2str(USRP2_UDP_DATA_PORT), device_addr )); err0_transports.push_back(udp_zero_copy::make( - dev_addr_i["addr"], num2str(USRP2_UDP_ERR0_PORT), device_addr + dev_addr_i["addr"], num2str(USRP2_UDP_ERR0_PORT), device_addr_t() )); } -- cgit v1.2.3 From b6983381e46f5bb1156da2e40580a97fd09b9e37 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 22 Dec 2010 12:04:55 -0800 Subject: udp_ports: added message handling to alignment code --- host/lib/transport/vrt_packet_handler.hpp | 1 + host/lib/usrp/usrp2/io_impl.cpp | 25 +++++++++++++++++++------ 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/host/lib/transport/vrt_packet_handler.hpp b/host/lib/transport/vrt_packet_handler.hpp index 278bcfeaa..7f8d84308 100644 --- a/host/lib/transport/vrt_packet_handler.hpp +++ b/host/lib/transport/vrt_packet_handler.hpp @@ -91,6 +91,7 @@ template UHD_INLINE T get_context_code( //vrt unpack each managed buffer uhd::transport::vrt::if_packet_info_t if_packet_info; for (size_t i = 0; i < state.width; i++){ + if (state.managed_buffs[i].get() == NULL) continue; //better have a message packet coming up... //extract packet words and check thats its enough to move on size_t num_packet_words32 = state.managed_buffs[i]->size()/sizeof(boost::uint32_t); diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index fbab0202a..d11031f3c 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -342,7 +342,7 @@ static UHD_INLINE time_spec_t extract_time_spec( static UHD_INLINE void extract_packet_info( managed_recv_buffer::sptr &buff, vrt::if_packet_info_t &prev_info, - time_spec_t &time, bool &clear + time_spec_t &time, bool &clear, bool &msg ){ //extract packet info vrt::if_packet_info_t next_info; @@ -356,9 +356,20 @@ static UHD_INLINE void extract_packet_info( time = extract_time_spec(next_info); clear = extract_time_spec(prev_info) > time; + msg = prev_info.packet_type != vrt::if_packet_info_t::PACKET_TYPE_DATA; prev_info = next_info; } +static UHD_INLINE bool handle_msg_packet( + vrt_packet_handler::managed_recv_buffs_t &buffs, size_t index +){ + for (size_t i = 0; i < buffs.size(); i++){ + if (i == index) continue; + buffs[i].reset(); //set NULL + } + return true; +} + UHD_INLINE bool usrp2_impl::io_impl::get_recv_buffs( const std::vector &xports, vrt_packet_handler::managed_recv_buffs_t &buffs, @@ -367,9 +378,9 @@ UHD_INLINE bool usrp2_impl::io_impl::get_recv_buffs( if (buffs.size() == 1){ buffs[0] = xports[0]->get_recv_buff(timeout); if (buffs[0].get() == NULL) return false; - bool clear; time_spec_t time; //unused variables + bool clear, msg; time_spec_t time; //unused variables //call extract_packet_info to handle printing the overflows - extract_packet_info(buffs[0], this->prev_infos[0], time, clear); + extract_packet_info(buffs[0], this->prev_infos[0], time, clear, msg); return true; } //-------------------- begin alignment logic ---------------------// @@ -377,7 +388,7 @@ UHD_INLINE bool usrp2_impl::io_impl::get_recv_buffs( managed_recv_buffer::sptr buff_tmp; std::list _all_indexes, indexes_to_do; for (size_t i = 0; i < buffs.size(); i++) _all_indexes.push_back(i); - bool clear; + bool clear, msg; time_spec_t expected_time; //respond to a clear by starting from scratch @@ -389,9 +400,10 @@ UHD_INLINE bool usrp2_impl::io_impl::get_recv_buffs( size_t index = indexes_to_do.front(); buff_tmp = xports[index]->get_recv_buff(from_time_dur(exit_time - boost::get_system_time())); if (buff_tmp.get() == NULL) return false; - extract_packet_info(buff_tmp, this->prev_infos[index], expected_time, clear); + extract_packet_info(buff_tmp, this->prev_infos[index], expected_time, clear, msg); if (clear) goto got_clear; buffs[index] = buff_tmp; + if (msg) return handle_msg_packet(buffs, index); indexes_to_do.pop_front(); //get an aligned set of elements from the buffers: @@ -402,9 +414,10 @@ UHD_INLINE bool usrp2_impl::io_impl::get_recv_buffs( buff_tmp = xports[index]->get_recv_buff(from_time_dur(exit_time - boost::get_system_time())); if (buff_tmp.get() == NULL) return false; time_spec_t this_time; - extract_packet_info(buff_tmp, this->prev_infos[index], this_time, clear); + extract_packet_info(buff_tmp, this->prev_infos[index], this_time, clear, msg); if (clear) goto got_clear; buffs[index] = buff_tmp; + if (msg) return handle_msg_packet(buffs, index); //if the sequence id matches: // remove this index from the list and continue -- cgit v1.2.3 From de45f2234ca7ce8a1efd79525323bef55f1f9d44 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 22 Dec 2010 16:02:09 -0800 Subject: udp_ports: enable async recv in xport, set performance params in top level, things working --- host/docs/transport.rst | 2 +- host/lib/transport/udp_zero_copy_asio.cpp | 7 ++++--- host/lib/usrp/usrp2/io_impl.cpp | 2 +- host/lib/usrp/usrp2/usrp2_impl.cpp | 11 +++++++++-- 4 files changed, 15 insertions(+), 7 deletions(-) diff --git a/host/docs/transport.rst b/host/docs/transport.rst index d9abd4923..018f909c1 100644 --- a/host/docs/transport.rst +++ b/host/docs/transport.rst @@ -36,7 +36,7 @@ The following parameters can be used to alter the transport's default behavior: * **num_send_frames:** The number of send buffers to allocate * **concurrency_hint:** The number of threads to run the IO service -**Note:** num_send_frames and concurrency_hint will not have an effect +**Note:** num_send_frames will not have an effect as the asynchronous send implementation is currently disabled. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/host/lib/transport/udp_zero_copy_asio.cpp b/host/lib/transport/udp_zero_copy_asio.cpp index c758fa894..bbd63836c 100644 --- a/host/lib/transport/udp_zero_copy_asio.cpp +++ b/host/lib/transport/udp_zero_copy_asio.cpp @@ -37,14 +37,15 @@ namespace asio = boost::asio; **********************************************************************/ //Define this to the the boost async io calls to perform receive. //Otherwise, get_recv_buff uses a blocking receive with timeout. -//#define USE_ASIO_ASYNC_RECV +#define USE_ASIO_ASYNC_RECV //Define this to the the boost async io calls to perform send. //Otherwise, the commit callback uses a blocking send. //#define USE_ASIO_ASYNC_SEND -//enough buffering for half a second of samples at full rate on usrp2 -static const size_t MIN_RECV_SOCK_BUFF_SIZE = size_t(4 * 25e6 * 0.5); +//By default, this buffer is sized insufficiently small. +//For peformance, this buffer should be 10s of megabytes. +static const size_t MIN_RECV_SOCK_BUFF_SIZE = size_t(10e3); //Large buffers cause more underflow at high rates. //Perhaps this is due to the kernel scheduling, diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index d11031f3c..5a6c0983c 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -356,7 +356,7 @@ static UHD_INLINE void extract_packet_info( time = extract_time_spec(next_info); clear = extract_time_spec(prev_info) > time; - msg = prev_info.packet_type != vrt::if_packet_info_t::PACKET_TYPE_DATA; + msg = next_info.packet_type != vrt::if_packet_info_t::PACKET_TYPE_DATA; prev_info = next_info; } diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp index 3f8da5fda..f910999d4 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.cpp +++ b/host/lib/usrp/usrp2/usrp2_impl.cpp @@ -197,7 +197,14 @@ static device_addrs_t usrp2_find(const device_addr_t &hint_){ * Make **********************************************************************/ static device::sptr usrp2_make(const device_addr_t &device_addr){ -sep_indexed_dev_addrs(device_addr); + + //setup the dsp transport hints (default to a large recv buff) + device_addr_t dsp_xport_hints = device_addr; + if (not dsp_xport_hints.has_key("recv_buff_size")){ + //set to half-a-second of buffering at max rate + dsp_xport_hints["recv_buff_size"] = "50e6"; + } + //create a ctrl and data transport for each address std::vector ctrl_transports; std::vector data_transports; @@ -209,7 +216,7 @@ sep_indexed_dev_addrs(device_addr); dev_addr_i["addr"], num2str(USRP2_UDP_CTRL_PORT) )); data_transports.push_back(udp_zero_copy::make( - dev_addr_i["addr"], num2str(USRP2_UDP_DATA_PORT), device_addr + dev_addr_i["addr"], num2str(USRP2_UDP_DATA_PORT), dsp_xport_hints )); err0_transports.push_back(udp_zero_copy::make( dev_addr_i["addr"], num2str(USRP2_UDP_ERR0_PORT), device_addr_t() -- cgit v1.2.3