usrp x310 full duplex: receiving flowgraph can cause underflow issue at transmitter side - gnuradio

we are using one usrp x310 with two UBX 160 in a full duplex mode (one ubx for transmitting and the second one for receiving, with a 10G connection). In the code, two separate TX and RX flowgraphs are established (under a single process).
top_block:
self.txpath = tx_hier(...)
self.rxpath = rx_hier(...)
self.source = uhd_receiver(...) # set up usrp, subdev: A:0
self.sink = uhd_transmitter(...) # set up usrp, subdev B:0
self.connect(self.source, self.rxpath)
self.connect(self.txpath, self.sink)
However, in the actual test, we found that once RX flowgraph is busy at processing data, the transmitter will suffer from severe underflow problem while sending packets. Sample rate is just 5Msps, using TX flowgraph alone will not have underflow and RX flowgraph alone no overflow either under the same sample rate.
Since these two flowgraphs are separate, and that gnuradio will assign one thread to one block, it seems to me that processing data should not have impact at transmitting (independent). I am wondering how could this happen. I tried to use gr::hier_blocks::set_processor_affinity to separate core resources also, but it didn't work. Maybe blocks at transmitter can't get the resource it needs while RX flowgraph is busy at processing?
Any explanations to this observation and any advice about how to tackle this will be greatly appreciated!

Related

STM32f103 HAL USB - UART bridge

I have a third party device that is UART programmable.
I need to create a USB - UART bridge with a functional password (programming only after entering the correct password)
generated the code using the latest version of STM32CubeMX for Atollic TrueSTUDIO for STM32 9.3.0 ...
I transfer data between USB and UART through a buffer (one for usb-uart, and another one for uart-usb)
when I try to transfer several characters everything is OK, but when I try to transfer a large data packet, problems start due to the fact that the USB speed is much higher than the UART ...
there are two questions:
1.How do I tell USB that I need to stop transferring data and wait until the UART (buffer) is busy
2.How on the side of the microcontroller to get the baud rate set on the PC (set when the terminal is connected to the virtual COM port)
USB provides flow control. That's what you need to implement. A general introduction can be found here:
https://medium.com/#manuel.bl/usb-for-microcontrollers-part-4-handling-large-amounts-of-data-f577565c4c7d
Basically, the setup for the USB-to-UART direction should be:
Indicate that the code is ready to receive a USB packet
Receive a USB packet
Indicate that you are no longer ready to receive a USB packet
Transmit the data via UART
Start over
Step 0: Initial setup
Call USBD_CDC_SetRxBuffer to set the buffer for receiving the USB data. Unless you use several buffers to achieve higher throughput, a single call at the start of the program is sufficient.
Step 1: Ready to receive data
Call USBD_CDC_ReceivePacket. Other than what the name implies, this function indicates that the app is ready to receive data. It immediately returns before the data has actually been received.
Step 2: Receive a USB packet
You don't need to do anything here. It will happen automatically. Once it's complete, CDC_Itf_Receive will be called.
Step 3: Indicate that you are no longer ready to receive a USB packet
Nothing to do here. This happens automatically whenever a packet has been received (and double buffering is not enabled).
Step 4: Transmit the data via UART
I guess you know how to do this. It's up to you whether you want to do it in a blocking fashion or using DMA.
Since a callback is involved, you cannot put this code into the main loop. It might be possible to put all code into CDC_Itf_Receive if blocking UART is used. It would appear in the order 2, 3, 4, 1. Additionally, initialization is needed (0 and 1).
In the UART-to-USB direction, you would need to implement flow control on the UART. The USB flow control is managed by the host. Even though USB is much faster than UART, flow control is relevant as the application on the host can process data as slow as it likes to.
Regarding question 2: I'm not sure I understand it... The microcontroller cannot set the baud rate on the host. Either the host can specify a baud rate (transmitted over USB and applied to UART), or if the UART has a fixed baud rate, you can ignore baud rate (any baud rate set on the host side will work as it does not apply to USB).

DMA_SxCR Enable bit unable to be written on stm32f412

I'm trying to start a DMA transfer on my stm32f412, and I've got everything set up to the point where I'm setting the control registers on the DMA channels/streams for TX and RX. I am able to set the enable (Bit 0) on the TX, but not the RX.
The datasheet has 3 options for the bit being cleared by hardware: 1.) On a DMA end of transfer (stream ready to be configured) 2.) If a transfer error occurs on the AHB master buses 3.) When the FIFO threshold on memory AHB port is not compatible with the size of the burst.
I don't think it could be the first or the third, because the DMA transfer hasn't even started yet, and there isn't a burst configured, it's just a single transfer. I'm not quite certain what the second means, but there aren't transfer errors marked in the error registers.
Any avenues to look into would be appreciated
Edit: Ugh, I was looking at the wrong registers for to find the DMA_LISR and _HISR. There was a transfer error on my RX channel.
From the description of DMA_SxCR_EN bit in the reference manual:
Note: Before setting EN bit to '1' to start a new transfer, the event flags corresponding to the
stream in DMA_LISR or DMA_HISR register must be cleared.
In my experience, these event flags include not only the error flags, but also the regular event flags like Transfer Complete or Half Transfer. In some cases, I also ended up clearing FIFO error flag, although I can't remember the reason behind it.
This problem manifests itself as "DMA works only once". In your case, it doesn't work even once, so there can be other problems. Still, I think it's worth trying to clear all the status flags before enabling the stream.

Constant carrier digital transmission in GNURadio with USRP

