Class that combined FATFileSystem with a USBMSD device, similar to LocalFileSystem

Dependencies:   USBDevice

Dependents:   SD_USB_FS_HelloWorld S25FL216K_USBFileSystem USBFileSystem_RAMDISK_HelloWorld

Introduction

USBFileSystem is a combination of FATFileSystem and USB-MSD (Mass-Storage Device). This way it allows you to create a filesystem that is both accessible on your PC with the USB cable plugged in, and on the device itself. This is very similar to LocalFileSystem, only you can use any Serial Flash, SD, etc as storage medium.

If your code works with either FATFileSystem or USBMSD it will with very little modification also work with USBFileSystem.

Basic functionality

Since both FATFileSystem and USBMSD write binary data to a the storage medium, if both are writing somewhere at the same time we have a problem. This library makes the medium read only for the local side, if USB is writing, and vice versa. Local is considered to be writing as long as you have opened a file for write. USB is considered writing as soon as a write command comes from USB, and this continues for a short time after the last write command. This is needed because I cannot know when the last sector is written by USB, so I have to wait a little while to see if more data is written.

Reading

You can still read when the other one is writing. This can result in issues. Using the functions given you can easily make sure that won't happen. However regardless if you do that or not, it is a good idea to make sure your program can handle unexpected situations. For example if you open a file locally, and you get a NULL pointer, do not immediatly go into an error condition, but just try it again.

USB MSD on your PC

