Increase USB flash drive reliability

Hey

I’m looking for suggestions on how to increase the reliability of flash drives (USB sticks).

We use a USB flash drive and mount it to the FileSystem to store configuration data fetched from our backend and to temporarily store data when the internet connection is down. However, we often experience issues where our controllers (custom board with a SCM20260E) in the field are unable to mount or write to the flash drives. The typical problem seems to be corruption and after formatting the drive on a PC, it works again. Sometimes, even just inserting the drive into a PC and then remounting it to the controller makes it work again.

We flush and stop writes to the drive during a controlled restart but this doesn’t solve our reliability issue.

public class StorageMapping
{
    public StorageController Controller { get; set; }
    public StorageMapping(StorageController controller)
    {
        Controller = controller;
    }
}

public class USBController
{
    IDriveProvider _driver;
    StorageController _storageController;
    public DriveInfo[] _driveInfo;
    public USBController(StorageMapping controller)
    {
        _storageController = controller.Controller;
        var usbHostController = UsbHostController.GetDefault();

        usbHostController.OnConnectionChangedEvent +=
            UsbHostController_OnConnectionChangedEvent;
        usbHostController.Enable();
    }

    public IDriveProvider Driver
    {
        get { return _driver; }
    }

    public StorageController Controller
    {
        get { return _storageController; }
    }

    private void UsbHostController_OnConnectionChangedEvent
    (UsbHostController sender, DeviceConnectionEventArgs e)
    {
        switch (e.DeviceStatus)
        {
            case DeviceConnectionStatus.Connected:
                switch (e.Type)
                {
                    case BaseDevice.DeviceType.MassStorage:
                        try
                        {
                            _driver = FileSystem.Mount(_storageController.Hdc);
                            if(_driver == null)
                            {
                                Logger.Logger.Error("USBController | Failed to mount storage device, try formatting it");
                                if (FileSystem.Format(_storageController.Hdc, force: true))
                                {
                                    _driver = FileSystem.Mount(_storageController.Hdc);
                                }
                                else
                                    Logger.Logger.Error("USBController | Failed to format device");
                            }
                            _driveInfo = DriveInfo.GetDrives();
                        }
                        catch (Exception ex)
                        {

                            Logger.Logger.Fatal("USBController | " + ex.ToString());
                        }
                        break;

                    default:
                        Logger.Logger.Debug("USBController | USB device is not storage!");
                        break;
                }
                break;

            case DeviceConnectionStatus.Disconnected:
                //Unmount filesystem if it was mounted.
                Logger.Logger.Debug("USBController | Device Disconnected");
                try
                {
                    FileSystem.Unmount(_storageController.Hdc);
                }
                catch(Exception ex) 
                {
                    Logger.Logger.Error($"USBController | failed to unmount: {ex.Message}");
                }
                _driveInfo = DriveInfo.GetDrives();
                break;

            case DeviceConnectionStatus.Bad:
                Logger.Logger.Error("USBController | Bad Device");
                break;
        }
    }
}

public class SlimFileSystemWrapper()
{
         void SaveObject(byte[] buffer, string path)
        {
            if (buffer == null || buffer.Length == 0)
                return;
            using (FileStream fs = new FileStream(path, FileMode.OpenOrCreate))
            {
                fs.Write(buffer, 0, buffer.Length);
                fs.Flush();
            }
        }

        void SaveObject(object obj, string path)
        {
            string s = string.Empty;
            if(obj.GetType() != typeof(string))
                s = jsonConverter.SerializeObject(obj);
            else
                s = (string)obj;

            using (FileStream fs = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write))
            {
                byte[] arr = Encoding.UTF8.GetBytes(s);
                fs.Write(arr, 0, arr.Length);
                fs.Flush();
            }
        }

        byte[] ReadFileAsByteArray(string path)
        {
            byte[] buffer = null;

            using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read))
            {
                buffer = new byte[fs.Length];
                fs.Read(buffer, 0, buffer.Length);
            }

            return buffer == null ? new byte[0]: buffer;
        }

        string ReadFileAsString(string path)
        {
            using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read))
            {
                StreamReader sr = new StreamReader(fs);
                return sr.ReadToEnd();
            }
        }
}

we need usb branch, simple code to reproduce issue.

I’ve added code to the post

yes, thanks, we will look into it soon

Update:

I got a USB stick to crash in one of our controllers at the office. Windows can see the file, but attempting to open it in Notepad results in a ‘file not found’ error.


We have already anticipated that corrupted files might occur in the field. Therefore, we have a default policy in our controller that treats a read error as an indication of corruption, prompting an attempt to delete the file. However, File.Delete causes the controller to hang, and a reboot is the only way to recover it.