How to early termination async read from FPGA

43 views
Skip to first unread message

Daniel Benitez

unread,
Sep 25, 2015, 3:39:38 PM9/25/15
to FPGALink Users
Hello,

First of all,  I want to congratulate Chris for this excellent tool. I had not been able to reach this phase of my project without it, so thank you very much for sharing this with us.

Right now, I am trying to read a 5MPixels OmniVision camera with a Raspberry PI using a Nexys2-500 FPGA board as interface. I use a python application in the Raspberry PI to read asynchronously (flReadChannelAsyncSumbit, flReadChannelAsyncWait) the RAW image through the USB port using a 32KB reading FIFO as a buffer into the FPGA, but sometimes the Raspberry PI is not able to keep the throughtput and loses some data pixels of the image. This causes that the python application freezes waiting for data indefinitely. I think this behavior could be logical taking in account that the camera is providing data at a speed of 25MB/s, and maybe sometimes the USB controller or the Raspberry PI are not able to keep the pacing, so I assume this. Nevertheless, I would need a way to implement an early termination of the reading operation, indicating to the python application that no more data are available from the reading FIFO into the FPGA board. I had thought about using a timeout from the python application, but maybe it would be a better solution if the FPGA could say to the Raspberry PI that no more data are available and close the communication channel.

I am a little lost about how exactly the early termination of a read operation can be implemented and the way that the FPGA tell the host that there is NO more data and close the communication channel. From what I can gather from the documentation, while a reading is being done through a channel, no other channel can be accessed, so I suppose that a second channel can not be used to handle the early termination. Please, could anyone tell me how exactly implement the early termination in the FPGA for a read operation?

I would really appreciate any help or hint.

Regards,

Daniel   

     

Peter Stuge

unread,
Sep 25, 2015, 4:11:16 PM9/25/15
to FPGALink Users
Daniel Benitez wrote:
> sometimes the Raspberry PI is not able to keep the throughtput

What you need to do is to submit multiple async USB transfers ahead
of time. These transfers go down to the USB host controller, which
will process them in order. Linux being a general-purpose OS will not
meet any of your deadlines except by accident, so you need to make
sure to take advantage of the hardware offloading that is available
with USB, by submitting multiple transfers to the host controller,
for it to carry out independently of any software.

So much for the USB layer. Based on nothing but the name of the
function, I guess that you can also submit multple FPGALink reads.
Try that.

You need to submit enough transfers to keep the bus busy for as long
as Linux needs to respond to host controller interrupts. At a very
minimum 10ms, but 100ms would be a lot better.


> I am a little lost about how exactly the early termination of a
> read operation can be implemented and the way that the FPGA tell
> the host that there is NO more data and close the communication
> channel.

A USB device can't close its communication channel; USB is completely
driven by the host.


> could anyone tell me how exactly implement the early termination in
> the FPGA for a read operation?

Again on USB level (sorry, I know that much better than I know FPGALink)
you'd use a separate (control or interrupt) endpoint for out-of-band
communication.


//Peter

Chris McClelland

unread,
Sep 26, 2015, 7:55:38 AM9/26/15
to fpgalin...@googlegroups.com

Last time I benchmarked the USB controller on the RPi, it maxed out at about 19MiB/s, and the ethernet port appeared to eat at least some of that too. So unless the RPi2 has better throughput, it will be tricky to get 25MiB/s without the FPGA being forced to drop pixels.

At least on Intel hardware, you can max out the USB host by submitting two requests for 64KiB chunks using the async API functions you mentioned, and ping-ponging them.

The FX2 micro on your Nexys2 does have a mechanism allowing the FPGA to request an early read termination (the "packet end" pin), but I have never got around to implementing it, and I don't know how it manifests on the USB side (but I trust Peter's opinion on that). So, at present there is no mechanism within FPGALink for doing early read terminations. Naturally, if you get it working, patches are welcome!

Chris