I'm trying to implement the UPLINK of a Ground Station controlling a small satellite. The idea is that the link should stay always active in between each transmitted telecommand. For this, I need to insert some DUMMY or IDLE sequence bytes such as 0xAA or similar.
I have found that some people already faced a similar issue and posted their questions here:
https://www.ruby-forum.com/t/constant-carrier-digital-transmission/163379
https://lists.gnu.org/archive/html/discuss-gnuradio/2016-08/msg00148.html
So far, the best I could achieve was to modify the EventStream Source block from https://github.com/osh/gr-eventstream in order to preload the vectors with my dummy sequence (i.e. 0xAA) instead of preloading them with zeroes. This is a general overview of the GNURadio graph I'm using:
GNURadio Flowgraph Picture
This solution however introduces a huge latency and the sent message does not appear at the output until a huge amount of time has expired (in the order of several seconds).
Is there a way of programming the USRP using GNURadio so that it constantly sends a fixed sequence which should only be interrupted when an incoming message is passed? I assume that the USRP has the ability of reading tagged streams in order to schedule transmissions. However, I'm not sure how to fit this in my specific application.
Thanks beforehand!
Joa
I believe this could be done using a TCP or UDP source block.
Your control information could be sent to the socket using TCP/UDP. GNU Radio would then collect and transmit the packets. Your master control program would then have to handle the IDLE stuffing but solving the problem external to GNU Radio is easier.
Your master control program would basically do the following:
1. tx control data as needed
2. if no control data ready before next packet must be sent send an IDLE packet

wavfile_sink: Value nan can not be represented in the target integer type

I have a couple of gnuradio apps that communicate across the internet. The flow graphs are rather complex, so I boiled them down to simplest form to re-create an issue I'm seeing.
The issue is that, when I invoke the client, it connects to the server as expected, but immediately throws an exception "Value nan can not be represented in the target integer type" and appears to be coming from the wavfile sink block.
I simplified the server down to a simple dial tone flow graph that presents the dial tone signal on a TCP port. The client can connect to that port and expect to receive the dialtone signal.
If I run the client and server on the same computer and connect using localhost, the client connects fine and works as expected. However if the client and server are separated at a distance (over the internet) then I receive the nan exception every time.
Theories:
Perhaps the client is starting up and not receiving data soon enough (connect time + 20ms latency) and the wavfile block is receiving NaN's from the socket PDU or stream to tagged stream block?
Perhaps the data is being mangled as it cross the internet in such a way that the packets aren't arriving as expected - fragmentation? I tried MTU 512 but the problem still exists. Trued MTU 10000: same result.
Maybe I'm overlooking a simple usage/syntax error when building my flowgraph
There's a bug in the wavfile sink and it should more gracefully handle the absence of data.
UPDATE 1:
Logged a bug report to gnuradio project https://github.com/gnuradio/gnuradio/issues/1763
UPDATE 2:
The socket PDU block seems to play a significant role. If I tweak the packet length parameter of the stream to tagged stream block, along with the MTU parameter of the socket PDU block, I can get either error free stream with dropped packets (low MTU) or a dead stream with NaN exception (high MTU).
Server Flowgraph
Client Flowgraph (XYZ.com is of course not my real IP)
wav result across the internet (20-100ms latency)
This wav file is 1k and is truncated probably at the same time as the exception but it's hard to tell for sure.
wav result across local interface (1ms or less latency)
Across the local interface the client runs happily until I stop it. Received signal is as expected.
One small thing - notice the glitchy initial first few samples? Not sure if this is a factor. Probably not. But the data is junk for the first 10ms or so even across local interface.

Having difficulty sending small lwip packets immediately using the lwip API

I am creating a server on a ST Cortex M3 device. I am using the lwip API and FreeRTOS. All is working, but the response time is way off. I am currently using lwip 1.3.2 and FreeRTOS 7.3.
A single client connects to the server and must have some time-critical data sent frequently. These packets are on the order of 6 or so bytes. Other times, I am sending upwards of 20K.
The problem I am having is that these smaller packets seem to be taking forever to be sent. I assume this is because lwip is waiting for more data to be enqueued to make more efficient transmissions. I cannot wait around for 2 or 3 seconds for the data to be sent; the client is expecting the data nominally in a few micro-seconds or milli-seconds.
I have tried using lwip_send and lwip_write. (I understand that one is the same as the other with a flag passed at the end. Just had to try...) I have tried setting TCP_NODELAY on the socket to no avail. I tried to set SO_SNDLOWAT to '1', but this always returned -1, so I do not think it is supported.
I do not want to redo all of my code using TCP RAW. Is there a way to invoke the tcp_output() function outside of TCP RAW mode? Is there any way to speed things up or is this just how slow lwip TCP with small packets is?
Any and all suggestions are welcome. Thanks.
--EDIT--
I would also like to add that once I am ready to transmit, I make sure that my TX task in FreeRTOS is at the highest priority. There are no other tasks running up to the point at which I call lwip_send/write.
I'm fairly experienced with bare metal lwIP on xilinx and lwip does not wait to send things out. It will pump packets out as fast as your interrupts are acknowledged based on the ethernet hardware. I've been using UDP only. What is coming to mind though, is your problem might be on the receive end. If you are doing TCP, maybe those small packets are coming out late because you are having receive issues. What you need to do is find in the code the lowest level point at which ethernet is transmit, put a general purpose output toggle on that. Then also put a general purpose output toggle on when a ethernet packet is received. Look at the signals on a scope. If it confirms your hypothesis, then move the output toggles around to narrow down the issue. Wash, rinse and repeat until you are down to where the issue its. It's crude and time consuming, but oftentimes this brute force approach solves many "impossible" embedded software problems, due to pure determination. Good luck!