Netduino home hardware projects downloads community

Jump to content


The Netduino forums have been replaced by new forums at community.wildernesslabs.co. This site has been preserved for archival purposes only and the ability to make new accounts or posts has been turned off.

ericcox

Member Since 17 Nov 2010
Offline Last Active Jan 25 2013 02:18 AM
-----

#43916 Multithreading and writing to SD card

Posted by ericcox on 22 January 2013 - 08:14 AM

Here's how I usually implement this problem on the full version of .NET on the PC: use one thread for the GPS data, one for the sensor data, and a third thread to send the data to the SD card.  You could use a Queue object to manage the data flow.  Your worker threads would stuff the data into the queue, using a locking object to eliminate collisions. I haven't used this kind of thing on the NetMF however - there may be threading idiosyncrasies on NetMF for which I haven't accounted.

 

 

object lockObject = new Object();Queue queue = new queue();AutoResetEvent dataIsAvailable = new AutoResetEvent(false);public static void Main(){  ... Create Logging Thread   (Make sure to start this one first)  ... Create GPS Thread  ... Create Sensor Thread  Thread.Sleep(Timeout.Infinite);}public void GPSThreadStart(){   while (true)   {     .... raw GPS data received     ... create data object from raw GPS data     	 lock (lockObject)     {         queue.Enqueue(data);     }	 dataIsAvailable.Set();   }}(Sensor thread is the same basic idea)public void LoggingThreadStart(){   while ( true )   {	  dataIsAvailable.WaitOne();	  while (queue.Count > 0 ) 	  {		 object data;         lock (lockObject)         {           data = queue.DeQueue();         }		 ... Write data to SD card	  }   }}

 

The AutoResetEvent allows the threads to wait until data is available without using any CPU cycles.  The lock() statements make sure the Dequeue/Enqueue calls are completed before a thread context switch is allowed, avoiding collisions.  Using this scheme, you can enqueue sensor data inside interrupt handlers, and even write the logging data to the same file if you like.  When I do that, I usually use a base class to enforce a common record format, then derived classes for each different type of record.

 

Hope that helps,

Eric




#43618 WiFly Shield code

Posted by ericcox on 17 January 2013 - 09:28 PM

Hi all, WARNING: ALPHA CODE AHEAD! For those using the Wifly Shield from Sparkfun, here is a patch against rev 21420 of the netmf toolbox that adds direct support for the WiFly Shield with it's SC16IS750 SPI-To-Uart bridge.  The idea was to utilize the WiFlyGSX class as much as possible and separate the SC16IS750 code from it, so it could be useful in other configurations.  I wanted to make sure that we didn't have two separate WiFlyGSX classes out there - one with SC16IS750 support and one for use with a standard Uart - that we'd continually have to keep in sync. There are four main classes and an interface: WiFlyGSX The original, slightly modified to use ISerialPort, and adds a couple of functions that I needed for my project.    Spi2UartBridge Controls the SC16IS750 SPI-to-Uart bridge chip.  Implements ISerialPort, so should be transparent to the WiFlyGSX code.  It's interrupt driven - no polling - and supports the few GPIO pins on the SC16IS750.  I had some code in here that allowed you to use an in-memory buffer to improve performance, but had to yank it out to simplify debugging when I ran into a data transfer problem.  Assuming that code wasn't the cause of the problem, I'll probably add it back in later. Please note that I've only implemented the members of ISerialPort in Spi2UartBridge that I needed to use the WiFlyGSX code due to time constraints.  That's the reason I'm posting this in patch form rather than giving it to Stephan for inclusion in the Toolbox at this time - it's not a problem if you're just using the WiFly Shield, because WiFlyGSX only uses the implemented SerialPort members.  But someone implementing another SerialPort-using class may need all the members of SerialPort. In other words, this class is not really useful as a generic transparent replacement SerialPort - but that is the goal.  Time-permitting I'll implement all of the ones appropriate for the SC16IS750 on the SerialPortEx class.   WiFlyShield Encapulates the two classes above, and houses functions that require *both* the SC16IS750 and the WlyFly: resetting the WiFly, and resetting to factory defaults, via hardware pins.  Will probably add a method to control the Force Awake pin later. SerialPortEx Virtualizes the SerialPort/Spi2UartBridge by wrapping a real SerialPort and implementing ISerialPort members.  Should be simple/stable enough for developers to use as a target rather than a real SerialPort, so their code could be used with a SerialPort-lookalike in the future.

 

Basic use:

1. Create an SPI port

2. Create a Spi2UartBridge and pass it the SPI port

3. Create a WiFlyShield and pass it the Spi2UartBridge

4. Reference WiFlyShield.WiFlyGsx to access the WifFlyModule

 

namespace WiFlyTest{	public class Program	{		public static void Main()		{			var configuration = new SPI.Configuration(Pins.GPIO_PIN_D10, false, 0, 0, false, true, 4000, SPI.SPI_module.SPI1);			var spi = new SPI(configuration); 			using (var bridge = new Spi2UartBridge(spi, Pins.GPIO_PIN_D7))			{				bridge.DebugMode = true;				bridge.TestPin = 2;				bridge.BaudRate = 9600;				var shield = new WiFlyShield(bridge, debugMode: true);								shield.ResetToFactoryViaHardware(); 				shield.WiFlyGsx.SetAntenna(Antenna.Internal);				shield.WiFlyGsx.EnableDHCP();				shield.WiFlyGsx.JoinNetwork("testw", Authentication: WiFlyGSX.AuthMode.WPA2_PSK, Key: "<key>"); 				while (shield.WiFlyGsx.LocalIP == "0.0.0.0")				{					Thread.Sleep(1000);				} 				Debug.Print("Success!");			}		}	} }

 

Disclaimer: This code is, of course, posted with no guarantees of any kind.  If it works for you, great!  If not, send me a detailed description of what's going on and I'll try to fix it.  (If you have the time to debug and send a patch, that would be great)  Please note that if you change any of the register-manipulation code for the SC16IS750, you're on your own  :P  

Oh, also - this was developed on a Netuino Plus.  Not sure if their are any changes necessary for the NP2.  But the NP2 is my eventual target, so if you can wait, the code will be modified as appropriate in a future release (another reason it's not quite ready to be in the Toolbox).

Attached Files




home    hardware    projects    downloads    community    where to buy    contact Copyright © 2016 Wilderness Labs Inc.  |  Legal   |   CC BY-SA
This webpage is licensed under a Creative Commons Attribution-ShareAlike License.