SD card help

How do i append a line of text to a file every 5 seconds based on time.

This is what i got so far, its crashing

 #### Exception System.IO.IOException - CLR_E_UNAUTHORIZED_ACCESS (1) ####
    #### Message: 
    #### System.IO.FileSystemManager::AddToOpenList [IP: 0086] ####
    #### System.IO.FileStream::.ctor [IP: 005b] ####

  while (true)
            {
                sdcard.CreateDirectory(DateTime.Now.Year.ToString());
                sdcard.SaveDataToFile("Test", DateTime.Now.DayOfYear.ToString());
                Thread.Sleep(5000);
            }

 public void CreateDirectory(string name) {
            RootDirectory.CreateSubdirectory(name);
            Directory.SetCurrentDirectory($"{RootDirectory.FullName}{name}");
        }

        public void SaveDataToFile(string data, string fileName)
        {
            FileStream file = new FileStream($"{Directory.GetCurrentDirectory()}{fileName}.txt", FileMode.OpenOrCreate);
            file.Seek(0, SeekOrigin.End);
            byte[] bytes = Encoding.UTF8.GetBytes($"{DateTime.Now}-{data}{Environment.NewLine}");
            file.Write(bytes, 0, bytes.Length);
            file.Flush();
            Debug.WriteLine("Saved...");
        }

I want to create a folder each year, and a file each dayOfYear and data every 5 seconds to that file

The docs are as usual incomplete, and .NET apis are completely different.

It is crashing because you never close the file. You should close after writing.

file.write(bytes, 0, bytes.Length);
file.Close();
file.Flush();

You could probably make it easier by opening the file in append mode.

FileStream file = new FileStream($"{Directory.GetCurrentDirectory()}{fileName}.txt", FileMode.Append);

The docs are as usual incomplete, and .NET apis are completely different.

Disagree. Me, and I think many others, managed to get things working with the GHI docs and the .NET API documentation. Why would GHI make their docs a replica of the .NET docs? No point in that…

1 Like

this is actually relevant to an issue I’m currently dealing with as well. Once it’s working, let it run for a while and see if it eventually will fail to write to the card.

Only Close is what was needed. Flush after Close gives an error.
Close is not mentioned in the docs…

@sgtyar95 what do you mean by fail?
does it crash after a while? how long?
or the data is just missing? do you remove sd card?

i let it run for 2 hours every 5 seconds it run OK, i then just remove the card, and last ~30 seconds is lost due to removal

File flush doesn’t save everything. There is a media flush… I am trying to remember…

You’re right. You should flush before closing.
I typed that code from memory…

does it crash after a while? how long?

In my experience it only goes wrong if the power is pulled out at the wrong moment, this can corrupt the SD card requiring a format.

Usually it’ll run for ten minutes or so (writes every ten seconds) then it will throw an InvalidOperationException when i try to write to the card. It will open and read OK, but it will no longer write properly until I reformat it.

it seems to be related to which card I’m using though, I currently have a dev board on my desk that’s been running for a day now with no issues with a different card. I am just interested to see if anyone else has seen this behavior.

What kind of good cards and bad cards?

I bought 10 of the cheapest i could find locally, they’re running fine :stuck_out_tongue:

I also seem to have a problem with the SD card. I have a SQLite database with approximately 1500 rows with 11 integer columns. Sometimes I get the following exception:

#### Exception GHIElectronics.TinyCLR.Data.SQLite.QueryExecutionException - 0x00000000 (38) ###
#### Message: disk I/O error
#### GHIElectronics.TinyCLR.Data.SQLite.SQLiteDatabase::ExecuteNonQuery [IP: 002d] ####

In NETMF with the speed parameter “SDCard.Mount (2500)” everything worked correctly.

What parameters should have an SD card for seamless operation in SITCore devices?

There is no option to set SD lock on TinyCLR.

It is on the list : Support SD Clock · Issue #844 · ghi-electronics/TinyCLR-Libraries (github.com)

humm… GitHub - carlk3/no-OS-FatFS-SD-SPI-RPi-Pico: A FAT filesystem with SPI driver for SD card on Raspberry Pi Pico
dual wielding sd card

Can you provide a small code that we can reproduce? Following what we see, it could be depend on SD card quality but hopefully we can see something in our cards.

TinyCLR has clock fixed 24 or 25Mb I believe. In netmf if you increase from 2.5 to 10 or 12Mb, if it failed then that card doesn’t happy with higher speed.

I was wrong, the speed was set to 25000 not 2500 in NETMF for G400-S. I’m going to try other SD cards. Currently I am using SD cards with Class 10.

I send a short code that always ends with an exception.

Tested on custom board with SCM20260N and Dev board (SCM20260D Dev Rev C)

Tested SD cards:
SanDisk 32GB V30
Kingston 32GB V10
GOODRAM 4GB Class10

using GHIElectronics.TinyCLR.Data.SQLite;
using GHIElectronics.TinyCLR.Devices.Storage;
using GHIElectronics.TinyCLR.IO;
using GHIElectronics.TinyCLR.Pins;
using System;
using System.Collections;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Threading;

namespace TinyCLRSDCard
{
    class Program
    {
        static void Main()
        {
            Debug.EnableGCMessages(true);

            StorageController sd = StorageController.FromName(SC20260.StorageController.SdCard);
            IDriveProvider drive = FileSystem.Mount(sd.Hdc);

            string directory = drive.Name + "\\DB";
            DirectoryInfo directoryInfo = new DirectoryInfo(directory);

            if (directoryInfo.Exists)
            {
                directoryInfo.Delete(true);
            }

            directoryInfo.Create();

            for(int i = 0; i < 10; i++)
            {
                new Database(directory, i);
            }

            while (true) ;
        }
    }

