Using the Lightning Memory-Mapped IO Driver in Windows 10 IoT Core Apps

Tags: windows-10, iot, raspberry-pi, C#, software, software-engineering, windows-on-devices, howto

The default I/O drivers in Windows 10 IoT Core are slow. I’ve tried to follow square wave inputs and the best throughput I can achieve is in the order of 30 milliseconds per transition, a maximum measurable frequency of about 30Hz. Even on a Netduino, with its interpreted MSIL runtime and single-core CPU, I could achieve measurements down to about 1 millisecond or 1000 Hz. Not necessarily in real-time, but in .NET MicroFramework, interrupt pins time-stamp their events so with clever programming the timing can be recovered. Not so in IoT core, an input pin generates an event which has no timing information and is slow, Slow, SLOW.

I was encouraged to discover the “Lightning bus provider” which uses a direct memory-mapped driver instead of the default “inbox” driver. I assume it is called an “inbox” driver not because it is ‘in the box’ but because it has an inbox and uses a message passing protocol, which would explain why it is as fast as treacle in winter.

I spent hours and hours trying to get the lightning providers to work but was defeated at every stage by fragmented, incomplete documentation. Finally, I have it working so here’s how I did it, including all the parts of the documentation that Microsoft left out!

  1. Get the Lightning Provider source code. There is no NuGet package. Repeat after me: no NuGet! This was the first bear trap I fell into, since there is in fact a package called Microsoft.IoT.Lightning, however this is NOT the Lightning provider, but a development dependency used by the provider source code. The ‘Project Site’ link for this package unhelpfully linkt to nowhere-in-particular, so it took me a while to figure this out. You need to download or clone a copy of the library source codefrom GitHub. Then, copy the “Microsoft.IoT.Lightning.Providers/Providers” folder into your own solution, and in Visual Studio, select File –> Add –> Existing Projec… and open the Microsoft.Iot.Lightning.Providers.vcxproj C++ project to include it in your solution.
  2. Build the Lightning bus provider. I found this to be a bit fiddly as the tooling seems to get a bit confused. I find it best to proceed as follows:
    1. first Build –> Clean the solution,
    2. then manually restore the NuGet packages by right-clicking the solution and selecting Restore NuGet Packages… Notice that one of the packages that gets restored is the aforementioned Microsoft.IoT.Lightning package. I’m not sure why Microsoft hasn’t marked this as a Development Dependency to avoid this confusion!
    3. Finally, Build –> Rebuild Solution.
  3. Once you have a building bus provider, you can then referencethe project from your own code, and the following code should not produce any compilation errors:
    if (LightningProvider.IsLightningEnabled)
    {
        // Set Lightning as the default provider
        LowLevelDevicesController.DefaultProvider = LightningProvider.GetAggregateProvider();
    }
  4. If you now run your project without doing any reconfiguration on the target device, your code should detect that the Lightning providers are NOT enabled and the code should fall back to the default ‘inbox’ driver and work normally.
  5. In order to actually activate the Lightning providers, you need to first reconfigure the target device and secondly update your project’s package manifest. This second step eluded me for a long time! So, use the web-based device manager to enable the Lightning drivers as shownbelow and reboot the device:
    Devices Page
  6. Finally, you need to edit your project’s Package.appxmanifest file, and add the following entries:
    1. At the top of the file, add an additional XML namespace declaration, so that your <Package> tage looks like this:
      image
    2. Next, towards the bottom of the file, add these two lines to the <Capabilities> element:
      image
  7. That’s it! Next time you deploy and run your package, you should notice that your code detects the lightning drivers and enables them as teh default! <PHEW>.

I spent almost a month, on and off, trying to figure this out. I hope this article saves you some of the grief I had.

Postscript: as of Windows 10 IoT Core build 10586 (December 2015) there appears to be a serious bug in the I2C provider that results in the bus speed being too fast when ‘Standard’ mode is selected. If your device works with the ‘inbox’ driver but experiences data corruption with the Lightning provider, then this could be the cause. Please monitor the issue on GitHub for more information. You might like to subscribe to the issue and possibly post a ‘me too’ comment to raise awareness witht he developers.

No Comments

Add a Comment

Let Us Help You

Find us on Facebook