When you write to / read from a USB drive Windows (and I expect other OS's too) will cache everything. The result is that once you read a file on your PC, it will never change, even if your mbed does change the data. And if you write/delete a file when the mbed is locally using the file system, it will be read only, however your PC will tell you data was succesfully written/removed.

If this is a problem for your device, you can disconnect the USB part when the mbed is writing to the storage medium locally. The library can do this automatically for you.

Required code

The virtual functions that need to be implemented by you are:

virtual int disk_initialize() { return 0; }
virtual int _disk_status() { return 0; }
virtual int disk_read(uint8_t * buffer, uint64_t sector) { return 0;}
virtual int _disk_write(const uint8_t * buffer, uint64_t sector) = 0;
virtual int disk_sync() { return 0; }
virtual uint64_t disk_sectors() = 0;

Some of those are optional, but disk_read, _disk_write and disk_sectors have to be defined in the child class.

Sector size

The sector size must be 512 bytes. In USBMSD this requirement isn't present, but FATFileSystem has this requirement!

Function name

Note the '_' at the beginning of _disk_status and _disk_write. You may not inherit it without the '_', that will break the library. Since the parent libraries made it virtual I cannot block it from happening, so just watch out.

Available functions for the user

The USBFileSystem library allows for some extra functions the user can use. The API documentation lists them, but summarized: You can attach functions which are called once either USB is writing to the storage medium, or when this is done locally. There are two functions which will tell you if currently USB/local is writing to the storage medium, and you can set the usbMode. Set it to mode 0 and USB is read only when the storage is used locally, set it to mode 1 and it is disconnected (default and recommended).

Besides that there are of course the standard USB functions (connect/disconnect for example), and you can use 'fopen', 'mkdir', etc similar to FATFileSystem.

Hello World

Currently available:

RAM-disk for KL25Z and LPC1768 (this one disappeared for some reason, I re-published it, should still work):

Import programUSBFileSystem_RAMDISK_HelloWorld

RAMDisk example for the USBFileSystem

Wi-Go serial flash:

Import programS25FL216K_HelloWorld

Helloworld program for the S25FL216K flash memory in combination with USBFileSystem

SD card (different from others):

Import programSD_USB_FS_HelloWorld

SD USB MSD helloworld

Note that this one is not mine, if you have problems with it check if there are updates for the library.

Committer:
Sissors
Date:
Sun Jan 18 21:43:06 2015 +0000
Revision:
8:a9e1dffac4bd
Parent:
6:15b73dae124e
Actually use count argument

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Sissors 0:dabe3383ef23 1 #include "USBFileSystem.h"
Sissors 0:dabe3383ef23 2
Sissors 0:dabe3383ef23 3 #define USBWRITE_TIMEOUT 100
Sissors 0:dabe3383ef23 4
Sissors 0:dabe3383ef23 5 USBFileSystem::USBFileSystem(const char* n) : FATFileSystem_ds(n) {
Sissors 0:dabe3383ef23 6 localFunction = NULL;
Sissors 0:dabe3383ef23 7 usbFunction = NULL;
Sissors 0:dabe3383ef23 8 usbfree = true;
Sissors 0:dabe3383ef23 9 local_count = 0;
Sissors 2:9af05743d551 10 usbMode(1);
Sissors 0:dabe3383ef23 11 }
Sissors 0:dabe3383ef23 12
Sissors 0:dabe3383ef23 13
Sissors 0:dabe3383ef23 14 FileHandle* USBFileSystem::open(const char* name, int flags){
Sissors 0:dabe3383ef23 15 char n[64];
Sissors 0:dabe3383ef23 16 sprintf(n, "%d:/%s", _fsid, name);
Sissors 0:dabe3383ef23 17 bool write = true;
Sissors 0:dabe3383ef23 18
Sissors 0:dabe3383ef23 19 /* POSIX flags -> FatFS open mode */
Sissors 0:dabe3383ef23 20 BYTE openmode;
Sissors 0:dabe3383ef23 21 if (flags & O_RDWR) {
Sissors 0:dabe3383ef23 22 openmode = FA_READ|FA_WRITE;
Sissors 0:dabe3383ef23 23 localOpen(true);
Sissors 0:dabe3383ef23 24 } else if(flags & O_WRONLY) {
Sissors 0:dabe3383ef23 25 openmode = FA_WRITE;
Sissors 0:dabe3383ef23 26 localOpen(true);
Sissors 0:dabe3383ef23 27 } else {
Sissors 0:dabe3383ef23 28 openmode = FA_READ;
Sissors 0:dabe3383ef23 29 write = false;
Sissors 0:dabe3383ef23 30 }
Sissors 0:dabe3383ef23 31 if(flags & O_CREAT) {
Sissors 0:dabe3383ef23 32 if(flags & O_TRUNC) {
Sissors 0:dabe3383ef23 33 openmode |= FA_CREATE_ALWAYS;
Sissors 0:dabe3383ef23 34 } else {
Sissors 0:dabe3383ef23 35 openmode |= FA_OPEN_ALWAYS;
Sissors 0:dabe3383ef23 36 }
Sissors 0:dabe3383ef23 37 }
Sissors 0:dabe3383ef23 38
Sissors 0:dabe3383ef23 39 FIL fh;
Sissors 0:dabe3383ef23 40 FRESULT res = f_open(&fh, n, openmode);
Sissors 0:dabe3383ef23 41 if (res) {
Sissors 0:dabe3383ef23 42 if (write)
Sissors 0:dabe3383ef23 43 local_count--;
Sissors 0:dabe3383ef23 44 return NULL;
Sissors 0:dabe3383ef23 45 }
Sissors 0:dabe3383ef23 46 if (flags & O_APPEND) {
Sissors 0:dabe3383ef23 47 f_lseek(&fh, fh.fsize);
Sissors 0:dabe3383ef23 48 }
Sissors 0:dabe3383ef23 49 return new USBFileHandle(fh, this, write);
Sissors 0:dabe3383ef23 50 }
Sissors 0:dabe3383ef23 51
Sissors 0:dabe3383ef23 52 bool USBFileSystem::localSafe( void ){
Sissors 0:dabe3383ef23 53 return (local_count == 0);
Sissors 0:dabe3383ef23 54 }
Sissors 0:dabe3383ef23 55
Sissors 0:dabe3383ef23 56 bool USBFileSystem::usbSafe( void ){
Sissors 0:dabe3383ef23 57 return usbfree;
Sissors 0:dabe3383ef23 58 }
Sissors 0:dabe3383ef23 59
Sissors 0:dabe3383ef23 60 int USBFileSystem::disk_status_fat() {
Sissors 0:dabe3383ef23 61 int retval = _disk_status();
Sissors 0:dabe3383ef23 62
Sissors 0:dabe3383ef23 63 if ((retval == 0) && (!usbSafe()))
Sissors 0:dabe3383ef23 64 return 4;
Sissors 0:dabe3383ef23 65 else
Sissors 0:dabe3383ef23 66 return retval;
Sissors 0:dabe3383ef23 67 }
Sissors 0:dabe3383ef23 68
Sissors 0:dabe3383ef23 69 int USBFileSystem::disk_status_msd() {
Sissors 0:dabe3383ef23 70 int retval = _disk_status();
Sissors 0:dabe3383ef23 71
Sissors 0:dabe3383ef23 72 if ((retval == 0) && (!localSafe()))
Sissors 0:dabe3383ef23 73 return 4;
Sissors 0:dabe3383ef23 74 else
Sissors 0:dabe3383ef23 75 return retval;
Sissors 0:dabe3383ef23 76 }
Sissors 0:dabe3383ef23 77
Sissors 6:15b73dae124e 78 int USBFileSystem::disk_write(const uint8_t * data, uint64_t block, uint8_t count) {
Sissors 0:dabe3383ef23 79 if (localSafe()) {
Sissors 0:dabe3383ef23 80 if (usbfree && (usbFunction!=NULL) )
Sissors 0:dabe3383ef23 81 usbFunction(false);
Sissors 0:dabe3383ef23 82
Sissors 0:dabe3383ef23 83 usbfree = false;
Sissors 0:dabe3383ef23 84 }
Sissors 0:dabe3383ef23 85
Sissors 8:a9e1dffac4bd 86 int retval= _disk_write(data, block, count);
Sissors 0:dabe3383ef23 87
Sissors 0:dabe3383ef23 88 if (localSafe())
Sissors 0:dabe3383ef23 89 usb_write.attach_us(this, &USBFileSystem::usbFree, USBWRITE_TIMEOUT * 1000);
Sissors 0:dabe3383ef23 90
Sissors 0:dabe3383ef23 91 return retval;
Sissors 0:dabe3383ef23 92 }
Sissors 0:dabe3383ef23 93
Sissors 0:dabe3383ef23 94 void USBFileSystem::localOpen(bool open) {
Sissors 0:dabe3383ef23 95 if (open) {
Sissors 0:dabe3383ef23 96 local_count++;
Sissors 0:dabe3383ef23 97 } else {
Sissors 0:dabe3383ef23 98 local_count--;
Sissors 0:dabe3383ef23 99 }
Sissors 0:dabe3383ef23 100
Sissors 0:dabe3383ef23 101 //Pseudo-IRQ
Sissors 1:4ba08d11e36e 102 if (open && (local_count == 1)) {
Sissors 1:4ba08d11e36e 103 if (usbmode == 1)
Sissors 1:4ba08d11e36e 104 disconnect();
Sissors 1:4ba08d11e36e 105 if (localFunction != NULL)
Sissors 0:dabe3383ef23 106 (*localFunction)(false);
Sissors 1:4ba08d11e36e 107 }
Sissors 1:4ba08d11e36e 108 if (!open && (local_count == 0)) {
Sissors 1:4ba08d11e36e 109 if (usbmode == 1)
Sissors 1:4ba08d11e36e 110 connect();
Sissors 1:4ba08d11e36e 111 if (localFunction != NULL)
Sissors 0:dabe3383ef23 112 (*localFunction)(true);
Sissors 0:dabe3383ef23 113 }
Sissors 0:dabe3383ef23 114 }
Sissors 0:dabe3383ef23 115
Sissors 0:dabe3383ef23 116 void USBFileSystem::attachLocal(void (*function)(bool)) {
Sissors 0:dabe3383ef23 117 localFunction = function;
Sissors 0:dabe3383ef23 118 }
Sissors 0:dabe3383ef23 119
Sissors 0:dabe3383ef23 120 void USBFileSystem::attachUSB(void (*function)(bool)) {
Sissors 0:dabe3383ef23 121 usbFunction = function;
Sissors 0:dabe3383ef23 122 }
Sissors 0:dabe3383ef23 123
Sissors 0:dabe3383ef23 124 void USBFileSystem::usbFree( void ) {
Sissors 0:dabe3383ef23 125 usbfree = true;
Sissors 0:dabe3383ef23 126 if (usbFunction != NULL)
Sissors 0:dabe3383ef23 127 usbFunction(true);
Sissors 1:4ba08d11e36e 128 }
Sissors 1:4ba08d11e36e 129
Sissors 1:4ba08d11e36e 130 void USBFileSystem::usbMode(int mode) {
Sissors 1:4ba08d11e36e 131 usbmode = mode;
Sissors 0:dabe3383ef23 132 }