Hi Marcus, Robin,
I've set the tx_metadata, yet the issue still occurs. There are constant
streams of underruns when receiving and transmitting on the same channel.
I've attached the code
________________________________
From: USRP-users <[email protected]> on behalf of Marcus D.
Leech via USRP-users <[email protected]>
Sent: Monday, August 14, 2017 11:32:21 AM
To: [email protected]
Subject: Re: [USRP-users] Buffer underrun issue with simultaneous transmit and
receive on the X310
On 08/14/2017 02:27 PM, Jason W Zheng via USRP-users wrote:
How should I set the tx metadata? My application will essentially stream
continuously.
Thanks,
Jason
>From the tx_samples_from_file example code (which you should probably study)
uhd::tx_metadata_t md;
md.start_of_burst = false;
md.end_of_burst = false;
________________________________
From: ROBIN TORTORA <[email protected]><mailto:[email protected]>
Sent: Monday, August 14, 2017 11:17:07 AM
To: Jason W Zheng via USRP-users; Jason W Zheng
Subject: Re: [USRP-users] Buffer underrun issue with simultaneous transmit and
receive on the X310
I dont see you setting the tx metadata object members to any values, so you are
essentially going to tx with default metadata IF there is a constructor that
initializes all the members to a consistent value...
On August 14, 2017 at 1:56 PM Jason W Zheng via USRP-users
<[email protected]><mailto:[email protected]> wrote:
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
<[email protected]><mailto:[email protected]>
on behalf of Jason W Zheng via USRP-users
<[email protected]><mailto:[email protected]>
Sent: Monday, August 7, 2017 1:05:05 PM
To: [email protected]<mailto:[email protected]>
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
_______________________________________________
USRP-users mailing list
[email protected]<mailto:[email protected]>
http://lists.ettus.com/mailman/listinfo/usrp-users_lists.ettus.com
_______________________________________________
USRP-users mailing list
[email protected]<mailto:[email protected]>
http://lists.ettus.com/mailman/listinfo/usrp-users_lists.ettus.com
// // 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, uhd::tx_metadata_t
md);
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];
uhd::tx_metadata_t md;
md.start_of_burst = true;
md.end_of_burst = false;
md.has_time_spec = true;
md.time_spec = uhd::time_spec_t(0.1);
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],md);
}
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;
md.start_of_burst = false;
md.has_time_spec = false;
}
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
[email protected]
http://lists.ettus.com/mailman/listinfo/usrp-users_lists.ettus.com