Main Site Documentation

Exception when writing to SD


#1

On the Domino my application throws the following exception when writing to SD.

    
 #### Exception System.IO.IOException - CLR_E_INVALID_DRIVER (6) ####
    #### Message: 
    #### Microsoft.SPOT.IO.NativeIO::GetAttributes [IP: 0000] ####
    #### System.IO.FileStream::.ctor [IP: 005c] ####
    #### System.IO.FileStream::.ctor [IP: 0009] ####
    #### MyProject.Serial::WriteToFile [IP: 000f] ####
    #### MyProject.Serial::SerialWorker [IP: 00e2] ####
A first chance exception of type 'System.IO.IOException' occurred in Microsoft.SPOT.IO.dll
A first chance exception of type 'System.IO.IOException' occurred in System.IO.dll
An unhandled exception of type 'System.IO.IOException' occurred in System.IO.dll

I was trying to find some more info about the CLR_E_INVALID_DRIVER (6)error, but haven’t found anything yet.

I haven’t added any code (yet), cause the project is big and I haven’t been able to isolate the problem so far.

Remarkable is the code for writing and reading to SD works as long the network interface is disabled. The network is initialized with


WIZnet_W5100.Enable(SPI.SPI_module.SPI1, (Cpu.Pin)FEZ_Pin.Digital.Di10, (Cpu.Pin)FEZ_Pin.Digital.Di9, true); 

Can enabling the network interface interfere with writing to SD?


#2

Can you make a very small but complete program that shows the problem? This way we can test it here for you.


#3

Gus, thank you for your reply. I’ve created an example below that throws the exception. When no file is written at all in Thread2 the exception shows

[quote] #### Exception System.IO.IOException - CLR_E_INVALID_DRIVER (6) ####
[/quote]
When one, two or more files are written, the exception shows

[quote] #### Exception System.IO.IOException - CLR_E_INVALID_DRIVER (5) ####
[/quote]
The code to init the network is never executed, cause the exception is thrown before. That is in contrast to what I wrote before.


using GHIElectronics.NETMF.FEZ;
using GHIElectronics.NETMF.IO;
using GHIElectronics.NETMF.Net;
using GHIElectronics.NETMF.Net.NetworkInformation;
using Microsoft.SPOT;
using Microsoft.SPOT.IO;
using Microsoft.SPOT.Hardware;
using System;
using System.IO;
using System.Threading;

// References
// FEZDomino_GHIElectronics.NETMF.FEZ
// GHIElectronics.NETMF.IO
// GHIElectronics.NETMF.Net
// GHIElectronics.NETMF.System
// GHIElectronics.NETMF.W5100
// Microsoft.SPOT.Hardware
// Microsoft.SPOT.IO
// Microsoft.SPOT.Native
// mscorlib
// System.IO

// Using version 4.1.4.0

namespace NetworkAndStorageTest
{
    public class Program
    {
        static String _path = @ "\SD\Test";

        public static void Main()
        {
            Debug.EnableGCMessages(false);

            // Init SD
            InitSD();

            // Write SD
            WriteSD(DateTime.UtcNow.Ticks.ToString() + ".t1.txt");

            // Read SD
            ReadSD();

            // Create new Thread2 object
            Thread2 t = new Thread2();

            // Set main thread to sleep 15s
            Thread.Sleep(15000);

            // Init Network
            Debug.Print("Initing Network");
            InitNetwork();

        }

        public static void InitSD()
        {
            PersistentStorage ps = new PersistentStorage("SD");
            Debug.Print("Mounting SD");
            ps.MountFileSystem();
            Debug.Print("Mounted SD");
            Thread.Sleep(1000);
        }

        public static void ReadSD()
        {
            String[] files = Directory.GetFiles(_path);
            for (int i = 0; i < files.Length; i++)
            {
                FileInfo fi = new FileInfo(files[i]);
                Debug.Print("Read    " + fi.Name + " " + fi.LastWriteTimeUtc.ToString("yyyy-MM-dd HH:mm:ss") + " " + fi.Length);
                //File.Delete(fi.FullName);
            }
        }

