G400D- Unable to write file-content to sd-card

hello there

I am using G400D and MF 4.3.
I am able to create files, write into files, check if written/created files exist… but after powering off my controller, all data are gone away.
At least I tried to unmount the SDCard, no impact on this behave.
I am able to read data from database without any problem. Also I was able to do read/add transactions with success.

what’s the problem?

regards

You have to Flush() your writer to commit the changes to the file.

The file system does a lot of data buffering internally to speed up the file access time and to increase the life of the flash media. When you write data to a file,it is often saved somewhere in the internal buffers (rather than immediately being written to the media). To make sure the data is stored on the media, you need to flush the data. Flushing (or closing) a file is the only way to guarantee that the data you are trying to write is on the actual media; in addition to the file data, there is other information,such as directory information, that may not be written to the media when the file is flushed. For example, if you delete a file and remove the card from the system, the file is probably not actually erased because the directory structure was not flushed.

Under current versions of .NET Micro Framework, with the Flush method of FileStream, there can be a variable time delay before the buffers are actually written to the media; which reportedly can be as large as a minute (see: https://netmf.codeplex.com/workitem/2149 )​. To guarantee that the file buffers and the meta-data are written to the media you need to flush the volume:

VolumeInfo.GetVolumes()[0].FlushAll(), or
new Microsoft.SPOT.IO.VolumeInfo(“\SD”).FlushAll().
Ideally, you would unmount the media before it is removed from the system. This may not be always possible and so a FlushAll will guarantee your data is saved.

1 Like

@ EvoMotors - Flush didn’t work, was one of my first ideas. Thanks, very helpful link!!

@ EvoMotors - I there a difference between volume.flushall and sdcard.flush(all)? the buffering method is clear for me, if you try to do a lot of write operations on a single file, you’ll get once an io exception.

Did you try to VolumeInfo.GetVolumes()[0].FlushAll() or new Microsoft.SPOT.IO.VolumeInfo("\SD").FlushAll() ? FlushAll will guarantee your data is saved.

Can you post the code so we can help? It sound like you are not flushing (the io exception)

@ EvoMotors - VolumeInfo.GetVolumes()[0].FlushAll() did not work. After the Flush Operation I am waiting 10s to unmount SD and power off the device. No IO-Exception! changing from FAT32 to FAT16 does not result in a succeed

demo code:
SDCarte_ = new SDCard();
SDCarte_.Mount();

                if (SDCarte_.Mounted)
                {
                    bool fs_ready = false;
                    RemovableMedia.Insert += (a, b) =>
                    {
                        fs_ready = true;
                    };
                    while (!fs_ready)
                    {
                        System.Threading.Thread.Sleep(1);
                    }

                    rootDirectoryvar = VolumeInfo.GetVolumes()[0].RootDirectory;

                    string f2 = @ "\SD\hello.txt";
                    FileStream FileHandle = new FileStream(f2, FileMode.Create, FileAccess.ReadWrite);
                    byte[] data =
                       Encoding.UTF8.GetBytes("This string will go in the file!");
                    FileHandle.Write(data, 0, data.Length);
                    FileHandle.Close();

                    //VolumeInfo.GetVolumes()[0].FlushAll();    //not working
                    new Microsoft.SPOT.IO.VolumeInfo("\\SD").FlushAll(); //not working
                    SDCarte_.Unmount();

I don’t see the code where you flushing FileStream I also don’t see the code where you disposing FileStream. Try this:

using (FileStream FileHandle = new FileStream("f2", FileMode.Create, FileAccess.ReadWrite))
{
    byte[] data = Encoding.UTF8.GetBytes("This string will go in the file!");
    FileHandle.Write(data, 0, data.Length);
    FileHandle.Close();
    FileHandle.Flush();
}}
//VolumeInfo.GetVolumes()[0].FlushAll(); //not working
new Microsoft.SPOT.IO.VolumeInfo("\\SD").FlushAll(); //not working
SDCarte_.Unmount();


@ EvoMotors - first flush, afterwards close to avoid access of any disposed object. no file has been written

The above code will throw an ObjectDisposedException as you are closing the FileStream before accessing it through the flush method.

The correct order would be :


using (FileStream FileHandle = new FileStream("f2", FileMode.Create, FileAccess.ReadWrite))
{
    byte[] data = Encoding.UTF8.GetBytes("This string will go in the file!");
    FileHandle.Write(data, 0, data.Length);
    FileHandle.Flush();
    FileHandle.Close();
}}
//VolumeInfo.GetVolumes()[0].FlushAll(); //not working
new Microsoft.SPOT.IO.VolumeInfo("\\SD").FlushAll(); //not working
SDCarte_.Unmount(

But the Flush method is really not necessary after the Close method is called as closing the FileStream will flush the buffer automatically.

@ scardinale - no error - no file written
f2 assumed as filename onto SD storage device

how does it take to write back data to the sd-card?
I also tried to use an existing file and appended one text-line. no execution error - nothing written.

  1. Sorry, my mistake about Closing FileStream after Flushing (I’m writing the code in the web browser and cannot confirm that it works or even compile)

  2. I know what you mean, but for some reason the file is not getting written for him.

Can you try StreamWriter insted of FileStream? Also I noticed that I put “f2” instead of f2 in my previous sample code, so if you didn’t correct it you’ll have to check if file with name f2 got written.

using (StreamWriter FileHandle = new StreamWriter(f2))
{
    FileHandle.Write("This string will go in the file!");
    FileHandle.Flush();
}

@ EvoMotors - Streamwriter including .Flush Call - was not successful

Explain not successful. Did not got written? Got an error?

Obviously something is wrong. I and many others writing files to SD card all the time. I’m successfully writing files to SD card with G120TH and G400TH

@ EvoMotors - written without any error; seems to be successfully. after power off and checking filesystem on the pc - no changes on filesystem are available

@ cyberh0me - I’ll try. what about the hardware. the lines are connected correct but I read some about capacitor…
possibly there is a wrong behave caused by hardware.

result:

  1. read existing file content … ok
  2. add file content without error
  3. read back file changes … ok
  4. power down and restart
  5. read file content (“This st”) …result
  6. power down and read content at pc

read file content (“This st”) …result

the only on difference to the previous tests was, In debug mode I didn’t stop execution after unmount.

the partial success in write operation is not always reproduceable.

i plan to write nearly a MegByte of data - this small amount of chars must be no problem in any case

In past I experienced at microcontroller a required minimum blocksize. does it matter on microframework?

I have used your code with minor modifications using a G400TH and a Sparkfun SD Breakout board also on a custom board based on the G400D. It is 100% successful every time.

If you run this code and it fails, the problem must be in your configuration.



        private static SDCard _sd;

        public static void Main()
        {
            _sd = new SDCard();
            _sd.Mount();

            if (_sd.Mounted)
            {
                bool fsReady = false;
                RemovableMedia.Insert += (a, b) =>
                {
                    fsReady = true;
                };
                while (!fsReady)
                {
                    Thread.Sleep(1);
                }

                string rootDirectoryvar = VolumeInfo.GetVolumes()[0].RootDirectory;

                string f2 = @ "\SD\hello.txt";
                FileStream fileHandle = new FileStream(f2, FileMode.Append);
                byte[] data = Encoding.UTF8.GetBytes("This string will go in the file!\r\n");
                fileHandle.Write(data, 0, data.Length);
                fileHandle.Close();

                VolumeInfo.GetVolumes()[0].FlushAll(); // is working
                //new VolumeInfo("\\SD").FlushAll(); // is working

                var readFileHandle = new FileStream(rootDirectoryvar + @ "\hello.txt", FileMode.Open, FileAccess.Read);
                data = new byte[readFileHandle.Length];
                var readCount = readFileHandle.Read(data, 0, data.Length);
                readFileHandle.Close();
                readFileHandle.Dispose();
                Debug.Print("The size of data read is: " + readCount);
                Debug.Print("Data from file:");
                Debug.Print(new string(Encoding.UTF8.GetChars(data), 0, readCount));

                _sd.Unmount();
                _sd.Dispose();
                _sd = null;

            }
        }

1 Like