Since I haven't gotten a response in a week, I thought some source code might help. I've removed any buffer dependencies leaving just the receive thread and transmit thread. The receive thread is constant receiving to a buffer, while the transmit thread is constantly transmitting 0s from another buffer.
On the x310, when I receive and transmit from the same channel (same daughterboard), I get underflows (U's on the console), no matter what the rate. When I put receive and transmit on separate channels, the U's go away. How do I fix my source code so I can receive and transmit from the same channel without underflows? Thanks, Jason ________________________________ From: USRP-users <usrp-users-boun...@lists.ettus.com> on behalf of Jason W Zheng via USRP-users <usrp-users@lists.ettus.com> Sent: Monday, August 7, 2017 1:05:05 PM To: usrp-users@lists.ettus.com Subject: [USRP-users] Buffer underrun issue with simultaneous transmit and receive on the X310 Hi, I'm building an application where I receive data from the x310, process the data, then transmit it out. I have 3 separate threads running, one for each task. The receive task is constantly receiving data from the x310 at 200MS/s and putting it into a buffer. The process task takes data from the receive buffer, processes it, and puts it into a transmit buffer. The transmit task is constantly transmitting data from the transmit buffer at 12.5 MS/s. I get constant underruns (U's on the console) when I try to receive and transmit from the same channel on the x310. However, when I transmit and receive on separate channels, underruns no longer occur. I would like to figure out a solution to this problem as I want to processes two 200MS/s streams on 1 x310. This problem occurs no matter the sample rates. I've tried lowering the receive rate to 50MS/s (while transmitting 4x the data to balance things out) and there are still constant underruns though at a lower rate. I know processing time is not the issue as I've profiled the time it takes to process, and I have even removed the processing task from the application altogether (receive data to a buffer and do nothing with the data; constantly transmit 0's from the transmit buffer) and the underruns still occur. I'm running on UHD 3.11.0, and the x310 is is configured with basic TX/RX daughterboards and flashed with the XG image for use over two 10 gig ethernet links. Thanks, Jason
// // CUDA runtime // #include <cuda_runtime.h> // // helper functions and utilities to work with CUDA // #include <helper_cuda.h> // #include <helper_functions.h> #include <iostream> #include <fstream> #include <iomanip> #include <stdlib.h> #include <vector> #include <csignal> #include <boost/date_time.hpp> #include <boost/thread/thread.hpp> #include <thread> //#include <unistd.h> #include <time.h> #include <uhd/utils/thread_priority.hpp> #include <uhd/utils/safe_main.hpp> #include <uhd/usrp/multi_usrp.hpp> #include <uhd/types/tune_request.hpp> typedef std::complex<short> Complex; // Constants and signal variables static bool stop_signal_called = false; const int NUM_CHANNELS = 1; const int BUFF_SIZE = 64000; //function prototypes here void recvTask(Complex *buff, uhd::rx_streamer::sptr rx_stream); void txTask(Complex *buff, uhd::tx_streamer::sptr tx_stream); void sig_int_handler(int){ std::cout << "Interrupt Signal Received" << std::endl; stop_signal_called = true; } int UHD_SAFE_MAIN(int argc, char *argv[]) { uhd::set_thread_priority_safe(); //type=x300,addr=192.168.30.2,second_addr=192.168.40.2 std::cout << std::endl; std::cout << boost::format("Creating the usrp device") << std::endl; uhd::usrp::multi_usrp::sptr usrp = uhd::usrp::multi_usrp::make(std::string("type=x300,addr=192.168.30.2,second_addr=192.168.40.2")); std::cout << std::endl; //set stream args uhd::stream_args_t stream_args("sc16"); double samp_rate_tx = 100e6; double samp_rate_rx = 100e6; uhd::tune_request_t tune_request(0); //Lock mboard clocks usrp->set_clock_source(std::string("internal")); //set rx parameters usrp->set_rx_rate(samp_rate_rx); usrp->set_rx_freq(tune_request); usrp->set_rx_gain(0); //set tx parameters usrp->set_tx_rate(samp_rate_tx); usrp->set_tx_freq(tune_request); usrp->set_tx_gain(0); std::signal(SIGINT, &sig_int_handler); std::cout << "Press Ctrl + C to stop streaming..." << std::endl; //create buffers, 2 per channel (1 for tx, 1 for rx) // transmitting complex shorts -> typedef as Complex Complex *rx_buffs[NUM_CHANNELS]; Complex *tx_buffs[NUM_CHANNELS]; for (int i = 0; i < NUM_CHANNELS; i++){ rx_buffs[i] = new Complex[BUFF_SIZE]; tx_buffs[i] = new Complex[BUFF_SIZE]; // only transmitting 0's std::fill(tx_buffs[i], tx_buffs[i]+BUFF_SIZE, 0); } ////////////////////////////////////////////////////////////////////////////// ////////////////START RECEIVE AND TRANSMIT THREADS//////////////////////////// ////////////////////////////////////////////////////////////////////////////// printf("setting up threading\n"); usrp -> set_time_now(uhd::time_spec_t(0.0)); // set up RX streams and threads std::thread rx_threads[NUM_CHANNELS]; uhd::rx_streamer::sptr rx_streams[NUM_CHANNELS]; for (int i = 0; i < NUM_CHANNELS; i++){ stream_args.channels = std::vector<size_t>(1,i); rx_streams[i] = usrp->get_rx_stream(stream_args); //setup streaming auto stream_mode = uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS; uhd::stream_cmd_t stream_cmd(stream_mode); stream_cmd.num_samps = 0; stream_cmd.stream_now = true; stream_cmd.time_spec = uhd::time_spec_t(); rx_streams[i]->issue_stream_cmd(stream_cmd); //start rx thread std::cout << "Starting rx thread " << i << std::endl; rx_threads[i] = std::thread(recvTask,rx_buffs[i],rx_streams[i]); } // set up TX streams and threads std::thread tx_threads[NUM_CHANNELS]; uhd::tx_streamer::sptr tx_streams[NUM_CHANNELS]; for (int i = 0; i < NUM_CHANNELS; i++){ stream_args.channels = std::vector<size_t>(1,i); tx_streams[i] = usrp->get_tx_stream(stream_args); //start the thread std::cout << "Starting tx thread " << i << std::endl; tx_threads[i] = std::thread(txTask,tx_buffs[i],tx_streams[i]); } printf("Waiting to join threads\n"); for (int i = 0; i < NUM_CHANNELS; i++){ //join threads tx_threads[i].join(); rx_threads[i].join(); } return EXIT_SUCCESS; } void recvTask(Complex *buff, uhd::rx_streamer::sptr rx_stream){ uhd::rx_metadata_t md; size_t num_acc_samps = 0; size_t amount_received = 0; unsigned overflows = 0; struct timespec start_time; clock_gettime(CLOCK_MONOTONIC, &start_time); while(!stop_signal_called){ amount_received = rx_stream->recv(buff,BUFF_SIZE,md,3.0); if (amount_received != BUFF_SIZE){ printf("receive not equal\n");} //handle the error codes switch(md.error_code){ case uhd::rx_metadata_t::ERROR_CODE_NONE: break; case uhd::rx_metadata_t::ERROR_CODE_TIMEOUT: std::cerr << "T"; continue; case uhd::rx_metadata_t::ERROR_CODE_OVERFLOW: overflows++; std::cerr << "Got an Overflow Indication" << std::endl; continue; default: std::cout << boost::format( "Got error code 0x%x, exiting loop..." ) % md.error_code << std::endl; goto done_loop; } num_acc_samps += amount_received; } done_loop: // tell receive to stop streaming auto stream_cmd = uhd::stream_cmd_t(uhd::stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS); rx_stream->issue_stream_cmd(stream_cmd); struct timespec end_time; clock_gettime(CLOCK_MONOTONIC, &end_time); double runtime = (end_time.tv_sec - start_time.tv_sec) + (end_time.tv_nsec - start_time.tv_nsec ) / 1000000000.0; std::cout << std::endl << "Received " << num_acc_samps << " samples in " << runtime << "s" << " Throughput = " << num_acc_samps / 1e6 /runtime << " Msps" << std::endl; //finished std::cout << "Overflows=" << overflows << std::endl << std::endl; } void txTask(Complex *buff, uhd::tx_streamer::sptr tx_stream){ uhd::tx_metadata_t md; size_t num_acc_samps = 0; struct timespec start_time; clock_gettime(CLOCK_MONOTONIC, &start_time); while(!stop_signal_called){ size_t samples_sent = tx_stream->send(buff,BUFF_SIZE,md); num_acc_samps += samples_sent; } struct timespec end_time; clock_gettime(CLOCK_MONOTONIC, &end_time); double runtime = (end_time.tv_sec - start_time.tv_sec) + (end_time.tv_nsec - start_time.tv_nsec ) / 1000000000.0; std::cout << std::endl << "Sent " << num_acc_samps << " samples in " << runtime << "s" << " Throughput = " << num_acc_samps / 1e6 /runtime << " Msps" << std::endl; //send a mini EOB packet // md.end_of_burst = true; // tx_stream -> send("",0,md); printf("End transmit \n"); }
_______________________________________________ USRP-users mailing list USRP-users@lists.ettus.com http://lists.ettus.com/mailman/listinfo/usrp-users_lists.ettus.com