diff options
author | Josh Blum <josh@joshknows.com> | 2011-07-03 17:40:13 -0700 |
---|---|---|
committer | Josh Blum <josh@joshknows.com> | 2011-07-03 17:40:13 -0700 |
commit | 34265334d18589a377ab42df211eb33054340ae6 (patch) | |
tree | 0efdf423fa95ed92ce2a9d77ddac6371d9256b83 /host | |
parent | 89989fdb2d92a6072b737a8864b50c9daa5c614a (diff) | |
download | uhd-34265334d18589a377ab42df211eb33054340ae6.tar.gz uhd-34265334d18589a377ab42df211eb33054340ae6.tar.bz2 uhd-34265334d18589a377ab42df211eb33054340ae6.zip |
uhd: added inline message testing to the messages example
Renamed the example to test_messages (not just async).
Fixed bug in super recv packet handler related to messages.
Basically, the sequence number for messages should be ignored.
Fixed some quirks with usrp1 soft time control to get it work as well.
Diffstat (limited to 'host')
-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; } } |