    class Database
    {
        private static int numRows = 0;
        private SQLiteDatabase database;
        private Random rand;

        public Database(string directory, int instanceIndex)
        {
            database = new SQLiteDatabase($"{directory}\\database{instanceIndex}.SQLite");

            database.ExecuteNonQuery("CREATE TABLE Foo (Id INTEGER PRIMARY KEY AUTOINCREMENT, BarA EntryIndex, BarB INTEGER, BarC INTEGER, BarD INTEGER, BarE INTEGER, BarF INTEGER, BarG INTEGER, BarH INTEGER, BarI INTEGER, BarJ INTEGER);");
            rand = new Random();

            new Thread(() =>
            {
                while (true)
                {
                    for (int i = 0; i < 10; i++)
                    {
                        database.ExecuteNonQuery($"INSERT INTO Foo (BarA, BarB, BarC, BarD, BarE, BarF, BarG, BarH, BarI, BarJ) VALUES ({rand.Next()}, {rand.Next()}, {rand.Next()}, {rand.Next()}, {rand.Next()}, {rand.Next()}, {rand.Next()}, {rand.Next()}, {rand.Next()}, {rand.Next()})");
                    
                        Debug.WriteLine($"Instance: {instanceIndex}, Num rows: {++numRows}");
                    }

                    Thread.Sleep(rand.Next(500));
                }

            }).Start();
        }
    }
}


...
Instance: 4, Num rows: 37
Instance: 5, Num rows: 38
Instance: 6, Num rows: 39
Instance: 6, Num rows: 40
Instance: 6, Num rows: 41
Instance: 0, Num rows: 42
Instance: 1, Num rows: 43
Instance: 2, Num rows: 44
Instance: 3, Num rows: 45
Instance: 4, Num rows: 46
Instance: 5, Num rows: 47
Instance: 6, Num rows: 48
    #### Exception GHIElectronics.TinyCLR.Data.SQLite.QueryExecutionException - 0x00000000 (1) ####
    #### Message: unable to open database file
    #### GHIElectronics.TinyCLR.Data.SQLite.SQLiteDatabase::ExecuteNonQuery [IP: 002d] ####
    #### TinyCLRSDCard.Program::Main [IP: 0048] ####
Instance: 0, Num rows: 49
Instance: 1, Num rows: 50
Instance: 2, Num rows: 51
    #### Exception GHIElectronics.TinyCLR.Data.SQLite.QueryExecutionException - 0x00000000 (5) ####
    #### Message: unable to open database file
    #### GHIElectronics.TinyCLR.Data.SQLite.SQLiteDatabase::ExecuteNonQuery [IP: 002d] ####
Instance: 3, Num rows: 52
    #### Exception GHIElectronics.TinyCLR.Data.SQLite.QueryExecutionException - 0x00000000 (6) ####
    #### Message: unable to open database file
    #### GHIElectronics.TinyCLR.Data.SQLite.SQLiteDatabase::ExecuteNonQuery [IP: 002d] ####
Instance: 4, Num rows: 53
    #### Exception GHIElectronics.TinyCLR.Data.SQLite.QueryExecutionException - 0x00000000 (7) ####
    #### Message: unable to open database file
    #### GHIElectronics.TinyCLR.Data.SQLite.SQLiteDatabase::ExecuteNonQuery [IP: 002d] ####
Instance: 5, Num rows: 54
    #### Exception GHIElectronics.TinyCLR.Data.SQLite.QueryExecutionException - 0x00000000 (8) ####
    #### Message: unable to open database file
    #### GHIElectronics.TinyCLR.Data.SQLite.SQLiteDatabase::ExecuteNonQuery [IP: 002d] ####
Instance: 6, Num rows: 55
    #### Exception GHIElectronics.TinyCLR.Data.SQLite.QueryExecutionException - 0x00000000 (9) ####
    #### Message: unable to open database file
    #### GHIElectronics.TinyCLR.Data.SQLite.SQLiteDatabase::ExecuteNonQuery [IP: 002d] ####
Exception thrown: 'GHIElectronics.TinyCLR.Data.SQLite.QueryExecutionException' in GHIElectronics.TinyCLR.Data.SQLite.dll
Exception thrown: 'GHIElectronics.TinyCLR.Data.SQLite.QueryExecutionException' in GHIElectronics.TinyCLR.Data.SQLite.dll
Exception thrown: 'GHIElectronics.TinyCLR.Data.SQLite.QueryExecutionException' in GHIElectronics.TinyCLR.Data.SQLite.dll
Exception thrown: 'GHIElectronics.TinyCLR.Data.SQLite.QueryExecutionException' in GHIElectronics.TinyCLR.Data.SQLite.dll
Exception thrown: 'GHIElectronics.TinyCLR.Data.SQLite.QueryExecutionException' in GHIElectronics.TinyCLR.Data.SQLite.dll
Exception thrown: 'GHIElectronics.TinyCLR.Data.SQLite.QueryExecutionException' in GHIElectronics.TinyCLR.Data.SQLite.dll
An unhandled exception of type 'GHIElectronics.TinyCLR.Data.SQLite.QueryExecutionException' occurred in GHIElectronics.TinyCLR.Data.SQLite.dll
Additional information: unable to open database file

Thanks, we will take a look.

SQLite raise exception with SD card. · Issue #1028 · ghi-electronics/TinyCLR-Libraries (github.com)