--
You received this message because you are subscribed to the "FPGALink Users" mailgroup (see https://github.com/makestuff/libfpgalink/wiki/FPGALink).
 
To post to this group, send email to fpgalin...@googlegroups.com
To unsubscribe from this group, send email to
fpgalink-user...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/fpgalink-users?hl=en
---
You received this message because you are subscribed to the Google Groups "FPGALink Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to fpgalink-user...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Daniel Benitez

unread,
Sep 28, 2015, 3:36:52 AM9/28/15
to FPGALink Users
Hello Chris,

Thank you very much for your reply. They have been of great help to clarify the situation.

I have tested the same python application in a host PC with Windows 7 OS and a Raspberry PI Model B+, and Chris is right that the throughtput in the Raspberry PI is lower, because I only get two of ten RAW images correctly, while I get five of ten RAW images when they are taken using the Windows 7 PC.

I will investigate the option to use the packet end pin, but as Peter suggests, maybe the quickly solution would be to implement a separate early-termination operation from the Raspberry Pi, like a timeout or a pin connected between the Raspberry and the FPGA to indicate this situation.

Thanks again and regards,

Daniel

Daniel Benitez

unread,
Sep 28, 2015, 3:49:13 AM9/28/15
to FPGALink Users
Hello Peter,

You are totally right in the way the USB controller works. I got the maximum throuhput using two async submit (flReadChannelAsyncSubmit) of 64KiB to keep the USB bus busy. When I use other reading configuration or chuck size, the reading FIFO in not able to keep the pacing and part of the image is lost.

I was afraid that there woulld be no way to implement a early termination from the FPGA side, but now that you have confirmed it, I think I will try to implement a timeout or other interrupt mechanism from the host side.

Thank you very much for your reply and help.

Regards,

Daniel

Sumit Chaturvedi

unread,
Mar 23, 2018, 4:10:14 PM3/23/18
to FPGALink Users
Hello! I have a similar issue so I thought it best to post over here. If this is the wrong place, I'm sorry. In an assignment, I'm required to read on multiple channels of my Xilinx Altera. Some of these channels may never have data written on them. In this case, when I call flReadChannelAsyncAwait (after a call to flReadChannelAsyncSubmit), the terminal freezes. Is there any way I can find out if something is not being written to a channel. Thanks :)

Chris McClelland

unread,
Mar 24, 2018, 10:10:23 AM3/24/18
to fpgalin...@googlegroups.com
You could dedicate one channel to providing "data-available" notifications for a group of other channels. For example, you could have channel 8 return bytes that represent the state of the valid signals for channels 0-7. So you sit there in a tight loop reading channel 8, and when you get a nonzero byte you know you need to start reading from the channels indicating data-ready by the bits that are set in the byte from channel 8. That works well if you have many separate channels to read from, but you don't care too much about latency (or have large enough FIFOs inside the FPGA that the read latency doesn't matter). Or if you have a bunch of FIFOs you could designate odd-numbered channels to return the FIFO depths of the corresponding even-numbered channels.

Another possibility (if speed is an issue) is to multiplex many "virtual" channels over one "physical" channel (i.e implement a higher-level protocol in the application layer). For example, you could have a protocol like this:

Byte 0 - message channel (0-254)
Byte 1 - message length (0-255, with 0 representing 256)
Byte 2...N - message payload

Designating 1-255 as virtual channels means you can set aside 255 for a "heartbeat". You can make a counter inside the FPGA which is zero'd whenever a message is sent, and which sends a "heartbeat" when it overflows. So, you end up with a datastream which looks like this:

