Thread A is sampling a 32 bit buffered 4 bit port and sending the data to thread B.
Thread B receives the data, unzips after receiving every second word, checks for Start/End flags and stores data into an array if needed.
Another Thread C zips bytes and outputs data on a 4 bit port, feeding Thread A over a loopback.
On doing some testing, I realized that some of the values I sent have gone missing. On about 3 MHz clock frequency everything works well. Increasing the frequency will lead to data being lost (~50% loss at 10MHz).
With help of a logic analyzier I can confirm that Thread C is sending out data as intended, up to about 20MHz clock frequency.
The code for reading values from the ports should be okay, I don't think there is a problem here (or?):
Code: Select all
while(1){
[[ordered]] // both events may trigger at the same time, make sure we check transmission status first
select{
case portInfsync when pinseq(0x1) :> void @ uiTimestampSync:
if(uiBytesExpected){
uiBytesExpected += 2; // we expect two more bytes (= 1 more DSP word) for each frame sync
} else {
// if we were not expecting bytes, then trnsmission jsut started and we need to sync
portInData @ uiTimestampSync + 8 :> uiData; // data starting one bit after sync signal
rxServerProcessing_c <: uiData; // send to processing thread
uiBytesExpected += 1; // we expect one more byte
}
break;
case uiBytesExpected => portInData :> uiData : // Read a byte if more bytes are expected
rxServerProcessing_c <: uiData; // bytes should be aligned to fsync after first timed input
uiBytesExpected--;
break;
} // select
} // while
The processing thread looks like this:
Code: Select all
while(1){
select{
case rxServerProcessing_c :> uiRecData:
uifOddByteCount ^= 1;
uiaRecDataBuffer[uifOddByteCount] = uiRecData;
if (!uifOddByteCount) {
// UNZIP done here
...
// check for flags, store bytes to an array
...
} // if (!uifOddByteCount)
break;
} // select
} // while(1)
For testing, I sent values 0f 0..99.
Test result (bytes received/sent):
3,5 MHz: 100/100
4,2 MHz: 100/100
5,0 MHz: 88/100, first miss: byte 34
7,1 MHz: 64/100, first miss: byte 14
10 MHz: 50 /100, first miss: byte 10, Bytes in wrong order: 0 1 2 3 4 5 6 7 8 9 19 11 21 13 27 23 29 25 68 62
Im wondering what might be happening.
Streaming channels are asynchronous, are they buffered too? If yes, how much data can they hold? What happens if I send data to a streaming channel faster than the retrieving end can handle the input?
Do you see any problems on the approach for the data sampling thread?
Edit: I did some testing with gprof. As I use events to read data from the channel I hoping to see some wait time on low clock frequencies (hundreds of KHz), with the wait time approaching zero on increasing frequencies, when computing cannot keep up anymore. But I couldn't figure out any differences in the results. Does a read action on a streaming channel not wait for input data either? If not, what does it do if the code is meant to use data that has been read?
Edit2:
some time measurements revealed the problem:
Code: Select all
timer_ti :> uiTimeStart;
// UNZIP done here
...
// check for flags, store bytes to an array
...
timer_ti :> uiTimeEnd;
printf("z%u sc%u\n", (uiTimeZip - uiTimeStart),(uiTimeEnd - uiTimeZip));
lead to a compute time of 3.37us for 2x32 bit being received. On a 4 bit port that equals 16 clock cycles, so if I don't want to sample data faster than it can be computed,my clock frequency is limited to about 4,7 MHz.