diff options
-rw-r--r-- | host/examples/CMakeLists.txt | 2 | ||||
-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.hpp | 28 | ||||
-rw-r--r-- | host/lib/usrp/usrp1/soft_time_ctrl.cpp | 11 | ||||
-rw-r--r-- | host/tests/sph_recv_test.cpp | 3 |
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; } } |