Skip to content

om_FlashFS

I&CG edited this page Jan 17, 2019 · 5 revisions

om::FlashFS

Overview:

  1. flashFs is provided as global variable from the cpp file. Just enable Serial and Wire ...
   #include <Wire.h>
   #include <FlashFS.h>
   ...
   void setup()
   {
     Serial.begin(115200);
     Wire.begin();
     ...
  1. Open the device and check integrity (uses default device address 0x50), format the device and pass up to 9 characters as name:
   while(!flashFs.openDevice())
   {
     Serial.println("unknown data content");
     // return;	// keep previous content?
     flashFs.format("Game_1");
   }
  1. Display the EEPROMs content (may be used as example how to do it in your project)
   flashFs.dir();

outputs something like:

------------------------------------
Flash: Game_1        Version:  1-000
Idx File       Size   Start

   320 bytes used,  32448 bytes free
------------------------------------
  1. (Re-)Create and write a resource file. Important: though displayed in the directory, you'll never deal with flash memory addresses explicitly. Filenames may be up to 9 characters long. That's more than enough for such a small storage device.
   struct Position {
     int x, y, z;
   };
   int      age = 42;
   float    account = 25.36;
   uint32_t points = 3552234;
   char     name[15]; 
   position where;

   flashFs.createFile("Player", 200); // size may have been calculated before.
   flashFs.write(age);
   flashFs.write(account);
   flashFs.write(points);
   flashFs.write(name, 15);
   flashFs.write(where);
   flashFs.write(where);              // 2nd one required later ... ;-)
  1. Enjoy the EEPROMs content again
   flashFs.dir();

outputs something like:

------------------------------------
Flash: Game_1        Version:  1-000
Idx File       Size   Start
  0 Player        200 0x000140

   576 bytes used,  32192 bytes free
------------------------------------
  1. Some time later, read back the data:
   flashFs.openFile("Player"); // returns size, may be checked.
   age     = flashFs.read<int>();
   account = flashFs.read<float>();
   points  = flashFs.read<uint32_t>();
   flashFs.read(name, 15);	
   flashFs.read(where);        // avoid additional copy.
   where = flashFs.read<>();   // should have the same result.
  1. ... or remove the data:
   flashFs.deleteFile("Player");

Public const's and structs:

Const values are provided inside the FlashFS class and may be changed in future versions.

MAGIC_TLFILESYSTEM  = 0x544C4653;   // "TLFS", tribute to ... ;-)                   
FILESYSTEMVERSION   = 0x0100;	// major 01, minor 00
MAXFILEENTRIES      = 16;                            
MAXNAMELEN          = 9;            // -> device and file names                  
DEFAULT_EEPROM_ADDR = 0x050;        // if not changed by A0-A2 pins at the EEPROM         

Only for the purpose of displaying a directory structure:

   struct FileEntry
   {
     uint32_t	startAddress;	        // for internal use only
     char	name[MAXNAMELEN+1];     // + 1 to hold terminating '\0'
     uint32_t	size;                   // requested file size
   };

Methods:

Constructor

  • FlashFS(uint8_t deviceAddress, uint32_t deviceSize, uint8_t pageSize);
    Constructor, used to initialize the global instance flashFs.

Utilities

  • void setDebugEnable(bool mode);
    Enable debug output to Serial on internal processes

  • int lastError() const;
    Returns the latests error.

Device managemenet

  • bool openDevice(uint8_t deviceAddress, uint32_t deviceSize, uint8_t pageSize);
    Mount device using new device parameters. Continues in openDevice()

  • bool openDevice();
    Mount device using default or previously assigned parameters. Reads directory and return true, if a valid directory structure is identified. MAGIC_TLFILESYSTEM, FILESYSTEMVERSION must match, the number of file entries must not exceed MAXFILEENTRIES.

  • void format(const char* storageName);
    Writes magics and empty directoy into the EEPROM starting at address 0x0. Currently 320 bytes are required.
    WARNING! ALL PREVIOUSLY STORED FILES WILL BE LOST!

  • void dir() const;
    Outputs pretty formatted directory to Serial.

  • const char* storageName() const;
    Returns name of device which was specified with format()

  • uint16_t storageVersion() const;
    Returns version of directory and filesystem. Major version encoded in MSB, minor in LSB.

  • int numFiles() const;
    Returns number of resource files registered in the directory.

  • const FileEntry* fileEntry(int idx);
    Returns pointer to the read-only internal entry structure. Only for the purpose of displaying a directory structure. Never modify on your own!

Files management

  • bool exists(const char* fileName) const;
    Check if resource file exists.

  • int deleteFile(const char* fileName);
    Delete file if it exists. Returns ERROR_NONE or ERROR_FILE_NOT_FOUND.

  • int createFile(const char* fileName, uint32_t size);
    If the resource file exists, delete it. Select the smallest memory gap on the chip, which is large enough to hold the specified size. Attention: There's (not yet) no way to let the file grow dynamically. Returns the requested file size on succes or one of ERROR_DIR_TABLE_FULL, ERROR_NOT_ENOUGH_SPACE. The file is openend on success for both reading and writing.

  • int openFile(const char* fileName);
    If the resource file exists, open it for both, reading and writing. Returns the requested file size on succes or ERROR_FILE_NOT_FOUND.

  • int cleanFile(uint32_t fillWord = 0x0);
    The file is completely overwritten with an endless sequence of fillword. You may also use any other value as 0xBAADF00D or 0x42424242 if you like to identify the use of uninitialized mem locations.

  • void close();
    Close the current file. This call is optional since its automatically executed changing to another resource file. Data is flushed immediately on writes to the EEPROM, so there's no risk of data loss.

  • bool eof() const;
    Check if read/write is at the end of the resource file or the resource file is closed.

  • uint32_t pos() const;
    Returns current read/write position relative to the files beginning.

  • uint32_t setPos(int32_t pos);
    Assign a new read/write position relative to the files beginning. Returns adjusted position (>= 0) or ERROR_FILE_NOT_OPENED, ERROR_POSITION_NEGATIVE, ERROR_POSITION_BEYOND_EOF.

  • uint32_t movePos(int32_t offset);
    Assign a new read/write position relative to the current position. Returns adjusted position (>= 0) or ERROR_FILE_NOT_OPENED, ERROR_POSITION_NEGATIVE, ERROR_POSITION_BEYOND_EOF.

Data access

  • int write(const void* data, uint32_t size);
    Writes size bytes refered by data into the resource file and adjust current file postion. The defined file size is never exceeded. The write operation is only executed if the data fits into the remaining file space. Returns the number of bytes written or ERROR_FILE_NOT_OPENED, ERROR_WRITING_BEYOND_EOF (.. tried to do so). Don't care for actual addresses used in the flash memory, choosing byte or page write commands, page breaks, etc.

  • template<typename T> int write(const T &data);
    Writes data into the resource file and adjust current file postion. The defined file size is never exceeded. The write operation is only executed if the data fits into the remaining file space. Returns the number of bytes written or ERROR_FILE_NOT_OPENED, ERROR_WRITING_BEYOND_EOF (.. tried to do so). Be aware that data must be trivially copyable, explicitly everything, that's still valid afer a memcpy()! Don't care for actual addresses used in the flash memory, choosing byte or page write commands, page breaks, etc.

  • int read(void* data, uint32_t size);
    Reads size bytes from the resource file into memory refered by data and adjust current file postion. The defined file size is never exceeded. The read operation is only executed if enough data is availbe from the remaining file space. Returns the number of bytes read or ERROR_FILE_NOT_OPENED, ERROR_READING_BEYOND_EOF (.. tried to do so). Don't care for actual addresses used in the flash memory, choosing byte or page read commands, etc.

  • template<typename T> T read();
    Reads and returns data of type T from the resource file and adjust current file postion. The defined file size is never exceeded. The read operation is only executed if enough data is availbe from the remaining file space. Returns the received data or default constructed data in case of error. Check for reading errors using lastError(): ERROR_FILE_NOT_OPENED, ERROR_READING_BEYOND_EOF (.. tried to do so). Don't care for actual addresses used in the flash memory, choosing byte or page read commands, etc.

  • template<typename T> int read(T &data);
    Reads and returns data of type T from the resource file into refered variable data and adjust current file postion. The defined file size is never exceeded. The read operation is only executed if enough data is availbe from the remaining file space. Returns the number of bytes read or ERROR_FILE_NOT_OPENED, ERROR_READING_BEYOND_EOF (.. tried to do so). Don't care for actual addresses used in the flash memory, choosing byte or page read commands, etc.

Error Codes:

Error values are provided inside the FlashFS class and may be changed/extended in future versions. Use always the constant values to compare, e.g. om::FlashFS::ERROR_DIR_TABLE_FULL. They are returned as negative number on methods, which should return a zero or positive number on success, noted in the comments.

ERROR_NONE = 0              // no error occured
ERROR_FILE_NOT_FOUND        // openFile, deleteFile
ERROR_FILE_NOT_OPENED       // cleanFile, read, write
ERROR_WRITING_BEYOND_EOF    // write
ERROR_READING_BEYOND_EOF    // read
ERROR_POSITION_NEGATIVE     // setPos, movePos
ERROR_POSITION_BEYOND_EOF   // setPos, movePos
ERROR_DIR_TABLE_FULL        // createFile
ERROR_NOT_ENOUGH_SPACE      // createFile