diff options
Diffstat (limited to 'host')
-rw-r--r-- | host/docs/usrp2.rst | 25 | ||||
-rw-r--r-- | host/include/uhd/transport/udp_simple.hpp | 3 | ||||
-rw-r--r-- | host/include/uhd/transport/vrt_if_packet.hpp | 7 | ||||
-rw-r--r-- | host/include/uhd/types/metadata.hpp | 5 | ||||
-rw-r--r-- | host/include/uhd/utils/CMakeLists.txt | 1 | ||||
-rw-r--r-- | host/include/uhd/utils/assert.hpp | 31 | ||||
-rw-r--r-- | host/include/uhd/utils/assert.ipp | 52 | ||||
-rwxr-xr-x | host/lib/transport/gen_vrt_if_packet.py | 48 | ||||
-rw-r--r-- | host/lib/transport/udp_zero_copy_asio.cpp | 22 | ||||
-rw-r--r-- | host/lib/transport/vrt_packet_handler.hpp | 50 | ||||
-rw-r--r-- | host/lib/types.cpp | 4 | ||||
-rw-r--r-- | host/lib/usrp/usrp2/fw_common.h | 53 | ||||
-rw-r--r-- | host/lib/usrp/usrp2/io_impl.cpp | 4 | ||||
-rw-r--r-- | host/lib/usrp/usrp2/usrp2_iface.cpp | 9 | ||||
-rw-r--r-- | host/lib/usrp/usrp2/usrp2_impl.cpp | 19 | ||||
-rw-r--r-- | host/lib/usrp/usrp2/usrp2_impl.hpp | 16 |
16 files changed, 220 insertions, 129 deletions
diff --git a/host/docs/usrp2.rst b/host/docs/usrp2.rst index d3ae1dec7..76b27fd31 100644 --- a/host/docs/usrp2.rst +++ b/host/docs/usrp2.rst @@ -88,7 +88,7 @@ Setup the host interface The USRP2 communicates at the IP/UDP layer over the gigabit ethernet. The default IP address of the USRP2 is **192.168.10.2** You will need to configure the host's ethernet interface with a static IP address to enable communication. -An address of **192.168.10.1** is recommended. +An address of **192.168.10.1** and a subnet mask of **255.255.255.0** is recommended. **Note:** When using the UHD, if an IP address for the USRP2 is not specified, @@ -97,6 +97,26 @@ On some systems, the firewall will block UDP broadcast packets. 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, +and the corresponding USRP2 device should be assigned an address in that subnet. +Example: + +**Configuration for USRP2 device 0:** + +* Ethernet interface IPv4 address: 192.168.10.1 +* Ethernet interface subnet mask: 255.255.255.0 +* USRP2 device IPv4 address: 192.168.10.2 + +**Configuration for USRP2 device 1:** + +* Ethernet interface IPv4 address: 192.168.20.1 +* Ethernet interface subnet mask: 255.255.255.0 +* USRP2 device IPv4 address: 192.168.20.2 + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Change the USRP2's IP address ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ You may need to change the USRP2's IP address for several reasons: @@ -122,7 +142,7 @@ Run the following commands: :: cd <prefix>/share/uhd/utils - ./usrp2_recovery.py --ifc=eth0 --new-ip=192.168.10.3 + sudo ./usrp2_recovery.py --ifc=eth0 --new-ip=192.168.10.3 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Debugging networking problems @@ -181,7 +201,6 @@ The device address string representation for 2 USRP2s with IPv4 addresses 192.16 addr=192.168.10.2 192.168.20.2 - ------------------------------------------------------------------------ Resize the send and receive buffers ------------------------------------------------------------------------ diff --git a/host/include/uhd/transport/udp_simple.hpp b/host/include/uhd/transport/udp_simple.hpp index 793ec4fd7..98dca02f0 100644 --- a/host/include/uhd/transport/udp_simple.hpp +++ b/host/include/uhd/transport/udp_simple.hpp @@ -29,6 +29,9 @@ class UHD_API udp_simple : boost::noncopyable{ public: typedef boost::shared_ptr<udp_simple> sptr; + //! The maximum number of bytes per udp packet. + static const size_t mtu = 1500 - 20 - 8; //default ipv4 mtu - ipv4 header - udp header + /*! * Make a new connected udp transport: * This transport is for sending and receiving diff --git a/host/include/uhd/transport/vrt_if_packet.hpp b/host/include/uhd/transport/vrt_if_packet.hpp index ccefe14ea..51bd81bb1 100644 --- a/host/include/uhd/transport/vrt_if_packet.hpp +++ b/host/include/uhd/transport/vrt_if_packet.hpp @@ -35,6 +35,13 @@ namespace vrt{ * the operation used (ie the pack or unpack function call). */ struct UHD_API if_packet_info_t{ + //packet type (pack only supports data) + enum packet_type_t { + PACKET_TYPE_DATA = 0x0, + PACKET_TYPE_EXTENSION = 0x1, + PACKET_TYPE_CONTEXT = 0x2 + } packet_type; + //size fields size_t num_payload_words32; //required in pack, derived in unpack size_t num_header_words32; //derived in pack, derived in unpack diff --git a/host/include/uhd/types/metadata.hpp b/host/include/uhd/types/metadata.hpp index f4c962ff7..6712e2594 100644 --- a/host/include/uhd/types/metadata.hpp +++ b/host/include/uhd/types/metadata.hpp @@ -52,10 +52,9 @@ namespace uhd{ * Burst flags: * Start of burst will be true for the first packet in the chain. * End of burst will be true for the last packet in the chain. - * --Not currently used in any known device implementation.-- */ - //bool start_of_burst; - //bool end_of_burst; + bool start_of_burst; + bool end_of_burst; /*! * Error conditions (TODO): diff --git a/host/include/uhd/utils/CMakeLists.txt b/host/include/uhd/utils/CMakeLists.txt index 36f86054a..d484788b2 100644 --- a/host/include/uhd/utils/CMakeLists.txt +++ b/host/include/uhd/utils/CMakeLists.txt @@ -18,6 +18,7 @@ INSTALL(FILES algorithm.hpp assert.hpp + assert.ipp byteswap.hpp byteswap.ipp exception.hpp diff --git a/host/include/uhd/utils/assert.hpp b/host/include/uhd/utils/assert.hpp index 2f0ed4ff1..7f7b71cfb 100644 --- a/host/include/uhd/utils/assert.hpp +++ b/host/include/uhd/utils/assert.hpp @@ -20,10 +20,6 @@ #include <uhd/config.hpp> #include <uhd/utils/exception.hpp> -#include <uhd/utils/algorithm.hpp> -#include <boost/format.hpp> -#include <boost/foreach.hpp> -#include <boost/lexical_cast.hpp> #include <stdexcept> #include <string> @@ -35,8 +31,9 @@ namespace uhd{ }; //! Throw an assert error with throw-site information - #define UHD_ASSERT_THROW(_x) if (not (_x)) \ - throw uhd::assert_error(UHD_THROW_SITE_INFO("assertion failed: " + std::string(#_x))) + #define UHD_ASSERT_THROW(_x) if (not (_x)) throw uhd::assert_error( \ + UHD_THROW_SITE_INFO("assertion failed: " + std::string(#_x)) \ + ); else void(0) /*! * Check that an element is found in a container. @@ -46,31 +43,17 @@ namespace uhd{ * * \param range a list of possible settings * \param value an element that may be in the list - * \param what a description of what is being set + * \param what a description of what the value is * \throw assertion_error when elem not in list */ template<typename T, typename Range> void assert_has( const Range &range, const T &value, const std::string &what = "unknown" - ){ - if (std::has(range, value)) return; - std::string possible_values = ""; - size_t i = 0; - BOOST_FOREACH(const T &v, range){ - if (i++ > 0) possible_values += ", "; - possible_values += boost::lexical_cast<std::string>(v); - } - throw uhd::assert_error(str(boost::format( - "assertion failed:\n" - " %s is not a valid %s.\n" - " possible values are: [%s].\n" - ) - % boost::lexical_cast<std::string>(value) - % what % possible_values - )); - } + ); }//namespace uhd +#include <uhd/utils/assert.ipp> + #endif /* INCLUDED_UHD_UTILS_ASSERT_HPP */ diff --git a/host/include/uhd/utils/assert.ipp b/host/include/uhd/utils/assert.ipp new file mode 100644 index 000000000..6a8b3e417 --- /dev/null +++ b/host/include/uhd/utils/assert.ipp @@ -0,0 +1,52 @@ +// +// 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 <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_UHD_UTILS_ASSERT_IPP +#define INCLUDED_UHD_UTILS_ASSERT_IPP + +#include <uhd/utils/algorithm.hpp> +#include <boost/format.hpp> +#include <boost/foreach.hpp> +#include <boost/lexical_cast.hpp> + +namespace uhd{ + + template<typename T, typename Range> UHD_INLINE void assert_has( + const Range &range, + const T &value, + const std::string &what + ){ + if (std::has(range, value)) return; + std::string possible_values = ""; + size_t i = 0; + BOOST_FOREACH(const T &v, range){ + if (i++ > 0) possible_values += ", "; + possible_values += boost::lexical_cast<std::string>(v); + } + throw uhd::assert_error(str(boost::format( + "assertion failed:\n" + " %s is not a valid %s.\n" + " possible values are: [%s].\n" + ) + % boost::lexical_cast<std::string>(value) + % what % possible_values + )); + } + +}//namespace uhd + +#endif /* INCLUDED_UHD_UTILS_ASSERT_IPP */ diff --git a/host/lib/transport/gen_vrt_if_packet.py b/host/lib/transport/gen_vrt_if_packet.py index 9b5bfca02..07ce391ee 100755 --- a/host/lib/transport/gen_vrt_if_packet.py +++ b/host/lib/transport/gen_vrt_if_packet.py @@ -61,13 +61,6 @@ using namespace uhd::transport; #set $tsf_p = 0b01000 #set $tlr_p = 0b10000 -static UHD_INLINE void pack_uint64_$(suffix)(boost::uint64_t num, boost::uint32_t *mem){ - //*(reinterpret_cast<boost::uint64_t *>(mem)) = $(XE_MACRO)(num); - //second word is lower 32 bits due to fpga implementation - mem[1] = $(XE_MACRO)(boost::uint32_t(num >> 0)); - mem[0] = $(XE_MACRO)(boost::uint32_t(num >> 32)); -} - void vrt::if_hdr_pack_$(suffix)( boost::uint32_t *packet_buff, if_packet_info_t &if_packet_info @@ -94,8 +87,10 @@ void vrt::if_hdr_pack_$(suffix)( #end if ########## Class ID ########## #if $pred & $cid_p - pack_uint64_$(suffix)(if_packet_info.cid, packet_buff+$num_header_words); - #set $num_header_words += 2 + packet_buff[$num_header_words] = 0; //not implemented + #set $num_header_words += 1 + packet_buff[$num_header_words] = 0; //not implemented + #set $num_header_words += 1 #set $flags |= (0x1 << 27); #end if ########## Integer Time ########## @@ -106,8 +101,10 @@ void vrt::if_hdr_pack_$(suffix)( #end if ########## Fractional Time ########## #if $pred & $tsf_p - pack_uint64_$(suffix)(if_packet_info.tsf, packet_buff+$num_header_words); - #set $num_header_words += 2 + packet_buff[$num_header_words] = $(XE_MACRO)(boost::uint32_t(if_packet_info.tsf >> 32)); + #set $num_header_words += 1 + packet_buff[$num_header_words] = $(XE_MACRO)(boost::uint32_t(if_packet_info.tsf >> 0)); + #set $num_header_words += 1 #set $flags |= (0x1 << 20); #end if ########## Trailer ########## @@ -116,7 +113,6 @@ void vrt::if_hdr_pack_$(suffix)( #set $flags |= (0x1 << 26); #set $num_trailer_words = 1; #else - //packet_buff[$num_header_words+if_packet_info.num_payload_words32] = 0; #set $num_trailer_words = 0; #end if ########## Variables ########## @@ -139,13 +135,6 @@ void vrt::if_hdr_pack_$(suffix)( )); } -static UHD_INLINE void unpack_uint64_$(suffix)(boost::uint64_t &num, const boost::uint32_t *mem){ - //num = $(XE_MACRO)(*reinterpret_cast<const boost::uint64_t *>(mem)); - //second word is lower 32 bits due to fpga implementation - num = boost::uint64_t($(XE_MACRO)(mem[1])) << 0; - num |= boost::uint64_t($(XE_MACRO)(mem[0])) << 32; -} - void vrt::if_hdr_unpack_$(suffix)( const boost::uint32_t *packet_buff, if_packet_info_t &if_packet_info @@ -153,13 +142,16 @@ void vrt::if_hdr_unpack_$(suffix)( //extract vrt header boost::uint32_t vrt_hdr_word = $(XE_MACRO)(packet_buff[0]); size_t packet_words32 = vrt_hdr_word & 0xffff; - if_packet_info.packet_count = (vrt_hdr_word >> 16) & 0xf; - //failure cases + //failure case if (if_packet_info.num_packet_words32 < packet_words32) throw std::runtime_error("bad vrt header or packet fragment"); - if (vrt_hdr_word & (0x7 << 29)) - throw std::runtime_error("bad vrt header or unsupported packet type"); + + //extract fields from the header + if_packet_info.packet_type = if_packet_info_t::packet_type_t(vrt_hdr_word >> 29); + if_packet_info.packet_count = (vrt_hdr_word >> 16) & 0xf; + if_packet_info.sob = bool(vrt_hdr_word & $hex(0x1 << 25)); + if_packet_info.eob = bool(vrt_hdr_word & $hex(0x1 << 24)); boost::uint8_t pred = 0; if(vrt_hdr_word & $hex(0x1 << 28)) pred |= $hex($sid_p); @@ -184,7 +176,7 @@ void vrt::if_hdr_unpack_$(suffix)( ########## Class ID ########## #if $pred & $cid_p if_packet_info.has_cid = true; - unpack_uint64_$(suffix)(if_packet_info.cid, packet_buff+$num_header_words); + if_packet_info.cid = 0; //not implemented #set $num_header_words += 2 #else if_packet_info.has_cid = false; @@ -200,15 +192,17 @@ void vrt::if_hdr_unpack_$(suffix)( ########## Fractional Time ########## #if $pred & $tsf_p if_packet_info.has_tsf = true; - unpack_uint64_$(suffix)(if_packet_info.tsf, packet_buff+$num_header_words); - #set $num_header_words += 2 + if_packet_info.tsf = boost::uint64_t($(XE_MACRO)(packet_buff[$num_header_words])) << 32; + #set $num_header_words += 1 + if_packet_info.tsf |= boost::uint64_t($(XE_MACRO)(packet_buff[$num_header_words])) << 0; + #set $num_header_words += 1 #else if_packet_info.has_tsf = false; #end if ########## Trailer ########## #if $pred & $tlr_p if_packet_info.has_tlr = true; - if_packet_info.tlr = $(XE_MACRO)(packet_buff[$num_header_words+packet_words32]); + if_packet_info.tlr = $(XE_MACRO)(packet_buff[packet_words32-1]); #set $num_trailer_words = 1; #else if_packet_info.has_tlr = false; diff --git a/host/lib/transport/udp_zero_copy_asio.cpp b/host/lib/transport/udp_zero_copy_asio.cpp index 7f9292d24..e3f3ef5bf 100644 --- a/host/lib/transport/udp_zero_copy_asio.cpp +++ b/host/lib/transport/udp_zero_copy_asio.cpp @@ -16,6 +16,7 @@ // #include <uhd/transport/udp_zero_copy.hpp> +#include <uhd/transport/udp_simple.hpp> //mtu #include <uhd/utils/assert.hpp> #include <boost/cstdint.hpp> #include <boost/asio.hpp> @@ -29,7 +30,6 @@ using namespace uhd::transport; **********************************************************************/ //enough buffering for half a second of samples at full rate on usrp2 static const size_t MIN_SOCK_BUFF_SIZE = size_t(sizeof(boost::uint32_t) * 25e6 * 0.5); -static const size_t MAX_DGRAM_SIZE = 1500; //assume max size on send and recv static const double RECV_TIMEOUT = 0.1; //100 ms /*********************************************************************** @@ -51,8 +51,8 @@ public: const std::string &addr, const std::string &port ): - phony_zero_copy_recv_if(MAX_DGRAM_SIZE), - phony_zero_copy_send_if(MAX_DGRAM_SIZE) + phony_zero_copy_recv_if(udp_simple::mtu), + phony_zero_copy_send_if(udp_simple::mtu) { //std::cout << boost::format("Creating udp transport for %s %s") % addr % port << std::endl; @@ -93,11 +93,11 @@ public: //This way, the transport caller will have an idea about how much buffering to create. size_t get_num_recv_frames(void) const{ - return this->get_buff_size<boost::asio::socket_base::receive_buffer_size>()/MAX_DGRAM_SIZE; + return this->get_buff_size<boost::asio::socket_base::receive_buffer_size>()/udp_simple::mtu; } size_t get_num_send_frames(void) const{ - return this->get_buff_size<boost::asio::socket_base::send_buffer_size>()/MAX_DGRAM_SIZE; + return this->get_buff_size<boost::asio::socket_base::send_buffer_size>()/udp_simple::mtu; } private: @@ -155,17 +155,17 @@ template<typename Opt> static void resize_buff_helper( else std::cout << boost::format( "Current %s sock buff size: %d bytes" ) % name % actual_size << std::endl; + if (actual_size < target_size) std::cerr << boost::format( + "Warning:\n" + " The %s buffer is smaller than the requested size.\n" + " The minimum recommended buffer size is %d bytes.\n" + " See the USRP2 application notes on buffer resizing.\n" + ) % name % MIN_SOCK_BUFF_SIZE << std::endl; } //otherwise, ensure that the buffer is at least the minimum size else if (udp_trans->get_buff_size<Opt>() < MIN_SOCK_BUFF_SIZE){ resize_buff_helper<Opt>(udp_trans, MIN_SOCK_BUFF_SIZE, name); - if (udp_trans->get_buff_size<Opt>() < MIN_SOCK_BUFF_SIZE){ - std::cerr << boost::format( - "Warning: the %s buffer size is smaller than the recommended size of %d bytes.\n" - " See the USRP2 application notes on buffer resizing." - ) % name % MIN_SOCK_BUFF_SIZE << std::endl; - } } } diff --git a/host/lib/transport/vrt_packet_handler.hpp b/host/lib/transport/vrt_packet_handler.hpp index 68edeb1e1..11d749a81 100644 --- a/host/lib/transport/vrt_packet_handler.hpp +++ b/host/lib/transport/vrt_packet_handler.hpp @@ -21,6 +21,7 @@ #include <uhd/config.hpp> #include <uhd/device.hpp> #include <uhd/utils/assert.hpp> +#include <uhd/utils/byteswap.hpp> #include <uhd/types/io_type.hpp> #include <uhd/types/otw_type.hpp> #include <uhd/types/metadata.hpp> @@ -39,6 +40,9 @@ namespace vrt_packet_handler{ **********************************************************************/ typedef std::vector<uhd::transport::managed_recv_buffer::sptr> managed_recv_buffs_t; typedef boost::function<bool(managed_recv_buffs_t &)> get_recv_buffs_t; + typedef boost::function<void(size_t /*which channel*/)> handle_overrun_t; + + void handle_overrun_nop(size_t){} struct recv_state{ //width of the receiver in channels @@ -53,7 +57,7 @@ namespace vrt_packet_handler{ size_t size_of_copy_buffs; size_t fragment_offset_in_samps; - recv_state(size_t width): + recv_state(size_t width = 1): width(width), next_packet_seq(width, 0), managed_buffs(width), @@ -75,20 +79,25 @@ namespace vrt_packet_handler{ uhd::rx_metadata_t &metadata, double tick_rate, vrt_unpacker_type vrt_unpacker, + const handle_overrun_t &handle_overrun, size_t vrt_header_offset_words32 ){ - size_t num_packet_words32 = state.managed_buffs[0]->size()/sizeof(boost::uint32_t); - if (num_packet_words32 <= vrt_header_offset_words32){ - state.size_of_copy_buffs = 0; - return; //must exit here after setting the buffer - } - //vrt unpack each managed buffer uhd::transport::vrt::if_packet_info_t if_packet_info; for (size_t i = 0; i < state.width; i++){ + + //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); + if (num_packet_words32 <= vrt_header_offset_words32){ + state.size_of_copy_buffs = 0; + return; //must exit here after setting the buffer + } + + //unpack the vrt header into the info struct const boost::uint32_t *vrt_hdr = state.managed_buffs[i]->cast<const boost::uint32_t *>() + vrt_header_offset_words32; if_packet_info.num_packet_words32 = num_packet_words32 - vrt_header_offset_words32; vrt_unpacker(vrt_hdr, if_packet_info); + const boost::uint32_t *vrt_data = vrt_hdr + if_packet_info.num_header_words32; //handle the packet count / sequence number if (if_packet_info.packet_count != state.next_packet_seq[i]){ @@ -96,8 +105,19 @@ namespace vrt_packet_handler{ } state.next_packet_seq[i] = (if_packet_info.packet_count+1)%16; + //make sure that its a data packet (TODO handle non-data packets) + if (if_packet_info.packet_type != uhd::transport::vrt::if_packet_info_t::PACKET_TYPE_DATA){ + std::cout << "vrt packet handler _recv1_helper got non data packet" << std::endl; + //extract the context word (we dont know the endianness so mirror the bytes) + boost::uint32_t word0 = vrt_data[0] | uhd::byteswap(vrt_data[0]); + if (word0 & 8) handle_overrun(i); + // 4: broken chain, 2: late command... + state.size_of_copy_buffs = 0; + return; //must exit here after setting the buffer + } + //setup the buffer to point to the data - state.copy_buffs[i] = reinterpret_cast<const boost::uint8_t *>(vrt_hdr + if_packet_info.num_header_words32); + state.copy_buffs[i] = reinterpret_cast<const boost::uint8_t *>(vrt_data); //store the minimum payload length into the copy buffer length size_t num_payload_bytes = if_packet_info.num_payload_words32*sizeof(boost::uint32_t); @@ -111,6 +131,9 @@ namespace vrt_packet_handler{ metadata.time_spec = uhd::time_spec_t( time_t(if_packet_info.tsi), size_t(if_packet_info.tsf), tick_rate ); + metadata.start_of_burst = if_packet_info.sob; + static const int tlr_eob_flags = (1 << 20) | (1 << 8); //enable and indicator bits + metadata.end_of_burst = if_packet_info.has_tlr and (int(if_packet_info.tlr & tlr_eob_flags) == tlr_eob_flags); } /******************************************************************* @@ -129,7 +152,7 @@ namespace vrt_packet_handler{ double tick_rate, vrt_unpacker_type vrt_unpacker, const get_recv_buffs_t &get_recv_buffs, - //use these two params to handle a layer above vrt + const handle_overrun_t &handle_overrun, size_t vrt_header_offset_words32 ){ metadata.has_time_spec = false; //false unless set in the helper @@ -140,7 +163,9 @@ namespace vrt_packet_handler{ if (not get_recv_buffs(state.managed_buffs)) return 0; try{ _recv1_helper( - state, metadata, tick_rate, vrt_unpacker, vrt_header_offset_words32 + state, metadata, tick_rate, + vrt_unpacker, handle_overrun, + vrt_header_offset_words32 ); }catch(const std::exception &e){ std::cerr << "Error (recv): " << e.what() << std::endl; @@ -191,7 +216,7 @@ namespace vrt_packet_handler{ double tick_rate, vrt_unpacker_type vrt_unpacker, const get_recv_buffs_t &get_recv_buffs, - //use these two params to handle a layer above vrt + const handle_overrun_t &handle_overrun = &handle_overrun_nop, size_t vrt_header_offset_words32 = 0 ){ switch(recv_mode){ @@ -208,6 +233,7 @@ namespace vrt_packet_handler{ tick_rate, vrt_unpacker, get_recv_buffs, + handle_overrun, vrt_header_offset_words32 ); } @@ -227,6 +253,7 @@ namespace vrt_packet_handler{ tick_rate, vrt_unpacker, get_recv_buffs, + handle_overrun, vrt_header_offset_words32 ); if (num_samps == 0) break; //had a recv timeout or error, break loop @@ -315,7 +342,6 @@ namespace vrt_packet_handler{ vrt_packer_type vrt_packer, const get_send_buffs_t &get_send_buffs, size_t max_samples_per_packet, - //use these two params to handle a layer above vrt size_t vrt_header_offset_words32 = 0 ){ //translate the metadata to vrt if packet info diff --git a/host/lib/types.cpp b/host/lib/types.cpp index 9cf2a2220..1e7917ad7 100644 --- a/host/lib/types.cpp +++ b/host/lib/types.cpp @@ -99,7 +99,9 @@ rx_metadata_t::rx_metadata_t(void): has_time_spec(false), time_spec(time_spec_t()), more_fragments(false), - fragment_offset(0) + fragment_offset(0), + start_of_burst(false), + end_of_burst(false) { /* NOP */ } diff --git a/host/lib/usrp/usrp2/fw_common.h b/host/lib/usrp/usrp2/fw_common.h index 4c66aa41e..fd728e393 100644 --- a/host/lib/usrp/usrp2/fw_common.h +++ b/host/lib/usrp/usrp2/fw_common.h @@ -24,18 +24,14 @@ * Therefore, this header may only contain valid C code. */ #ifdef __cplusplus -#include <boost/cstdint.hpp> -#define _SINS_ boost:://stdint namespace when in c++ + #include <boost/cstdint.hpp> + #define __stdint(type) boost::type extern "C" { #else -#include <stdint.h> -#define _SINS_ + #include <stdint.h> + #define __stdint(type) type #endif -// define limits on bytes per udp packet -#define USRP2_MTU_BYTES 1500 -#define USRP2_UDP_BYTES ((USRP2_MTU_BYTES) - (2 + 14 + 20 + 8)) //size of headers (pad, eth, ip, udp) - //defines the protocol version in this shared header //increment this value when the protocol is changed #define USRP2_PROTO_VERSION 5 @@ -43,10 +39,6 @@ extern "C" { //used to differentiate control packets over data port #define USRP2_INVALID_VRT_HEADER 0 -// size of the vrt header and trailer to the host -#define USRP2_HOST_RX_VRT_HEADER_WORDS32 5 -#define USRP2_HOST_RX_VRT_TRAILER_WORDS32 1 //FIXME fpga sets wrong header size when no trailer present - // udp ports for the usrp2 communication // Dynamic and/or private ports: 49152-65535 #define USRP2_UDP_CTRL_PORT 49152 @@ -90,34 +82,35 @@ typedef enum{ } usrp2_clk_edge_t; typedef struct{ - _SINS_ uint32_t proto_ver; - _SINS_ uint32_t id; - _SINS_ uint32_t seq; + __stdint(uint32_t) proto_ver; + __stdint(uint32_t) id; + __stdint(uint32_t) seq; union{ - _SINS_ uint32_t ip_addr; + __stdint(uint32_t) ip_addr; struct { - _SINS_ uint8_t dev; - _SINS_ uint8_t miso_edge; - _SINS_ uint8_t mosi_edge; - _SINS_ uint8_t readback; - _SINS_ uint32_t data; - _SINS_ uint8_t num_bits; + __stdint(uint8_t) dev; + __stdint(uint8_t) miso_edge; + __stdint(uint8_t) mosi_edge; + __stdint(uint8_t) readback; + __stdint(uint32_t) data; + __stdint(uint8_t) num_bits; } spi_args; struct { - _SINS_ uint8_t addr; - _SINS_ uint8_t bytes; - _SINS_ uint8_t data[20]; + __stdint(uint8_t) addr; + __stdint(uint8_t) bytes; + __stdint(uint8_t) data[20]; } i2c_args; struct { - _SINS_ uint32_t addr; - _SINS_ uint32_t data; - _SINS_ uint32_t addrhi; - _SINS_ uint32_t datahi; - _SINS_ uint8_t num_bytes; //1, 2, 4, 8 + __stdint(uint32_t) addr; + __stdint(uint32_t) data; + __stdint(uint32_t) addrhi; + __stdint(uint32_t) datahi; + __stdint(uint8_t) num_bytes; //1, 2, 4, 8 } poke_args; } data; } usrp2_ctrl_data_t; +#undef __stdint #ifdef __cplusplus } #endif diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index c96528694..0853f48be 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -135,7 +135,7 @@ void usrp2_impl::io_init(void){ for (size_t i = 0; i < _data_transports.size(); i++){ _io_impl->recv_pirate_crew.create_thread(boost::bind( &usrp2_impl::io_impl::recv_pirate_loop, - _io_impl, _data_transports.at(i), + _io_impl.get(), _data_transports.at(i), _mboards.at(i), i )); } @@ -195,6 +195,6 @@ size_t usrp2_impl::recv( io_type, _io_helper.get_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, _1) + boost::bind(&usrp2_impl::io_impl::get_recv_buffs, _io_impl.get(), _1) ); } diff --git a/host/lib/usrp/usrp2/usrp2_iface.cpp b/host/lib/usrp/usrp2/usrp2_iface.cpp index 8552edd1f..eaaa722ac 100644 --- a/host/lib/usrp/usrp2/usrp2_iface.cpp +++ b/host/lib/usrp/usrp2/usrp2_iface.cpp @@ -26,13 +26,14 @@ #include <algorithm> using namespace uhd; +using namespace uhd::transport; class usrp2_iface_impl : public usrp2_iface{ public: /*********************************************************************** * Structors **********************************************************************/ - usrp2_iface_impl(transport::udp_simple::sptr ctrl_transport){ + usrp2_iface_impl(udp_simple::sptr ctrl_transport){ _ctrl_transport = ctrl_transport; } @@ -160,7 +161,7 @@ public: _ctrl_transport->send(boost::asio::buffer(&out_copy, sizeof(usrp2_ctrl_data_t))); //loop until we get the packet or timeout - boost::uint8_t usrp2_ctrl_data_in_mem[USRP2_UDP_BYTES]; //allocate max bytes for recv + boost::uint8_t usrp2_ctrl_data_in_mem[udp_simple::mtu]; //allocate max bytes for recv const usrp2_ctrl_data_t *ctrl_data_in = reinterpret_cast<const usrp2_ctrl_data_t *>(usrp2_ctrl_data_in_mem); while(true){ size_t len = _ctrl_transport->recv(boost::asio::buffer(usrp2_ctrl_data_in_mem)); @@ -182,7 +183,7 @@ public: private: //this lovely lady makes it all possible - transport::udp_simple::sptr _ctrl_transport; + udp_simple::sptr _ctrl_transport; //used in send/recv boost::mutex _ctrl_mutex; @@ -222,6 +223,6 @@ private: /*********************************************************************** * Public make function for usrp2 interface **********************************************************************/ -usrp2_iface::sptr usrp2_iface::make(transport::udp_simple::sptr ctrl_transport){ +usrp2_iface::sptr usrp2_iface::make(udp_simple::sptr ctrl_transport){ return usrp2_iface::sptr(new usrp2_iface_impl(ctrl_transport)); } diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp index 3402c26b1..02f53bc69 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.cpp +++ b/host/lib/usrp/usrp2/usrp2_impl.cpp @@ -99,8 +99,8 @@ static uhd::device_addrs_t usrp2_find(const device_addr_t &hint){ udp_transport->send(boost::asio::buffer(&ctrl_data_out, sizeof(ctrl_data_out))); //loop and recieve until the timeout - boost::uint8_t usrp2_ctrl_data_in_mem[USRP2_UDP_BYTES]; //allocate max bytes for recv - usrp2_ctrl_data_t *ctrl_data_in = reinterpret_cast<usrp2_ctrl_data_t *>(usrp2_ctrl_data_in_mem); + boost::uint8_t usrp2_ctrl_data_in_mem[udp_simple::mtu]; //allocate max bytes for recv + const usrp2_ctrl_data_t *ctrl_data_in = reinterpret_cast<const usrp2_ctrl_data_t *>(usrp2_ctrl_data_in_mem); while(true){ size_t len = udp_transport->recv(asio::buffer(usrp2_ctrl_data_in_mem)); //std::cout << len << "\n"; @@ -127,14 +127,25 @@ static uhd::device_addrs_t usrp2_find(const device_addr_t &hint){ /*********************************************************************** * Make **********************************************************************/ +template <typename out_type, typename in_type> +out_type lexical_cast(const in_type &in){ + try{ + return boost::lexical_cast<out_type>(in); + }catch(...){ + throw std::runtime_error(str(boost::format( + "failed to cast \"%s\" to type \"%s\"" + ) % boost::lexical_cast<std::string>(in) % typeid(out_type).name())); + } +} + static device::sptr usrp2_make(const device_addr_t &device_addr){ //extract the receive and send buffer sizes size_t recv_buff_size = 0, send_buff_size= 0 ; if (device_addr.has_key("recv_buff_size")){ - recv_buff_size = size_t(boost::lexical_cast<double>(device_addr["recv_buff_size"])); + recv_buff_size = size_t(lexical_cast<double>(device_addr["recv_buff_size"])); } if (device_addr.has_key("send_buff_size")){ - send_buff_size = size_t(boost::lexical_cast<double>(device_addr["send_buff_size"])); + send_buff_size = size_t(lexical_cast<double>(device_addr["send_buff_size"])); } //create a ctrl and data transport for each address diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp index 42630a3e4..186516447 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -32,6 +32,7 @@ #include <boost/shared_ptr.hpp> #include <boost/function.hpp> #include <uhd/transport/vrt_if_packet.hpp> +#include <uhd/transport/udp_simple.hpp> //mtu #include <uhd/transport/udp_zero_copy.hpp> #include <uhd/usrp/dboard_manager.hpp> @@ -106,15 +107,14 @@ public: private: uhd::otw_type_t _rx_otw_type, _tx_otw_type; - static const size_t _max_rx_bytes_per_packet = - USRP2_UDP_BYTES - - USRP2_HOST_RX_VRT_HEADER_WORDS32*sizeof(boost::uint32_t) - - USRP2_HOST_RX_VRT_TRAILER_WORDS32*sizeof(boost::uint32_t) + static const size_t _max_rx_bytes_per_packet = uhd::transport::udp_simple::mtu + - uhd::transport::vrt::max_if_hdr_words32*sizeof(boost::uint32_t) + - sizeof(uhd::transport::vrt::if_packet_info_t().tlr) //forced to have trailer + + sizeof(uhd::transport::vrt::if_packet_info_t().cid) //no class id ever used ; - static const size_t _max_tx_bytes_per_packet = - USRP2_UDP_BYTES - - uhd::transport::vrt::max_if_hdr_words32*sizeof(boost::uint32_t) - - sizeof(uhd::transport::vrt::if_packet_info_t().cid) //no class id ever used + static const size_t _max_tx_bytes_per_packet = uhd::transport::udp_simple::mtu + - uhd::transport::vrt::max_if_hdr_words32*sizeof(boost::uint32_t) + + sizeof(uhd::transport::vrt::if_packet_info_t().cid) //no class id ever used ; }; |