Hi all and Josh,
What I want to do is to control the streaming from the USRP by my own
python code.
usrp_source provides the start() and the stop() to control the streaming
by
issuing the command to USRP.
However, when I try to use them in my python code, lots of problems
block
me.
As my observation, when the flow graph is started, the gr_block.start()
is
actually called automatically. And the streaming is started right after
the
tb.start(). I want the streaming to be held until I explicitly call the
usrp_source.start(). So I firstly tried usrp_source.stop() firstly as
below:
tb.start() # start flow graph self.source.u.stop() time.sleep(10) # wait 10 seconds to start the streaming tb.source.u.start()
But the flow graph exits instantly at the stop(), as the
usrp_source.work()
will return WORK_DONE due to the streaming timeout (see
gr_uhd_usrp_source.cc).
Thus, I decide to change the code in gr_uhd_usrp_source.cc as below:
- When the usrp_source.start() is firstly called by the
constructor of gr_block_executor,
I hold the streaming command. So the streaming will not be started
when
tb.start().
- When usrp_source.start() is called in the second times, the
streaming
command is really issued to USRP. Code is like this:
bool start(void){ #ifdef GR_UHD_USE_STREAM_API _rx_stream = _dev->get_rx_stream(_stream_args); _samps_per_packet = _rx_stream->get_max_num_samps(); #endif // alex: need to wait the demand to start the streaming // Note, start is firstly called by the gr_block_executor
constructor
_start_count++; //update the _start_count to enbale the next
start
streaming.
if (_start_on_demand == true && _start_count == 1){
return true; //First time called, not streaming
}
In gr_uhd_usrp_source::work(), if ERROR_CODE_TIMEOUT is reported,
the code will try more instead of returning WORK_DONE:
case uhd::rx_metadata_t::ERROR_CODE_TIMEOUT:
//Assume that the user called stop() on the flow graph.
//However, a timeout can occur under error conditions.
if (_start_on_demand == true)
//Start is first called by the gr_block_executor
//We are still waiting for the mannual start command
return work(noutput_items, input_items, output_items);
return WORK_DONE;
Unfortunately, although the new code passes the build, the behavior is
still strange, for below python code:
tb.start() # start flow graph
time.sleep(10) # wait 10 seconds to start the streaming
tb.source.u.start()
Now the streaming is not started when tb.start() is called in the
beginning. But when 10 seconds sleep ends, the flow graph crashes by
reporting: “***glibc detected *** python: corrupted double-linked list:
0x00007fcb640011c0”, apparently on calling the
usrp_source.start() manually. I seems some memory issue happens, but in
usrp_source.start(), it just tries send a command to USRP.
I suppose the streaming start and stop should be used easily but not
know
why such kind of problem happens.
Still debugging it, any comments are appreciated.
–
Alex,
Dreams can come true just believe.