I'm writing UWP application in C# for Windows 10 IoT Core on Raspberry Pi 3B, which is supposed to interact with TI ADS1601 16-bit ADC. In order to communicate with this chip, I have to bitbang simple SPI-like serial communication protocol, and first init the conversion through timely sent signals, which is illustrated on below image, taken from ADS1601 manual:
In order to init ADC, I have to sent SYNC pulse according to CLK (clock signal) from crystal generator, and upon reading valid response from chip, it is ready for data retrieval. Detecting edges is where I start to experience difficulties.
My code, inspired directly by official Windows IoT Core GPIO example:
// Open GPIO 27 - CLK (clock generator signal) listener
CLK2 = gpio.OpenPin(27);
CLK2.SetDriveMode(GpioPinDriveMode.Input);
CLK2.ValueChanged += EdgeDetCLKOnValueChanged; // event handler
Event handler looks like this:
private void EdgeDetCLKOnValueChanged(GpioPin sender, GpioPinValueChangedEventArgs args)
{
if (args.Edge.Equals(GpioPinEdge.FallingEdge))
CLKedge = F_; //F_ == 0b11110000;
if (args.Edge.Equals(GpioPinEdge.RisingEdge))
CLKedge = _R; //_R == 0b00001111;
}
It basically just sets a fancy token, indicating which edge occurred. It is being used and cleared in method responsible for communication init. Basically I use (i would like to use) such handlers for ValueChange event for a couple of other pins.
All of these (token, GpioPin instance, event handler and init methods) are members of same public class SimpleSerialProtocol. Whole code can be inspected here.
THE PROBLEM is, when event handler is getting attached and starts firing (because it works), garbage collector goes nuts and starts popping out way too often, to the degree it freezes whole application.
- top box displays memory usage and yellow dots represent occurrences of GC.
In this project, I have CLK frequency selector, and when I select lowest frequency (around 112Hz) app sorta works (GC fires every 5-10s), but sometimes data frame I receive from ADC gets messed up. As I start selecting higher frequencies, GC pops out more and more frequently (which makes sense, as ValueChanged event on GpioPin is being excited more often) to the point where app freezes and crashes. I can also illustrate this behavior with this image,
taken from in-VisualStudio Performance Profiler test. It represents about 30 sec of idle app operation, on the left there is present (subscribed) ValueChanged handler, on the right it is commented out. Also, in the left picture every other activity is filtered out, so it could fit somehow and show degree of havoc wreaked by garbage collector, represented by orange bars.
I am very intimidated by this problem, as I imagine all garbage collection stuff is infinitely complicated. Could you help me eliminate this, clearly erroneous behavior? Pardon my verbose description, I hope that it is as compact as it could and, nonetheless, understandable.
EDIT
I made a few Snaphots from Memory Usage tool
and there is displayed state of heap and summed up difference in objects/references quantity between those snapshots (I made first one on idle before subscribing handlers to ValueChanged and four more throughout various operation, which are using these handlers).
In differences listing, most of differences is in RuntimeType objects, and when I choose this item for more details, there is this phrase on top of list:
Object[] (pinned access) (it is displayed in Polish, so my attempt at translating it may be wrong).
I do not now, however, what this might mean, and I can't find any more specific information about this objects (like some references to my code).