The purpose of this application is to allow easy manipulation of the QSPI file system from a PC
Dependencies: EALib USBDevice mbed
main.cpp
00001 /****************************************************************************** 00002 * Includes 00003 *****************************************************************************/ 00004 00005 #include "mbed.h" 00006 00007 #include "QSPIFileSystem.h" 00008 00009 #include "USBMSD_RAMFS.h" 00010 #include "RAMFileSystem.h" 00011 #include "sdram.h" 00012 #include "crc.h" 00013 00014 /****************************************************************************** 00015 * Typedefs and defines 00016 *****************************************************************************/ 00017 00018 typedef bool (*syncFunc)(const char* name, bool isDir); 00019 00020 #define RAM_FS_SIZE (20*1024*1024) //20MB 00021 00022 /****************************************************************************** 00023 * Local variables 00024 *****************************************************************************/ 00025 00026 QSPIFileSystem qspi("qspi"); 00027 //RAMFileSystem ramfs(0xA0000000, 20*1024*1024, "ram"); 00028 //USBMSD_RAMFS usbmsd(&ramfs); 00029 00030 DigitalOut myled1(LED1); 00031 DigitalOut myled2(LED2); 00032 DigitalIn button(p23); 00033 00034 DigitalOut myled(LED1); 00035 static char lsbuff[NAME_MAX+1]; 00036 00037 static char image_file_name[128] = { '\0' }; 00038 00039 /****************************************************************************** 00040 * Local functions 00041 *****************************************************************************/ 00042 00043 static void ledShowProgress() 00044 { 00045 static int state = 0; 00046 state = (state + 1) % 2; 00047 switch (state) 00048 { 00049 case 0: 00050 myled1 = 1; 00051 myled2 = 0; 00052 break; 00053 00054 case 1: 00055 default: 00056 myled1 = 0; 00057 myled2 = 1; 00058 } 00059 } 00060 00061 static void handleError(const char* msg) 00062 { 00063 printf(msg); 00064 while(true) { 00065 myled1 = 1; 00066 myled2 = 1; 00067 wait(0.3); 00068 myled1 = 0; 00069 myled2 = 0; 00070 wait(0.3); 00071 } 00072 } 00073 00074 static void waitForButtonPress() 00075 { 00076 printf("Press button to sync file systems\n"); 00077 00078 myled1 = 1; 00079 myled2 = 1; 00080 while(button.read() == 1) { 00081 wait(0.1); 00082 } 00083 myled1 = 0; 00084 printf("Button pressed, now release it\n"); 00085 while(button.read() == 0) { 00086 wait(0.1); 00087 } 00088 } 00089 00090 static void addNotFormattedFile() 00091 { 00092 FILE *fp = fopen("/ram/qspi_not_formatted.txt", "w"); 00093 if (fp != NULL) { 00094 fprintf(fp, "The QSPI file system has not be formatted and this program can't do it.\n"); 00095 fprintf(fp, "Format the QSPI file system and then run this program again!\n"); 00096 fclose(fp); 00097 } 00098 } 00099 00100 static bool recursiveProcessFS(char* buff, const char* name, syncFunc func, bool adding) 00101 { 00102 uint32_t len = strlen(buff); 00103 if (len > 0) { 00104 if (buff[len - 1] != '/') { 00105 buff[len++] = '/'; 00106 buff[len] = '\0'; 00107 } 00108 } 00109 strcat(buff, name); 00110 len += strlen(name); 00111 00112 DIR *d = opendir(buff); 00113 bool result = true; // success 00114 if (d != NULL) { 00115 if (adding) { 00116 // when processing in adding mode folders must be created before it's content 00117 result = func(buff, true); 00118 } 00119 struct dirent *p; 00120 while (result && ((p = readdir(d)) != NULL)) { 00121 result = recursiveProcessFS(buff, p->d_name, func, adding); 00122 buff[len] = '\0'; 00123 } 00124 closedir(d); 00125 if (result && !adding) { 00126 // when processing in removing mode folders must be deleted after it's content 00127 result = func(buff, true); 00128 } 00129 } else { 00130 // a file 00131 result = func(buff, false); 00132 } 00133 return result; 00134 } 00135 00136 static uint32_t fileLen(FILE* f) 00137 { 00138 uint32_t pos = ftell(f); 00139 fseek(f, 0, SEEK_END); 00140 uint32_t size = ftell(f); 00141 fseek(f, pos, SEEK_SET); 00142 return size; 00143 } 00144 00145 static bool copy(FILE* fSrc, FILE* fDst) 00146 { 00147 char buff[512]; 00148 uint32_t left = fileLen(fSrc); 00149 uint32_t num; 00150 uint32_t chunk; 00151 00152 fseek(fSrc, 0, SEEK_SET); 00153 do { 00154 chunk = (left < 512) ? left : 512; 00155 num = fread(buff, 1, chunk, fSrc); 00156 if (num > 0) { 00157 uint32_t tmp = fwrite(buff, 1, num, fDst); 00158 if (tmp != num) { 00159 // failed to write 00160 return false; 00161 } 00162 left -= num; 00163 ledShowProgress(); 00164 } 00165 } while(num > 0 && left > 0); 00166 00167 // copied entire file 00168 return true; 00169 } 00170 00171 static bool identicalFiles(const char* srcName, const char* dstName) 00172 { 00173 FILE* fSrc = NULL; 00174 FILE* fDst = NULL; 00175 bool identical = false; 00176 do 00177 { 00178 fSrc = fopen(srcName, "r"); 00179 if (fSrc == NULL) { 00180 break; 00181 } 00182 fDst = fopen(dstName, "r"); 00183 if (fDst == NULL) { 00184 break; 00185 } 00186 if (fileLen(fSrc) != fileLen(fDst)) { 00187 break; 00188 } 00189 if (crc_Read(fSrc) != crc_Read(fDst)) { 00190 break; 00191 } 00192 00193 // All tests passed so the files are identical 00194 identical = true; 00195 00196 } while(false); 00197 00198 if (fSrc != NULL) { 00199 fclose(fSrc); 00200 } 00201 if (fDst != NULL) { 00202 fclose(fDst); 00203 } 00204 00205 return identical; 00206 } 00207 00208 static bool addExisting(const char* srcName, bool isDir, const char* dstName) 00209 { 00210 bool result = true; // success 00211 if (isDir) { 00212 DIR *d = opendir(dstName); 00213 if (d == NULL) { 00214 if (dstName[1] != 'r') { printf("%s, new dir, adding\n", dstName); } 00215 if (mkdir(dstName, 0) != 0) { 00216 printf("Failed to create folder %s\n", dstName); 00217 result = false; // dir did not exist and could not be created 00218 } 00219 } else { 00220 closedir(d); 00221 } 00222 } else if (!identicalFiles(srcName, dstName)) { 00223 // Compare the files to avoid replacing with same 00224 FILE* fSrc = fopen(srcName, "r"); 00225 if (fSrc != NULL) { 00226 FILE* fDst = fopen(dstName, "w"); // open and truncate 00227 if (fDst != NULL) { 00228 if (dstName[1] != 'r') { printf("%s, changed, updating\n", dstName); } 00229 result = copy(fSrc, fDst); 00230 if (!result) { 00231 printf("Failed to copy %s to %s\n", srcName, dstName); 00232 } 00233 fclose(fDst); 00234 } else { 00235 printf("Failed to create file %s\n", dstName); 00236 result = false; // unable to create file 00237 } 00238 fclose(fSrc); 00239 } else { 00240 printf("Failed to copen source file file %s\n", srcName); 00241 result = false; // unable to open source 00242 } 00243 } else { 00244 if (dstName[1] != 'r') { printf("%s identical, skipping\n", dstName); } 00245 } 00246 return result; 00247 } 00248 00249 static bool addExistingToQspi(const char* name, bool isDir) 00250 { 00251 // create the target file name by replacing /ram/ with /qspi/ 00252 char buff[256]; 00253 buff[0] = '\0'; 00254 strcat(buff, "/qspi/"); 00255 strcat(buff, name+5); 00256 00257 // Don't add the file created by createImageFile() 00258 if (strcmp(name, image_file_name) == 0) { 00259 return true; 00260 } 00261 00262 return addExisting(name, isDir, buff); 00263 } 00264 00265 static bool addExistingToRAM(const char* name, bool isDir) 00266 { 00267 // create the target file name by replacing /qspi/ with /ram/ 00268 char buff[256]; 00269 buff[0] = '\0'; 00270 strcat(buff, "/ram/"); 00271 strcat(buff, name+6); 00272 return addExisting(name, isDir, buff); 00273 } 00274 00275 static bool removeIfMissing(const char* toLookFor, const char* toRemove, bool isDir) 00276 { 00277 int result = 0; //success 00278 if (isDir) { 00279 DIR *d = opendir(toLookFor); 00280 if (d == NULL) { 00281 // dir doesn't exist => delete it 00282 if (toRemove[1] != 'r') { printf("%s, missing, deleting dir\n", toRemove); } 00283 result = remove(toRemove); 00284 ledShowProgress(); 00285 } else { 00286 // dir exist => don't delete 00287 closedir(d); 00288 } 00289 } else { 00290 FILE* f = fopen(toLookFor, "r"); 00291 if (f == NULL) { 00292 // file doesn't exist => delete it 00293 if (toRemove[1] != 'r') { printf("%s, missing, deleting file\n", toRemove); } 00294 result = remove(toRemove); 00295 ledShowProgress(); 00296 } else { 00297 // file exist => don't delete 00298 fclose(f); 00299 } 00300 } 00301 return (result == 0); 00302 } 00303 00304 static bool removeMissingFromQspi(const char* name, bool isDir) 00305 { 00306 // create the target file name by replacing /qspi/ with /ram/ 00307 char buff[256]; 00308 buff[0] = '\0'; 00309 strcat(buff, "/ram/"); 00310 strcat(buff, name+6); 00311 removeIfMissing(buff, name, isDir); 00312 return true; 00313 } 00314 00315 static bool removeMissingFromRAM(const char* name, bool isDir) 00316 { 00317 // create the target file name by replacing /ram/ with /qspi/ 00318 char buff[256]; 00319 buff[0] = '\0'; 00320 strcat(buff, "/qspi/"); 00321 strcat(buff, name+5); 00322 00323 // Don't remove the file created by createImageFile() 00324 if (strcmp(name, image_file_name) == 0) { 00325 return true; 00326 } 00327 00328 removeIfMissing(buff, name, isDir); 00329 return true; 00330 } 00331 00332 static void syncDir(const char* to, const char* from) 00333 { 00334 printf("Starting to sync %s on top of %s (This may take time. LED1 & 2 blink for each file)\n", from, to); 00335 00336 char* buff = (char*)malloc(512); 00337 if (buff != NULL) 00338 { 00339 buff[0] = '\0'; 00340 if (strcmp(to, "/qspi/") == 0) { 00341 if (!recursiveProcessFS(buff, to, removeMissingFromQspi, false)) { 00342 printf("Failed to remove files from %s that were missing on %s\n", to, from); 00343 } else { 00344 buff[0] = '\0'; 00345 if (!recursiveProcessFS(buff, from, addExistingToQspi, true)) { 00346 printf("Failed to add files to %s that existed on %s\n", to, from); 00347 } 00348 } 00349 } else { 00350 if (!recursiveProcessFS(buff, to, removeMissingFromRAM, false)) { 00351 printf("Failed to remove files from %s that were missing on %s\n", to, from); 00352 } else { 00353 buff[0] = '\0'; 00354 if (!recursiveProcessFS(buff, from, addExistingToRAM, true)) { 00355 printf("Failed to add files to %s that existed on %s\n", to, from); 00356 } 00357 } 00358 } 00359 free(buff); 00360 } 00361 printf("Sync completed\n"); 00362 } 00363 00364 00365 static void createImageFile() 00366 { 00367 uint32_t startAddr; 00368 uint32_t endAddr; 00369 uint32_t size; 00370 00371 printf("Creating image of existing (if any) QSPI file system\n"); 00372 00373 if (!qspi.getMemoryBoundaries(&startAddr, &endAddr)) 00374 { 00375 handleError("QSPI FS not formatted or impossible to determine it's size\n"); 00376 } 00377 00378 // Align the start address to an even multiple of 1MB 00379 startAddr = startAddr & 0xfff00000; 00380 00381 // Update the file to match the size of the file system 00382 size = endAddr - startAddr; 00383 if ((size < 0x00100000) || (size > 0x00800000) || ((size & 0xfffff) > 0)) 00384 { 00385 sprintf(lsbuff, "QSPI FS size is not supported (%u bytes)\n", size); 00386 handleError(lsbuff); 00387 } 00388 sprintf(image_file_name, "/ram/.current/fs_image.fs%d", (size >> 20)); 00389 00390 // NOTE: The line below is very very !!!! important. For some weird reason the 00391 // RAM file system must have at least one folder on it before USB is connected. 00392 // If the RAM file system doesn't have any folders on it the result is that 00393 // the content of the RAM file system will be the same after USB is disconnected 00394 // as it was before connecting - regardless of what is added. Very strange indeed. 00395 mkdir("/ram/.current", 0); 00396 00397 printf("QSPI FS max size is %d MB\n", (size >> 20)); 00398 00399 FILE *fp = fopen(image_file_name, "w"); 00400 if (fp != NULL) 00401 { 00402 while (size > 0) 00403 { 00404 uint32_t written = fwrite((char*)(endAddr - size), 1, size, fp); 00405 size -= written; 00406 if (written == 0) 00407 { 00408 handleError("Failed to create QSPI image file\n"); 00409 } 00410 } 00411 fclose(fp); 00412 } 00413 } 00414 00415 static bool list(const char* name, bool isDir) 00416 { 00417 if (isDir) { 00418 printf("d: %s\n", name); 00419 } else { 00420 FILE* f = fopen(name, "r"); 00421 if (f != NULL) { 00422 uint32_t len = fileLen(f); 00423 printf("f: %7u %s\n", len, name); 00424 fclose(f); 00425 } else { 00426 printf("f: ??? %s\n", name); 00427 } 00428 } 00429 return true; 00430 } 00431 00432 static void recursiveList(const char* dirname) 00433 { 00434 printf("\nRecursive list of file and folders in %s\n", dirname); 00435 char* buff = (char*)malloc(512); 00436 if (buff != NULL) 00437 { 00438 buff[0] = '\0'; 00439 recursiveProcessFS(buff, dirname, list, true); 00440 free(buff); 00441 } 00442 } 00443 00444 /****************************************************************************** 00445 * Main function 00446 *****************************************************************************/ 00447 int main() 00448 { 00449 printf("\n-----------------\n\nWelcome to the QSPI file system tool...\n"); 00450 00451 // 1) Make sure that the button works 00452 // 2) Init SDRAM and allocate space for the RAM file system 00453 // 3) Setup RAM FS 00454 // 4a) If QSPI FS is not formatted: 00455 // i) Create a "qspi_not_formatted.txt" file in the root of the file system 00456 // 4b) QSPI FS formatted 00457 // i) Create an image file of the QSPI FS 00458 // ii) Sync QSPI FS on top of RAM FS 00459 // 5) Connect USB 00460 // 6a) If QSPI FS is not formatted: Loop forever doing nothing 00461 // 6b) QSPI FS formatted: Wait for button press 00462 // 7) Button pressed, Disconnect USB 00463 // 8) QSPI formatted 00464 // i) Sync RAM FS on top of QSPI FS 00465 // ii) Goto 3) 00466 // 00467 00468 // 1) 00469 button.mode(PullUp); 00470 00471 // 2) 00472 if (sdram_init()) { 00473 handleError("Failed to initialize SDRAM\n"); 00474 } 00475 00476 void* fsmem = malloc(RAM_FS_SIZE); 00477 if (fsmem == NULL) { 00478 handleError("Failed to allocate memory for RAM file system\n"); 00479 } 00480 RAMFileSystem ramfs((uint32_t)fsmem, RAM_FS_SIZE, "ram"); 00481 USBMSD_RAMFS usbmsd(&ramfs); 00482 00483 while(true) 00484 { 00485 // 3) 00486 ramfs.format(); 00487 00488 // 4a) 00489 bool qspiFormatted = qspi.isformatted(); 00490 if (!qspiFormatted) 00491 { 00492 addNotFormattedFile(); 00493 } 00494 00495 // 4b) 00496 else 00497 { 00498 //addTestFile(); 00499 createImageFile(); 00500 00501 // Copy QSPI FS to RAM FS 00502 syncDir("/ram/", "/qspi/"); 00503 } 00504 00505 // 5) 00506 printf("Insert the USB cable!\n"); 00507 printf("Starting USB...\n"); 00508 for (int i = 0; i < 10; i++) 00509 { 00510 if (usbmsd.connect()) 00511 { 00512 printf("Connected!\n"); 00513 break; 00514 } 00515 printf("Failed to connect USB, testing again...\n"); 00516 printf("Insert (or remove and then insert) the USB cable!\n"); 00517 wait(1); 00518 } 00519 00520 // 6b) 00521 if (qspiFormatted) 00522 { 00523 waitForButtonPress(); 00524 } 00525 else 00526 { 00527 // 6a) no point in waiting for buttons if no file system 00528 while (1) {}; 00529 } 00530 00531 // 7) 00532 usbmsd.disconnect(); 00533 printf("Disconnected!\n"); 00534 00535 // 8) Copy RAM FS to QSPI FS 00536 recursiveList("/ram/"); 00537 syncDir("/qspi/", "/ram/"); 00538 } 00539 }
Generated on Wed Jul 13 2022 17:18:12 by 1.7.2