Main Site Documentation

Uncatchable System.IO.IOException


#1

The following code produces a System.IO.IOException that I can’t catch:


public class Program
{
    public static void Main()
    {
        try
        {
            while (true)
            {
                if (GHIElectronics.NETMF.IO.PersistentStorage.DetectSDCard())
                {
                    using (PersistentStorage ps = new PersistentStorage("SD"))
                    {
                        ps.MountFileSystem();
                        Debug.Print("SD");
                        ps.UnmountFileSystem();
                        //I tried this here to no avail: ps.Dispose();
                    }
                }
                Thread.Sleep(1000);
            }
        }
        catch
        { }
    }
}

I’m using a Mini 1.3 with sdexp 1.0. The program runs fine if no SD card is inserted as soon as I insert one it gets through the loop successfully once and then fails with the following printed to the debug output:

I should be able to catch this exception and clearly can’t so my only thought is that the PersistantStorage class is triggering an exception out on a different execution context where it is not being caught.

The background is I’m putting together a library which I want to run on Mini, Domino, and Chipworx so that it watches for available filesystems, SD, USB, NAND, and serves out files to an overlying application for settings etc. I wanted it to check for new resources every second or so and close out resources immediately after accesses. This won’t work if I can’t catch this exception. Perhaps there is a better way?

Thanks.


#2

Have you thought of making the detection of storage event driven, so you are not looping and don’t have the second delay if a device is detected?


#3

Wow, quick on the reply RJ,
Actually event driven is how I’ll be doing it on the Chipworx as the larger SD card slot has a card detect pin which you can just put to a GPIO and detect events with an interruptport. This doesn’t work with the microSD which doesn’t have that. Which I think is what the DetectSDCard function is there for. The documentation notes it only works on USBizi and EMX.
The Microsoft.SPOT.IO namespace has the RemovableMedia class which has insert and eject events which I tried using like this:


            Microsoft.SPOT.IO.RemovableMedia.Eject += new Microsoft.SPOT.IO.EjectEventHandler(RemovableMedia_Eject);
            Microsoft.SPOT.IO.RemovableMedia.Insert += new Microsoft.SPOT.IO.InsertEventHandler(RemovableMedia_Insert);

but they didn’t seem to trigger for the SD(maybe only for USB?)
As you say the looping/waiting isn’t the best way, but for the uSD I don’t know of a better way.
However even if I could use events here there would still be an issue if I did an operation on a SD card and then closed the resource and then immediately opened it again for a different operation.


#4

This only happens if you unmount very quickly (within milliseconds) after mounting. Because NETMF couldn’t process it yet. But exception is harmless.


#5

You can detect the state of the uSd card with:

if (PersistentStorage.DetectSDCard())...

The only drawback is the first time you call this function it will power cycle the SD card, so it is best to call it up front in your constructor to prevent any strange occurrences later. You can set up an ExtendedTimer to detect changes in the SD cards state and emit events if it is inserted/removed.


#6

Thanks, the issue is definitely unmounting quickly after mounting. I wrote the following class to test it and throw an exception if there is an unmount request too quickly:


// A wrapper for persistant storage to throw an exception if mount/unmount are called too quickly
public class SafePersistentStorage : PersistentStorage, IDisposable
{
    // The minimum ammount of time allowed between a mount and unmount of this filesystem.
    private static TimeSpan MountToUnmountMinTime = new TimeSpan(0, 0, 1);
    // The time when this instance was last mounted
    private DateTime MountedTime;
    // True when this instance is presently mounted, false otherwise
    private bool IsMounted = false;
    // A lock object for mounting operations
    private static object MountLock = new object();
    // Constructors just pass through constructors to base class
    public SafePersistentStorage(string DeviceID)
        : base(DeviceID) { }
    public SafePersistentStorage(USBH_Device usbDevice)
        : base(usbDevice) { }
    public SafePersistentStorage(USBH_Device usbDevice, byte massStorageLogicalUnit)
        : base(usbDevice, massStorageLogicalUnit) { }

    public new void MountFileSystem()
    {
        lock (MountLock)    //lock for thread-safety
        {
            if (!IsMounted) //only mount if not already
            {
                base.MountFileSystem();         //mount the filesystem
                MountedTime = DateTime.Now;     //save the time that we mounted
                IsMounted = true;               //set mounted state var
            }
        }
    }

    public new void UnmountFileSystem()
    {
        lock (MountLock)    //lock for thread-safety
        {
            if (IsMounted)  //only unmount if already mounted
            {
                if (MountedTime.Add(MountToUnmountMinTime) > DateTime.Now)  //check min time has elapsed before unmounting
                    throw new InvalidOperationException(string.Concat("Cannot unmount a filesystem within: ",
                        MountToUnmountMinTime.ToString(), " of mounting it."));
                base.UnmountFileSystem();       //unmount the filesystem
                IsMounted = false;              //set mounted state var
            }
        }
    }
}

I now can’t get an error I can’t catch. I however did run into one other thing using:

if (PersistentStorage.DetectSDCard())…

Sometimes after I eject the card physically DetectSDCard still returns true. The even more interesting thing is that I couldn’t get this to happen on the domino. If I call detect SD card repeatedly after a bit it seems to get the right answer, and if I try to mount the card I get an exception that I can catch so there’s no real show-stopper just strange behavior.
Jeff_Birt, I’m wondering why it is power cycling, is it is doing it to reconfigure the pins to use the DAT3 as a chip detect?


#7

Here is the method I’m using to detect changes in the SD card state on a Domino. It was driven from adn ExtendedTimer tick of its own but now is called as part of a timer event that also checks the USB client state (that is why the argument is commented out.)

The way this is written allows you to use the:

RemovableMedia.Insert += SD_Insert;
RemovableMedia.Eject += SD_Eject;

event handlers. This works flawlessly for me on a Domino.

       
public enum SDState { Removed, Inserted };

 /// <summary>
        /// Looks for a change in SD card inserted state on each tick
        /// </summary>
        /// <param name="target"></param>
        void sdTimerHandler(/*object target*/)
        {
            sdInserted = PersistentStorage.DetectSDCard();
            
            // if one of the other has changed raise fire event
            if (sdInserted & sdState != SDState.Inserted)
            {
                // fire SD_Inserted
                //Debug.Print("SD card has been inserted");
                sd = new PersistentStorage("SD");
                ms.AttachLun(0, sd, " ", " ");
                sd.MountFileSystem();
                sdState = SDState.Inserted;
            }
            else if (!sdInserted & sdState != SDState.Removed)
            {   
                // fires SD_Removed
                //Debug.Print("SD card has been removed");
                try
                {
                    sd.UnmountFileSystem();
                }
                catch
                {
                    //Debug.Print("SD file system was not mounted");
                }
                sd.Dispose();
                sdState = SDState.Removed;
            }
        }