From bf77d1f6e38e1cb561520408ecff8f633f5cefc7 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Fri, 9 Jul 2010 17:35:15 -0700 Subject: uhd: added error codes to rx metadata, switched examples to use vrt packet handler fills in error codes and inspects non-data packet --- host/examples/benchmark_rx_rate.cpp | 5 ++++- host/examples/rx_timed_samples.cpp | 9 ++++++--- host/include/uhd/device.hpp | 2 +- host/include/uhd/types/metadata.hpp | 29 ++++++++++++++++++++++++++--- host/lib/transport/gen_vrt_if_packet.py | 4 ++-- host/lib/transport/vrt_packet_handler.hpp | 31 +++++++++++++++++++------------ host/lib/types.cpp | 3 ++- 7 files changed, 60 insertions(+), 23 deletions(-) (limited to 'host') diff --git a/host/examples/benchmark_rx_rate.cpp b/host/examples/benchmark_rx_rate.cpp index 7b512e56e..ba4dd34d0 100644 --- a/host/examples/benchmark_rx_rate.cpp +++ b/host/examples/benchmark_rx_rate.cpp @@ -53,10 +53,13 @@ static inline void test_device( uhd::io_type_t::COMPLEX_FLOAT32, uhd::device::RECV_MODE_ONE_PACKET ); - if (num_rx_samps == 0){ + if (num_rx_samps == 0 and md.error_code == uhd::rx_metadata_t::ERROR_CODE_TIMEOUT){ std::cerr << "Unexpected timeout on recv, exit test..." << std::endl; return; } + if (num_rx_samps == 0){ + std::cerr << "Unexpected error on recv, continuing..." << std::endl; + } if (not md.has_time_spec){ std::cerr << "Metadata missing time spec, exit test..." << std::endl; return; diff --git a/host/examples/rx_timed_samples.cpp b/host/examples/rx_timed_samples.cpp index fcf662c4e..95f805007 100644 --- a/host/examples/rx_timed_samples.cpp +++ b/host/examples/rx_timed_samples.cpp @@ -93,13 +93,16 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ uhd::device::RECV_MODE_ONE_PACKET ); if (num_rx_samps == 0 and num_acc_samps > 0){ - std::cout << "Got timeout before all samples received, possible packet loss, exiting loop..." << std::endl; + std::cout << boost::format( + "Got error code 0x%x before all samples received, possible packet loss, exiting loop..." + ) % md.error_code << std::endl; break; } if (num_rx_samps == 0) continue; //wait for packets with contents - if(verbose) std::cout << boost::format("Got packet: %u samples, %u full secs, %f frac secs") - % num_rx_samps % md.time_spec.get_full_secs() % md.time_spec.get_frac_secs() << std::endl; + if(verbose) std::cout << boost::format( + "Got packet: %u samples, %u full secs, %f frac secs" + ) % num_rx_samps % md.time_spec.get_full_secs() % md.time_spec.get_frac_secs() << std::endl; num_acc_samps += num_rx_samps; } diff --git a/host/include/uhd/device.hpp b/host/include/uhd/device.hpp index a0c29f2e6..a19d22880 100644 --- a/host/include/uhd/device.hpp +++ b/host/include/uhd/device.hpp @@ -174,7 +174,7 @@ public: * \param metadata data to fill describing the buffer * \param io_type the type of data to fill into the buffer * \param recv_mode tells recv how to load the buffer - * \return the number of samples received + * \return the number of samples received or 0 on error */ virtual size_t recv( const std::vector &buffs, diff --git a/host/include/uhd/types/metadata.hpp b/host/include/uhd/types/metadata.hpp index 6712e2594..039196250 100644 --- a/host/include/uhd/types/metadata.hpp +++ b/host/include/uhd/types/metadata.hpp @@ -57,10 +57,33 @@ namespace uhd{ bool end_of_burst; /*! - * Error conditions (TODO): - * Previous packets dropped? - * Timed-out on receive? + * Error conditions: + * - none: no error associated with this metadata + * - timeout: no packet received, underlying code timed-out + * - late command: a stream command was issued in the past + * - broken chain: expected another stream command + * - overrun: an internal receive buffer has overrun + * - bad packet: the buffer was unrecognizable as a vrt packet + * + * Note: When an overrun occurs in continuous streaming mode, + * the device will continue to send samples to the host. + * For other streaming modes, streaming will discontinue + * until the user issues a new stream command. + * + * Note: The metadata fields have meaning for the following error codes: + * - none + * - late command + * - broken chain + * - overrun */ + enum error_code_t { + ERROR_CODE_NONE = 0x0, + ERROR_CODE_TIMEOUT = 0x1, + ERROR_CODE_LATE_COMMAND = 0x2, + ERROR_CODE_BROKEN_CHAIN = 0x4, + ERROR_CODE_OVERRUN = 0x8, + ERROR_CODE_BAD_PACKET = 0xf + } error_code; /*! * The default constructor: diff --git a/host/lib/transport/gen_vrt_if_packet.py b/host/lib/transport/gen_vrt_if_packet.py index 07ce391ee..7438f5ff4 100755 --- a/host/lib/transport/gen_vrt_if_packet.py +++ b/host/lib/transport/gen_vrt_if_packet.py @@ -150,8 +150,8 @@ void vrt::if_hdr_unpack_$(suffix)( //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)); + //if_packet_info.sob = bool(vrt_hdr_word & $hex(0x1 << 25)); //not implemented + //if_packet_info.eob = bool(vrt_hdr_word & $hex(0x1 << 24)); //not implemented boost::uint8_t pred = 0; if(vrt_hdr_word & $hex(0x1 << 28)) pred |= $hex($sid_p); diff --git a/host/lib/transport/vrt_packet_handler.hpp b/host/lib/transport/vrt_packet_handler.hpp index 11d749a81..c0d6bbe12 100644 --- a/host/lib/transport/vrt_packet_handler.hpp +++ b/host/lib/transport/vrt_packet_handler.hpp @@ -42,7 +42,7 @@ namespace vrt_packet_handler{ typedef boost::function get_recv_buffs_t; typedef boost::function handle_overrun_t; - void handle_overrun_nop(size_t){} + static inline void handle_overrun_nop(size_t){} struct recv_state{ //width of the receiver in channels @@ -89,8 +89,7 @@ namespace vrt_packet_handler{ //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 + throw std::runtime_error("recv buffer smaller than vrt packet offset"); } //unpack the vrt header into the info struct @@ -105,15 +104,16 @@ 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) + //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){ - 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 + if (word0 & uhd::rx_metadata_t::ERROR_CODE_OVERRUN) handle_overrun(i); + metadata.error_code = uhd::rx_metadata_t::error_code_t(word0 & 0xf); + + //break to exit loop and store metadata below + state.size_of_copy_buffs = 0; break; } //setup the buffer to point to the data @@ -131,9 +131,10 @@ 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_sob_flags = (1 << 21) | (1 << 9); //enable and indicator bits + metadata.start_of_burst = if_packet_info.has_tlr and (int(if_packet_info.tlr & tlr_sob_flags) == tlr_sob_flags); 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); + metadata.end_of_burst = if_packet_info.has_tlr and (int(if_packet_info.tlr & tlr_eob_flags) == tlr_eob_flags); } /******************************************************************* @@ -156,11 +157,15 @@ namespace vrt_packet_handler{ size_t vrt_header_offset_words32 ){ metadata.has_time_spec = false; //false unless set in the helper + metadata.error_code = uhd::rx_metadata_t::ERROR_CODE_NONE; //perform a receive if no rx data is waiting to be copied if (state.size_of_copy_buffs == 0){ state.fragment_offset_in_samps = 0; - if (not get_recv_buffs(state.managed_buffs)) return 0; + if (not get_recv_buffs(state.managed_buffs)){ + metadata.error_code = uhd::rx_metadata_t::ERROR_CODE_TIMEOUT; + return 0; + } try{ _recv1_helper( state, metadata, tick_rate, @@ -168,7 +173,9 @@ namespace vrt_packet_handler{ vrt_header_offset_words32 ); }catch(const std::exception &e){ + state.size_of_copy_buffs = 0; //reset copy buffs size std::cerr << "Error (recv): " << e.what() << std::endl; + metadata.error_code = uhd::rx_metadata_t::ERROR_CODE_BAD_PACKET; return 0; } } diff --git a/host/lib/types.cpp b/host/lib/types.cpp index 1e7917ad7..e0ce61058 100644 --- a/host/lib/types.cpp +++ b/host/lib/types.cpp @@ -101,7 +101,8 @@ rx_metadata_t::rx_metadata_t(void): more_fragments(false), fragment_offset(0), start_of_burst(false), - end_of_burst(false) + end_of_burst(false), + error_code(ERROR_CODE_NONE) { /* NOP */ } -- cgit v1.2.3