        public static void WriteSD(String fileName)
        {
            if (!Directory.Exists(_path))
                Directory.CreateDirectory(_path);

            using (FileStream fs = new FileStream(_path + @ "\" + fileName, FileMode.OpenOrCreate))
            {
                byte[] buffer = System.Text.Encoding.UTF8.GetBytes(DateTime.UtcNow.ToString());
                fs.Write(buffer, 0, buffer.Length);
                fs.Close();
            }

            FileInfo fi = new FileInfo(_path + @ "\" + fileName);
            Debug.Print("Written "+ fi.Name + " " + fi.LastWriteTimeUtc.ToString("yyyy-MM-dd HH:mm:ss") + " " + fi.Length);
        }

        public static void InitNetwork()
        {
            byte[] mac = {00, 00, 00, 10, 20, 30};
            byte[] ip = {192, 168, 253, 189};
            byte[] subnet = {255, 255, 255, 0};
            byte[] gateway = {192, 168, 253, 254};
            byte[] dns = {192, 168, 253, 254};     

            WIZnet_W5100.Enable(SPI.SPI_module.SPI1, (Cpu.Pin)FEZ_Pin.Digital.Di10, (Cpu.Pin)FEZ_Pin.Digital.Di9, true); 
            NetworkInterface.EnableStaticIP(ip, subnet, gateway, mac);
            NetworkInterface.EnableStaticDns(dns);
        }
    }


    // Writes a file to SD every 2 seconds
    class Thread2
    {
        String _path = @ "\SD\Test";
        Thread _thread;

        public Thread2()
        {
            _thread = new Thread(MainThread2);
            Debug.Print("Starting thread 2");
            _thread.Start();
            Debug.Print("Started thread 2");
        }

        public void MainThread2()
        {
            Thread.Sleep(2000);
            while (true)
            {
                String fileName = DateTime.UtcNow.Ticks.ToString() + ".t2.txt";
                Debug.Print("Writing " + fileName);
                // System throws exception on next line
                // Some times it will write no, one, two or three files before the exception occurs.  
                using (FileStream fs = new FileStream(_path + @ "\" + fileName, FileMode.OpenOrCreate))
                {                
                    byte[] buffer = System.Text.Encoding.UTF8.GetBytes(DateTime.UtcNow.ToString());
                    fs.Write(buffer, 0, buffer.Length);
                    fs.Close();
                }
                FileInfo fi = new FileInfo(_path + @ "\" + fileName);
                Debug.Print("Written " + fi.Name + " " + fi.LastWriteTimeUtc.ToString("yyyy-MM-dd HH:mm:ss") + " " + fi.Length);

                Thread.Sleep(2000);
            }
        }
    }
}


#4

Never remove the GC messages while debugging.

public static void InitSD()
        {
            PersistentStorage ps = new PersistentStorage("SD");
            Debug.Print("Mounting SD");
            ps.MountFileSystem();
            Debug.Print("Mounted SD");
            Thread.Sleep(1000);
        }

Is it possible that the GC is collecting out your “ps” object? This is why the GC output will help.


#5

As Gus pointed out, I would make PersistentStorage a class variable. Remember you need to Unmount it properly at some point, or you might have some file system corruption issues.


#6

Ethernet power consumption is high. USB power might not be enough to power the system.
Either try another USB port which is directly connected to your PC or powered hub, or use external power.


#7

Good tip about the GC messages.

It appears the GC is indeed collecting the PersistentStorage object. It seems logical cause it’s only referred to in the scope of the InitSD method. Moving the reference for PersistentStorage to a wider scope works.
Thanks.

For example:


static PersistentStorage _ps;

public static void InitSD()
{
    _ps = new PersistentStorage("SD");
    Debug.Print("Mounting SD");
    _ps.MountFileSystem();
    Debug.Print("Mounted SD");
    Thread.Sleep(1000);
}