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:
Wed Oct 23 20:32:07 2013 +0000
Revision:
2:9af05743d551
FATFileSystem 'Tiny' option enabled -> Primary to solve a buffering issue when USB writes a file, also reduces RAM consumed
;
; USBDevice back to main branch
;
; USBMode 1 is default now

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Sissors 2:9af05743d551 1 /*-----------------------------------------------------------------------*/
Sissors 2:9af05743d551 2 /* Low level disk I/O module skeleton for FatFs (C)ChaN, 2007 */
Sissors 2:9af05743d551 3 /*-----------------------------------------------------------------------*/
Sissors 2:9af05743d551 4 /* This is a stub disk I/O module that acts as front end of the existing */
Sissors 2:9af05743d551 5 /* disk I/O modules and attach it to FatFs module with common interface. */
Sissors 2:9af05743d551 6 /*-----------------------------------------------------------------------*/
Sissors 2:9af05743d551 7 #include "ffconf.h"
Sissors 2:9af05743d551 8 #include "diskio.h"
Sissors 2:9af05743d551 9
Sissors 2:9af05743d551 10 #include "mbed_debug.h"
Sissors 2:9af05743d551 11 #include "FATFileSystem.h"
Sissors 2:9af05743d551 12
Sissors 2:9af05743d551 13 using namespace mbed;
Sissors 2:9af05743d551 14
Sissors 2:9af05743d551 15 DSTATUS disk_initialize (
Sissors 2:9af05743d551 16 BYTE drv /* Physical drive nmuber (0..) */
Sissors 2:9af05743d551 17 )
Sissors 2:9af05743d551 18 {
Sissors 2:9af05743d551 19 debug_if(FFS_DBG, "disk_initialize on drv [%d]\n", drv);
Sissors 2:9af05743d551 20 return (DSTATUS)FATFileSystem::_ffs[drv]->disk_initialize();
Sissors 2:9af05743d551 21 }
Sissors 2:9af05743d551 22
Sissors 2:9af05743d551 23 DSTATUS disk_status (
Sissors 2:9af05743d551 24 BYTE drv /* Physical drive nmuber (0..) */
Sissors 2:9af05743d551 25 )
Sissors 2:9af05743d551 26 {
Sissors 2:9af05743d551 27 debug_if(FFS_DBG, "disk_status on drv [%d]\n", drv);
Sissors 2:9af05743d551 28 return (DSTATUS)FATFileSystem::_ffs[drv]->disk_status();
Sissors 2:9af05743d551 29 }
Sissors 2:9af05743d551 30
Sissors 2:9af05743d551 31 DRESULT disk_read (
Sissors 2:9af05743d551 32 BYTE drv, /* Physical drive nmuber (0..) */
Sissors 2:9af05743d551 33 BYTE *buff, /* Data buffer to store read data */
Sissors 2:9af05743d551 34 DWORD sector, /* Sector address (LBA) */
Sissors 2:9af05743d551 35 BYTE count /* Number of sectors to read (1..255) */
Sissors 2:9af05743d551 36 )
Sissors 2:9af05743d551 37 {
Sissors 2:9af05743d551 38 debug_if(FFS_DBG, "disk_read(sector %d, count %d) on drv [%d]\n", sector, count, drv);
Sissors 2:9af05743d551 39 for(DWORD s=sector; s<sector+count; s++) {
Sissors 2:9af05743d551 40 debug_if(FFS_DBG, " disk_read(sector %d)\n", s);
Sissors 2:9af05743d551 41 int res = FATFileSystem::_ffs[drv]->disk_read((uint8_t*)buff, s);
Sissors 2:9af05743d551 42 if(res) {
Sissors 2:9af05743d551 43 return RES_PARERR;
Sissors 2:9af05743d551 44 }
Sissors 2:9af05743d551 45 buff += 512;
Sissors 2:9af05743d551 46 }
Sissors 2:9af05743d551 47 return RES_OK;
Sissors 2:9af05743d551 48 }
Sissors 2:9af05743d551 49
Sissors 2:9af05743d551 50 #if _READONLY == 0
Sissors 2:9af05743d551 51 DRESULT disk_write (
Sissors 2:9af05743d551 52 BYTE drv, /* Physical drive nmuber (0..) */
Sissors 2:9af05743d551 53 const BYTE *buff, /* Data to be written */
Sissors 2:9af05743d551 54 DWORD sector, /* Sector address (LBA) */
Sissors 2:9af05743d551 55 BYTE count /* Number of sectors to write (1..255) */
Sissors 2:9af05743d551 56 )
Sissors 2:9af05743d551 57 {
Sissors 2:9af05743d551 58 debug_if(FFS_DBG, "disk_write(sector %d, count %d) on drv [%d]\n", sector, count, drv);
Sissors 2:9af05743d551 59 for(DWORD s = sector; s < sector + count; s++) {
Sissors 2:9af05743d551 60 debug_if(FFS_DBG, " disk_write(sector %d)\n", s);
Sissors 2:9af05743d551 61 int res = FATFileSystem::_ffs[drv]->disk_write((uint8_t*)buff, s);
Sissors 2:9af05743d551 62 if(res) {
Sissors 2:9af05743d551 63 return RES_PARERR;
Sissors 2:9af05743d551 64 }
Sissors 2:9af05743d551 65 buff += 512;
Sissors 2:9af05743d551 66 }
Sissors 2:9af05743d551 67 return RES_OK;
Sissors 2:9af05743d551 68 }
Sissors 2:9af05743d551 69 #endif /* _READONLY */
Sissors 2:9af05743d551 70
Sissors 2:9af05743d551 71 DRESULT disk_ioctl (
Sissors 2:9af05743d551 72 BYTE drv, /* Physical drive nmuber (0..) */
Sissors 2:9af05743d551 73 BYTE ctrl, /* Control code */
Sissors 2:9af05743d551 74 void *buff /* Buffer to send/receive control data */
Sissors 2:9af05743d551 75 )
Sissors 2:9af05743d551 76 {
Sissors 2:9af05743d551 77 debug_if(FFS_DBG, "disk_ioctl(%d)\n", ctrl);
Sissors 2:9af05743d551 78 switch(ctrl) {
Sissors 2:9af05743d551 79 case CTRL_SYNC:
Sissors 2:9af05743d551 80 if(FATFileSystem::_ffs[drv] == NULL) {
Sissors 2:9af05743d551 81 return RES_NOTRDY;
Sissors 2:9af05743d551 82 } else if(FATFileSystem::_ffs[drv]->disk_sync()) {
Sissors 2:9af05743d551 83 return RES_ERROR;
Sissors 2:9af05743d551 84 }
Sissors 2:9af05743d551 85 return RES_OK;
Sissors 2:9af05743d551 86 case GET_SECTOR_COUNT:
Sissors 2:9af05743d551 87 if(FATFileSystem::_ffs[drv] == NULL) {
Sissors 2:9af05743d551 88 return RES_NOTRDY;
Sissors 2:9af05743d551 89 } else {
Sissors 2:9af05743d551 90 DWORD res = FATFileSystem::_ffs[drv]->disk_sectors();
Sissors 2:9af05743d551 91 if(res > 0) {
Sissors 2:9af05743d551 92 *((DWORD*)buff) = res; // minimum allowed
Sissors 2:9af05743d551 93 return RES_OK;
Sissors 2:9af05743d551 94 } else {
Sissors 2:9af05743d551 95 return RES_ERROR;
Sissors 2:9af05743d551 96 }
Sissors 2:9af05743d551 97 }
Sissors 2:9af05743d551 98 case GET_BLOCK_SIZE:
Sissors 2:9af05743d551 99 *((DWORD*)buff) = 1; // default when not known
Sissors 2:9af05743d551 100 return RES_OK;
Sissors 2:9af05743d551 101
Sissors 2:9af05743d551 102 }
Sissors 2:9af05743d551 103 return RES_PARERR;
Sissors 2:9af05743d551 104 }