summaryrefslogtreecommitdiffstats
path: root/host/lib
diff options
context:
space:
mode:
Diffstat (limited to 'host/lib')
-rw-r--r--host/lib/device.cpp2
-rw-r--r--host/lib/transport/udp_zero_copy_asio.cpp16
-rw-r--r--host/lib/transport/vrt_packet_handler.hpp35
-rw-r--r--host/lib/types.cpp12
-rw-r--r--host/lib/usrp/usrp2/io_impl.cpp41
-rw-r--r--host/lib/usrp/usrp2/mboard_impl.cpp6
-rw-r--r--host/lib/usrp/usrp2/usrp2_impl.hpp1
-rw-r--r--host/lib/usrp/usrp2/usrp2_regs.cpp3
-rw-r--r--host/lib/usrp/usrp2/usrp2_regs.hpp12
9 files changed, 93 insertions, 35 deletions
diff --git a/host/lib/device.cpp b/host/lib/device.cpp
index 431595c4f..d575ebaab 100644
--- a/host/lib/device.cpp
+++ b/host/lib/device.cpp
@@ -12,7 +12,7 @@
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
-// asize_t with this program. If not, see <http://www.gnu.org/licenses/>.
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
#include <uhd/device.hpp>
diff --git a/host/lib/transport/udp_zero_copy_asio.cpp b/host/lib/transport/udp_zero_copy_asio.cpp
index bfbcf62d8..bbbabf6d0 100644
--- a/host/lib/transport/udp_zero_copy_asio.cpp
+++ b/host/lib/transport/udp_zero_copy_asio.cpp
@@ -29,7 +29,11 @@ using namespace uhd::transport;
* Constants
**********************************************************************/
//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 MIN_RECV_SOCK_BUFF_SIZE = size_t(sizeof(boost::uint32_t) * 25e6 * 0.5);
+//Large buffers cause more underflow at high rates.
+//Perhaps this is due to the kernel scheduling,
+//but may change with host-based flow control.
+static const size_t MIN_SEND_SOCK_BUFF_SIZE = size_t(10e3);
static const double RECV_TIMEOUT = 0.1; //100 ms
/***********************************************************************
@@ -143,6 +147,10 @@ template<typename Opt> static void resize_buff_helper(
size_t target_size,
const std::string &name
){
+ size_t min_sock_buff_size = 0;
+ if (name == "recv") min_sock_buff_size = MIN_RECV_SOCK_BUFF_SIZE;
+ if (name == "send") min_sock_buff_size = MIN_SEND_SOCK_BUFF_SIZE;
+
//resize the buffer if size was provided
if (target_size > 0){
size_t actual_size = udp_trans->resize_buff<Opt>(target_size);
@@ -158,14 +166,14 @@ template<typename Opt> static void resize_buff_helper(
" 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;
+ ) % name % min_sock_buff_size << std::endl;
}
//only enable on platforms that are happy with the large buffer resize
#if defined(UHD_PLATFORM_LINUX) || defined(UHD_PLATFORM_WIN32)
//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);
+ else if (udp_trans->get_buff_size<Opt>() < min_sock_buff_size){
+ resize_buff_helper<Opt>(udp_trans, min_sock_buff_size, name);
}
#endif /*defined(UHD_PLATFORM_LINUX) || defined(UHD_PLATFORM_WIN32)*/
}
diff --git a/host/lib/transport/vrt_packet_handler.hpp b/host/lib/transport/vrt_packet_handler.hpp
index cf9d649dd..7e0588f03 100644
--- a/host/lib/transport/vrt_packet_handler.hpp
+++ b/host/lib/transport/vrt_packet_handler.hpp
@@ -35,15 +35,25 @@
namespace vrt_packet_handler{
+template <typename T> UHD_INLINE T get_context_code(
+ const boost::uint32_t *vrt_hdr,
+ const uhd::transport::vrt::if_packet_info_t &if_packet_info
+){
+ //extract the context word (we dont know the endianness so mirror the bytes)
+ boost::uint32_t word0 = vrt_hdr[if_packet_info.num_header_words32] |
+ uhd::byteswap(vrt_hdr[if_packet_info.num_header_words32]);
+ return T(word0 & 0xff);
+}
+
/***********************************************************************
* vrt packet handler for recv
**********************************************************************/
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;
+ typedef boost::function<void(size_t /*which channel*/)> handle_overflow_t;
typedef boost::function<void(const boost::uint32_t *, uhd::transport::vrt::if_packet_info_t &)> vrt_unpacker_t;
- static inline void handle_overrun_nop(size_t){}
+ static inline void handle_overflow_nop(size_t){}
struct recv_state{
//width of the receiver in channels
@@ -75,7 +85,7 @@ namespace vrt_packet_handler{
uhd::rx_metadata_t &metadata,
double tick_rate,
const vrt_unpacker_t &vrt_unpacker,
- const handle_overrun_t &handle_overrun,
+ const handle_overflow_t &handle_overflow,
size_t vrt_header_offset_words32
){
//vrt unpack each managed buffer
@@ -92,22 +102,19 @@ namespace vrt_packet_handler{
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 non-data packet case and parse its contents
if (if_packet_info.packet_type != uhd::transport::vrt::if_packet_info_t::PACKET_TYPE_DATA){
- //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 & uhd::rx_metadata_t::ERROR_CODE_OVERRUN) handle_overrun(i);
- metadata.error_code = uhd::rx_metadata_t::error_code_t(word0 & 0xf);
+ metadata.error_code = get_context_code<uhd::rx_metadata_t::error_code_t>(vrt_hdr, if_packet_info);
+ if (metadata.error_code == uhd::rx_metadata_t::ERROR_CODE_OVERFLOW) handle_overflow(i);
//break to exit loop and store metadata below
state.size_of_copy_buffs = 0; break;
}
//setup the buffer to point to the data
- state.copy_buffs[i] = reinterpret_cast<const boost::uint8_t *>(vrt_data);
+ state.copy_buffs[i] = reinterpret_cast<const boost::uint8_t *>(vrt_hdr + if_packet_info.num_header_words32);
//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 +149,7 @@ namespace vrt_packet_handler{
double tick_rate,
const vrt_unpacker_t &vrt_unpacker,
const get_recv_buffs_t &get_recv_buffs,
- const handle_overrun_t &handle_overrun,
+ const handle_overflow_t &handle_overflow,
size_t vrt_header_offset_words32
){
metadata.error_code = uhd::rx_metadata_t::ERROR_CODE_NONE;
@@ -157,7 +164,7 @@ namespace vrt_packet_handler{
try{
_recv1_helper(
state, metadata, tick_rate,
- vrt_unpacker, handle_overrun,
+ vrt_unpacker, handle_overflow,
vrt_header_offset_words32
);
}catch(const std::exception &e){
@@ -216,7 +223,7 @@ namespace vrt_packet_handler{
double tick_rate,
const vrt_unpacker_t &vrt_unpacker,
const get_recv_buffs_t &get_recv_buffs,
- const handle_overrun_t &handle_overrun = &handle_overrun_nop,
+ const handle_overflow_t &handle_overflow = &handle_overflow_nop,
size_t vrt_header_offset_words32 = 0
){
switch(recv_mode){
@@ -233,7 +240,7 @@ namespace vrt_packet_handler{
tick_rate,
vrt_unpacker,
get_recv_buffs,
- handle_overrun,
+ handle_overflow,
vrt_header_offset_words32
);
}
@@ -253,7 +260,7 @@ namespace vrt_packet_handler{
tick_rate,
vrt_unpacker,
get_recv_buffs,
- handle_overrun,
+ handle_overflow,
vrt_header_offset_words32
);
if (num_samps == 0) break; //had a recv timeout or error, break loop
diff --git a/host/lib/types.cpp b/host/lib/types.cpp
index fdc435fef..1cfe84832 100644
--- a/host/lib/types.cpp
+++ b/host/lib/types.cpp
@@ -98,18 +98,6 @@ stream_cmd_t::stream_cmd_t(const stream_mode_t &stream_mode):
/***********************************************************************
* metadata
**********************************************************************/
-rx_metadata_t::rx_metadata_t(void):
- has_time_spec(false),
- time_spec(time_spec_t()),
- more_fragments(false),
- fragment_offset(0),
- start_of_burst(false),
- end_of_burst(false),
- error_code(ERROR_CODE_NONE)
-{
- /* NOP */
-}
-
tx_metadata_t::tx_metadata_t(void):
has_time_spec(false),
time_spec(time_spec_t()),
diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp
index 7e7ce40a2..aa6d15783 100644
--- a/host/lib/usrp/usrp2/io_impl.cpp
+++ b/host/lib/usrp/usrp2/io_impl.cpp
@@ -32,6 +32,8 @@ using namespace uhd::usrp;
using namespace uhd::transport;
namespace asio = boost::asio;
+static const int underflow_flags = async_metadata_t::EVENT_CODE_UNDERFLOW | async_metadata_t::EVENT_CODE_UNDERFLOW_IN_PACKET;
+
/***********************************************************************
* io impl details (internal to this file)
* - pirate crew
@@ -44,7 +46,8 @@ struct usrp2_impl::io_impl{
io_impl(size_t num_frames, size_t width):
packet_handler_recv_state(width),
- recv_pirate_booty(alignment_buffer_type::make(num_frames, width))
+ recv_pirate_booty(alignment_buffer_type::make(num_frames, width)),
+ async_msg_fifo(bounded_buffer<async_metadata_t>::make(100/*messages deep*/))
{
/* NOP */
}
@@ -69,6 +72,7 @@ struct usrp2_impl::io_impl{
boost::thread_group recv_pirate_crew;
bool recv_pirate_crew_raiding;
alignment_buffer_type::sptr recv_pirate_booty;
+ bounded_buffer<async_metadata_t>::sptr async_msg_fifo;
};
/***********************************************************************
@@ -93,12 +97,31 @@ void usrp2_impl::io_impl::recv_pirate_loop(
//extract the vrt header packet info
vrt::if_packet_info_t if_packet_info;
if_packet_info.num_packet_words32 = buff->size()/sizeof(boost::uint32_t);
- vrt::if_hdr_unpack_be(buff->cast<const boost::uint32_t *>(), if_packet_info);
+ const boost::uint32_t *vrt_hdr = buff->cast<const boost::uint32_t *>();
+ vrt::if_hdr_unpack_be(vrt_hdr, if_packet_info);
+
+ //handle a tx async report message
+ if (if_packet_info.sid == 1 and if_packet_info.packet_type != vrt::if_packet_info_t::PACKET_TYPE_DATA){
+
+ //fill in the async metadata
+ async_metadata_t metadata;
+ metadata.channel = index;
+ metadata.has_time_spec = if_packet_info.has_tsi and if_packet_info.has_tsf;
+ metadata.time_spec = time_spec_t(
+ time_t(if_packet_info.tsi), size_t(if_packet_info.tsf), mboard->get_master_clock_freq()
+ );
+ metadata.event_code = vrt_packet_handler::get_context_code<async_metadata_t::event_code_t>(vrt_hdr, if_packet_info);
+
+ //print the famous U, and push the metadata into the message queue
+ if (metadata.event_code & underflow_flags) std::cerr << "U";
+ async_msg_fifo->push_with_pop_on_full(metadata);
+ continue;
+ }
//handle the packet count / sequence number
if (if_packet_info.packet_count != next_packet_seq){
//std::cerr << "S" << (if_packet_info.packet_count - next_packet_seq)%16;
- std::cerr << "O"; //report overrun (drops in the kernel)
+ std::cerr << "O"; //report overflow (drops in the kernel)
}
next_packet_seq = (if_packet_info.packet_count+1)%16;
@@ -150,6 +173,18 @@ void usrp2_impl::io_init(void){
}
/***********************************************************************
+ * Async Data
+ **********************************************************************/
+bool usrp2_impl::recv_async_msg(
+ async_metadata_t &async_metadata, size_t timeout_ms
+){
+ boost::this_thread::disable_interruption di; //disable because the wait can throw
+ return _io_impl->async_msg_fifo->pop_with_timed_wait(
+ async_metadata, boost::posix_time::milliseconds(timeout_ms)
+ );
+}
+
+/***********************************************************************
* Send Data
**********************************************************************/
bool get_send_buffs(
diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp
index 938bf8466..133e6f989 100644
--- a/host/lib/usrp/usrp2/mboard_impl.cpp
+++ b/host/lib/usrp/usrp2/mboard_impl.cpp
@@ -75,6 +75,7 @@ usrp2_mboard_impl::usrp2_mboard_impl(
_iface->poke32(_iface->regs.rx_ctrl_nchannels, 1);
_iface->poke32(_iface->regs.rx_ctrl_clear_overrun, 1); //reset
_iface->poke32(_iface->regs.rx_ctrl_vrt_header, 0
+
| (0x1 << 28) //if data with stream id
| (0x1 << 26) //has trailer
| (0x3 << 22) //integer time other
@@ -84,6 +85,11 @@ usrp2_mboard_impl::usrp2_mboard_impl(
_iface->poke32(_iface->regs.rx_ctrl_vrt_trailer, 0);
_iface->poke32(_iface->regs.time64_tps, size_t(get_master_clock_freq()));
+ //init the tx control registers
+ _iface->poke32(_iface->regs.tx_ctrl_num_chan, 0); //1 channel
+ _iface->poke32(_iface->regs.tx_ctrl_clear_state, 1); //reset
+ _iface->poke32(_iface->regs.tx_ctrl_report_sid, 1); //sid 1 (different from rx)
+
//init the ddc
init_ddc_config();
diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp
index cae1b21d6..2eaf12350 100644
--- a/host/lib/usrp/usrp2/usrp2_impl.hpp
+++ b/host/lib/usrp/usrp2/usrp2_impl.hpp
@@ -235,6 +235,7 @@ public:
uhd::rx_metadata_t &, const uhd::io_type_t &,
uhd::device::recv_mode_t, size_t
);
+ bool recv_async_msg(uhd::async_metadata_t &, size_t);
private:
//device properties interface
diff --git a/host/lib/usrp/usrp2/usrp2_regs.cpp b/host/lib/usrp/usrp2/usrp2_regs.cpp
index 071ba0cd2..e40407f99 100644
--- a/host/lib/usrp/usrp2/usrp2_regs.cpp
+++ b/host/lib/usrp/usrp2/usrp2_regs.cpp
@@ -89,6 +89,9 @@ usrp2_regs_t usrp2_get_regs(int hw_rev) {
x.rx_ctrl_vrt_trailer = sr_addr(misc_output_base, x.sr_rx_ctrl + 6);
x.rx_ctrl_nsamps_per_pkt = sr_addr(misc_output_base, x.sr_rx_ctrl + 7);
x.rx_ctrl_nchannels = sr_addr(misc_output_base, x.sr_rx_ctrl + 8);
+ x.tx_ctrl_num_chan = sr_addr(misc_output_base, x.sr_tx_ctrl + 0);
+ x.tx_ctrl_clear_state = sr_addr(misc_output_base, x.sr_tx_ctrl + 1);
+ x.tx_ctrl_report_sid = sr_addr(misc_output_base, x.sr_tx_ctrl + 2);
return x;
}
diff --git a/host/lib/usrp/usrp2/usrp2_regs.hpp b/host/lib/usrp/usrp2/usrp2_regs.hpp
index 0ebce6a85..8dbd6c4b4 100644
--- a/host/lib/usrp/usrp2/usrp2_regs.hpp
+++ b/host/lib/usrp/usrp2/usrp2_regs.hpp
@@ -94,6 +94,9 @@ typedef struct {
int rx_ctrl_vrt_trailer;
int rx_ctrl_nsamps_per_pkt;
int rx_ctrl_nchannels;
+ int tx_ctrl_num_chan;
+ int tx_ctrl_clear_state;
+ int tx_ctrl_report_sid;
} usrp2_regs_t;
extern const usrp2_regs_t usrp2_regs; //the register definitions, set in usrp2_regs.cpp and usrp2p_regs.cpp
@@ -248,8 +251,15 @@ usrp2_regs_t usrp2_get_regs(int hw_rev);
///////////////////////////////////////////////////
-// VITA RX CTRL regs
+// RX CTRL regs
///////////////////////////////////////////////////
+///////////////////////////////////////////////////
+// TX CTRL regs
+///////////////////////////////////////////////////
+//#define U2_REG_TX_CTRL_NUM_CHAN _SR_ADDR(SR_TX_CTRL + 0)
+//#define U2_REG_TX_CTRL_CLEAR_STATE _SR_ADDR(SR_TX_CTRL + 1)
+//#define U2_REG_TX_CTRL_REPORT_SID _SR_ADDR(SR_TX_CTRL + 2)
+
#endif /* INCLUDED_USRP2_REGS_HPP */