[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Discuss-gnuradio] usrp_basic_rx::stop appears to take a long time,

From: Dave Gotwisner
Subject: Re: [Discuss-gnuradio] usrp_basic_rx::stop appears to take a long time, and reading after stop always returns > 0 bytes
Date: Tue, 29 May 2007 17:06:37 -0700
User-agent: Mozilla Thunderbird 1.0.7 (Windows/20050923)

Eric Blossom wrote:

On Fri, May 25, 2007 at 04:23:29PM -0700, Dave Gotwisner wrote:
I am working on an application that will tune to multiple frequencies,
and capture a small number of samples at each frequency for further

The program loop, is essentially, a series of configuration commands
(such as set_rx_frequency, etc.), followed by a start() command. I
then do read() until I get the requested number of samples. I then do
a stop(), and for the hell of it, loop on a read (until there is no

For the purpose of the test, I am using the default buffer sizes for
the ::make call (I also tried fusbBlockSize == 1024 and fusbNblocks =
8K). The decim rate used for the usrp_standard_rx constructor is 8. I
am trying to capture 100,000 samples at each frequency.
There's absolutely no reason to be using fusb_nblocks == 8192.
Try using fusb_block_size = 4096 and fusb_nblocks = 16
I tried it with 4K/16. I am now running at fusb_block_size = 16K and fusb_nblocks = 512. I also tried with 16K/16. Results for both are similar.

What I am observing is that it takes a very small fraction of a second
to get to my 100,000 samples (as expected), but when I do the stop(),
it is hanging in the stop() command for 8 seconds. Drilling down, into
the usrp_basic_rx::stop() command, we spend 6 seconds in
d_ephandle->stop(), where it is trying to free up 8189 URB requests
in fusb_devhandle::_cancel_pending_rqsts() [1 IOCTL per
USBDEVFS_DISCARDURB call] and 2 seconds in
fusb_devhandle_linux::_reap. A capture that takes approximately 1/16
of a second shouldn't then take 8 seconds closing itself out.
Changing to the larger block size significantly sped up the stop() call. I have now dropped (improved) to about 6 captures a second, instead of one every 8 seconds. The increased block size apparently decreased the URB release overhead significantly.

The second observation, is that I loop forever (30 minutes before I
gave up) after doing the stop, where read() is still returning data
(valid or not, I don't know). I would expect that stop() should flush
any data, or at least, prevent any new data from coming into the
system, but this doesn't appear to be the case. Given my application,
I must tie the data for each sample to a specific frequency, so
guaranteeing that the first (through last) reads for any tuning
operation all apply to that tuning operation.
Reading the documentation for the usrp_standard_rx class's start() and stop() commands indicate they are to start and stop data transfers. The read after stop returning forever was my mistake. I am used to read() returning a size_t. The problem is, size_t is unsigned, and the usrp read returns -1 (or in unsigned land, a very large number). Changing from size_t to int fixed this problem.

Is something broke, or (as is more likely the case), am I missing
something? Is anyone else trying to use libusrp in a similar manner?

In the GNU Radio code, which you don't appear to be using, we have gnuradio-examples/python/usrp/usrp_spectrum_sense.py, which does
something similar to what you are doing.
I looked at the example, and if my understanding of the code is right, you never stop getting data from the USRP (or shut it off). You change the frequency, and suck samples for a fixed period of time (throwing them out [basically, the amount of time it would take to flush the old data through the USB buffering system]) before capturing again (and using them). Does my usrp_spectrum_sense.py understanding match reality? I am not really a Python person. It seems to me that an efficient start/stop implementation would be more effective than having to read data that you never need.

In our case, we want to walk a large frequency range, capturing data for approximately 100 - 200 milliseconds per frequency, and would prefer to have less than 50 milliseconds of overhead between captures. We also need to do this on a potentially loaded CPU, so we need large enough buffering to reduce the likelyhood of us overrunning (assuming other tasks, such as games or other CPU hogs want much of the available CPU resources). The amount of CPU resource we need should be out of the available CPU after other things run, rather than as the highest priority task. From calculations based upon your proposed buffering, I get (4096*16)/32 MB/s) = ~2 milliseconds of buffering, we feel we need a minimum of about 50 milliseconds of buffering, hence the large numbers for fusb_block_size.

FYI, I tried building the trunk code on my ubuntu box, and when I did the "./configure" command, it reported problems finding guile. If I look at the packages on my machine, synaptic reports that guile 1.6.7-2 is installed on the machine, which should match the requirements from the readme file.


reply via email to

[Prev in Thread] Current Thread [Next in Thread]