From be430761fb7e526e80b67d70e3cf488c6dd02495 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 7 Jul 2010 19:32:47 -0700 Subject: usrp2: use the actual pointer in bind so the sptr is not copied --- host/lib/usrp/usrp2/io_impl.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'host') 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) ); } -- cgit v1.2.3 From c72bc56ba6d5b0457f03967a8f8d8e5602fdf14d Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 7 Jul 2010 23:48:09 -0700 Subject: usrp2: moved common defined for udp mtu and implemented change. The uhp mtu is now defined in uhd_simple.hpp. The fw common code does not need to know this information. Fixed a calculation bug in the usrp2 impl code for max samples. --- host/include/uhd/transport/udp_simple.hpp | 3 +++ host/lib/transport/udp_zero_copy_asio.cpp | 10 +++++----- host/lib/usrp/usrp2/fw_common.h | 8 -------- host/lib/usrp/usrp2/usrp2_iface.cpp | 9 +++++---- host/lib/usrp/usrp2/usrp2_impl.cpp | 4 ++-- host/lib/usrp/usrp2/usrp2_impl.hpp | 16 ++++++++-------- 6 files changed, 23 insertions(+), 27 deletions(-) (limited to 'host') 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 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/lib/transport/udp_zero_copy_asio.cpp b/host/lib/transport/udp_zero_copy_asio.cpp index 7f9292d24..86ea275c1 100644 --- a/host/lib/transport/udp_zero_copy_asio.cpp +++ b/host/lib/transport/udp_zero_copy_asio.cpp @@ -16,6 +16,7 @@ // #include +#include //mtu #include #include #include @@ -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()/MAX_DGRAM_SIZE; + return this->get_buff_size()/udp_simple::mtu; } size_t get_num_send_frames(void) const{ - return this->get_buff_size()/MAX_DGRAM_SIZE; + return this->get_buff_size()/udp_simple::mtu; } private: diff --git a/host/lib/usrp/usrp2/fw_common.h b/host/lib/usrp/usrp2/fw_common.h index 4c66aa41e..f1761c5a6 100644 --- a/host/lib/usrp/usrp2/fw_common.h +++ b/host/lib/usrp/usrp2/fw_common.h @@ -32,10 +32,6 @@ extern "C" { #define _SINS_ #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 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 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(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..9d1ac991f 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_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(usrp2_ctrl_data_in_mem); while(true){ size_t len = udp_transport->recv(asio::buffer(usrp2_ctrl_data_in_mem)); //std::cout << len << "\n"; 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 #include #include +#include //mtu #include #include @@ -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 ; }; -- cgit v1.2.3 From ab617b492ed2dc47a814f8c01f60f7639ba633e7 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 8 Jul 2010 00:36:47 -0700 Subject: usrp2: clean up fw common with nicer looking macro for stdint namespace --- host/lib/usrp/usrp2/fw_common.h | 45 +++++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 22 deletions(-) (limited to 'host') diff --git a/host/lib/usrp/usrp2/fw_common.h b/host/lib/usrp/usrp2/fw_common.h index f1761c5a6..fd728e393 100644 --- a/host/lib/usrp/usrp2/fw_common.h +++ b/host/lib/usrp/usrp2/fw_common.h @@ -24,12 +24,12 @@ * Therefore, this header may only contain valid C code. */ #ifdef __cplusplus -#include -#define _SINS_ boost:://stdint namespace when in c++ + #include + #define __stdint(type) boost::type extern "C" { #else -#include -#define _SINS_ + #include + #define __stdint(type) type #endif //defines the protocol version in this shared header @@ -82,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 -- cgit v1.2.3 From f6217746dce159085b9941a8fcc9f6407f7fdd5e Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 8 Jul 2010 12:52:15 -0700 Subject: uhd: moved assert implementation into ipp file, fixed potential bug with assert throw macro --- host/include/uhd/utils/CMakeLists.txt | 1 + host/include/uhd/utils/assert.hpp | 31 +++++---------------- host/include/uhd/utils/assert.ipp | 52 +++++++++++++++++++++++++++++++++++ 3 files changed, 60 insertions(+), 24 deletions(-) create mode 100644 host/include/uhd/utils/assert.ipp (limited to 'host') 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 #include -#include -#include -#include -#include #include #include @@ -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 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(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(value) - % what % possible_values - )); - } + ); }//namespace uhd +#include + #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 . +// + +#ifndef INCLUDED_UHD_UTILS_ASSERT_IPP +#define INCLUDED_UHD_UTILS_ASSERT_IPP + +#include +#include +#include +#include + +namespace uhd{ + + template 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(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(value) + % what % possible_values + )); + } + +}//namespace uhd + +#endif /* INCLUDED_UHD_UTILS_ASSERT_IPP */ -- cgit v1.2.3 From da9d47011e02f2b18fccda00dbea0b9d9c0dc704 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 8 Jul 2010 13:01:49 -0700 Subject: usrp2: added notes on multiple device network setup, improved warnings for buff size stuff --- host/docs/usrp2.rst | 25 ++++++++++++++++++++++--- host/lib/transport/udp_zero_copy_asio.cpp | 12 ++++++------ host/lib/usrp/usrp2/usrp2_impl.cpp | 15 +++++++++++++-- 3 files changed, 41 insertions(+), 11 deletions(-) (limited to 'host') 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, @@ -96,6 +96,26 @@ the software will use UDP broadcast packets to locate the USRP2. 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 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -122,7 +142,7 @@ Run the following commands: :: cd /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/lib/transport/udp_zero_copy_asio.cpp b/host/lib/transport/udp_zero_copy_asio.cpp index 86ea275c1..e3f3ef5bf 100644 --- a/host/lib/transport/udp_zero_copy_asio.cpp +++ b/host/lib/transport/udp_zero_copy_asio.cpp @@ -155,17 +155,17 @@ template 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() < MIN_SOCK_BUFF_SIZE){ resize_buff_helper(udp_trans, MIN_SOCK_BUFF_SIZE, name); - if (udp_trans->get_buff_size() < 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/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp index 9d1ac991f..02f53bc69 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.cpp +++ b/host/lib/usrp/usrp2/usrp2_impl.cpp @@ -127,14 +127,25 @@ static uhd::device_addrs_t usrp2_find(const device_addr_t &hint){ /*********************************************************************** * Make **********************************************************************/ +template +out_type lexical_cast(const in_type &in){ + try{ + return boost::lexical_cast(in); + }catch(...){ + throw std::runtime_error(str(boost::format( + "failed to cast \"%s\" to type \"%s\"" + ) % boost::lexical_cast(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(device_addr["recv_buff_size"])); + recv_buff_size = size_t(lexical_cast(device_addr["recv_buff_size"])); } if (device_addr.has_key("send_buff_size")){ - send_buff_size = size_t(boost::lexical_cast(device_addr["send_buff_size"])); + send_buff_size = size_t(lexical_cast(device_addr["send_buff_size"])); } //create a ctrl and data transport for each address -- cgit v1.2.3 From 8867df0d7e0948c2091aff1a5c4adbcdd083fe4a Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 8 Jul 2010 19:51:59 -0700 Subject: uhd: added packet type to vrt if info struct, added burst flags to rx metadata, fixed vrt if packet parsing bugs --- host/include/uhd/transport/vrt_if_packet.hpp | 7 ++++ host/include/uhd/types/metadata.hpp | 5 ++- host/lib/transport/gen_vrt_if_packet.py | 48 ++++++++++++---------------- host/lib/transport/vrt_packet_handler.hpp | 25 +++++++++++---- host/lib/types.cpp | 4 ++- 5 files changed, 52 insertions(+), 37 deletions(-) (limited to 'host') 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/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(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(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/vrt_packet_handler.hpp b/host/lib/transport/vrt_packet_handler.hpp index 68edeb1e1..f06fe94c0 100644 --- a/host/lib/transport/vrt_packet_handler.hpp +++ b/host/lib/transport/vrt_packet_handler.hpp @@ -77,15 +77,18 @@ namespace vrt_packet_handler{ vrt_unpacker_type vrt_unpacker, 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() + vrt_header_offset_words32; if_packet_info.num_packet_words32 = num_packet_words32 - vrt_header_offset_words32; vrt_unpacker(vrt_hdr, if_packet_info); @@ -96,6 +99,13 @@ 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; + 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(vrt_hdr + if_packet_info.num_header_words32); @@ -111,6 +121,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); } /******************************************************************* 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 */ } -- cgit v1.2.3 From ecd7308793ad639880faf2a44f3b8b603d87c7fd Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Fri, 9 Jul 2010 10:55:17 -0700 Subject: uhd: callback in vrt packet handler to handle overrun --- host/lib/transport/vrt_packet_handler.hpp | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) (limited to 'host') diff --git a/host/lib/transport/vrt_packet_handler.hpp b/host/lib/transport/vrt_packet_handler.hpp index f06fe94c0..11d749a81 100644 --- a/host/lib/transport/vrt_packet_handler.hpp +++ b/host/lib/transport/vrt_packet_handler.hpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -39,6 +40,9 @@ namespace vrt_packet_handler{ **********************************************************************/ typedef std::vector managed_recv_buffs_t; typedef boost::function get_recv_buffs_t; + typedef boost::function 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,6 +79,7 @@ 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 ){ //vrt unpack each managed buffer @@ -92,6 +97,7 @@ namespace vrt_packet_handler{ const boost::uint32_t *vrt_hdr = state.managed_buffs[i]->cast() + 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]){ @@ -102,12 +108,16 @@ namespace vrt_packet_handler{ //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(vrt_hdr + if_packet_info.num_header_words32); + state.copy_buffs[i] = reinterpret_cast(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); @@ -142,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 @@ -153,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; @@ -204,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){ @@ -221,6 +233,7 @@ namespace vrt_packet_handler{ tick_rate, vrt_unpacker, get_recv_buffs, + handle_overrun, vrt_header_offset_words32 ); } @@ -240,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 @@ -328,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 -- cgit v1.2.3