Imagine you are feeding a DAC a nice waveform at 10 mhz and cannot pause to go read channel data to fill up your buffer and then continue with your fast output loop. Such an act would glitch the output data.
Also imagine that there is a pipe into the XCORE serving a bunch of other things going on (interleaved data), and if the thread servicing this incoming pipe of data had to spend its days filling a channel, it couldn't do much else. And it too would have a gap as it had to go get more data.
This is the old FPGA problem of clock domains. Usually it gets solved with a fifo. If we had xcore fifo resources we'd just do:
Code: Select all
thread 1:
loop
fifo <: 8 bit port of data bursty at 50 mhz
thread 2:
fifo :> DAC at 20 mhz
In any case I did wind up solving this issue by writing double buffered "endpoint" objects. The basic use is:
Code: Select all
thread 1:
write_dbuff( data ) ;
thread 2:
read_dbuff( data);
Anyone solve this with similar constructs, or even better-- with XCORE/XC primitives built in? I just couldn't figure out how to do it without rolling my own shizzle.
As a side note, I extended this concept with "endpoints". It's kinda like xc channels, but with double buffers built in. The above pseudocode takes a channel and streams the data to another core where it is double buffered. 1 thread is consumed on the sending core, and 1 thread at the receiving The consuming thread (on the same core as the rx) keeps calling read_dbuff() for uninterrupted data.
I had to write so much stuff to do this, I'm starting to wonder if someone was witty and did this another way. Maybe I overlooked something easier.
In any case, this exercise has yielded a few cool constructs that are useful to me aside from e to this: traditional thread signals using assembly 'lock' instructions, a double buffer "class" that doesn't use any form of formal synchronization (one reading thread, one writing thread, same object), and my own channels that can be passed around without the usual restrictions (going in structs, etc). I will probably clean them up and share once I determine A) they work and B) don't demonstrate that I did things the hard way. :)
Note that all this had to be done in C (thank you XMOS for allowing C dev!!!) as I really find XC too restrictive for me. Again, maybe it's because I don't X-THINK properly but the entire purist no sharing memory and no passing resources in structs hurts my brain.