aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosh Blum <josh@joshknows.com>2010-07-09 17:56:19 +0000
committerJosh Blum <josh@joshknows.com>2010-07-09 17:56:19 +0000
commit8dd01e451e9102db06daed171c18d9fbb848df97 (patch)
tree2965e6ca706cd140b637d7a44617f55c0e3b5649
parentad511bd81d726918a11ab1218a4bc48f8eaf6efe (diff)
parentecd7308793ad639880faf2a44f3b8b603d87c7fd (diff)
downloaduhd-8dd01e451e9102db06daed171c18d9fbb848df97.tar.gz
uhd-8dd01e451e9102db06daed171c18d9fbb848df97.tar.bz2
uhd-8dd01e451e9102db06daed171c18d9fbb848df97.zip
Merge branch 'error_handling' of ettus.sourcerepo.com:ettus/uhdpriv into usrp_e
-rw-r--r--host/docs/usrp2.rst25
-rw-r--r--host/include/uhd/transport/udp_simple.hpp3
-rw-r--r--host/include/uhd/transport/vrt_if_packet.hpp7
-rw-r--r--host/include/uhd/types/metadata.hpp5
-rw-r--r--host/include/uhd/utils/CMakeLists.txt1
-rw-r--r--host/include/uhd/utils/assert.hpp31
-rw-r--r--host/include/uhd/utils/assert.ipp52
-rwxr-xr-xhost/lib/transport/gen_vrt_if_packet.py48
-rw-r--r--host/lib/transport/udp_zero_copy_asio.cpp22
-rw-r--r--host/lib/transport/vrt_packet_handler.hpp50
-rw-r--r--host/lib/types.cpp4
-rw-r--r--host/lib/usrp/usrp2/fw_common.h53
-rw-r--r--host/lib/usrp/usrp2/io_impl.cpp4
-rw-r--r--host/lib/usrp/usrp2/usrp2_iface.cpp9
-rw-r--r--host/lib/usrp/usrp2/usrp2_impl.cpp19
-rw-r--r--host/lib/usrp/usrp2/usrp2_impl.hpp16
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
;
};