From 20381a1c839ded4eb58728d3a1fd3a952d2444f6 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 19 Jul 2010 18:56:33 -0700 Subject: usrp2: added registers and handling for tx async reports --- host/lib/usrp/usrp2/io_impl.cpp | 6 ++++++ host/lib/usrp/usrp2/mboard_impl.cpp | 7 ++++++- host/lib/usrp/usrp2/usrp2_regs.hpp | 9 ++++++++- 3 files changed, 20 insertions(+), 2 deletions(-) (limited to 'host/lib/usrp/usrp2') diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index 430f28390..e4a49184e 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -95,6 +95,12 @@ void usrp2_impl::io_impl::recv_pirate_loop( if_packet_info.num_packet_words32 = buff->size()/sizeof(boost::uint32_t); vrt::if_hdr_unpack_be(buff->cast(), if_packet_info); + //handle a tx async report message (TODO forward info) + if (if_packet_info.sid == 1 and if_packet_info.packet_type != vrt::if_packet_info_t::PACKET_TYPE_DATA){ + std::cerr << "U"; + 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; diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp index 7518d3114..b3b03c11c 100644 --- a/host/lib/usrp/usrp2/mboard_impl.cpp +++ b/host/lib/usrp/usrp2/mboard_impl.cpp @@ -67,7 +67,7 @@ usrp2_mboard_impl::usrp2_mboard_impl( _allowed_decim_and_interp_rates.push_back(i); } - //setup the vrt rx registers + //init the rx control registers _iface->poke32(U2_REG_RX_CTRL_NSAMPS_PER_PKT, _io_helper.get_max_recv_samps_per_packet()); _iface->poke32(U2_REG_RX_CTRL_NCHANNELS, 1); _iface->poke32(U2_REG_RX_CTRL_CLEAR_OVERRUN, 1); //reset @@ -81,6 +81,11 @@ usrp2_mboard_impl::usrp2_mboard_impl( _iface->poke32(U2_REG_RX_CTRL_VRT_TRAILER, 0); _iface->poke32(U2_REG_TIME64_TPS, size_t(get_master_clock_freq())); + //init the tx control registers + _iface->poke32(U2_REG_TX_CTRL_NUM_CHAN, 0); //1 channel + _iface->poke32(U2_REG_TX_CTRL_CLEAR_STATE, 1); //reset + _iface->poke32(U2_REG_TX_CTRL_REPORT_SID, 1); //sid 1 (different from rx) + //init the ddc init_ddc_config(); diff --git a/host/lib/usrp/usrp2/usrp2_regs.hpp b/host/lib/usrp/usrp2/usrp2_regs.hpp index 1a5864c85..aa8bd860f 100644 --- a/host/lib/usrp/usrp2/usrp2_regs.hpp +++ b/host/lib/usrp/usrp2/usrp2_regs.hpp @@ -226,7 +226,7 @@ #define U2_REG_ATR_FULL_RXSIDE U2_REG_ATR_BASE + 14 /////////////////////////////////////////////////// -// VITA RX CTRL regs +// RX CTRL regs /////////////////////////////////////////////////// // The following 3 are logically a single command register. // They are clocked into the underlying fifo when time_ticks is written. @@ -241,4 +241,11 @@ #define U2_REG_RX_CTRL_NSAMPS_PER_PKT _SR_ADDR(SR_RX_CTRL + 7) #define U2_REG_RX_CTRL_NCHANNELS _SR_ADDR(SR_RX_CTRL + 8) // 1 in basic case, up to 4 for vector sources +/////////////////////////////////////////////////// +// 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 */ -- cgit v1.2.3 From 90465e6bcda596b28ab823e698b078708828da0c Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 20 Jul 2010 18:51:36 -0700 Subject: uhd: added async recv message call to device api implemented in usrp2 io impl added async metadata type --- host/examples/benchmark_rx_rate.cpp | 2 +- host/include/uhd/device.hpp | 11 ++++++++ host/include/uhd/types/metadata.hpp | 44 +++++++++++++++++++++++-------- host/lib/transport/vrt_packet_handler.hpp | 18 ++++++------- host/lib/types.cpp | 12 --------- host/lib/usrp/usrp2/io_impl.cpp | 40 ++++++++++++++++++++++++---- host/lib/usrp/usrp2/usrp2_impl.hpp | 1 + 7 files changed, 90 insertions(+), 38 deletions(-) (limited to 'host/lib/usrp/usrp2') diff --git a/host/examples/benchmark_rx_rate.cpp b/host/examples/benchmark_rx_rate.cpp index 752facb0d..8fae813cf 100644 --- a/host/examples/benchmark_rx_rate.cpp +++ b/host/examples/benchmark_rx_rate.cpp @@ -66,7 +66,7 @@ static inline void test_device( //handle the error codes switch(md.error_code){ case uhd::rx_metadata_t::ERROR_CODE_NONE: - case uhd::rx_metadata_t::ERROR_CODE_OVERRUN: + case uhd::rx_metadata_t::ERROR_CODE_OVERFLOW: break; default: diff --git a/host/include/uhd/device.hpp b/host/include/uhd/device.hpp index ee297ec8a..78bb83c66 100644 --- a/host/include/uhd/device.hpp +++ b/host/include/uhd/device.hpp @@ -219,6 +219,17 @@ public: */ virtual size_t get_max_recv_samps_per_packet(void) const = 0; + /*! + * Receive and asynchronous message from the device. + * \param async_metadata the metadata to be filled in + * \param timeout_ms the timeout in milliseconds to wait for a message + * \return true when the async_metadata is valid, false for timeout + */ + virtual bool recv_async_msg( + async_metadata_t &async_metadata, + size_t timeout_ms = default_recv_timeout_ms + ) = 0; + }; } //namespace uhd diff --git a/host/include/uhd/types/metadata.hpp b/host/include/uhd/types/metadata.hpp index 039196250..43ddf875f 100644 --- a/host/include/uhd/types/metadata.hpp +++ b/host/include/uhd/types/metadata.hpp @@ -26,7 +26,7 @@ namespace uhd{ /*! * RX metadata structure for describing sent IF data. - * Includes stream ID, time specification, and fragmentation flags. + * Includes time specification, fragmentation flags, burst flags, and error codes. * The receive routines will convert IF data headers into metadata. */ struct UHD_API rx_metadata_t{ @@ -62,7 +62,7 @@ namespace uhd{ * - 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 + * - overflow: an internal receive buffer has filled * - bad packet: the buffer was unrecognizable as a vrt packet * * Note: When an overrun occurs in continuous streaming mode, @@ -74,27 +74,21 @@ namespace uhd{ * - none * - late command * - broken chain - * - overrun + * - overflow */ 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_OVERFLOW = 0x8, ERROR_CODE_BAD_PACKET = 0xf } error_code; - - /*! - * The default constructor: - * Sets the fields to default values (flags set to false). - */ - rx_metadata_t(void); }; /*! * TX metadata structure for describing received IF data. - * Includes stream ID, time specification, and burst flags. + * Includes time specification, and start and stop burst flags. * The send routines will convert the metadata to IF data headers. */ struct UHD_API tx_metadata_t{ @@ -121,6 +115,34 @@ namespace uhd{ tx_metadata_t(void); }; + /*! + * Async metadata structure for describing transmit related events. + */ + struct UHD_API async_metadata_t{ + //! The channel number in a mimo configuration + size_t channel; + + /*! + * Time specification: when the async event occurred. + */ + bool has_time_spec; + time_spec_t time_spec; + + /*! + * Event codes: + * - success: a packet was successfully transmitted + * - underflow: an internal send buffer has emptied + * - sequence error: packet loss between host and device + * - time error: packet had time that was late (or too early) + */ + enum event_code_t { + EVENT_CODE_SUCCESS = 0x1, + EVENT_CODE_UNDERFLOW = 0x2, + EVENT_CODE_SEQ_ERROR = 0x4, + EVENT_CODE_TIME_ERROR = 0x8 + } event_code; + }; + } //namespace uhd #endif /* INCLUDED_UHD_TYPES_METADATA_HPP */ diff --git a/host/lib/transport/vrt_packet_handler.hpp b/host/lib/transport/vrt_packet_handler.hpp index 07ad9115c..3eddcec6d 100644 --- a/host/lib/transport/vrt_packet_handler.hpp +++ b/host/lib/transport/vrt_packet_handler.hpp @@ -40,10 +40,10 @@ namespace vrt_packet_handler{ **********************************************************************/ typedef std::vector managed_recv_buffs_t; typedef boost::function get_recv_buffs_t; - typedef boost::function handle_overrun_t; + typedef boost::function handle_overflow_t; typedef boost::function 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 +75,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 @@ -99,7 +99,7 @@ namespace vrt_packet_handler{ //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); + if (word0 & uhd::rx_metadata_t::ERROR_CODE_OVERFLOW) handle_overflow(i); metadata.error_code = uhd::rx_metadata_t::error_code_t(word0 & 0xf); //break to exit loop and store metadata below @@ -142,7 +142,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 +157,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 +216,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 +233,7 @@ namespace vrt_packet_handler{ tick_rate, vrt_unpacker, get_recv_buffs, - handle_overrun, + handle_overflow, vrt_header_offset_words32 ); } @@ -253,7 +253,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 1947fdf00..455a30b47 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -44,7 +44,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::make(100/*messages deep*/)) { /* NOP */ } @@ -69,6 +70,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::sptr async_msg_fifo; size_t recv_timeout_ms; }; @@ -94,18 +96,34 @@ 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(), if_packet_info); + const boost::uint32_t *vrt_hdr = buff->cast(); + vrt::if_hdr_unpack_be(vrt_hdr, if_packet_info); - //handle a tx async report message (TODO forward 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){ - std::cerr << "U"; + const boost::uint32_t *vrt_data = vrt_hdr + if_packet_info.num_header_words32; + //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]); + + //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 = uhd::async_metadata_t::event_code_t(word0 & 0xf); + + //print the famous U, and push the metadata into the message queue + if (metadata.event_code == async_metadata_t::EVENT_CODE_UNDERFLOW) 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; @@ -156,6 +174,18 @@ void usrp2_impl::io_init(void){ std::cout << "Recv pirate num frames: " << num_frames << std::endl; } +/*********************************************************************** + * 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 **********************************************************************/ 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 -- cgit v1.2.3 From 19c15883a9054727c13f4eb5471cc961fe54c40d Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 21 Jul 2010 19:34:29 -0700 Subject: usrp2: added async event types, and common code for handling context words --- host/include/uhd/types/metadata.hpp | 6 +++++- host/lib/transport/vrt_packet_handler.hpp | 19 +++++++++++++------ host/lib/usrp/usrp2/io_impl.cpp | 5 +---- 3 files changed, 19 insertions(+), 11 deletions(-) (limited to 'host/lib/usrp/usrp2') diff --git a/host/include/uhd/types/metadata.hpp b/host/include/uhd/types/metadata.hpp index 43ddf875f..65952941c 100644 --- a/host/include/uhd/types/metadata.hpp +++ b/host/include/uhd/types/metadata.hpp @@ -134,12 +134,16 @@ namespace uhd{ * - underflow: an internal send buffer has emptied * - sequence error: packet loss between host and device * - time error: packet had time that was late (or too early) + * - underflow in packet: underflow occurred inside a packet + * - sequence error in burst: packet loss within a burst */ enum event_code_t { EVENT_CODE_SUCCESS = 0x1, EVENT_CODE_UNDERFLOW = 0x2, EVENT_CODE_SEQ_ERROR = 0x4, - EVENT_CODE_TIME_ERROR = 0x8 + EVENT_CODE_TIME_ERROR = 0x8, + EVENT_CODE_UNDERFLOW_IN_PACKET = 0x10, + EVENT_CODE_SEQ_ERROR_IN_BURST = 0x20 } event_code; }; diff --git a/host/lib/transport/vrt_packet_handler.hpp b/host/lib/transport/vrt_packet_handler.hpp index 3eddcec6d..0cc5eef76 100644 --- a/host/lib/transport/vrt_packet_handler.hpp +++ b/host/lib/transport/vrt_packet_handler.hpp @@ -35,6 +35,16 @@ namespace vrt_packet_handler{ +template 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 **********************************************************************/ @@ -92,22 +102,19 @@ namespace vrt_packet_handler{ const boost::uint32_t *vrt_hdr = state.managed_buffs[i]->cast() + 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_OVERFLOW) handle_overflow(i); - metadata.error_code = uhd::rx_metadata_t::error_code_t(word0 & 0xf); + metadata.error_code = get_context_code(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(vrt_data); + state.copy_buffs[i] = reinterpret_cast(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); diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index 455a30b47..9a7f34531 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -101,9 +101,6 @@ void usrp2_impl::io_impl::recv_pirate_loop( //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){ - const boost::uint32_t *vrt_data = vrt_hdr + if_packet_info.num_header_words32; - //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]); //fill in the async metadata async_metadata_t metadata; @@ -112,7 +109,7 @@ void usrp2_impl::io_impl::recv_pirate_loop( 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 = uhd::async_metadata_t::event_code_t(word0 & 0xf); + metadata.event_code = vrt_packet_handler::get_context_code(vrt_hdr, if_packet_info); //print the famous U, and push the metadata into the message queue if (metadata.event_code == async_metadata_t::EVENT_CODE_UNDERFLOW) std::cerr << "U"; -- cgit v1.2.3