The purpose of this application is to allow easy manipulation of the QSPI file system from a PC

Dependencies:   EALib USBDevice mbed

The purpose of this application is to allow easy manipulation of the QSPI file system from a PC.

The application makes the LPC4088 QuickStart Board appear as a USB Memory Stick when connected to a PC. The PC will see the current content of the QSPI file system plus an image file of the file system that can be downloaded and (at a later time) be used to restore the file system to it's current state.

To use this application:

  1. Make sure that the QSPI file system has been formatted (using either the app_qspi_format application or one of the erase.* images).
  2. Download the app_qspifs_memstick application using drag-n-drop and then reset the board
  3. Optionally start a terminal program to read the status messages from the application
  4. Connect a USB cable to the micro USB slot on the back of the LPC4088 QuickStart Board, underneath the ethernet connector, and then to the PC
  5. The PC will install drivers if needed and then the USB Memory Stick will be available as a new drive
  6. Modify the file system to suit your needs
  7. With the USB cable still connected, press the button on the LPC4088 QuickStart Board
  8. The application will now:
    1. disconnect the USB Memory Stick
    2. write all changes to the QSPI flash memory
    3. create a new image file of the updated QSPI file system and store it in the .current/ folder
    4. connect the USB Memory Stick again
  9. Continue from step 6. until satisfied

Note 1: The file system that is exposed is a copy (in SDRAM) of the QSPI file system. The reason for this is that the USBMSD class requires a FAT file system.

Note 2: The image files created in step 8.3 above will be a *.fsX file (where the 'X' is the size of the file system in MB so *.fs1 for a 1MByte file system). The *.fsX file extensions are recognized by the HDK and can be used to drag-n-drop to the MBED drive in the same way as the *.bin files are. A *.fsX file will not overwrite the program stored in internal flash.

Committer:
embeddedartists
Date:
Thu Sep 26 09:21:11 2013 +0000
Revision:
0:bd0d999bb6fb
First version

Who changed what in which revision?

