The purpose of this application is to allow easy manipulation of the QSPI file system from a PC (**NOTE**: Application doesn't work with update to mbed OS 5 since USB Device support is currently not available for LPC4088)
Dependencies: DMBasicGUI DMSupport
Note
This application doesn't work with the latest updates to mbed OS 5 since USB Device support is currently not available for LPC4088
The purpose of this application is to allow easy manipulation of the QSPI file system from a PC.
The application makes the LPC4088 Display Module 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:
- Download the lpc4088_displaymodule_fs_aid application using drag-n-drop and then reset the board
- Optionally start a terminal program to read the status messages from the application
- Connect a USB cable to the mini USB slot on the back of the LPC4088 Display Module, and then to the PC
- The PC will install drivers if needed and then the USB Memory Stick will be available as a new drive
- Modify the file system to suit your needs
- With the USB cable still connected, press the USER/ISP/SW1 button on the LPC4088 Display Module
- The application will now:
- disconnect the USB Memory Stick
- write all changes to the QSPI flash memory
- create a new image file of the updated QSPI file system and store it in the .current/ folder
- connect the USB Memory Stick again
- Continue from step 5. until satisfied
Note 1: If the QSPI doesn't have a file system on it or to replace the current one with a new, possibly of a different size, file system just add a file with the name format_qspi_X_mb (where X should be replace with the wanted file system size in Mb). For a 10 Mb file system the file name should be format_qspi_10_mb.
Note 2: 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 3: The image files created in step 7.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.
main.cpp@1:b04139d88c59, 2016-05-16 (annotated)
- Committer:
- alindvall
- Date:
- Mon May 16 08:13:27 2016 +0000
- Revision:
- 1:b04139d88c59
- Parent:
- 0:06e35dd73c95
Added support for formatting of QSPI file system via special files.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
alindvall | 0:06e35dd73c95 | 1 | /****************************************************************************** |
alindvall | 0:06e35dd73c95 | 2 | * Includes |
alindvall | 0:06e35dd73c95 | 3 | *****************************************************************************/ |
alindvall | 1:b04139d88c59 | 4 | |
alindvall | 0:06e35dd73c95 | 5 | #include "mbed.h" |
alindvall | 0:06e35dd73c95 | 6 | #include "mbed_interface.h" |
alindvall | 0:06e35dd73c95 | 7 | #include "rtos.h" |
alindvall | 0:06e35dd73c95 | 8 | |
alindvall | 0:06e35dd73c95 | 9 | #include "DMBoard.h" |
alindvall | 0:06e35dd73c95 | 10 | #include "RAMFileSystem.h" |
alindvall | 0:06e35dd73c95 | 11 | #include "USBMSD_RAMFS.h" |
alindvall | 0:06e35dd73c95 | 12 | |
alindvall | 0:06e35dd73c95 | 13 | #include "crc.h" |
alindvall | 0:06e35dd73c95 | 14 | |
alindvall | 0:06e35dd73c95 | 15 | #include "lpc_swim.h" |
alindvall | 0:06e35dd73c95 | 16 | #include "lpc_swim_font.h" |
alindvall | 0:06e35dd73c95 | 17 | #include "lpc_winfreesystem14x16.h" |
alindvall | 0:06e35dd73c95 | 18 | |
alindvall | 0:06e35dd73c95 | 19 | /****************************************************************************** |
alindvall | 0:06e35dd73c95 | 20 | * Typedefs and defines |
alindvall | 0:06e35dd73c95 | 21 | *****************************************************************************/ |
alindvall | 0:06e35dd73c95 | 22 | |
alindvall | 0:06e35dd73c95 | 23 | typedef bool (*syncFunc)(const char* name, bool isDir); |
alindvall | 0:06e35dd73c95 | 24 | |
alindvall | 0:06e35dd73c95 | 25 | /* Size of RAM file system */ |
alindvall | 0:06e35dd73c95 | 26 | #define RAM_FS_SIZE (20*1024*1024) |
alindvall | 0:06e35dd73c95 | 27 | |
alindvall | 0:06e35dd73c95 | 28 | |
alindvall | 0:06e35dd73c95 | 29 | /****************************************************************************** |
alindvall | 0:06e35dd73c95 | 30 | * Local variables |
alindvall | 0:06e35dd73c95 | 31 | *****************************************************************************/ |
alindvall | 0:06e35dd73c95 | 32 | |
alindvall | 0:06e35dd73c95 | 33 | //DigitalOut myled1(LED1); |
alindvall | 0:06e35dd73c95 | 34 | //DigitalOut myled2(LED2); |
alindvall | 0:06e35dd73c95 | 35 | //DigitalIn button(p23); |
alindvall | 0:06e35dd73c95 | 36 | |
alindvall | 0:06e35dd73c95 | 37 | //DigitalOut myled(LED1); |
alindvall | 0:06e35dd73c95 | 38 | static char lsbuff[NAME_MAX+1]; |
alindvall | 0:06e35dd73c95 | 39 | |
alindvall | 0:06e35dd73c95 | 40 | static char image_file_name[128] = { '\0' }; |
alindvall | 0:06e35dd73c95 | 41 | |
alindvall | 0:06e35dd73c95 | 42 | /****************************************************************************** |
alindvall | 0:06e35dd73c95 | 43 | * Local functions |
alindvall | 0:06e35dd73c95 | 44 | *****************************************************************************/ |
alindvall | 0:06e35dd73c95 | 45 | |
alindvall | 0:06e35dd73c95 | 46 | |
alindvall | 0:06e35dd73c95 | 47 | static void ledShowProgress() |
alindvall | 0:06e35dd73c95 | 48 | { |
alindvall | 0:06e35dd73c95 | 49 | static int state = 0; |
alindvall | 0:06e35dd73c95 | 50 | state = (state + 1) % 2; |
alindvall | 1:b04139d88c59 | 51 | |
alindvall | 1:b04139d88c59 | 52 | DMBoard* board = &DMBoard::instance(); |
alindvall | 1:b04139d88c59 | 53 | board->setLED(DMBoard::Led1, state==0); |
alindvall | 1:b04139d88c59 | 54 | board->setLED(DMBoard::Led2, state!=0); |
alindvall | 0:06e35dd73c95 | 55 | } |
alindvall | 0:06e35dd73c95 | 56 | |
alindvall | 0:06e35dd73c95 | 57 | static void handleError(const char* msg) |
alindvall | 0:06e35dd73c95 | 58 | { |
alindvall | 1:b04139d88c59 | 59 | DMBoard* board = &DMBoard::instance(); |
alindvall | 1:b04139d88c59 | 60 | board->logger()->printf(msg); |
alindvall | 0:06e35dd73c95 | 61 | while(true) { |
alindvall | 0:06e35dd73c95 | 62 | board->setLED(DMBoard::Led1, false); |
alindvall | 0:06e35dd73c95 | 63 | board->setLED(DMBoard::Led2, false); |
alindvall | 0:06e35dd73c95 | 64 | wait(0.3); |
alindvall | 0:06e35dd73c95 | 65 | board->setLED(DMBoard::Led1, true); |
alindvall | 0:06e35dd73c95 | 66 | board->setLED(DMBoard::Led2, true); |
alindvall | 0:06e35dd73c95 | 67 | wait(0.3); |
alindvall | 0:06e35dd73c95 | 68 | } |
alindvall | 0:06e35dd73c95 | 69 | } |
alindvall | 0:06e35dd73c95 | 70 | |
alindvall | 0:06e35dd73c95 | 71 | static void waitForButtonPress() |
alindvall | 0:06e35dd73c95 | 72 | { |
alindvall | 1:b04139d88c59 | 73 | DMBoard* board = &DMBoard::instance(); |
alindvall | 0:06e35dd73c95 | 74 | printf("Press button to sync file systems\n"); |
alindvall | 0:06e35dd73c95 | 75 | |
alindvall | 0:06e35dd73c95 | 76 | board->setLED(DMBoard::Led1, false); |
alindvall | 0:06e35dd73c95 | 77 | board->setLED(DMBoard::Led2, false); |
alindvall | 0:06e35dd73c95 | 78 | while(!board->buttonPressed()) { |
alindvall | 0:06e35dd73c95 | 79 | wait(0.1); |
alindvall | 0:06e35dd73c95 | 80 | } |
alindvall | 0:06e35dd73c95 | 81 | board->setLED(DMBoard::Led1, true); |
alindvall | 0:06e35dd73c95 | 82 | printf("Button pressed, now release it\n"); |
alindvall | 0:06e35dd73c95 | 83 | while(board->buttonPressed()) { |
alindvall | 0:06e35dd73c95 | 84 | wait(0.1); |
alindvall | 0:06e35dd73c95 | 85 | } |
alindvall | 0:06e35dd73c95 | 86 | } |
alindvall | 0:06e35dd73c95 | 87 | |
alindvall | 0:06e35dd73c95 | 88 | static void addNotFormattedFile() |
alindvall | 0:06e35dd73c95 | 89 | { |
alindvall | 0:06e35dd73c95 | 90 | FILE *fp = fopen("/ram/qspi_not_formatted.txt", "w"); |
alindvall | 0:06e35dd73c95 | 91 | if (fp != NULL) { |
alindvall | 1:b04139d88c59 | 92 | fprintf(fp, "The QSPI file system has not be formatted. To format create a\n"); |
alindvall | 1:b04139d88c59 | 93 | fprintf(fp, "file with the name \"format_qspi_X_mb\" on the drive and then\n"); |
alindvall | 1:b04139d88c59 | 94 | fprintf(fp, "press the USER/ISP/SW1 button to format\n"); |
alindvall | 1:b04139d88c59 | 95 | fprintf(fp, "The X in the file name should be replaced with the desired\n"); |
alindvall | 1:b04139d88c59 | 96 | fprintf(fp, "file system size in Mb (1 to 16). For a 10 Mb file sytem the file\n"); |
alindvall | 1:b04139d88c59 | 97 | fprintf(fp, "name would be format_qspi_10_mb.\n"); |
alindvall | 0:06e35dd73c95 | 98 | fclose(fp); |
alindvall | 0:06e35dd73c95 | 99 | } |
alindvall | 0:06e35dd73c95 | 100 | } |
alindvall | 0:06e35dd73c95 | 101 | |
alindvall | 0:06e35dd73c95 | 102 | static bool recursiveProcessFS(char* buff, const char* name, syncFunc func, bool adding) |
alindvall | 0:06e35dd73c95 | 103 | { |
alindvall | 0:06e35dd73c95 | 104 | uint32_t len = strlen(buff); |
alindvall | 0:06e35dd73c95 | 105 | if (len > 0) { |
alindvall | 0:06e35dd73c95 | 106 | if (buff[len - 1] != '/') { |
alindvall | 0:06e35dd73c95 | 107 | buff[len++] = '/'; |
alindvall | 0:06e35dd73c95 | 108 | buff[len] = '\0'; |
alindvall | 0:06e35dd73c95 | 109 | } |
alindvall | 0:06e35dd73c95 | 110 | } |
alindvall | 0:06e35dd73c95 | 111 | strcat(buff, name); |
alindvall | 0:06e35dd73c95 | 112 | len += strlen(name); |
alindvall | 0:06e35dd73c95 | 113 | |
alindvall | 0:06e35dd73c95 | 114 | DIR *d = opendir(buff); |
alindvall | 0:06e35dd73c95 | 115 | bool result = true; // success |
alindvall | 0:06e35dd73c95 | 116 | if (d != NULL) { |
alindvall | 0:06e35dd73c95 | 117 | if (adding) { |
alindvall | 0:06e35dd73c95 | 118 | // when processing in adding mode folders must be created before it's content |
alindvall | 0:06e35dd73c95 | 119 | result = func(buff, true); |
alindvall | 0:06e35dd73c95 | 120 | } |
alindvall | 0:06e35dd73c95 | 121 | struct dirent *p; |
alindvall | 0:06e35dd73c95 | 122 | while (result && ((p = readdir(d)) != NULL)) { |
alindvall | 0:06e35dd73c95 | 123 | result = recursiveProcessFS(buff, p->d_name, func, adding); |
alindvall | 0:06e35dd73c95 | 124 | buff[len] = '\0'; |
alindvall | 0:06e35dd73c95 | 125 | } |
alindvall | 0:06e35dd73c95 | 126 | closedir(d); |
alindvall | 0:06e35dd73c95 | 127 | if (result && !adding) { |
alindvall | 0:06e35dd73c95 | 128 | // when processing in removing mode folders must be deleted after it's content |
alindvall | 0:06e35dd73c95 | 129 | result = func(buff, true); |
alindvall | 0:06e35dd73c95 | 130 | } |
alindvall | 0:06e35dd73c95 | 131 | } else { |
alindvall | 0:06e35dd73c95 | 132 | // a file |
alindvall | 0:06e35dd73c95 | 133 | result = func(buff, false); |
alindvall | 0:06e35dd73c95 | 134 | } |
alindvall | 0:06e35dd73c95 | 135 | return result; |
alindvall | 0:06e35dd73c95 | 136 | } |
alindvall | 0:06e35dd73c95 | 137 | |
alindvall | 0:06e35dd73c95 | 138 | static uint32_t fileLen(FILE* f) |
alindvall | 0:06e35dd73c95 | 139 | { |
alindvall | 0:06e35dd73c95 | 140 | uint32_t pos = ftell(f); |
alindvall | 0:06e35dd73c95 | 141 | fseek(f, 0, SEEK_END); |
alindvall | 0:06e35dd73c95 | 142 | uint32_t size = ftell(f); |
alindvall | 0:06e35dd73c95 | 143 | fseek(f, pos, SEEK_SET); |
alindvall | 0:06e35dd73c95 | 144 | return size; |
alindvall | 0:06e35dd73c95 | 145 | } |
alindvall | 0:06e35dd73c95 | 146 | |
alindvall | 0:06e35dd73c95 | 147 | static bool copy(FILE* fSrc, FILE* fDst) |
alindvall | 0:06e35dd73c95 | 148 | { |
alindvall | 0:06e35dd73c95 | 149 | char buff[512]; |
alindvall | 0:06e35dd73c95 | 150 | uint32_t left = fileLen(fSrc); |
alindvall | 0:06e35dd73c95 | 151 | uint32_t num; |
alindvall | 0:06e35dd73c95 | 152 | uint32_t chunk; |
alindvall | 0:06e35dd73c95 | 153 | |
alindvall | 0:06e35dd73c95 | 154 | fseek(fSrc, 0, SEEK_SET); |
alindvall | 0:06e35dd73c95 | 155 | do { |
alindvall | 0:06e35dd73c95 | 156 | chunk = (left < 512) ? left : 512; |
alindvall | 0:06e35dd73c95 | 157 | num = fread(buff, 1, chunk, fSrc); |
alindvall | 0:06e35dd73c95 | 158 | if (num > 0) { |
alindvall | 0:06e35dd73c95 | 159 | uint32_t tmp = fwrite(buff, 1, num, fDst); |
alindvall | 0:06e35dd73c95 | 160 | if (tmp != num) { |
alindvall | 0:06e35dd73c95 | 161 | // failed to write |
alindvall | 0:06e35dd73c95 | 162 | return false; |
alindvall | 0:06e35dd73c95 | 163 | } |
alindvall | 0:06e35dd73c95 | 164 | left -= num; |
alindvall | 0:06e35dd73c95 | 165 | ledShowProgress(); |
alindvall | 0:06e35dd73c95 | 166 | } |
alindvall | 0:06e35dd73c95 | 167 | } while(num > 0 && left > 0); |
alindvall | 0:06e35dd73c95 | 168 | |
alindvall | 0:06e35dd73c95 | 169 | // copied entire file |
alindvall | 0:06e35dd73c95 | 170 | return true; |
alindvall | 0:06e35dd73c95 | 171 | } |
alindvall | 0:06e35dd73c95 | 172 | |
alindvall | 0:06e35dd73c95 | 173 | static bool identicalFiles(const char* srcName, const char* dstName) |
alindvall | 0:06e35dd73c95 | 174 | { |
alindvall | 0:06e35dd73c95 | 175 | FILE* fSrc = NULL; |
alindvall | 0:06e35dd73c95 | 176 | FILE* fDst = NULL; |
alindvall | 0:06e35dd73c95 | 177 | bool identical = false; |
alindvall | 0:06e35dd73c95 | 178 | do |
alindvall | 0:06e35dd73c95 | 179 | { |
alindvall | 0:06e35dd73c95 | 180 | fSrc = fopen(srcName, "r"); |
alindvall | 0:06e35dd73c95 | 181 | if (fSrc == NULL) { |
alindvall | 0:06e35dd73c95 | 182 | break; |
alindvall | 0:06e35dd73c95 | 183 | } |
alindvall | 0:06e35dd73c95 | 184 | fDst = fopen(dstName, "r"); |
alindvall | 0:06e35dd73c95 | 185 | if (fDst == NULL) { |
alindvall | 0:06e35dd73c95 | 186 | break; |
alindvall | 0:06e35dd73c95 | 187 | } |
alindvall | 0:06e35dd73c95 | 188 | if (fileLen(fSrc) != fileLen(fDst)) { |
alindvall | 0:06e35dd73c95 | 189 | break; |
alindvall | 0:06e35dd73c95 | 190 | } |
alindvall | 0:06e35dd73c95 | 191 | if (crc_File(fSrc) != crc_File(fDst)) { |
alindvall | 0:06e35dd73c95 | 192 | break; |
alindvall | 0:06e35dd73c95 | 193 | } |
alindvall | 0:06e35dd73c95 | 194 | |
alindvall | 0:06e35dd73c95 | 195 | // All tests passed so the files are identical |
alindvall | 0:06e35dd73c95 | 196 | identical = true; |
alindvall | 0:06e35dd73c95 | 197 | |
alindvall | 0:06e35dd73c95 | 198 | } while(false); |
alindvall | 0:06e35dd73c95 | 199 | |
alindvall | 0:06e35dd73c95 | 200 | if (fSrc != NULL) { |
alindvall | 0:06e35dd73c95 | 201 | fclose(fSrc); |
alindvall | 0:06e35dd73c95 | 202 | } |
alindvall | 0:06e35dd73c95 | 203 | if (fDst != NULL) { |
alindvall | 0:06e35dd73c95 | 204 | fclose(fDst); |
alindvall | 0:06e35dd73c95 | 205 | } |
alindvall | 0:06e35dd73c95 | 206 | |
alindvall | 0:06e35dd73c95 | 207 | return identical; |
alindvall | 0:06e35dd73c95 | 208 | } |
alindvall | 0:06e35dd73c95 | 209 | |
alindvall | 0:06e35dd73c95 | 210 | static bool addExisting(const char* srcName, bool isDir, const char* dstName) |
alindvall | 0:06e35dd73c95 | 211 | { |
alindvall | 0:06e35dd73c95 | 212 | bool result = true; // success |
alindvall | 0:06e35dd73c95 | 213 | if (isDir) { |
alindvall | 0:06e35dd73c95 | 214 | DIR *d = opendir(dstName); |
alindvall | 0:06e35dd73c95 | 215 | if (d == NULL) { |
alindvall | 0:06e35dd73c95 | 216 | if (dstName[1] != 'r') { printf("%s, new dir, adding\n", dstName); } |
alindvall | 0:06e35dd73c95 | 217 | if (mkdir(dstName, 0) != 0) { |
alindvall | 0:06e35dd73c95 | 218 | printf("Failed to create folder %s\n", dstName); |
alindvall | 0:06e35dd73c95 | 219 | result = false; // dir did not exist and could not be created |
alindvall | 0:06e35dd73c95 | 220 | } |
alindvall | 0:06e35dd73c95 | 221 | } else { |
alindvall | 0:06e35dd73c95 | 222 | closedir(d); |
alindvall | 0:06e35dd73c95 | 223 | } |
alindvall | 0:06e35dd73c95 | 224 | } else if (!identicalFiles(srcName, dstName)) { |
alindvall | 0:06e35dd73c95 | 225 | // Compare the files to avoid replacing with same |
alindvall | 0:06e35dd73c95 | 226 | FILE* fSrc = fopen(srcName, "r"); |
alindvall | 0:06e35dd73c95 | 227 | if (fSrc != NULL) { |
alindvall | 0:06e35dd73c95 | 228 | FILE* fDst = fopen(dstName, "w"); // open and truncate |
alindvall | 0:06e35dd73c95 | 229 | if (fDst != NULL) { |
alindvall | 0:06e35dd73c95 | 230 | if (dstName[1] != 'r') { printf("%s, changed, updating\n", dstName); } |
alindvall | 0:06e35dd73c95 | 231 | result = copy(fSrc, fDst); |
alindvall | 0:06e35dd73c95 | 232 | if (!result) { |
alindvall | 0:06e35dd73c95 | 233 | printf("Failed to copy %s to %s\n", srcName, dstName); |
alindvall | 0:06e35dd73c95 | 234 | } |
alindvall | 0:06e35dd73c95 | 235 | fclose(fDst); |
alindvall | 0:06e35dd73c95 | 236 | } else { |
alindvall | 0:06e35dd73c95 | 237 | printf("Failed to create file %s\n", dstName); |
alindvall | 0:06e35dd73c95 | 238 | result = false; // unable to create file |
alindvall | 0:06e35dd73c95 | 239 | } |
alindvall | 0:06e35dd73c95 | 240 | fclose(fSrc); |
alindvall | 0:06e35dd73c95 | 241 | } else { |
alindvall | 0:06e35dd73c95 | 242 | printf("Failed to copen source file file %s\n", srcName); |
alindvall | 0:06e35dd73c95 | 243 | result = false; // unable to open source |
alindvall | 0:06e35dd73c95 | 244 | } |
alindvall | 0:06e35dd73c95 | 245 | } else { |
alindvall | 0:06e35dd73c95 | 246 | if (dstName[1] != 'r') { printf("%s identical, skipping\n", dstName); } |
alindvall | 0:06e35dd73c95 | 247 | } |
alindvall | 0:06e35dd73c95 | 248 | return result; |
alindvall | 0:06e35dd73c95 | 249 | } |
alindvall | 0:06e35dd73c95 | 250 | |
alindvall | 0:06e35dd73c95 | 251 | static bool addExistingToQspi(const char* name, bool isDir) |
alindvall | 0:06e35dd73c95 | 252 | { |
alindvall | 0:06e35dd73c95 | 253 | // create the target file name by replacing /ram/ with /qspi/ |
alindvall | 0:06e35dd73c95 | 254 | char buff[256]; |
alindvall | 0:06e35dd73c95 | 255 | buff[0] = '\0'; |
alindvall | 0:06e35dd73c95 | 256 | strcat(buff, "/qspi/"); |
alindvall | 0:06e35dd73c95 | 257 | strcat(buff, name+5); |
alindvall | 0:06e35dd73c95 | 258 | |
alindvall | 0:06e35dd73c95 | 259 | // Don't add the file created by createImageFile() |
alindvall | 0:06e35dd73c95 | 260 | if (strcmp(name, image_file_name) == 0) { |
alindvall | 0:06e35dd73c95 | 261 | return true; |
alindvall | 0:06e35dd73c95 | 262 | } |
alindvall | 0:06e35dd73c95 | 263 | |
alindvall | 0:06e35dd73c95 | 264 | return addExisting(name, isDir, buff); |
alindvall | 0:06e35dd73c95 | 265 | } |
alindvall | 0:06e35dd73c95 | 266 | |
alindvall | 0:06e35dd73c95 | 267 | static bool addExistingToRAM(const char* name, bool isDir) |
alindvall | 0:06e35dd73c95 | 268 | { |
alindvall | 0:06e35dd73c95 | 269 | // create the target file name by replacing /qspi/ with /ram/ |
alindvall | 0:06e35dd73c95 | 270 | char buff[256]; |
alindvall | 0:06e35dd73c95 | 271 | buff[0] = '\0'; |
alindvall | 0:06e35dd73c95 | 272 | strcat(buff, "/ram/"); |
alindvall | 0:06e35dd73c95 | 273 | strcat(buff, name+6); |
alindvall | 0:06e35dd73c95 | 274 | return addExisting(name, isDir, buff); |
alindvall | 0:06e35dd73c95 | 275 | } |
alindvall | 0:06e35dd73c95 | 276 | |
alindvall | 0:06e35dd73c95 | 277 | static bool removeIfMissing(const char* toLookFor, const char* toRemove, bool isDir) |
alindvall | 0:06e35dd73c95 | 278 | { |
alindvall | 0:06e35dd73c95 | 279 | int result = 0; //success |
alindvall | 0:06e35dd73c95 | 280 | if (isDir) { |
alindvall | 0:06e35dd73c95 | 281 | DIR *d = opendir(toLookFor); |
alindvall | 0:06e35dd73c95 | 282 | if (d == NULL) { |
alindvall | 0:06e35dd73c95 | 283 | // dir doesn't exist => delete it |
alindvall | 0:06e35dd73c95 | 284 | if (toRemove[1] != 'r') { printf("%s, missing, deleting dir\n", toRemove); } |
alindvall | 0:06e35dd73c95 | 285 | result = remove(toRemove); |
alindvall | 0:06e35dd73c95 | 286 | ledShowProgress(); |
alindvall | 0:06e35dd73c95 | 287 | } else { |
alindvall | 0:06e35dd73c95 | 288 | // dir exist => don't delete |
alindvall | 0:06e35dd73c95 | 289 | closedir(d); |
alindvall | 0:06e35dd73c95 | 290 | } |
alindvall | 0:06e35dd73c95 | 291 | } else { |
alindvall | 0:06e35dd73c95 | 292 | FILE* f = fopen(toLookFor, "r"); |
alindvall | 0:06e35dd73c95 | 293 | if (f == NULL) { |
alindvall | 0:06e35dd73c95 | 294 | // file doesn't exist => delete it |
alindvall | 0:06e35dd73c95 | 295 | if (toRemove[1] != 'r') { printf("%s, missing, deleting file\n", toRemove); } |
alindvall | 0:06e35dd73c95 | 296 | result = remove(toRemove); |
alindvall | 0:06e35dd73c95 | 297 | ledShowProgress(); |
alindvall | 0:06e35dd73c95 | 298 | } else { |
alindvall | 0:06e35dd73c95 | 299 | // file exist => don't delete |
alindvall | 0:06e35dd73c95 | 300 | fclose(f); |
alindvall | 0:06e35dd73c95 | 301 | } |
alindvall | 0:06e35dd73c95 | 302 | } |
alindvall | 0:06e35dd73c95 | 303 | return (result == 0); |
alindvall | 0:06e35dd73c95 | 304 | } |
alindvall | 0:06e35dd73c95 | 305 | |
alindvall | 0:06e35dd73c95 | 306 | static bool removeMissingFromQspi(const char* name, bool isDir) |
alindvall | 0:06e35dd73c95 | 307 | { |
alindvall | 0:06e35dd73c95 | 308 | // create the target file name by replacing /qspi/ with /ram/ |
alindvall | 0:06e35dd73c95 | 309 | char buff[256]; |
alindvall | 0:06e35dd73c95 | 310 | buff[0] = '\0'; |
alindvall | 0:06e35dd73c95 | 311 | strcat(buff, "/ram/"); |
alindvall | 0:06e35dd73c95 | 312 | strcat(buff, name+6); |
alindvall | 0:06e35dd73c95 | 313 | removeIfMissing(buff, name, isDir); |
alindvall | 0:06e35dd73c95 | 314 | return true; |
alindvall | 0:06e35dd73c95 | 315 | } |
alindvall | 0:06e35dd73c95 | 316 | |
alindvall | 0:06e35dd73c95 | 317 | static bool removeMissingFromRAM(const char* name, bool isDir) |
alindvall | 0:06e35dd73c95 | 318 | { |
alindvall | 0:06e35dd73c95 | 319 | // create the target file name by replacing /ram/ with /qspi/ |
alindvall | 0:06e35dd73c95 | 320 | char buff[256]; |
alindvall | 0:06e35dd73c95 | 321 | buff[0] = '\0'; |
alindvall | 0:06e35dd73c95 | 322 | strcat(buff, "/qspi/"); |
alindvall | 0:06e35dd73c95 | 323 | strcat(buff, name+5); |
alindvall | 0:06e35dd73c95 | 324 | |
alindvall | 0:06e35dd73c95 | 325 | // Don't remove the file created by createImageFile() |
alindvall | 0:06e35dd73c95 | 326 | if (strcmp(name, image_file_name) == 0) { |
alindvall | 0:06e35dd73c95 | 327 | return true; |
alindvall | 0:06e35dd73c95 | 328 | } |
alindvall | 0:06e35dd73c95 | 329 | |
alindvall | 0:06e35dd73c95 | 330 | removeIfMissing(buff, name, isDir); |
alindvall | 0:06e35dd73c95 | 331 | return true; |
alindvall | 0:06e35dd73c95 | 332 | } |
alindvall | 0:06e35dd73c95 | 333 | |
alindvall | 0:06e35dd73c95 | 334 | static void syncDir(const char* to, const char* from) |
alindvall | 0:06e35dd73c95 | 335 | { |
alindvall | 0:06e35dd73c95 | 336 | printf("Starting to sync %s on top of %s (This may take time. LED1 & 2 blink for each file)\n", from, to); |
alindvall | 0:06e35dd73c95 | 337 | |
alindvall | 0:06e35dd73c95 | 338 | char* buff = (char*)malloc(512); |
alindvall | 0:06e35dd73c95 | 339 | if (buff != NULL) |
alindvall | 0:06e35dd73c95 | 340 | { |
alindvall | 0:06e35dd73c95 | 341 | buff[0] = '\0'; |
alindvall | 0:06e35dd73c95 | 342 | if (strcmp(to, "/qspi/") == 0) { |
alindvall | 0:06e35dd73c95 | 343 | if (!recursiveProcessFS(buff, to, removeMissingFromQspi, false)) { |
alindvall | 0:06e35dd73c95 | 344 | printf("Failed to remove files from %s that were missing on %s\n", to, from); |
alindvall | 0:06e35dd73c95 | 345 | } else { |
alindvall | 0:06e35dd73c95 | 346 | buff[0] = '\0'; |
alindvall | 0:06e35dd73c95 | 347 | if (!recursiveProcessFS(buff, from, addExistingToQspi, true)) { |
alindvall | 0:06e35dd73c95 | 348 | printf("Failed to add files to %s that existed on %s\n", to, from); |
alindvall | 0:06e35dd73c95 | 349 | } |
alindvall | 0:06e35dd73c95 | 350 | } |
alindvall | 0:06e35dd73c95 | 351 | } else { |
alindvall | 0:06e35dd73c95 | 352 | if (!recursiveProcessFS(buff, to, removeMissingFromRAM, false)) { |
alindvall | 0:06e35dd73c95 | 353 | printf("Failed to remove files from %s that were missing on %s\n", to, from); |
alindvall | 0:06e35dd73c95 | 354 | } else { |
alindvall | 0:06e35dd73c95 | 355 | buff[0] = '\0'; |
alindvall | 0:06e35dd73c95 | 356 | if (!recursiveProcessFS(buff, from, addExistingToRAM, true)) { |
alindvall | 0:06e35dd73c95 | 357 | printf("Failed to add files to %s that existed on %s\n", to, from); |
alindvall | 0:06e35dd73c95 | 358 | } |
alindvall | 0:06e35dd73c95 | 359 | } |
alindvall | 0:06e35dd73c95 | 360 | } |
alindvall | 0:06e35dd73c95 | 361 | free(buff); |
alindvall | 0:06e35dd73c95 | 362 | } |
alindvall | 0:06e35dd73c95 | 363 | printf("Sync completed\n"); |
alindvall | 0:06e35dd73c95 | 364 | } |
alindvall | 0:06e35dd73c95 | 365 | |
alindvall | 0:06e35dd73c95 | 366 | |
alindvall | 0:06e35dd73c95 | 367 | static void createImageFile(QSPIFileSystem* qspi) |
alindvall | 0:06e35dd73c95 | 368 | { |
alindvall | 0:06e35dd73c95 | 369 | uint32_t startAddr; |
alindvall | 0:06e35dd73c95 | 370 | uint32_t endAddr; |
alindvall | 0:06e35dd73c95 | 371 | uint32_t size; |
alindvall | 0:06e35dd73c95 | 372 | |
alindvall | 0:06e35dd73c95 | 373 | printf("Creating image of existing (if any) QSPI file system\n"); |
alindvall | 0:06e35dd73c95 | 374 | |
alindvall | 0:06e35dd73c95 | 375 | if (!qspi->getMemoryBoundaries(&startAddr, &endAddr)) |
alindvall | 0:06e35dd73c95 | 376 | { |
alindvall | 0:06e35dd73c95 | 377 | handleError("QSPI FS not formatted or impossible to determine it's size\n"); |
alindvall | 0:06e35dd73c95 | 378 | } |
alindvall | 0:06e35dd73c95 | 379 | |
alindvall | 0:06e35dd73c95 | 380 | // Align the start address to an even multiple of 1MB |
alindvall | 0:06e35dd73c95 | 381 | startAddr = startAddr & 0xfff00000; |
alindvall | 0:06e35dd73c95 | 382 | |
alindvall | 0:06e35dd73c95 | 383 | // Update the file to match the size of the file system |
alindvall | 0:06e35dd73c95 | 384 | size = endAddr - startAddr; |
alindvall | 0:06e35dd73c95 | 385 | if ((size < 0x00100000) || (size > 0x01000000) || ((size & 0xfffff) > 0)) |
alindvall | 0:06e35dd73c95 | 386 | { |
alindvall | 0:06e35dd73c95 | 387 | sprintf(lsbuff, "QSPI FS size is not supported (%u bytes)\n", size); |
alindvall | 0:06e35dd73c95 | 388 | handleError(lsbuff); |
alindvall | 0:06e35dd73c95 | 389 | } |
alindvall | 0:06e35dd73c95 | 390 | sprintf(image_file_name, "/ram/.current/fs_image.fs%d", (size >> 20)); |
alindvall | 1:b04139d88c59 | 391 | |
alindvall | 0:06e35dd73c95 | 392 | // NOTE: The line below is very very !!!! important. For some weird reason the |
alindvall | 0:06e35dd73c95 | 393 | // RAM file system must have at least one folder on it before USB is connected. |
alindvall | 0:06e35dd73c95 | 394 | // If the RAM file system doesn't have any folders on it the result is that |
alindvall | 0:06e35dd73c95 | 395 | // the content of the RAM file system will be the same after USB is disconnected |
alindvall | 0:06e35dd73c95 | 396 | // as it was before connecting - regardless of what is added. Very strange indeed. |
alindvall | 0:06e35dd73c95 | 397 | mkdir("/ram/.current", 0); |
alindvall | 0:06e35dd73c95 | 398 | |
alindvall | 0:06e35dd73c95 | 399 | printf("QSPI FS max size is %d MB\n", (size >> 20)); |
alindvall | 0:06e35dd73c95 | 400 | |
alindvall | 0:06e35dd73c95 | 401 | FILE *fp = fopen(image_file_name, "w"); |
alindvall | 0:06e35dd73c95 | 402 | if (fp != NULL) |
alindvall | 0:06e35dd73c95 | 403 | { |
alindvall | 0:06e35dd73c95 | 404 | while (size > 0) |
alindvall | 0:06e35dd73c95 | 405 | { |
alindvall | 0:06e35dd73c95 | 406 | uint32_t written = fwrite((char*)(endAddr - size), 1, size, fp); |
alindvall | 0:06e35dd73c95 | 407 | size -= written; |
alindvall | 0:06e35dd73c95 | 408 | if (written == 0) |
alindvall | 0:06e35dd73c95 | 409 | { |
alindvall | 0:06e35dd73c95 | 410 | handleError("Failed to create QSPI image file\n"); |
alindvall | 0:06e35dd73c95 | 411 | } |
alindvall | 0:06e35dd73c95 | 412 | } |
alindvall | 0:06e35dd73c95 | 413 | fclose(fp); |
alindvall | 0:06e35dd73c95 | 414 | } |
alindvall | 0:06e35dd73c95 | 415 | } |
alindvall | 0:06e35dd73c95 | 416 | |
alindvall | 0:06e35dd73c95 | 417 | static bool list(const char* name, bool isDir) |
alindvall | 0:06e35dd73c95 | 418 | { |
alindvall | 0:06e35dd73c95 | 419 | if (isDir) { |
alindvall | 0:06e35dd73c95 | 420 | printf("d: %s\n", name); |
alindvall | 0:06e35dd73c95 | 421 | } else { |
alindvall | 0:06e35dd73c95 | 422 | FILE* f = fopen(name, "r"); |
alindvall | 0:06e35dd73c95 | 423 | if (f != NULL) { |
alindvall | 0:06e35dd73c95 | 424 | uint32_t len = fileLen(f); |
alindvall | 0:06e35dd73c95 | 425 | printf("f: %7u %s\n", len, name); |
alindvall | 0:06e35dd73c95 | 426 | fclose(f); |
alindvall | 0:06e35dd73c95 | 427 | } else { |
alindvall | 0:06e35dd73c95 | 428 | printf("f: ??? %s\n", name); |
alindvall | 0:06e35dd73c95 | 429 | } |
alindvall | 0:06e35dd73c95 | 430 | } |
alindvall | 0:06e35dd73c95 | 431 | return true; |
alindvall | 0:06e35dd73c95 | 432 | } |
alindvall | 0:06e35dd73c95 | 433 | |
alindvall | 0:06e35dd73c95 | 434 | static void recursiveList(const char* dirname) |
alindvall | 0:06e35dd73c95 | 435 | { |
alindvall | 0:06e35dd73c95 | 436 | printf("\nRecursive list of file and folders in %s\n", dirname); |
alindvall | 0:06e35dd73c95 | 437 | char* buff = (char*)malloc(512); |
alindvall | 0:06e35dd73c95 | 438 | if (buff != NULL) |
alindvall | 0:06e35dd73c95 | 439 | { |
alindvall | 0:06e35dd73c95 | 440 | buff[0] = '\0'; |
alindvall | 0:06e35dd73c95 | 441 | recursiveProcessFS(buff, dirname, list, true); |
alindvall | 0:06e35dd73c95 | 442 | free(buff); |
alindvall | 0:06e35dd73c95 | 443 | } |
alindvall | 0:06e35dd73c95 | 444 | } |
alindvall | 0:06e35dd73c95 | 445 | |
alindvall | 1:b04139d88c59 | 446 | static bool formatIfRequested() |
alindvall | 1:b04139d88c59 | 447 | { |
alindvall | 1:b04139d88c59 | 448 | DMBoard* board = &DMBoard::instance(); |
alindvall | 1:b04139d88c59 | 449 | RtosLog* logger = board->logger(); |
alindvall | 1:b04139d88c59 | 450 | char marker[50]; |
alindvall | 1:b04139d88c59 | 451 | int size; |
alindvall | 1:b04139d88c59 | 452 | uint32_t maxSize = SPIFI::instance().memorySize()>>20; |
alindvall | 1:b04139d88c59 | 453 | |
alindvall | 1:b04139d88c59 | 454 | for (size = 1; size <= maxSize; size++) { |
alindvall | 1:b04139d88c59 | 455 | sprintf(marker, "/ram/format_qspi_%d_mb", size); |
alindvall | 1:b04139d88c59 | 456 | FILE *fp = fopen(marker, "r"); |
alindvall | 1:b04139d88c59 | 457 | if (fp != NULL) { |
alindvall | 1:b04139d88c59 | 458 | logger->printf("Found a marker file requesting to place a %d Mb file system on QSPI\n", size); |
alindvall | 1:b04139d88c59 | 459 | logger->printf("This operation may take up to a couple of minutes!\n"); |
alindvall | 1:b04139d88c59 | 460 | QSPIFileSystem* qspi = board->getQspiFS(); |
alindvall | 1:b04139d88c59 | 461 | |
alindvall | 1:b04139d88c59 | 462 | int err = qspi->format(size); |
alindvall | 1:b04139d88c59 | 463 | if (err == 0) { |
alindvall | 1:b04139d88c59 | 464 | logger->printf("Successfully added a %d Mb file system to QSPI!\n", size); |
alindvall | 1:b04139d88c59 | 465 | } else { |
alindvall | 1:b04139d88c59 | 466 | logger->printf("Failed to format QSPI!\n"); |
alindvall | 1:b04139d88c59 | 467 | } |
alindvall | 1:b04139d88c59 | 468 | // formatting was requested |
alindvall | 1:b04139d88c59 | 469 | return true; |
alindvall | 1:b04139d88c59 | 470 | } |
alindvall | 1:b04139d88c59 | 471 | } |
alindvall | 1:b04139d88c59 | 472 | // no formatting requested |
alindvall | 1:b04139d88c59 | 473 | return false; |
alindvall | 1:b04139d88c59 | 474 | } |
alindvall | 1:b04139d88c59 | 475 | |
alindvall | 0:06e35dd73c95 | 476 | static void showInfoScreen() |
alindvall | 0:06e35dd73c95 | 477 | { |
alindvall | 1:b04139d88c59 | 478 | static SWIM_WINDOW_T* win = NULL; |
alindvall | 1:b04139d88c59 | 479 | static void* fb = NULL; |
alindvall | 1:b04139d88c59 | 480 | |
alindvall | 0:06e35dd73c95 | 481 | Display* disp = DMBoard::instance().display(); |
alindvall | 0:06e35dd73c95 | 482 | win = (SWIM_WINDOW_T*)malloc(sizeof(SWIM_WINDOW_T)); |
alindvall | 0:06e35dd73c95 | 483 | fb = disp->allocateFramebuffer(); |
alindvall | 1:b04139d88c59 | 484 | |
alindvall | 1:b04139d88c59 | 485 | swim_window_open(win, |
alindvall | 0:06e35dd73c95 | 486 | disp->width(), disp->height(), // full size |
alindvall | 0:06e35dd73c95 | 487 | (COLOR_T*)fb, |
alindvall | 0:06e35dd73c95 | 488 | 0,0,disp->width()-1, disp->height()-1, // window position and size |
alindvall | 0:06e35dd73c95 | 489 | 0, // border |
alindvall | 0:06e35dd73c95 | 490 | BLUE, WHITE, BLACK); // colors: pen, backgr, forgr |
alindvall | 1:b04139d88c59 | 491 | |
alindvall | 1:b04139d88c59 | 492 | swim_set_font(win, (FONT_T*)&font_winfreesys14x16); |
alindvall | 0:06e35dd73c95 | 493 | |
alindvall | 0:06e35dd73c95 | 494 | // Show a message |
alindvall | 1:b04139d88c59 | 495 | swim_put_text_centered_win(win, "In this version all instructions are printed on the console!", disp->height()/2 - 20); |
alindvall | 1:b04139d88c59 | 496 | swim_put_text_centered_win(win, "Connect a terminal application using 115200, 8N1.", disp->height()/2 + 20); |
alindvall | 1:b04139d88c59 | 497 | |
alindvall | 0:06e35dd73c95 | 498 | // Start display in default mode (16-bit) |
alindvall | 0:06e35dd73c95 | 499 | Display::DisplayError disperr = disp->powerUp(fb); |
alindvall | 0:06e35dd73c95 | 500 | if (disperr != Display::DisplayError_Ok) { |
alindvall | 0:06e35dd73c95 | 501 | DMBoard::instance().logger()->printf("Failed to initialize the display, got error %d\r\n", disperr); |
alindvall | 0:06e35dd73c95 | 502 | wait_ms(2000); // allow RtosLog to flush messages |
alindvall | 0:06e35dd73c95 | 503 | mbed_die(); |
alindvall | 0:06e35dd73c95 | 504 | } |
alindvall | 0:06e35dd73c95 | 505 | } |
alindvall | 0:06e35dd73c95 | 506 | |
alindvall | 0:06e35dd73c95 | 507 | /****************************************************************************** |
alindvall | 0:06e35dd73c95 | 508 | * Main function |
alindvall | 0:06e35dd73c95 | 509 | *****************************************************************************/ |
alindvall | 0:06e35dd73c95 | 510 | int main() |
alindvall | 0:06e35dd73c95 | 511 | { |
alindvall | 0:06e35dd73c95 | 512 | DMBoard::BoardError err; |
alindvall | 0:06e35dd73c95 | 513 | DMBoard* board = &DMBoard::instance(); |
alindvall | 0:06e35dd73c95 | 514 | RtosLog* log = board->logger(); |
alindvall | 0:06e35dd73c95 | 515 | err = board->init(); |
alindvall | 0:06e35dd73c95 | 516 | if (err != DMBoard::Ok) { |
alindvall | 0:06e35dd73c95 | 517 | log->printf("Failed to initialize the board, got error %d\r\n", err); |
alindvall | 0:06e35dd73c95 | 518 | wait_ms(2000); // allow RtosLog to flush messages |
alindvall | 0:06e35dd73c95 | 519 | mbed_die(); |
alindvall | 0:06e35dd73c95 | 520 | } |
alindvall | 1:b04139d88c59 | 521 | |
alindvall | 0:06e35dd73c95 | 522 | log->printf("\n\n---\nQSPI file syncer app\nBuilt: " __DATE__ " at " __TIME__ "\n\n"); |
alindvall | 0:06e35dd73c95 | 523 | |
alindvall | 1:b04139d88c59 | 524 | showInfoScreen(); |
alindvall | 1:b04139d88c59 | 525 | |
alindvall | 0:06e35dd73c95 | 526 | // allocate a chunk of memory in the external SDRAM to use as a RAM file system |
alindvall | 0:06e35dd73c95 | 527 | void* fsmem = malloc(RAM_FS_SIZE); |
alindvall | 0:06e35dd73c95 | 528 | if (fsmem == NULL) { |
alindvall | 0:06e35dd73c95 | 529 | log->printf("Failed to allocate memory for RAM file system\n"); |
alindvall | 0:06e35dd73c95 | 530 | mbed_die(); |
alindvall | 0:06e35dd73c95 | 531 | } |
alindvall | 1:b04139d88c59 | 532 | |
alindvall | 0:06e35dd73c95 | 533 | // create a file system based on the allocated memory |
alindvall | 0:06e35dd73c95 | 534 | RAMFileSystem ramfs((uint32_t)fsmem, RAM_FS_SIZE, "ram"); |
alindvall | 1:b04139d88c59 | 535 | USBMSD_RAMFS usbmsd(&ramfs); |
alindvall | 1:b04139d88c59 | 536 | |
alindvall | 1:b04139d88c59 | 537 | while(true) |
alindvall | 1:b04139d88c59 | 538 | { |
alindvall | 0:06e35dd73c95 | 539 | // add an empty file system on it |
alindvall | 0:06e35dd73c95 | 540 | ramfs.format(); |
alindvall | 1:b04139d88c59 | 541 | |
alindvall | 1:b04139d88c59 | 542 | QSPIFileSystem* qspi = board->getQspiFS(); |
alindvall | 0:06e35dd73c95 | 543 | bool qspiFormatted = qspi->isformatted(); |
alindvall | 0:06e35dd73c95 | 544 | if (!qspiFormatted) |
alindvall | 0:06e35dd73c95 | 545 | { |
alindvall | 0:06e35dd73c95 | 546 | addNotFormattedFile(); |
alindvall | 0:06e35dd73c95 | 547 | } |
alindvall | 1:b04139d88c59 | 548 | else |
alindvall | 1:b04139d88c59 | 549 | { |
alindvall | 0:06e35dd73c95 | 550 | createImageFile(qspi); |
alindvall | 1:b04139d88c59 | 551 | |
alindvall | 0:06e35dd73c95 | 552 | // Copy QSPI FS to RAM FS |
alindvall | 0:06e35dd73c95 | 553 | syncDir("/ram/", "/qspi/"); |
alindvall | 1:b04139d88c59 | 554 | } |
alindvall | 1:b04139d88c59 | 555 | |
alindvall | 0:06e35dd73c95 | 556 | printf("Insert the USB cable!\n"); |
alindvall | 0:06e35dd73c95 | 557 | printf("Starting USB...\n"); |
alindvall | 0:06e35dd73c95 | 558 | for (int i = 0; i < 10; i++) |
alindvall | 0:06e35dd73c95 | 559 | { |
alindvall | 0:06e35dd73c95 | 560 | if (usbmsd.connect()) |
alindvall | 0:06e35dd73c95 | 561 | { |
alindvall | 0:06e35dd73c95 | 562 | printf("Connected!\n"); |
alindvall | 0:06e35dd73c95 | 563 | break; |
alindvall | 0:06e35dd73c95 | 564 | } |
alindvall | 0:06e35dd73c95 | 565 | printf("Failed to connect USB, testing again...\n"); |
alindvall | 0:06e35dd73c95 | 566 | printf("Insert (or remove and then insert) the USB cable!\n"); |
alindvall | 0:06e35dd73c95 | 567 | wait(1); |
alindvall | 0:06e35dd73c95 | 568 | } |
alindvall | 0:06e35dd73c95 | 569 | |
alindvall | 1:b04139d88c59 | 570 | waitForButtonPress(); |
alindvall | 0:06e35dd73c95 | 571 | |
alindvall | 0:06e35dd73c95 | 572 | usbmsd.disconnect(); |
alindvall | 0:06e35dd73c95 | 573 | printf("Disconnected!\n"); |
alindvall | 0:06e35dd73c95 | 574 | |
alindvall | 1:b04139d88c59 | 575 | // Look for (re)format instruction file |
alindvall | 1:b04139d88c59 | 576 | if (formatIfRequested()) { |
alindvall | 1:b04139d88c59 | 577 | continue; |
alindvall | 1:b04139d88c59 | 578 | } |
alindvall | 1:b04139d88c59 | 579 | |
alindvall | 1:b04139d88c59 | 580 | // Copy RAM FS to QSPI FS |
alindvall | 0:06e35dd73c95 | 581 | recursiveList("/ram/"); |
alindvall | 0:06e35dd73c95 | 582 | syncDir("/qspi/", "/ram/"); |
alindvall | 1:b04139d88c59 | 583 | } |
alindvall | 0:06e35dd73c95 | 584 | } |
alindvall | 0:06e35dd73c95 | 585 |