aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--host/examples/CMakeLists.txt2
-rw-r--r--host/examples/test_messages.cpp (renamed from host/examples/test_async_messages.cpp)140
-rw-r--r--host/lib/transport/super_recv_packet_handler.hpp28
-rw-r--r--host/lib/usrp/usrp1/soft_time_ctrl.cpp11
-rw-r--r--host/tests/sph_recv_test.cpp3
5 files changed, 150 insertions, 34 deletions
diff --git a/host/examples/CMakeLists.txt b/host/examples/CMakeLists.txt
index 10d1fddc3..bad7b72a6 100644
--- a/host/examples/CMakeLists.txt
+++ b/host/examples/CMakeLists.txt
@@ -24,7 +24,7 @@ SET(example_sources
rx_samples_to_file.cpp
rx_samples_to_udp.cpp
rx_timed_samples.cpp
- test_async_messages.cpp
+ test_messages.cpp
test_pps_input.cpp
tx_bursts.cpp
tx_samples_from_file.cpp
diff --git a/host/examples/test_async_messages.cpp b/host/examples/test_messages.cpp
index 7f922ed35..60d108184 100644
--- a/host/examples/test_async_messages.cpp
+++ b/host/examples/test_messages.cpp
@@ -18,6 +18,7 @@
#include <uhd/utils/thread_priority.hpp>
#include <uhd/utils/safe_main.hpp>
#include <uhd/utils/static.hpp>
+#include <uhd/types/stream_cmd.hpp>
#include <uhd/usrp/multi_usrp.hpp>
#include <boost/assign/list_of.hpp>
#include <boost/program_options.hpp>
@@ -31,6 +32,107 @@
namespace po = boost::program_options;
/*!
+ * Test the late command message:
+ * Issue a stream command with a time that is in the past.
+ * We expect to get an inline late command message.
+ */
+bool test_late_command_message(uhd::usrp::multi_usrp::sptr usrp){
+ std::cout << "Test late command message... " << std::flush;
+
+ usrp->set_time_now(uhd::time_spec_t(200.0)); //set time
+
+ uhd::stream_cmd_t stream_cmd(uhd::stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_DONE);
+ stream_cmd.num_samps = usrp->get_device()->get_max_recv_samps_per_packet();
+ stream_cmd.stream_now = false;
+ stream_cmd.time_spec = uhd::time_spec_t(100.0); //time in the past
+ usrp->issue_stream_cmd(stream_cmd);
+
+ std::vector<std::complex<float> > buff(usrp->get_device()->get_max_recv_samps_per_packet());
+ uhd::rx_metadata_t md;
+
+ const size_t nsamps = usrp->get_device()->recv(
+ &buff.front(), buff.size(), md,
+ uhd::io_type_t::COMPLEX_FLOAT32,
+ uhd::device::RECV_MODE_FULL_BUFF
+ );
+
+ switch(md.error_code){
+ case uhd::rx_metadata_t::ERROR_CODE_LATE_COMMAND:
+ std::cout << boost::format(
+ "success:\n"
+ " Got error code late command message.\n"
+ ) << std::endl;
+ return true;
+
+ case uhd::rx_metadata_t::ERROR_CODE_TIMEOUT:
+ std::cout << boost::format(
+ "failed:\n"
+ " Inline message recv timed out.\n"
+ ) << std::endl;
+ return false;
+
+ default:
+ std::cout << boost::format(
+ "failed:\n"
+ " Got unexpected error code 0x%x, nsamps %u.\n"
+ ) % md.error_code % nsamps << std::endl;
+ return false;
+ }
+}
+
+/*!
+ * Test the broken chain message:
+ * Issue a stream command with num samps and more.
+ * We expect to get an inline broken chain message.
+ */
+bool test_broken_chain_message(uhd::usrp::multi_usrp::sptr usrp){
+ std::cout << "Test broken chain message... " << std::flush;
+
+ uhd::stream_cmd_t stream_cmd(uhd::stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_MORE);
+ stream_cmd.stream_now = true;
+ stream_cmd.num_samps = usrp->get_device()->get_max_recv_samps_per_packet();
+ usrp->issue_stream_cmd(stream_cmd);
+
+ std::vector<std::complex<float> > buff(usrp->get_device()->get_max_recv_samps_per_packet());
+ uhd::rx_metadata_t md;
+
+ usrp->get_device()->recv( //once for the requested samples
+ &buff.front(), buff.size(), md,
+ uhd::io_type_t::COMPLEX_FLOAT32,
+ uhd::device::RECV_MODE_FULL_BUFF
+ );
+
+ usrp->get_device()->recv( //again for the inline message
+ &buff.front(), buff.size(), md,
+ uhd::io_type_t::COMPLEX_FLOAT32,
+ uhd::device::RECV_MODE_FULL_BUFF
+ );
+
+ switch(md.error_code){
+ case uhd::rx_metadata_t::ERROR_CODE_BROKEN_CHAIN:
+ std::cout << boost::format(
+ "success:\n"
+ " Got error code broken chain message.\n"
+ ) << std::endl;
+ return true;
+
+ case uhd::rx_metadata_t::ERROR_CODE_TIMEOUT:
+ std::cout << boost::format(
+ "failed:\n"
+ " Inline message recv timed out.\n"
+ ) << std::endl;
+ return false;
+
+ default:
+ std::cout << boost::format(
+ "failed:\n"
+ " Got unexpected error code 0x%x.\n"
+ ) % md.error_code << std::endl;
+ return false;
+ }
+}
+
+/*!
* Test the burst ack message:
* Send a burst of many samples that will fragment internally.
* We expect to get an burst ack async message.
@@ -169,9 +271,22 @@ bool test_time_error_message(uhd::usrp::multi_usrp::sptr usrp){
}
}
-void flush_async_md(uhd::usrp::multi_usrp::sptr usrp){
+void flush_async(uhd::usrp::multi_usrp::sptr usrp){
uhd::async_metadata_t async_md;
- while (usrp->get_device()->recv_async_msg(async_md, 1.0)){}
+ while (usrp->get_device()->recv_async_msg(async_md)){}
+}
+
+void flush_recv(uhd::usrp::multi_usrp::sptr usrp){
+ std::vector<std::complex<float> > buff(usrp->get_device()->get_max_recv_samps_per_packet());
+ uhd::rx_metadata_t md;
+
+ do{
+ usrp->get_device()->recv(
+ &buff.front(), buff.size(), md,
+ uhd::io_type_t::COMPLEX_FLOAT32,
+ uhd::device::RECV_MODE_FULL_BUFF
+ );
+ } while (md.error_code != uhd::rx_metadata_t::ERROR_CODE_TIMEOUT);
}
int UHD_SAFE_MAIN(int argc, char *argv[]){
@@ -179,7 +294,6 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
//variables to be set by po
std::string args;
- double rate;
size_t ntests;
//setup the program options
@@ -187,8 +301,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
desc.add_options()
("help", "help message")
("args", po::value<std::string>(&args)->default_value(""), "multi uhd device address args")
- ("rate", po::value<double>(&rate)->default_value(1.5e6), "rate of outgoing samples")
- ("ntests", po::value<size_t>(&ntests)->default_value(10), "number of tests to run")
+ ("ntests", po::value<size_t>(&ntests)->default_value(50), "number of tests to run")
;
po::variables_map vm;
po::store(po::parse_command_line(argc, argv, desc), vm);
@@ -196,7 +309,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
//print the help message
if (vm.count("help")){
- std::cout << boost::format("UHD Test Async Messages %s") % desc << std::endl;
+ std::cout << boost::format("UHD Test Messages %s") % desc << std::endl;
return ~0;
}
@@ -206,19 +319,16 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
uhd::usrp::multi_usrp::sptr usrp = uhd::usrp::multi_usrp::make(args);
std::cout << boost::format("Using Device: %s") % usrp->get_pp_string() << std::endl;
- //set the tx sample rate
- std::cout << boost::format("Setting TX Rate: %f Msps...") % (rate/1e6) << std::endl;
- usrp->set_tx_rate(rate);
- std::cout << boost::format("Actual TX Rate: %f Msps...") % (usrp->get_tx_rate()/1e6) << std::endl << std::endl;
-
//------------------------------------------------------------------
- // begin asyc messages test
+ // begin messages test
//------------------------------------------------------------------
static const uhd::dict<std::string, boost::function<bool(uhd::usrp::multi_usrp::sptr)> >
tests = boost::assign::map_list_of
("Test Burst ACK ", &test_burst_ack_message)
("Test Underflow ", &test_underflow_message)
("Test Time Error", &test_time_error_message)
+ ("Test Late Command", &test_late_command_message)
+ ("Test Broken Chain", &test_broken_chain_message)
;
//init result counts
@@ -229,10 +339,12 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
}
//run the tests, pick at random
+ std::srand(uhd::time_spec_t::get_system_time().get_full_secs());
for (size_t n = 0; n < ntests; n++){
std::string key = tests.keys()[std::rand() % tests.size()];
bool pass = tests[key](usrp);
- flush_async_md(usrp);
+ flush_async(usrp);
+ flush_recv(usrp);
//store result
if (pass) successes[key]++;
@@ -243,7 +355,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
std::cout << std::endl << "Summary:" << std::endl << std::endl;
BOOST_FOREACH(const std::string &key, tests.keys()){
std::cout << boost::format(
- "%s -> %3d successes, %3d failures"
+ "%s -> %3u successes, %3u failures"
) % key % successes[key] % failures[key] << std::endl;
}
diff --git a/host/lib/transport/super_recv_packet_handler.hpp b/host/lib/transport/super_recv_packet_handler.hpp
index a27962042..d79e0b2c0 100644
--- a/host/lib/transport/super_recv_packet_handler.hpp
+++ b/host/lib/transport/super_recv_packet_handler.hpp
@@ -313,34 +313,30 @@ private:
info.time = time_spec_t(time_t(info.ifpi.tsi), size_t(info.ifpi.tsf), _tick_rate); //assumes has_tsi and has_tsf are true
info.copy_buff = reinterpret_cast<const char *>(info.vrt_hdr + info.ifpi.num_header_words32);
- //store the packet count for the next iteration
- #ifndef SRPH_DONT_CHECK_SEQUENCE
- const size_t expected_packet_count = _props[index].packet_count;
- _props[index].packet_count = (info.ifpi.packet_count + 1)%16;
- #endif
-
//--------------------------------------------------------------
//-- Determine return conditions:
//-- The order of these checks is HOLY.
//--------------------------------------------------------------
- //1) check for out of order timestamps
- if (info.ifpi.has_tsi and info.ifpi.has_tsf and prev_buffer_info[index].time > info.time){
- return PACKET_TIMESTAMP_ERROR;
- }
-
- //2) check for inline IF message packets
+ //1) check for inline IF message packets
if (info.ifpi.packet_type != vrt::if_packet_info_t::PACKET_TYPE_DATA){
return PACKET_INLINE_MESSAGE;
}
- //3) check for sequence errors
+ //2) check for sequence errors
#ifndef SRPH_DONT_CHECK_SEQUENCE
+ const size_t expected_packet_count = _props[index].packet_count;
+ _props[index].packet_count = (info.ifpi.packet_count + 1)%16;
if (expected_packet_count != info.ifpi.packet_count){
return PACKET_SEQUENCE_ERROR;
}
#endif
+ //3) check for out of order timestamps
+ if (info.ifpi.has_tsi and info.ifpi.has_tsf and prev_buffer_info[index].time > info.time){
+ return PACKET_TIMESTAMP_ERROR;
+ }
+
//4) otherwise the packet is normal!
return PACKET_IF_DATA;
}
@@ -446,8 +442,10 @@ private:
curr_info.metadata.start_of_burst = false;
curr_info.metadata.end_of_burst = false;
curr_info.metadata.error_code = rx_metadata_t::error_code_t(get_context_code(next_info[index].vrt_hdr, next_info[index].ifpi));
- if (curr_info.metadata.error_code == rx_metadata_t::ERROR_CODE_OVERFLOW) _props[index].handle_overflow();
- UHD_MSG(fastpath) << "O";
+ if (curr_info.metadata.error_code == rx_metadata_t::ERROR_CODE_OVERFLOW){
+ _props[index].handle_overflow();
+ UHD_MSG(fastpath) << "O";
+ }
return;
case PACKET_TIMEOUT_ERROR:
diff --git a/host/lib/usrp/usrp1/soft_time_ctrl.cpp b/host/lib/usrp/usrp1/soft_time_ctrl.cpp
index cf602185d..2728ff755 100644
--- a/host/lib/usrp/usrp1/soft_time_ctrl.cpp
+++ b/host/lib/usrp/usrp1/soft_time_ctrl.cpp
@@ -93,6 +93,12 @@ public:
void recv_post(rx_metadata_t &md, size_t &nsamps){
boost::mutex::scoped_lock lock(_update_mutex);
+ //Since it timed out on the receive, check for inline messages...
+ //Must do a post check because recv() will not wake up for a message.
+ if (md.error_code == rx_metadata_t::ERROR_CODE_TIMEOUT){
+ if (_inline_msg_queue.pop_with_haste(md)) return;
+ }
+
//load the metadata with the expected time
md.has_time_spec = true;
md.time_spec = time_now();
@@ -114,7 +120,7 @@ public:
case stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_DONE:
nsamps = _nsamps_remaining; //set nsamps, then stop
md.end_of_burst = true;
- stream_on_off(false);
+ this->issue_stream_cmd(stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS);
return;
default: break;
}
@@ -173,7 +179,8 @@ public:
metadata.time_spec = this->time_now();
metadata.error_code = rx_metadata_t::ERROR_CODE_LATE_COMMAND;
_inline_msg_queue.push_with_pop_on_full(metadata);
- _stream_mode = stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS;
+ this->issue_stream_cmd(stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS);
+ return;
}
else{
sleep_until_time(lock, time_at);
diff --git a/host/tests/sph_recv_test.cpp b/host/tests/sph_recv_test.cpp
index cd33452c6..1387e3b66 100644
--- a/host/tests/sph_recv_test.cpp
+++ b/host/tests/sph_recv_test.cpp
@@ -290,6 +290,7 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_one_channel_inline_message){
//generate a bunch of packets
for (size_t i = 0; i < NUM_PKTS_TO_TEST; i++){
+ ifpi.packet_type = uhd::transport::vrt::if_packet_info_t::PACKET_TYPE_DATA;
ifpi.num_payload_words32 = 10 + i%10;
dummy_recv_xport.push_back_packet(ifpi);
ifpi.packet_count++;
@@ -300,8 +301,6 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_one_channel_inline_message){
ifpi.packet_type = uhd::transport::vrt::if_packet_info_t::PACKET_TYPE_EXTENSION;
ifpi.num_payload_words32 = 1;
dummy_recv_xport.push_back_packet(ifpi, uhd::rx_metadata_t::ERROR_CODE_OVERFLOW);
- ifpi.packet_count++;
- ifpi.packet_type = uhd::transport::vrt::if_packet_info_t::PACKET_TYPE_DATA;
}
}