Working version

Dependents:   PUB_RA8875_Bitmap

This version of the FlashFileSystem is directly derived from a library of the same name by Adam Green. See Adam's original at Flash File System.

Important in the use of this library is the generation of the embedded resource. For this there is a companion tool - rofs.exe. Adam provided a link to the source in github. I used that but found I wanted a few more features, so I made a large number of changes.

ROFS.exe Features

  • Bidirectional:
    • Create flash file system from folder of resources
    • Extract resources from flash file system [.h/.bin]
  • w/reduced warnings
  • faster file system building
  • more internal documentation in the generated .h file
  • additional help information added

Windows EXE

  • Contact me by Private Email for a copy - the mbed site is not letting me upload it as a zip.
Committer:
WiredHome
Date:
Thu Apr 30 14:27:05 2020 +0000
Revision:
1:689c997b57bb
Parent:
0:6339b3e34014
Code cleanup

Who changed what in which revision?

UserRevisionLine numberNew contents of line
WiredHome 0:6339b3e34014 1 /* Copyright 2011 Adam Green (http://mbed.org/users/AdamGreen/)
WiredHome 0:6339b3e34014 2
WiredHome 0:6339b3e34014 3 Licensed under the Apache License, Version 2.0 (the "License");
WiredHome 0:6339b3e34014 4 you may not use this file except in compliance with the License.
WiredHome 0:6339b3e34014 5 You may obtain a copy of the License at
WiredHome 0:6339b3e34014 6
WiredHome 0:6339b3e34014 7 http://www.apache.org/licenses/LICENSE-2.0
WiredHome 0:6339b3e34014 8
WiredHome 0:6339b3e34014 9 Unless required by applicable law or agreed to in writing, software
WiredHome 0:6339b3e34014 10 distributed under the License is distributed on an "AS IS" BASIS,
WiredHome 0:6339b3e34014 11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
WiredHome 0:6339b3e34014 12 See the License for the specific language governing permissions and
WiredHome 0:6339b3e34014 13 limitations under the License.
WiredHome 0:6339b3e34014 14 */
WiredHome 0:6339b3e34014 15 /* Specifies the classes used to implement the FlashFileSystem which is a
WiredHome 0:6339b3e34014 16 read-only file system that exists in the internal FLASH of the mbed
WiredHome 0:6339b3e34014 17 device.
WiredHome 0:6339b3e34014 18 */
WiredHome 0:6339b3e34014 19 #ifndef _FLASHFILESYSTEM_H_
WiredHome 0:6339b3e34014 20 #define _FLASHFILESYSTEM_H_
WiredHome 0:6339b3e34014 21
WiredHome 0:6339b3e34014 22 #include "FileSystemLike.h"
WiredHome 0:6339b3e34014 23
WiredHome 0:6339b3e34014 24 // Control the number of concurrently open files and directories.
WiredHome 0:6339b3e34014 25 // Was originally 16 for each.
WiredHome 0:6339b3e34014 26 //
WiredHome 0:6339b3e34014 27 #define NUM_CONCURRENT_FILES 2
WiredHome 0:6339b3e34014 28 #define NUM_CONCURRENT_DIRS 2
WiredHome 0:6339b3e34014 29
WiredHome 0:6339b3e34014 30
WiredHome 0:6339b3e34014 31 // Forward declare file system entry structure used internally in
WiredHome 0:6339b3e34014 32 // FlashFileSystem.
WiredHome 0:6339b3e34014 33 struct _SFileSystemEntry;
WiredHome 0:6339b3e34014 34
WiredHome 0:6339b3e34014 35
WiredHome 0:6339b3e34014 36
WiredHome 0:6339b3e34014 37 // Represents an opened file object in the FlashFileSystem.
WiredHome 0:6339b3e34014 38 class FlashFileSystemFileHandle : public FileHandle
WiredHome 0:6339b3e34014 39 {
WiredHome 0:6339b3e34014 40 public:
WiredHome 0:6339b3e34014 41 FlashFileSystemFileHandle();
WiredHome 0:6339b3e34014 42 FlashFileSystemFileHandle(const char* pFileStart, const char* pFileEnd);
WiredHome 0:6339b3e34014 43
WiredHome 0:6339b3e34014 44 // FileHandle interface methods.
WiredHome 0:6339b3e34014 45 virtual ssize_t write(const void* buffer, size_t length);
WiredHome 0:6339b3e34014 46 virtual int close();
WiredHome 0:6339b3e34014 47 virtual ssize_t read(void* buffer, size_t length);
WiredHome 0:6339b3e34014 48 virtual int isatty();
WiredHome 0:6339b3e34014 49 virtual off_t lseek(off_t offset, int whence);
WiredHome 0:6339b3e34014 50 virtual int fsync();
WiredHome 0:6339b3e34014 51 virtual off_t flen();
WiredHome 0:6339b3e34014 52
WiredHome 0:6339b3e34014 53 // Used by FlashFileSystem to maintain entries in its handle table.
WiredHome 0:6339b3e34014 54 void SetEntry(const char* pFileStart, const char* pFileEnd)
WiredHome 0:6339b3e34014 55 {
WiredHome 0:6339b3e34014 56 m_pFileStart = pFileStart;
WiredHome 0:6339b3e34014 57 m_pFileEnd = pFileEnd;
WiredHome 0:6339b3e34014 58 m_pCurr = pFileStart;
WiredHome 0:6339b3e34014 59 }
WiredHome 0:6339b3e34014 60 int IsClosed()
WiredHome 0:6339b3e34014 61 {
WiredHome 0:6339b3e34014 62 return (NULL == m_pFileStart);
WiredHome 0:6339b3e34014 63 }
WiredHome 0:6339b3e34014 64
WiredHome 0:6339b3e34014 65 protected:
WiredHome 0:6339b3e34014 66 // Beginning offset of file in FLASH memory.
WiredHome 0:6339b3e34014 67 const char* m_pFileStart;
WiredHome 0:6339b3e34014 68 // Ending offset of file in FLASH memory.
WiredHome 0:6339b3e34014 69 const char* m_pFileEnd;
WiredHome 0:6339b3e34014 70 // Current position in file to be updated by read and seek operations.
WiredHome 0:6339b3e34014 71 const char* m_pCurr;
WiredHome 0:6339b3e34014 72 };
WiredHome 0:6339b3e34014 73
WiredHome 0:6339b3e34014 74
WiredHome 0:6339b3e34014 75 // Represents an open directory in the FlashFileSystem.
WiredHome 0:6339b3e34014 76 class FlashFileSystemDirHandle : public DirHandle
WiredHome 0:6339b3e34014 77 {
WiredHome 0:6339b3e34014 78 public:
WiredHome 0:6339b3e34014 79 // Constructors
WiredHome 0:6339b3e34014 80 FlashFileSystemDirHandle();
WiredHome 0:6339b3e34014 81 FlashFileSystemDirHandle(const char* pFLASHBase,
WiredHome 0:6339b3e34014 82 const _SFileSystemEntry* pFirstFileEntry,
WiredHome 0:6339b3e34014 83 unsigned int FileEntriesLeft,
WiredHome 0:6339b3e34014 84 unsigned int DirectoryNameLength);
WiredHome 0:6339b3e34014 85
WiredHome 0:6339b3e34014 86 // Used by FlashFileSystem to maintain DirHandle entries in its cache.
WiredHome 0:6339b3e34014 87 void SetEntry(const char* pFLASHBase,
WiredHome 0:6339b3e34014 88 const _SFileSystemEntry* pFirstFileEntry,
WiredHome 0:6339b3e34014 89 unsigned int FileEntriesLeft,
WiredHome 0:6339b3e34014 90 unsigned int DirectoryNameLength)
WiredHome 0:6339b3e34014 91 {
WiredHome 0:6339b3e34014 92 m_pFLASHBase = pFLASHBase;
WiredHome 0:6339b3e34014 93 m_pFirstFileEntry = pFirstFileEntry;
WiredHome 0:6339b3e34014 94 m_pCurrentFileEntry = pFirstFileEntry;
WiredHome 0:6339b3e34014 95 m_FileEntriesLeft = FileEntriesLeft;
WiredHome 0:6339b3e34014 96 m_DirectoryNameLength = DirectoryNameLength;
WiredHome 0:6339b3e34014 97 }
WiredHome 0:6339b3e34014 98 int IsClosed()
WiredHome 0:6339b3e34014 99 {
WiredHome 0:6339b3e34014 100 return (NULL == m_pFirstFileEntry);
WiredHome 0:6339b3e34014 101 }
WiredHome 0:6339b3e34014 102
WiredHome 0:6339b3e34014 103 // Methods defined by DirHandle interface.
WiredHome 0:6339b3e34014 104 virtual int closedir();
WiredHome 0:6339b3e34014 105 virtual struct dirent *readdir();
WiredHome 0:6339b3e34014 106 virtual void rewinddir();
WiredHome 0:6339b3e34014 107 virtual off_t telldir();
WiredHome 0:6339b3e34014 108 virtual void seekdir(off_t location);
WiredHome 0:6339b3e34014 109
WiredHome 0:6339b3e34014 110 protected:
WiredHome 0:6339b3e34014 111 // The first file entry for this directory. rewinddir() takes the
WiredHome 0:6339b3e34014 112 // iterator back to here.
WiredHome 0:6339b3e34014 113 const _SFileSystemEntry* m_pFirstFileEntry;
WiredHome 0:6339b3e34014 114 // The next file entry to be returned for this directory enumeration.
WiredHome 0:6339b3e34014 115 const _SFileSystemEntry* m_pCurrentFileEntry;
WiredHome 0:6339b3e34014 116 // Pointer to where the file system image is located in the device's FLASH.
WiredHome 0:6339b3e34014 117 const char* m_pFLASHBase;
WiredHome 0:6339b3e34014 118 // Contents of previously return directory entry structure.
WiredHome 0:6339b3e34014 119 struct dirent m_DirectoryEntry;
WiredHome 0:6339b3e34014 120 // This is the length of the directory name which was opened. When the
WiredHome 0:6339b3e34014 121 // first m_DirectoryNameLength characters change then we have iterated
WiredHome 0:6339b3e34014 122 // through to a different directory.
WiredHome 0:6339b3e34014 123 unsigned int m_DirectoryNameLength;
WiredHome 0:6339b3e34014 124 // The number of entries left in the file system file entries array.
WiredHome 0:6339b3e34014 125 unsigned int m_FileEntriesLeft;
WiredHome 0:6339b3e34014 126 };
WiredHome 0:6339b3e34014 127
WiredHome 0:6339b3e34014 128
WiredHome 0:6339b3e34014 129
WiredHome 0:6339b3e34014 130 /** A filesystem for accessing a read-only file system placed in the internal\n
WiredHome 0:6339b3e34014 131 * FLASH memory of the mbed board.
WiredHome 0:6339b3e34014 132 *\n
WiredHome 0:6339b3e34014 133 * The file system to be mounted by this file system should be created through\n
WiredHome 0:6339b3e34014 134 * the use of the fsbld utility on the PC.\n
WiredHome 0:6339b3e34014 135 *\n
WiredHome 0:6339b3e34014 136 * As fsbld creates two output files (a binary and a header file), there are two\n
WiredHome 0:6339b3e34014 137 * ways to add the resulting file system image:\n
WiredHome 0:6339b3e34014 138 * -# Concatenate the binary file system to the end of the .bin file created\n
WiredHome 0:6339b3e34014 139 * by the mbed online compiler before uploading to the mbed device.\n
WiredHome 0:6339b3e34014 140 * -# Import the header file into your project, include this file in your main\n
WiredHome 0:6339b3e34014 141 * file and add 'roFlashDrive' to the FlashfileSystem constructor call.\n
WiredHome 0:6339b3e34014 142 * eg : static FlashFileSystem flash("flash", roFlashDrive);\n
WiredHome 0:6339b3e34014 143 *
WiredHome 0:6339b3e34014 144 * A third (optional) parameter in the FlashfileSystem constructor call allows\n
WiredHome 0:6339b3e34014 145 * you to specify the size of the FLASH (KB) on the device (default = 512).\n
WiredHome 0:6339b3e34014 146 * eg (for a KL25Z device) : static FlashFileSystem flash("flash", NULL, 128);\n
WiredHome 0:6339b3e34014 147 * Note that in this example, the pointer to the header file has been omitted,\n
WiredHome 0:6339b3e34014 148 * so we need to append the binary file system ourselves (see above).\n
WiredHome 0:6339b3e34014 149 * When you use the binary file system header in your main file, you can\n
WiredHome 0:6339b3e34014 150 * use the roFlashDrive pointer.\n
WiredHome 0:6339b3e34014 151 * eg (for a KL25Z device) : static FlashFileSystem flash("flash", roFlashDrive, 128);\n
WiredHome 0:6339b3e34014 152 *\n
WiredHome 0:6339b3e34014 153 * NOTE: This file system is case-sensitive. Calling fopen("/flash/INDEX.html")\n
WiredHome 0:6339b3e34014 154 * won't successfully open a file named index.html in the root directory\n
WiredHome 0:6339b3e34014 155 * of the flash file system.\n
WiredHome 0:6339b3e34014 156 *
WiredHome 0:6339b3e34014 157 * Example:
WiredHome 0:6339b3e34014 158 * @code
WiredHome 0:6339b3e34014 159 #include <mbed.h>
WiredHome 0:6339b3e34014 160 #include "FlashFileSystem.h"
WiredHome 0:6339b3e34014 161 // Uncomment the line below when you imported the header file built with fsbld
WiredHome 0:6339b3e34014 162 // and replace <Flashdrive> with its correct filename
WiredHome 0:6339b3e34014 163 //#include "<FlashDrive>.h"
WiredHome 0:6339b3e34014 164
WiredHome 0:6339b3e34014 165 static void _RecursiveDir(const char* pDirectoryName, DIR* pDirectory = NULL)
WiredHome 0:6339b3e34014 166 {
WiredHome 0:6339b3e34014 167 DIR* pFreeDirectory = NULL;
WiredHome 0:6339b3e34014 168
WiredHome 0:6339b3e34014 169 size_t DirectoryNameLength = strlen(pDirectoryName);
WiredHome 0:6339b3e34014 170
WiredHome 0:6339b3e34014 171 // Open the specified directory.
WiredHome 0:6339b3e34014 172 if (!pDirectory)
WiredHome 0:6339b3e34014 173 {
WiredHome 0:6339b3e34014 174 pDirectory = opendir(pDirectoryName);
WiredHome 0:6339b3e34014 175 if (!pDirectory)
WiredHome 0:6339b3e34014 176 {
WiredHome 0:6339b3e34014 177 error("Failed to open directory '%s' for enumeration.\r\n",
WiredHome 0:6339b3e34014 178 pDirectoryName);
WiredHome 0:6339b3e34014 179 }
WiredHome 0:6339b3e34014 180
WiredHome 0:6339b3e34014 181 // Remember to free this directory enumerator.
WiredHome 0:6339b3e34014 182 pFreeDirectory = pDirectory;
WiredHome 0:6339b3e34014 183 }
WiredHome 0:6339b3e34014 184
WiredHome 0:6339b3e34014 185 // Determine if we should remove a trailing slash from future *printf()
WiredHome 0:6339b3e34014 186 // calls.
WiredHome 0:6339b3e34014 187 if (DirectoryNameLength && '/' == pDirectoryName[DirectoryNameLength-1])
WiredHome 0:6339b3e34014 188 {
WiredHome 0:6339b3e34014 189 DirectoryNameLength--;
WiredHome 0:6339b3e34014 190 }
WiredHome 0:6339b3e34014 191
WiredHome 0:6339b3e34014 192 // Iterate though each item contained within this directory and display
WiredHome 0:6339b3e34014 193 // it to the console.
WiredHome 0:6339b3e34014 194 struct dirent* DirEntry;
WiredHome 0:6339b3e34014 195 while((DirEntry = readdir(pDirectory)) != NULL)
WiredHome 0:6339b3e34014 196 {
WiredHome 0:6339b3e34014 197 char RecurseDirectoryName[256];
WiredHome 0:6339b3e34014 198 DIR* pSubdirectory;
WiredHome 0:6339b3e34014 199
WiredHome 0:6339b3e34014 200 // Try opening this file as a directory to see if it succeeds or not.
WiredHome 0:6339b3e34014 201 snprintf(RecurseDirectoryName, sizeof(RecurseDirectoryName),
WiredHome 0:6339b3e34014 202 "%.*s/%s",
WiredHome 0:6339b3e34014 203 DirectoryNameLength,
WiredHome 0:6339b3e34014 204 pDirectoryName,
WiredHome 0:6339b3e34014 205 DirEntry->d_name);
WiredHome 0:6339b3e34014 206 pSubdirectory = opendir(RecurseDirectoryName);
WiredHome 0:6339b3e34014 207
WiredHome 0:6339b3e34014 208 if (pSubdirectory)
WiredHome 0:6339b3e34014 209 {
WiredHome 0:6339b3e34014 210 _RecursiveDir(RecurseDirectoryName, pSubdirectory);
WiredHome 0:6339b3e34014 211 closedir(pSubdirectory);
WiredHome 0:6339b3e34014 212 }
WiredHome 0:6339b3e34014 213 else
WiredHome 0:6339b3e34014 214 {
WiredHome 0:6339b3e34014 215 printf(" %.*s/%s\n",
WiredHome 0:6339b3e34014 216 DirectoryNameLength,
WiredHome 0:6339b3e34014 217 pDirectoryName,
WiredHome 0:6339b3e34014 218 DirEntry->d_name);
WiredHome 0:6339b3e34014 219 }
WiredHome 0:6339b3e34014 220 }
WiredHome 0:6339b3e34014 221
WiredHome 0:6339b3e34014 222 // Close the directory enumerator if it was opened by this call.
WiredHome 0:6339b3e34014 223 if (pFreeDirectory)
WiredHome 0:6339b3e34014 224 {
WiredHome 0:6339b3e34014 225 closedir(pFreeDirectory);
WiredHome 0:6339b3e34014 226 }
WiredHome 0:6339b3e34014 227 }
WiredHome 0:6339b3e34014 228
WiredHome 0:6339b3e34014 229 int main()
WiredHome 0:6339b3e34014 230 {
WiredHome 0:6339b3e34014 231 static const char* Filename = "/flash/index.html";
WiredHome 0:6339b3e34014 232 char* ReadResult = NULL;
WiredHome 0:6339b3e34014 233 int SeekResult = -1;
WiredHome 0:6339b3e34014 234 char Buffer[128];
WiredHome 0:6339b3e34014 235
WiredHome 0:6339b3e34014 236 // Create the file system under the name "flash".
WiredHome 0:6339b3e34014 237 // NOTE : When you include the the header file built with fsbld,
WiredHome 0:6339b3e34014 238 // disable the first static FlashFileSystem... line
WiredHome 0:6339b3e34014 239 // and enable the second static FlashFileSystem... line.
WiredHome 0:6339b3e34014 240 static FlashFileSystem flash("flash");
WiredHome 0:6339b3e34014 241 // static FlashFileSystem flash("flash, roFlashDrive");
WiredHome 0:6339b3e34014 242 if (!flash.IsMounted())
WiredHome 0:6339b3e34014 243 {
WiredHome 0:6339b3e34014 244 error("Failed to mount FlashFileSystem.\r\n");
WiredHome 0:6339b3e34014 245 }
WiredHome 0:6339b3e34014 246
WiredHome 0:6339b3e34014 247 // Open "index.html" on the file system for reading.
WiredHome 0:6339b3e34014 248 FILE *fp = fopen(Filename, "r");
WiredHome 0:6339b3e34014 249 if (NULL == fp)
WiredHome 0:6339b3e34014 250 {
WiredHome 0:6339b3e34014 251 error("Failed to open %s\r\n", Filename);
WiredHome 0:6339b3e34014 252 }
WiredHome 0:6339b3e34014 253
WiredHome 0:6339b3e34014 254 // Use seek to determine the length of the file
WiredHome 0:6339b3e34014 255 SeekResult = fseek(fp, 0, SEEK_END);
WiredHome 0:6339b3e34014 256 if (SeekResult)
WiredHome 0:6339b3e34014 257 {
WiredHome 0:6339b3e34014 258 error("Failed to seek to end of %s.\r\n", Filename);
WiredHome 0:6339b3e34014 259 }
WiredHome 0:6339b3e34014 260 long FileLength = ftell(fp);
WiredHome 0:6339b3e34014 261 printf("%s is %ld bytes in length.\r\n", Filename, FileLength);
WiredHome 0:6339b3e34014 262
WiredHome 0:6339b3e34014 263 // Reset the file pointer to the beginning of the file
WiredHome 0:6339b3e34014 264 SeekResult = fseek(fp, 0, SEEK_SET);
WiredHome 0:6339b3e34014 265 if (SeekResult)
WiredHome 0:6339b3e34014 266 {
WiredHome 0:6339b3e34014 267 error("Failed to seek to beginning of %s.\r\n", Filename);
WiredHome 0:6339b3e34014 268 }
WiredHome 0:6339b3e34014 269
WiredHome 0:6339b3e34014 270 // Read the first line into Buffer and then display to user.
WiredHome 0:6339b3e34014 271 ReadResult = fgets(Buffer, sizeof(Buffer)/sizeof(Buffer[0]), fp);
WiredHome 0:6339b3e34014 272 if (NULL == ReadResult)
WiredHome 0:6339b3e34014 273 {
WiredHome 0:6339b3e34014 274 error("Failed to read first line of %s.\r\n", Filename);
WiredHome 0:6339b3e34014 275 }
WiredHome 0:6339b3e34014 276 printf("%s:1 %s", Filename, Buffer);
WiredHome 0:6339b3e34014 277
WiredHome 0:6339b3e34014 278 // Done with the file so close it.
WiredHome 0:6339b3e34014 279 fclose(fp);
WiredHome 0:6339b3e34014 280
WiredHome 0:6339b3e34014 281 // Enumerate all content on mounted file systems.
WiredHome 0:6339b3e34014 282 printf("\r\nList all files in /flash...\r\n");
WiredHome 0:6339b3e34014 283 _RecursiveDir("/flash");
WiredHome 0:6339b3e34014 284
WiredHome 0:6339b3e34014 285 printf("\r\nFlashFileSystem example has completed.\r\n");
WiredHome 0:6339b3e34014 286 }
WiredHome 0:6339b3e34014 287 * @endcode
WiredHome 0:6339b3e34014 288 */
WiredHome 0:6339b3e34014 289 class FlashFileSystem : public FileSystemLike
WiredHome 0:6339b3e34014 290 {
WiredHome 0:6339b3e34014 291 public:
WiredHome 0:6339b3e34014 292 FlashFileSystem(const char* pName, const uint8_t *pFlashDrive = NULL, const uint32_t FlashSize = 512);
WiredHome 0:6339b3e34014 293
WiredHome 0:6339b3e34014 294 virtual FileHandle* open(const char* pFilename, int Flags);
WiredHome 0:6339b3e34014 295 virtual DirHandle* opendir(const char *pDirectoryName);
WiredHome 0:6339b3e34014 296
WiredHome 0:6339b3e34014 297 virtual int IsMounted() { return (m_FileCount != 0); }
WiredHome 0:6339b3e34014 298
WiredHome 0:6339b3e34014 299 protected:
WiredHome 0:6339b3e34014 300 FlashFileSystemFileHandle* FindFreeFileHandle();
WiredHome 0:6339b3e34014 301 FlashFileSystemDirHandle* FindFreeDirHandle();
WiredHome 0:6339b3e34014 302
WiredHome 0:6339b3e34014 303 // File handle table used by this file system so that it doesn't need
WiredHome 0:6339b3e34014 304 // to dynamically allocate file handles at runtime.
WiredHome 0:6339b3e34014 305 FlashFileSystemFileHandle m_FileHandles[NUM_CONCURRENT_FILES];
WiredHome 0:6339b3e34014 306 // Directory handle table used by this file system so that it doesn't need
WiredHome 0:6339b3e34014 307 // to dynamically allocate file handles at runtime.
WiredHome 0:6339b3e34014 308 FlashFileSystemDirHandle m_DirHandles[NUM_CONCURRENT_DIRS];
WiredHome 0:6339b3e34014 309 // Pointer to where the file system image is located in the device's FLASH.
WiredHome 0:6339b3e34014 310 const char* m_pFLASHBase;
WiredHome 0:6339b3e34014 311 // Pointer to where the file entries are located in the device's FLASH.
WiredHome 0:6339b3e34014 312 const _SFileSystemEntry* m_pFileEntries;
WiredHome 0:6339b3e34014 313 // The number of files in the file system image.
WiredHome 0:6339b3e34014 314 unsigned int m_FileCount;
WiredHome 0:6339b3e34014 315 };
WiredHome 0:6339b3e34014 316
WiredHome 0:6339b3e34014 317 #endif // _FLASHFILESYSTEM_H_