UserRevisionLine numberNew contents of line
embeddedartists 0:bd0d999bb6fb 1 /******************************************************************************
embeddedartists 0:bd0d999bb6fb 2 * Includes
embeddedartists 0:bd0d999bb6fb 3 *****************************************************************************/
embeddedartists 0:bd0d999bb6fb 4
embeddedartists 0:bd0d999bb6fb 5 #include "mbed.h"
embeddedartists 0:bd0d999bb6fb 6
embeddedartists 0:bd0d999bb6fb 7 #include "QSPIFileSystem.h"
embeddedartists 0:bd0d999bb6fb 8
embeddedartists 0:bd0d999bb6fb 9 #include "USBMSD_RAMFS.h"
embeddedartists 0:bd0d999bb6fb 10 #include "RAMFileSystem.h"
embeddedartists 0:bd0d999bb6fb 11 #include "sdram.h"
embeddedartists 0:bd0d999bb6fb 12 #include "crc.h"
embeddedartists 0:bd0d999bb6fb 13
embeddedartists 0:bd0d999bb6fb 14 /******************************************************************************
embeddedartists 0:bd0d999bb6fb 15 * Typedefs and defines
embeddedartists 0:bd0d999bb6fb 16 *****************************************************************************/
embeddedartists 0:bd0d999bb6fb 17
embeddedartists 0:bd0d999bb6fb 18 typedef bool (*syncFunc)(const char* name, bool isDir);
embeddedartists 0:bd0d999bb6fb 19
embeddedartists 0:bd0d999bb6fb 20 #define RAM_FS_SIZE (20*1024*1024) //20MB
embeddedartists 0:bd0d999bb6fb 21
embeddedartists 0:bd0d999bb6fb 22 /******************************************************************************
embeddedartists 0:bd0d999bb6fb 23 * Local variables
embeddedartists 0:bd0d999bb6fb 24 *****************************************************************************/
embeddedartists 0:bd0d999bb6fb 25
embeddedartists 0:bd0d999bb6fb 26 QSPIFileSystem qspi("qspi");
embeddedartists 0:bd0d999bb6fb 27 //RAMFileSystem ramfs(0xA0000000, 20*1024*1024, "ram");
embeddedartists 0:bd0d999bb6fb 28 //USBMSD_RAMFS usbmsd(&ramfs);
embeddedartists 0:bd0d999bb6fb 29
embeddedartists 0:bd0d999bb6fb 30 DigitalOut myled1(LED1);
embeddedartists 0:bd0d999bb6fb 31 DigitalOut myled2(LED2);
embeddedartists 0:bd0d999bb6fb 32 DigitalIn button(p23);
embeddedartists 0:bd0d999bb6fb 33
embeddedartists 0:bd0d999bb6fb 34 DigitalOut myled(LED1);
embeddedartists 0:bd0d999bb6fb 35 static char lsbuff[NAME_MAX+1];
embeddedartists 0:bd0d999bb6fb 36
embeddedartists 0:bd0d999bb6fb 37 static char image_file_name[128] = { '\0' };
embeddedartists 0:bd0d999bb6fb 38
embeddedartists 0:bd0d999bb6fb 39 /******************************************************************************
embeddedartists 0:bd0d999bb6fb 40 * Local functions
embeddedartists 0:bd0d999bb6fb 41 *****************************************************************************/
embeddedartists 0:bd0d999bb6fb 42
embeddedartists 0:bd0d999bb6fb 43 static void ledShowProgress()
embeddedartists 0:bd0d999bb6fb 44 {
embeddedartists 0:bd0d999bb6fb 45 static int state = 0;
embeddedartists 0:bd0d999bb6fb 46 state = (state + 1) % 2;
embeddedartists 0:bd0d999bb6fb 47 switch (state)
embeddedartists 0:bd0d999bb6fb 48 {
embeddedartists 0:bd0d999bb6fb 49 case 0:
embeddedartists 0:bd0d999bb6fb 50 myled1 = 1;
embeddedartists 0:bd0d999bb6fb 51 myled2 = 0;
embeddedartists 0:bd0d999bb6fb 52 break;
embeddedartists 0:bd0d999bb6fb 53
embeddedartists 0:bd0d999bb6fb 54 case 1:
embeddedartists 0:bd0d999bb6fb 55 default:
embeddedartists 0:bd0d999bb6fb 56 myled1 = 0;
embeddedartists 0:bd0d999bb6fb 57 myled2 = 1;
embeddedartists 0:bd0d999bb6fb 58 }
embeddedartists 0:bd0d999bb6fb 59 }
embeddedartists 0:bd0d999bb6fb 60
embeddedartists 0:bd0d999bb6fb 61 static void handleError(const char* msg)
embeddedartists 0:bd0d999bb6fb 62 {
embeddedartists 0:bd0d999bb6fb 63 printf(msg);
embeddedartists 0:bd0d999bb6fb 64 while(true) {
embeddedartists 0:bd0d999bb6fb 65 myled1 = 1;
embeddedartists 0:bd0d999bb6fb 66 myled2 = 1;
embeddedartists 0:bd0d999bb6fb 67 wait(0.3);
embeddedartists 0:bd0d999bb6fb 68 myled1 = 0;
embeddedartists 0:bd0d999bb6fb 69 myled2 = 0;
embeddedartists 0:bd0d999bb6fb 70 wait(0.3);
embeddedartists 0:bd0d999bb6fb 71 }
embeddedartists 0:bd0d999bb6fb 72 }
embeddedartists 0:bd0d999bb6fb 73
embeddedartists 0:bd0d999bb6fb 74 static void waitForButtonPress()
embeddedartists 0:bd0d999bb6fb 75 {
embeddedartists 0:bd0d999bb6fb 76 printf("Press button to sync file systems\n");
embeddedartists 0:bd0d999bb6fb 77
embeddedartists 0:bd0d999bb6fb 78 myled1 = 1;
embeddedartists 0:bd0d999bb6fb 79 myled2 = 1;
embeddedartists 0:bd0d999bb6fb 80 while(button.read() == 1) {
embeddedartists 0:bd0d999bb6fb 81 wait(0.1);
embeddedartists 0:bd0d999bb6fb 82 }
embeddedartists 0:bd0d999bb6fb 83 myled1 = 0;
embeddedartists 0:bd0d999bb6fb 84 printf("Button pressed, now release it\n");
embeddedartists 0:bd0d999bb6fb 85 while(button.read() == 0) {
embeddedartists 0:bd0d999bb6fb 86 wait(0.1);
embeddedartists 0:bd0d999bb6fb 87 }
embeddedartists 0:bd0d999bb6fb 88 }
embeddedartists 0:bd0d999bb6fb 89
embeddedartists 0:bd0d999bb6fb 90 static void addNotFormattedFile()
embeddedartists 0:bd0d999bb6fb 91 {
embeddedartists 0:bd0d999bb6fb 92 FILE *fp = fopen("/ram/qspi_not_formatted.txt", "w");
embeddedartists 0:bd0d999bb6fb 93 if (fp != NULL) {
embeddedartists 0:bd0d999bb6fb 94 fprintf(fp, "The QSPI file system has not be formatted and this program can't do it.\n");
embeddedartists 0:bd0d999bb6fb 95 fprintf(fp, "Format the QSPI file system and then run this program again!\n");
embeddedartists 0:bd0d999bb6fb 96 fclose(fp);
embeddedartists 0:bd0d999bb6fb 97 }
embeddedartists 0:bd0d999bb6fb 98 }
embeddedartists 0:bd0d999bb6fb 99
embeddedartists 0:bd0d999bb6fb 100 static bool recursiveProcessFS(char* buff, const char* name, syncFunc func, bool adding)
embeddedartists 0:bd0d999bb6fb 101 {
embeddedartists 0:bd0d999bb6fb 102 uint32_t len = strlen(buff);
embeddedartists 0:bd0d999bb6fb 103 if (len > 0) {
embeddedartists 0:bd0d999bb6fb 104 if (buff[len - 1] != '/') {
embeddedartists 0:bd0d999bb6fb 105 buff[len++] = '/';
embeddedartists 0:bd0d999bb6fb 106 buff[len] = '\0';
embeddedartists 0:bd0d999bb6fb 107 }
embeddedartists 0:bd0d999bb6fb 108 }
embeddedartists 0:bd0d999bb6fb 109 strcat(buff, name);
embeddedartists 0:bd0d999bb6fb 110 len += strlen(name);
embeddedartists 0:bd0d999bb6fb 111
embeddedartists 0:bd0d999bb6fb 112 DIR *d = opendir(buff);
embeddedartists 0:bd0d999bb6fb 113 bool result = true; // success
embeddedartists 0:bd0d999bb6fb 114 if (d != NULL) {
embeddedartists 0:bd0d999bb6fb 115 if (adding) {
embeddedartists 0:bd0d999bb6fb 116 // when processing in adding mode folders must be created before it's content
embeddedartists 0:bd0d999bb6fb 117 result = func(buff, true);
embeddedartists 0:bd0d999bb6fb 118 }
embeddedartists 0:bd0d999bb6fb 119 struct dirent *p;
embeddedartists 0:bd0d999bb6fb 120 while (result && ((p = readdir(d)) != NULL)) {
embeddedartists 0:bd0d999bb6fb 121 result = recursiveProcessFS(buff, p->d_name, func, adding);
embeddedartists 0:bd0d999bb6fb 122 buff[len] = '\0';
embeddedartists 0:bd0d999bb6fb 123 }
embeddedartists 0:bd0d999bb6fb 124 closedir(d);
embeddedartists 0:bd0d999bb6fb 125 if (result && !adding) {
embeddedartists 0:bd0d999bb6fb 126 // when processing in removing mode folders must be deleted after it's content
embeddedartists 0:bd0d999bb6fb 127 result = func(buff, true);
embeddedartists 0:bd0d999bb6fb 128 }
embeddedartists 0:bd0d999bb6fb 129 } else {
embeddedartists 0:bd0d999bb6fb 130 // a file
embeddedartists 0:bd0d999bb6fb 131 result = func(buff, false);
embeddedartists 0:bd0d999bb6fb 132 }
embeddedartists 0:bd0d999bb6fb 133 return result;
embeddedartists 0:bd0d999bb6fb 134 }
embeddedartists 0:bd0d999bb6fb 135
embeddedartists 0:bd0d999bb6fb 136 static uint32_t fileLen(FILE* f)
embeddedartists 0:bd0d999bb6fb 137 {
embeddedartists 0:bd0d999bb6fb 138 uint32_t pos = ftell(f);
embeddedartists 0:bd0d999bb6fb 139 fseek(f, 0, SEEK_END);
embeddedartists 0:bd0d999bb6fb 140 uint32_t size = ftell(f);
embeddedartists 0:bd0d999bb6fb 141 fseek(f, pos, SEEK_SET);
embeddedartists 0:bd0d999bb6fb 142 return size;
embeddedartists 0:bd0d999bb6fb 143 }
embeddedartists 0:bd0d999bb6fb 144
embeddedartists 0:bd0d999bb6fb 145 static bool copy(FILE* fSrc, FILE* fDst)
embeddedartists 0:bd0d999bb6fb 146 {
embeddedartists 0:bd0d999bb6fb 147 char buff[512];
embeddedartists 0:bd0d999bb6fb 148 uint32_t left = fileLen(fSrc);
embeddedartists 0:bd0d999bb6fb 149 uint32_t num;
embeddedartists 0:bd0d999bb6fb 150 uint32_t chunk;
embeddedartists 0:bd0d999bb6fb 151
embeddedartists 0:bd0d999bb6fb 152 fseek(fSrc, 0, SEEK_SET);
embeddedartists 0:bd0d999bb6fb 153 do {
embeddedartists 0:bd0d999bb6fb 154 chunk = (left < 512) ? left : 512;
embeddedartists 0:bd0d999bb6fb 155 num = fread(buff, 1, chunk, fSrc);
embeddedartists 0:bd0d999bb6fb 156 if (num > 0) {
embeddedartists 0:bd0d999bb6fb 157 uint32_t tmp = fwrite(buff, 1, num, fDst);
embeddedartists 0:bd0d999bb6fb 158 if (tmp != num) {
embeddedartists 0:bd0d999bb6fb 159 // failed to write
embeddedartists 0:bd0d999bb6fb 160 return false;
embeddedartists 0:bd0d999bb6fb 161 }
embeddedartists 0:bd0d999bb6fb 162 left -= num;
embeddedartists 0:bd0d999bb6fb 163 ledShowProgress();
embeddedartists 0:bd0d999bb6fb 164 }
embeddedartists 0:bd0d999bb6fb 165 } while(num > 0 && left > 0);
embeddedartists 0:bd0d999bb6fb 166
embeddedartists 0:bd0d999bb6fb 167 // copied entire file
embeddedartists 0:bd0d999bb6fb 168 return true;
embeddedartists 0:bd0d999bb6fb 169 }
embeddedartists 0:bd0d999bb6fb 170
embeddedartists 0:bd0d999bb6fb 171 static bool identicalFiles(const char* srcName, const char* dstName)
embeddedartists 0:bd0d999bb6fb 172 {
embeddedartists 0:bd0d999bb6fb 173 FILE* fSrc = NULL;
embeddedartists 0:bd0d999bb6fb 174 FILE* fDst = NULL;
embeddedartists 0:bd0d999bb6fb 175 bool identical = false;
embeddedartists 0:bd0d999bb6fb 176 do
embeddedartists 0:bd0d999bb6fb 177 {
embeddedartists 0:bd0d999bb6fb 178 fSrc = fopen(srcName, "r");
embeddedartists 0:bd0d999bb6fb 179 if (fSrc == NULL) {
embeddedartists 0:bd0d999bb6fb 180 break;
embeddedartists 0:bd0d999bb6fb 181 }
embeddedartists 0:bd0d999bb6fb 182 fDst = fopen(dstName, "r");
embeddedartists 0:bd0d999bb6fb 183 if (fDst == NULL) {
embeddedartists 0:bd0d999bb6fb 184 break;
embeddedartists 0:bd0d999bb6fb 185 }
embeddedartists 0:bd0d999bb6fb 186 if (fileLen(fSrc) != fileLen(fDst)) {
embeddedartists 0:bd0d999bb6fb 187 break;
embeddedartists 0:bd0d999bb6fb 188 }
embeddedartists 0:bd0d999bb6fb 189 if (crc_Read(fSrc) != crc_Read(fDst)) {
embeddedartists 0:bd0d999bb6fb 190 break;
embeddedartists 0:bd0d999bb6fb 191 }
embeddedartists 0:bd0d999bb6fb 192
embeddedartists 0:bd0d999bb6fb 193 // All tests passed so the files are identical
embeddedartists 0:bd0d999bb6fb 194 identical = true;
embeddedartists 0:bd0d999bb6fb 195
embeddedartists 0:bd0d999bb6fb 196 } while(false);
embeddedartists 0:bd0d999bb6fb 197
embeddedartists 0:bd0d999bb6fb 198 if (fSrc != NULL) {
embeddedartists 0:bd0d999bb6fb 199 fclose(fSrc);
embeddedartists 0:bd0d999bb6fb 200 }
embeddedartists 0:bd0d999bb6fb 201 if (fDst != NULL) {
embeddedartists 0:bd0d999bb6fb 202 fclose(fDst);
embeddedartists 0:bd0d999bb6fb 203 }
embeddedartists 0:bd0d999bb6fb 204
embeddedartists 0:bd0d999bb6fb 205 return identical;
embeddedartists 0:bd0d999bb6fb 206 }
embeddedartists 0:bd0d999bb6fb 207
embeddedartists 0:bd0d999bb6fb 208 static bool addExisting(const char* srcName, bool isDir, const char* dstName)
embeddedartists 0:bd0d999bb6fb 209 {
embeddedartists 0:bd0d999bb6fb 210 bool result = true; // success
embeddedartists 0:bd0d999bb6fb 211 if (isDir) {
embeddedartists 0:bd0d999bb6fb 212 DIR *d = opendir(dstName);
embeddedartists 0:bd0d999bb6fb 213 if (d == NULL) {
embeddedartists 0:bd0d999bb6fb 214 if (dstName[1] != 'r') { printf("%s, new dir, adding\n", dstName); }
embeddedartists 0:bd0d999bb6fb 215 if (mkdir(dstName, 0) != 0) {
embeddedartists 0:bd0d999bb6fb 216 printf("Failed to create folder %s\n", dstName);
embeddedartists 0:bd0d999bb6fb 217 result = false; // dir did not exist and could not be created
embeddedartists 0:bd0d999bb6fb 218 }
embeddedartists 0:bd0d999bb6fb 219 } else {
embeddedartists 0:bd0d999bb6fb 220 closedir(d);
embeddedartists 0:bd0d999bb6fb 221 }
embeddedartists 0:bd0d999bb6fb 222 } else if (!identicalFiles(srcName, dstName)) {
embeddedartists 0:bd0d999bb6fb 223 // Compare the files to avoid replacing with same
embeddedartists 0:bd0d999bb6fb 224 FILE* fSrc = fopen(srcName, "r");
embeddedartists 0:bd0d999bb6fb 225 if (fSrc != NULL) {
embeddedartists 0:bd0d999bb6fb 226 FILE* fDst = fopen(dstName, "w"); // open and truncate
embeddedartists 0:bd0d999bb6fb 227 if (fDst != NULL) {
embeddedartists 0:bd0d999bb6fb 228 if (dstName[1] != 'r') { printf("%s, changed, updating\n", dstName); }
embeddedartists 0:bd0d999bb6fb 229 result = copy(fSrc, fDst);
embeddedartists 0:bd0d999bb6fb 230 if (!result) {
embeddedartists 0:bd0d999bb6fb 231 printf("Failed to copy %s to %s\n", srcName, dstName);
embeddedartists 0:bd0d999bb6fb 232 }
embeddedartists 0:bd0d999bb6fb 233 fclose(fDst);
embeddedartists 0:bd0d999bb6fb 234 } else {
embeddedartists 0:bd0d999bb6fb 235 printf("Failed to create file %s\n", dstName);
embeddedartists 0:bd0d999bb6fb 236 result = false; // unable to create file
embeddedartists 0:bd0d999bb6fb 237 }
embeddedartists 0:bd0d999bb6fb 238 fclose(fSrc);
embeddedartists 0:bd0d999bb6fb 239 } else {
embeddedartists 0:bd0d999bb6fb 240 printf("Failed to copen source file file %s\n", srcName);
embeddedartists 0:bd0d999bb6fb 241 result = false; // unable to open source
embeddedartists 0:bd0d999bb6fb 242 }
embeddedartists 0:bd0d999bb6fb 243 } else {
embeddedartists 0:bd0d999bb6fb 244 if (dstName[1] != 'r') { printf("%s identical, skipping\n", dstName); }
embeddedartists 0:bd0d999bb6fb 245 }
embeddedartists 0:bd0d999bb6fb 246 return result;
embeddedartists 0:bd0d999bb6fb 247 }
embeddedartists 0:bd0d999bb6fb 248
embeddedartists 0:bd0d999bb6fb 249 static bool addExistingToQspi(const char* name, bool isDir)
embeddedartists 0:bd0d999bb6fb 250 {
embeddedartists 0:bd0d999bb6fb 251 // create the target file name by replacing /ram/ with /qspi/
embeddedartists 0:bd0d999bb6fb 252 char buff[256];
embeddedartists 0:bd0d999bb6fb 253 buff[0] = '\0';
embeddedartists 0:bd0d999bb6fb 254 strcat(buff, "/qspi/");
embeddedartists 0:bd0d999bb6fb 255 strcat(buff, name+5);
embeddedartists 0:bd0d999bb6fb 256
embeddedartists 0:bd0d999bb6fb 257 // Don't add the file created by createImageFile()
embeddedartists 0:bd0d999bb6fb 258 if (strcmp(name, image_file_name) == 0) {
embeddedartists 0:bd0d999bb6fb 259 return true;
embeddedartists 0:bd0d999bb6fb 260 }
embeddedartists 0:bd0d999bb6fb 261
embeddedartists 0:bd0d999bb6fb 262 return addExisting(name, isDir, buff);
embeddedartists 0:bd0d999bb6fb 263 }
embeddedartists 0:bd0d999bb6fb 264
embeddedartists 0:bd0d999bb6fb 265 static bool addExistingToRAM(const char* name, bool isDir)
embeddedartists 0:bd0d999bb6fb 266 {
embeddedartists 0:bd0d999bb6fb 267 // create the target file name by replacing /qspi/ with /ram/
embeddedartists 0:bd0d999bb6fb 268 char buff[256];
embeddedartists 0:bd0d999bb6fb 269 buff[0] = '\0';
embeddedartists 0:bd0d999bb6fb 270 strcat(buff, "/ram/");
embeddedartists 0:bd0d999bb6fb 271 strcat(buff, name+6);
embeddedartists 0:bd0d999bb6fb 272 return addExisting(name, isDir, buff);
embeddedartists 0:bd0d999bb6fb 273 }
embeddedartists 0:bd0d999bb6fb 274
embeddedartists 0:bd0d999bb6fb 275 static bool removeIfMissing(const char* toLookFor, const char* toRemove, bool isDir)
embeddedartists 0:bd0d999bb6fb 276 {
embeddedartists 0:bd0d999bb6fb 277 int result = 0; //success
embeddedartists 0:bd0d999bb6fb 278 if (isDir) {
embeddedartists 0:bd0d999bb6fb 279 DIR *d = opendir(toLookFor);
embeddedartists 0:bd0d999bb6fb 280 if (d == NULL) {
embeddedartists 0:bd0d999bb6fb 281 // dir doesn't exist => delete it
embeddedartists 0:bd0d999bb6fb 282 if (toRemove[1] != 'r') { printf("%s, missing, deleting dir\n", toRemove); }
embeddedartists 0:bd0d999bb6fb 283 result = remove(toRemove);
embeddedartists 0:bd0d999bb6fb 284 ledShowProgress();
embeddedartists 0:bd0d999bb6fb 285 } else {
embeddedartists 0:bd0d999bb6fb 286 // dir exist => don't delete
embeddedartists 0:bd0d999bb6fb 287 closedir(d);
embeddedartists 0:bd0d999bb6fb 288 }
embeddedartists 0:bd0d999bb6fb 289 } else {
embeddedartists 0:bd0d999bb6fb 290 FILE* f = fopen(toLookFor, "r");
embeddedartists 0:bd0d999bb6fb 291 if (f == NULL) {
embeddedartists 0:bd0d999bb6fb 292 // file doesn't exist => delete it
embeddedartists 0:bd0d999bb6fb 293 if (toRemove[1] != 'r') { printf("%s, missing, deleting file\n", toRemove); }
embeddedartists 0:bd0d999bb6fb 294 result = remove(toRemove);
embeddedartists 0:bd0d999bb6fb 295 ledShowProgress();
embeddedartists 0:bd0d999bb6fb 296 } else {
embeddedartists 0:bd0d999bb6fb 297 // file exist => don't delete
embeddedartists 0:bd0d999bb6fb 298 fclose(f);
embeddedartists 0:bd0d999bb6fb 299 }
embeddedartists 0:bd0d999bb6fb 300 }
embeddedartists 0:bd0d999bb6fb 301 return (result == 0);
embeddedartists 0:bd0d999bb6fb 302 }
embeddedartists 0:bd0d999bb6fb 303
embeddedartists 0:bd0d999bb6fb 304 static bool removeMissingFromQspi(const char* name, bool isDir)
embeddedartists 0:bd0d999bb6fb 305 {
embeddedartists 0:bd0d999bb6fb 306 // create the target file name by replacing /qspi/ with /ram/
embeddedartists 0:bd0d999bb6fb 307 char buff[256];
embeddedartists 0:bd0d999bb6fb 308 buff[0] = '\0';
embeddedartists 0:bd0d999bb6fb 309 strcat(buff, "/ram/");
embeddedartists 0:bd0d999bb6fb 310 strcat(buff, name+6);
embeddedartists 0:bd0d999bb6fb 311 removeIfMissing(buff, name, isDir);
embeddedartists 0:bd0d999bb6fb 312 return true;
embeddedartists 0:bd0d999bb6fb 313 }
embeddedartists 0:bd0d999bb6fb 314
embeddedartists 0:bd0d999bb6fb 315 static bool removeMissingFromRAM(const char* name, bool isDir)
embeddedartists 0:bd0d999bb6fb 316 {
embeddedartists 0:bd0d999bb6fb 317 // create the target file name by replacing /ram/ with /qspi/
embeddedartists 0:bd0d999bb6fb 318 char buff[256];
embeddedartists 0:bd0d999bb6fb 319 buff[0] = '\0';
embeddedartists 0:bd0d999bb6fb 320 strcat(buff, "/qspi/");
embeddedartists 0:bd0d999bb6fb 321 strcat(buff, name+5);
embeddedartists 0:bd0d999bb6fb 322
embeddedartists 0:bd0d999bb6fb 323 // Don't remove the file created by createImageFile()
embeddedartists 0:bd0d999bb6fb 324 if (strcmp(name, image_file_name) == 0) {
embeddedartists 0:bd0d999bb6fb 325 return true;
embeddedartists 0:bd0d999bb6fb 326 }
embeddedartists 0:bd0d999bb6fb 327
embeddedartists 0:bd0d999bb6fb 328 removeIfMissing(buff, name, isDir);
embeddedartists 0:bd0d999bb6fb 329 return true;
embeddedartists 0:bd0d999bb6fb 330 }
embeddedartists 0:bd0d999bb6fb 331
embeddedartists 0:bd0d999bb6fb 332 static void syncDir(const char* to, const char* from)
embeddedartists 0:bd0d999bb6fb 333 {
embeddedartists 0:bd0d999bb6fb 334 printf("Starting to sync %s on top of %s (This may take time. LED1 & 2 blink for each file)\n", from, to);
embeddedartists 0:bd0d999bb6fb 335
embeddedartists 0:bd0d999bb6fb 336 char* buff = (char*)malloc(512);
embeddedartists 0:bd0d999bb6fb 337 if (buff != NULL)
embeddedartists 0:bd0d999bb6fb 338 {
embeddedartists 0:bd0d999bb6fb 339 buff[0] = '\0';
embeddedartists 0:bd0d999bb6fb 340 if (strcmp(to, "/qspi/") == 0) {
embeddedartists 0:bd0d999bb6fb 341 if (!recursiveProcessFS(buff, to, removeMissingFromQspi, false)) {
embeddedartists 0:bd0d999bb6fb 342 printf("Failed to remove files from %s that were missing on %s\n", to, from);
embeddedartists 0:bd0d999bb6fb 343 } else {
embeddedartists 0:bd0d999bb6fb 344 buff[0] = '\0';
embeddedartists 0:bd0d999bb6fb 345 if (!recursiveProcessFS(buff, from, addExistingToQspi, true)) {
embeddedartists 0:bd0d999bb6fb 346 printf("Failed to add files to %s that existed on %s\n", to, from);
embeddedartists 0:bd0d999bb6fb 347 }
embeddedartists 0:bd0d999bb6fb 348 }
embeddedartists 0:bd0d999bb6fb 349 } else {
embeddedartists 0:bd0d999bb6fb 350 if (!recursiveProcessFS(buff, to, removeMissingFromRAM, false)) {
embeddedartists 0:bd0d999bb6fb 351 printf("Failed to remove files from %s that were missing on %s\n", to, from);
embeddedartists 0:bd0d999bb6fb 352 } else {
embeddedartists 0:bd0d999bb6fb 353 buff[0] = '\0';
embeddedartists 0:bd0d999bb6fb 354 if (!recursiveProcessFS(buff, from, addExistingToRAM, true)) {
embeddedartists 0:bd0d999bb6fb 355 printf("Failed to add files to %s that existed on %s\n", to, from);
embeddedartists 0:bd0d999bb6fb 356 }
embeddedartists 0:bd0d999bb6fb 357 }
embeddedartists 0:bd0d999bb6fb 358 }
embeddedartists 0:bd0d999bb6fb 359 free(buff);
embeddedartists 0:bd0d999bb6fb 360 }
embeddedartists 0:bd0d999bb6fb 361 printf("Sync completed\n");
embeddedartists 0:bd0d999bb6fb 362 }
embeddedartists 0:bd0d999bb6fb 363
embeddedartists 0:bd0d999bb6fb 364
embeddedartists 0:bd0d999bb6fb 365 static void createImageFile()
embeddedartists 0:bd0d999bb6fb 366 {
embeddedartists 0:bd0d999bb6fb 367 uint32_t startAddr;
embeddedartists 0:bd0d999bb6fb 368 uint32_t endAddr;
embeddedartists 0:bd0d999bb6fb 369 uint32_t size;
embeddedartists 0:bd0d999bb6fb 370
embeddedartists 0:bd0d999bb6fb 371 printf("Creating image of existing (if any) QSPI file system\n");
embeddedartists 0:bd0d999bb6fb 372
embeddedartists 0:bd0d999bb6fb 373 if (!qspi.getMemoryBoundaries(&startAddr, &endAddr))
embeddedartists 0:bd0d999bb6fb 374 {
embeddedartists 0:bd0d999bb6fb 375 handleError("QSPI FS not formatted or impossible to determine it's size\n");
embeddedartists 0:bd0d999bb6fb 376 }
embeddedartists 0:bd0d999bb6fb 377
embeddedartists 0:bd0d999bb6fb 378 // Align the start address to an even multiple of 1MB
embeddedartists 0:bd0d999bb6fb 379 startAddr = startAddr & 0xfff00000;
embeddedartists 0:bd0d999bb6fb 380
embeddedartists 0:bd0d999bb6fb 381 // Update the file to match the size of the file system
embeddedartists 0:bd0d999bb6fb 382 size = endAddr - startAddr;
embeddedartists 0:bd0d999bb6fb 383 if ((size < 0x00100000) || (size > 0x00800000) || ((size & 0xfffff) > 0))
embeddedartists 0:bd0d999bb6fb 384 {
embeddedartists 0:bd0d999bb6fb 385 sprintf(lsbuff, "QSPI FS size is not supported (%u bytes)\n", size);
embeddedartists 0:bd0d999bb6fb 386 handleError(lsbuff);
embeddedartists 0:bd0d999bb6fb 387 }
embeddedartists 0:bd0d999bb6fb 388 sprintf(image_file_name, "/ram/.current/fs_image.fs%d", (size >> 20));
embeddedartists 0:bd0d999bb6fb 389
embeddedartists 0:bd0d999bb6fb 390 // NOTE: The line below is very very !!!! important. For some weird reason the
embeddedartists 0:bd0d999bb6fb 391 // RAM file system must have at least one folder on it before USB is connected.
embeddedartists 0:bd0d999bb6fb 392 // If the RAM file system doesn't have any folders on it the result is that
embeddedartists 0:bd0d999bb6fb 393 // the content of the RAM file system will be the same after USB is disconnected
embeddedartists 0:bd0d999bb6fb 394 // as it was before connecting - regardless of what is added. Very strange indeed.
embeddedartists 0:bd0d999bb6fb 395 mkdir("/ram/.current", 0);
embeddedartists 0:bd0d999bb6fb 396
embeddedartists 0:bd0d999bb6fb 397 printf("QSPI FS max size is %d MB\n", (size >> 20));
embeddedartists 0:bd0d999bb6fb 398
embeddedartists 0:bd0d999bb6fb 399 FILE *fp = fopen(image_file_name, "w");
embeddedartists 0:bd0d999bb6fb 400 if (fp != NULL)
embeddedartists 0:bd0d999bb6fb 401 {
embeddedartists 0:bd0d999bb6fb 402 while (size > 0)
embeddedartists 0:bd0d999bb6fb 403 {
embeddedartists 0:bd0d999bb6fb 404 uint32_t written = fwrite((char*)(endAddr - size), 1, size, fp);
embeddedartists 0:bd0d999bb6fb 405 size -= written;
embeddedartists 0:bd0d999bb6fb 406 if (written == 0)
embeddedartists 0:bd0d999bb6fb 407 {
embeddedartists 0:bd0d999bb6fb 408 handleError("Failed to create QSPI image file\n");
embeddedartists 0:bd0d999bb6fb 409 }
embeddedartists 0:bd0d999bb6fb 410 }
embeddedartists 0:bd0d999bb6fb 411 fclose(fp);
embeddedartists 0:bd0d999bb6fb 412 }
embeddedartists 0:bd0d999bb6fb 413 }
embeddedartists 0:bd0d999bb6fb 414
embeddedartists 0:bd0d999bb6fb 415 static bool list(const char* name, bool isDir)
embeddedartists 0:bd0d999bb6fb 416 {
embeddedartists 0:bd0d999bb6fb 417 if (isDir) {
embeddedartists 0:bd0d999bb6fb 418 printf("d: %s\n", name);
embeddedartists 0:bd0d999bb6fb 419 } else {
embeddedartists 0:bd0d999bb6fb 420 FILE* f = fopen(name, "r");
embeddedartists 0:bd0d999bb6fb 421 if (f != NULL) {
embeddedartists 0:bd0d999bb6fb 422 uint32_t len = fileLen(f);
embeddedartists 0:bd0d999bb6fb 423 printf("f: %7u %s\n", len, name);
embeddedartists 0:bd0d999bb6fb 424 fclose(f);
embeddedartists 0:bd0d999bb6fb 425 } else {
embeddedartists 0:bd0d999bb6fb 426 printf("f: ??? %s\n", name);
embeddedartists 0:bd0d999bb6fb 427 }
embeddedartists 0:bd0d999bb6fb 428 }
embeddedartists 0:bd0d999bb6fb 429 return true;
embeddedartists 0:bd0d999bb6fb 430 }
embeddedartists 0:bd0d999bb6fb 431
embeddedartists 0:bd0d999bb6fb 432 static void recursiveList(const char* dirname)
embeddedartists 0:bd0d999bb6fb 433 {
embeddedartists 0:bd0d999bb6fb 434 printf("\nRecursive list of file and folders in %s\n", dirname);
embeddedartists 0:bd0d999bb6fb 435 char* buff = (char*)malloc(512);
embeddedartists 0:bd0d999bb6fb 436 if (buff != NULL)
embeddedartists 0:bd0d999bb6fb 437 {
embeddedartists 0:bd0d999bb6fb 438 buff[0] = '\0';
embeddedartists 0:bd0d999bb6fb 439 recursiveProcessFS(buff, dirname, list, true);
embeddedartists 0:bd0d999bb6fb 440 free(buff);
embeddedartists 0:bd0d999bb6fb 441 }
embeddedartists 0:bd0d999bb6fb 442 }
embeddedartists 0:bd0d999bb6fb 443
embeddedartists 0:bd0d999bb6fb 444 /******************************************************************************
embeddedartists 0:bd0d999bb6fb 445 * Main function
embeddedartists 0:bd0d999bb6fb 446 *****************************************************************************/
embeddedartists 0:bd0d999bb6fb 447 int main()
embeddedartists 0:bd0d999bb6fb 448 {
embeddedartists 0:bd0d999bb6fb 449 printf("\n-----------------\n\nWelcome to the QSPI file system tool...\n");
embeddedartists 0:bd0d999bb6fb 450
embeddedartists 0:bd0d999bb6fb 451 // 1) Make sure that the button works
embeddedartists 0:bd0d999bb6fb 452 // 2) Init SDRAM and allocate space for the RAM file system
embeddedartists 0:bd0d999bb6fb 453 // 3) Setup RAM FS
embeddedartists 0:bd0d999bb6fb 454 // 4a) If QSPI FS is not formatted:
embeddedartists 0:bd0d999bb6fb 455 // i) Create a "qspi_not_formatted.txt" file in the root of the file system
embeddedartists 0:bd0d999bb6fb 456 // 4b) QSPI FS formatted
embeddedartists 0:bd0d999bb6fb 457 // i) Create an image file of the QSPI FS
embeddedartists 0:bd0d999bb6fb 458 // ii) Sync QSPI FS on top of RAM FS
embeddedartists 0:bd0d999bb6fb 459 // 5) Connect USB
embeddedartists 0:bd0d999bb6fb 460 // 6a) If QSPI FS is not formatted: Loop forever doing nothing
embeddedartists 0:bd0d999bb6fb 461 // 6b) QSPI FS formatted: Wait for button press
embeddedartists 0:bd0d999bb6fb 462 // 7) Button pressed, Disconnect USB
embeddedartists 0:bd0d999bb6fb 463 // 8) QSPI formatted
embeddedartists 0:bd0d999bb6fb 464 // i) Sync RAM FS on top of QSPI FS
embeddedartists 0:bd0d999bb6fb 465 // ii) Goto 3)
embeddedartists 0:bd0d999bb6fb 466 //
embeddedartists 0:bd0d999bb6fb 467
embeddedartists 0:bd0d999bb6fb 468 // 1)
embeddedartists 0:bd0d999bb6fb 469 button.mode(PullUp);
embeddedartists 0:bd0d999bb6fb 470
embeddedartists 0:bd0d999bb6fb 471 // 2)
embeddedartists 0:bd0d999bb6fb 472 if (sdram_init()) {
embeddedartists 0:bd0d999bb6fb 473 handleError("Failed to initialize SDRAM\n");
embeddedartists 0:bd0d999bb6fb 474 }
embeddedartists 0:bd0d999bb6fb 475
embeddedartists 0:bd0d999bb6fb 476 void* fsmem = malloc(RAM_FS_SIZE);
embeddedartists 0:bd0d999bb6fb 477 if (fsmem == NULL) {
embeddedartists 0:bd0d999bb6fb 478 handleError("Failed to allocate memory for RAM file system\n");
embeddedartists 0:bd0d999bb6fb 479 }
embeddedartists 0:bd0d999bb6fb 480 RAMFileSystem ramfs((uint32_t)fsmem, RAM_FS_SIZE, "ram");
embeddedartists 0:bd0d999bb6fb 481 USBMSD_RAMFS usbmsd(&ramfs);
embeddedartists 0:bd0d999bb6fb 482
embeddedartists 0:bd0d999bb6fb 483 while(true)
embeddedartists 0:bd0d999bb6fb 484 {
embeddedartists 0:bd0d999bb6fb 485 // 3)
embeddedartists 0:bd0d999bb6fb 486 ramfs.format();
embeddedartists 0:bd0d999bb6fb 487
embeddedartists 0:bd0d999bb6fb 488 // 4a)
embeddedartists 0:bd0d999bb6fb 489 bool qspiFormatted = qspi.isformatted();
embeddedartists 0:bd0d999bb6fb 490 if (!qspiFormatted)
embeddedartists 0:bd0d999bb6fb 491 {
embeddedartists 0:bd0d999bb6fb 492 addNotFormattedFile();
embeddedartists 0:bd0d999bb6fb 493 }
embeddedartists 0:bd0d999bb6fb 494
embeddedartists 0:bd0d999bb6fb 495 // 4b)
embeddedartists 0:bd0d999bb6fb 496 else
embeddedartists 0:bd0d999bb6fb 497 {
embeddedartists 0:bd0d999bb6fb 498 //addTestFile();
embeddedartists 0:bd0d999bb6fb 499 createImageFile();
embeddedartists 0:bd0d999bb6fb 500
embeddedartists 0:bd0d999bb6fb 501 // Copy QSPI FS to RAM FS
embeddedartists 0:bd0d999bb6fb 502 syncDir("/ram/", "/qspi/");
embeddedartists 0:bd0d999bb6fb 503 }
embeddedartists 0:bd0d999bb6fb 504
embeddedartists 0:bd0d999bb6fb 505 // 5)
embeddedartists 0:bd0d999bb6fb 506 printf("Insert the USB cable!\n");
embeddedartists 0:bd0d999bb6fb 507 printf("Starting USB...\n");
embeddedartists 0:bd0d999bb6fb 508 for (int i = 0; i < 10; i++)
embeddedartists 0:bd0d999bb6fb 509 {
embeddedartists 0:bd0d999bb6fb 510 if (usbmsd.connect())
embeddedartists 0:bd0d999bb6fb 511 {
embeddedartists 0:bd0d999bb6fb 512 printf("Connected!\n");
embeddedartists 0:bd0d999bb6fb 513 break;
embeddedartists 0:bd0d999bb6fb 514 }
embeddedartists 0:bd0d999bb6fb 515 printf("Failed to connect USB, testing again...\n");
embeddedartists 0:bd0d999bb6fb 516 printf("Insert (or remove and then insert) the USB cable!\n");
embeddedartists 0:bd0d999bb6fb 517 wait(1);
embeddedartists 0:bd0d999bb6fb 518 }
embeddedartists 0:bd0d999bb6fb 519
embeddedartists 0:bd0d999bb6fb 520 // 6b)
embeddedartists 0:bd0d999bb6fb 521 if (qspiFormatted)
embeddedartists 0:bd0d999bb6fb 522 {
embeddedartists 0:bd0d999bb6fb 523 waitForButtonPress();
embeddedartists 0:bd0d999bb6fb 524 }
embeddedartists 0:bd0d999bb6fb 525 else
embeddedartists 0:bd0d999bb6fb 526 {
embeddedartists 0:bd0d999bb6fb 527 // 6a) no point in waiting for buttons if no file system
embeddedartists 0:bd0d999bb6fb 528 while (1) {};
embeddedartists 0:bd0d999bb6fb 529 }
embeddedartists 0:bd0d999bb6fb 530
embeddedartists 0:bd0d999bb6fb 531 // 7)
embeddedartists 0:bd0d999bb6fb 532 usbmsd.disconnect();
embeddedartists 0:bd0d999bb6fb 533 printf("Disconnected!\n");
embeddedartists 0:bd0d999bb6fb 534
embeddedartists 0:bd0d999bb6fb 535 // 8) Copy RAM FS to QSPI FS
embeddedartists 0:bd0d999bb6fb 536 recursiveList("/ram/");
embeddedartists 0:bd0d999bb6fb 537 syncDir("/qspi/", "/ram/");
embeddedartists 0:bd0d999bb6fb 538 }
embeddedartists 0:bd0d999bb6fb 539 }