matwey / libopenvizsla

Host applications for OpenVizsla USB tool

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Rework ov_capture_stop()

matwey opened this issue · comments

@desowin while I agree with your proposal. There are questions:

  • Can we guarantee that HF0_LAST is always exists even there are no sniffed packets?
  • Are the packets sent atomically? I mean can we expect that the response to CSTREAM_CFG=0 won't send in the middle of some capture packet?

Can we guarantee that HF0_LAST is always exists even there are no sniffed packets?

Yes. Both the HF0_FIRST at beginning and HF0_LAST at the end are generated regardless of there being any actual USB packets.

Are the packets sent atomically? I mean can we expect that the response to CSTREAM_CFG=0 won't send in the middle of some capture packet?

All Producer packets are serialized so there is no problem with "response" appearing in middle of capture packet. If there is packet being captured at the time during which CSTREAM_CFG is written 0, the packet will be fully processed and only then the HF0_LAST packet will be generated.

While I don't fully understand the CmdProc yet, it seems that libopenvizsla does not really handle the interleaved traffic on FTDI channel A. Looking at gateware source it seems that both command responses and streaming data appears on the same FTDI channel. The streaming data is wrapped in 0xD0 burst blocks - the burst blocks encapsulate 0xA0 packets stream. However, when the register is written, ftdi read is performed directly and it can effectively discard burst block data leading to data loss and stream synchronization issues. It seems that the command response processing should really be handled within frame_decoder_proc, but that requires quite some rework...

I mean can we expect that the response to CSTREAM_CFG=0 won't send in the middle of some capture packet?

After looking closer at the stream the answer to this question is both yes and no. The 0xA0 packets are serialized (so HF0_LAST is always the last 0xA0 packet in the packet stream) but register writes are interleaved with the packets stream. If the register write happens during capture, then the response to it can appear in between any 0xD0 burst blocks.

There seem to be two issues on gateware side:

  • If 0xA0 packet stream length is odd, the last byte will hang
  • If the packet stream length is not multiple of host burst length (32) then the data won't be sent even if stream is stopped

Both are quite annoying, but are not really showstoppers for reworking the stream interleaving on host side. A very simple testcase would be to just keep changing CSTREAM_CFG between 0 and 1 with some meaningful delay (1 s would be plenty). Ideally for each 0->1 there should be matching HF0_FIRST and for each 1->0 there should be HF0_LAST. With current gateware the two above mentioned issues will be observed but doing enough CSTREAM_CFG writes (or having actual USB packets) will advance the stream further.

Indeed. I assumed that we do sync exchange (settings parameters, etc.) or do async capture. This is because I've initially found the protocol was very complicated to gracefully handle sync during async. I propose to left it as is and fix stopping the capture (transition from async to sync).

There is no sync exchange really - all incoming data is async. I don't think it is possible to fix stopping the capture without making register writes async (well, the write itself will happen when you send the command, the async part is related to the response that is interleaved on multiplexed channel).

If the user agrees to discard the async data when ov_capture_stop() is called, then the function behavior could be as the follows:

  • Write CSTREAM_CFG=0
  • Continue parsing incoming stream (we expect both burst blocks and register write ack).
  • Discard all burst blocks until HF0_LAST
  • Write SINK_GO=0 and friends.

Alternatively, we could discontinue ov_capture_stop() function and rework ov_capture_dispatch() to stop the capture at the exit. In this case we could expect command from the user handler:

typedef int (*ov_packet_decoder_callback)(struct ov_packet*, void*);

where int = 0 means continuing capture, and int = 1 means that the callback wants to stop the capture.

Why discard? I think it is up to the user to discard the data, the library should only allow requesting capture stop. The point is that regardless how many packets there are in SDRAM, when you send CSTREAM_CFG to 0 there won't be any packets that were on the bus after the 1 to 0 transition regardless when you receive the status confirmation for the CSTREAM_CFG. The write is in effect just a few clock cycles after the command appears on FTDI USB endpoint, so the delay could be considered negligible.

Both gateware issues related to data trapping are now fixed in #30. I only added the filler handling (effectively skipping it) in decoder, to get restart properly working the host software would need to be updated (stop order and asynchronous register status handling).

There are infinitely many USB packets at the wire, as well as Ethernet frames for instance. So, we cannot catch them all in any case. The user provides required number of packets in ov_capture_dispatch() or uses -1 and subsequential ov_capture_breakloop() call to notify that no anymore data are required. This is why current implementation of cha_stop_stream() sets SDRAM_HOST_READ_GO to zero first. Of course there is a race condition which cha_stop_stream() is incapable to handle currently.

So, the point was that (unrelated to what comes first SDRAM_HOST_READ_GO=0 or CSTREAM_CFG=0) we must not bother user when ov_capture_dispatch() is not running anymore. He clearly stated that there is enough packets (either by setting appropriate count as an argument of ov_capture_dispatch() or by calling ov_capture_breakloop()).

So, the point was that (unrelated to what comes first SDRAM_HOST_READ_GO=0 or CSTREAM_CFG=0) we must not bother user when ov_capture_dispatch() is not running anymore. He clearly stated that there is enough packets (either by setting appropriate count as an argument of ov_capture_dispatch() or by calling ov_capture_breakloop()).

This is only one use case. Another use case is that user wants to have all the packets that were present on the bus within two specific points in time - the capture start and capture stop (both controlled by user). In this case, the user definitely wants the data that was buffered in SDRAM prior to user setting CSTREAM_CFG to 0.

This is only one use case. Another use case is that user wants to have all the packets that were present on the bus within two specific points in time - the capture start and capture stop (both controlled by user). In this case, the user definitely wants the data that was buffered in SDRAM prior to user setting CSTREAM_CFG to 0.

I would say that you are talking about "software triggers"...
Even though we don't have hardware triggers in OV3, it would be great to have generic interface for triggers. However, do you think that software triggers can be really useful? I mean that uncertainty of the triggering moment seems to be great.

I would say that you are talking about "software triggers"... Even though we don't have hardware triggers in OV3, it would be great to have generic interface for triggers. However, do you think that software triggers can be really useful? I mean that uncertainty of the triggering moment seems to be great.

The uncertainty of triggering moment ("software trigger") is relatively low. Delay from scheduling OUT URB to the packets arriving on bus is generally the biggest factor (for cases requiring manual user interaction this is completely negligible). FTDI takes very few clock cycles to process OUT DATA packets received on interface A (the OUT endpoint is generally idle during capture) and gateware prioritizes host writes on FTDI interface A (host is expected to be sensible and throttle the writes to not starve capture data stream from interface A bus access).

Even if the uncertainty was significantly higher, software trigger is still worthwhile. I stop the capture after the "bug under investigation" occurs - I would be really annoyed if the capture tool would discard any packets that were captured prior to capture stop, because those very last packets can make a difference in understanding the issue.

In general, capturing few extra packets (after the trigger) due to uncertainty is not a problem, but losing any packet prior to trigger is an issue.

I think I've finally got it. You need a point of synchronization.