255  # heartbeat
255  # heartbeat
255  # heartbeat
255  # heartbeat
19, 4, 0xC0, 0xDE, 0xFA, 0xCE  # 0xC0DEFACE on channel 19
255  # heartbeat
255  # heartbeat
23, 2, 0xCA, 0xFE  # 0xCAFE on channel 23
255  # heartbeat
255  # heartbeat
255  # heartbeat
42, 0, 0xF4, 0x0D, 0x1F, 0xEF, 0x74, 0xBB, 0x4E, 0x68, 0x09, 0xF6, 0xCE, 0xBA, 0xD7, 0x08, 0xDB, 0x0A, 0xB9, 0x09, 0x79, 0x00, 0x35, 0xD2, 0xDF, 0x3D, 0x5D, 0x4E, 0xAC, 0x63, 0xC2, 0xCB, 0xC3, 0xA8, 0x59, 0x59, 0x15, 0xE1, 0xF2, 0xF7, 0x56, 0x75, 0x2D, 0x23, 0xA4, 0xAB, 0x03, 0x70, 0xEA, 0x47, 0x0E, 0x18, 0xEA, 0x2B, 0x82, 0xEA, 0x74, 0xF0, 0xEE, 0xAE, 0x0C, 0x29, 0xF5, 0x8B, 0x5D, 0xAB, 0x9C, 0x51, 0x5C, 0x6E, 0x56, 0x40, 0xD2, 0x94, 0x33, 0x3E, 0x3E, 0x7F, 0xBE, 0xC4, 0xF1, 0x19, 0xCB, 0x55, 0xE4, 0x60, 0x69, 0xEF, 0x55, 0x34, 0xE2, 0x60, 0x7F, 0x51, 0xDE, 0x6C, 0xD7, 0x4D, 0x54, 0xA1, 0x70, 0x82, 0xE0, 0x47, 0xFE, 0xE9, 0xB7, 0xB3, 0x4D, 0x9A, 0x2F, 0x8C, 0xD9, 0x2D, 0xBD, 0xA6, 0x1A, 0x64, 0x1D, 0xF9, 0x98, 0x59, 0x48, 0x70, 0xF9, 0x06, 0x7F, 0x5B, 0xC7, 0x03, 0xFF, 0xE4, 0x01, 0x98, 0xF1, 0x5C, 0x59, 0xD7, 0x4F, 0x67, 0x5F, 0xA9, 0x2A, 0x6B, 0x97, 0xE7, 0x47, 0x67, 0x06, 0x41, 0x2E, 0x10, 0xAB, 0x55, 0x65, 0xA7, 0x42, 0x53, 0xD3, 0xD2, 0x88, 0xB6, 0xF7, 0x9C, 0x6D, 0xBB, 0x05, 0x81, 0xAF, 0xF6, 0x8A, 0x31, 0x07, 0x08, 0x22, 0xA9, 0x6B, 0xF5, 0xC5, 0x68, 0x14, 0xDA, 0x40, 0x8F, 0x0F, 0x02, 0x77, 0x58, 0x4A, 0xBC, 0xC4, 0x06, 0x24, 0x4C, 0x77, 0xC0, 0xB1, 0x1B, 0xEC, 0xBF, 0x74, 0xB1, 0x0C, 0xF0, 0x24, 0x22, 0x24, 0xE3, 0xDD, 0x76, 0x3B, 0x2C, 0xA1, 0x47, 0x13, 0x23, 0xF1, 0x03, 0xFF, 0x78, 0xFA, 0xBE, 0x8E, 0x1D, 0xC2, 0x57, 0x64, 0x10, 0xE1, 0x2E, 0xB9, 0x47, 0x0A, 0xF5, 0xE1, 0x0A, 0xB8, 0x68, 0xFB, 0x18, 0x7E, 0x35, 0xA5, 0x1E, 0xF2, 0x26, 0x0C, 0x67, 0x23, 0x09, 0x58, 0x70, 0xE3, 0xAF, 0xCA, 0x23, 0xC8, 0x8E  # 256 bytes on channel 42
255  # heartbeat
255  # heartbeat

So, you can make your software sit in a loop reading blocks of data, and demultiplexing the messages on the channels. If no "real" data is being produced, you'll just get a long sequence of heartbeats, which you can discard. But that means the software will never hang. If you get such an arrangement working, it could be made generic and contributed back to the FPGALink project if you wish, so others facing a similar problem may benefit from your work.

Chris





To post to this group, send email to fpgalink-users@googlegroups.com

To unsubscribe from this group, send email to

For more options, visit this group at
http://groups.google.com/group/fpgalink-users?hl=en
---
You received this message because you are subscribed to the Google Groups "FPGALink Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to fpgalink-users+unsubscribe@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages