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:
- Make sure that the QSPI file system has been formatted (using either the app_qspi_format application or one of the erase.* images).
- Download the app_qspifs_memstick 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 micro USB slot on the back of the LPC4088 QuickStart Board, underneath the ethernet connector, 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 button on the LPC4088 QuickStart Board
- 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 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.
Revision 0:bd0d999bb6fb, committed 2013-09-26
- Comitter:
- embeddedartists
- Date:
- Thu Sep 26 09:21:11 2013 +0000
- Child:
- 1:bbf987874d5f
- Commit message:
- First version
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/EALib.lib Thu Sep 26 09:21:11 2013 +0000 @@ -0,0 +1,1 @@ +https://mbed.org/users/embeddedartists/code/EALib/#f3ef2b577bf6
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/RAMFileSystem.cpp Thu Sep 26 09:21:11 2013 +0000 @@ -0,0 +1,56 @@ +#include "RAMFileSystem.h" +#include "mbed_debug.h" + +#define RAMFS_DBG 0 + +#define SECTOR_SIZE 512 + +RAMFileSystem::RAMFileSystem(uint32_t addr, uint32_t size, const char* name) : + FATFileSystem(name) { + memStart = addr; + memSize = size - (size % SECTOR_SIZE); + status = 1; //1: disk not initialized +} + +int RAMFileSystem::disk_initialize() { + debug_if(RAMFS_DBG, "init RAM fs\n"); + status = 0; //OK + return status; +} + +int RAMFileSystem::disk_write(const uint8_t *buffer, uint64_t sector) { + debug_if(RAMFS_DBG, "write to sector %llu\n", sector); + if (sector >= disk_sectors()) { + return 1; + } + + memcpy((uint8_t*)(memStart + SECTOR_SIZE*((uint32_t)sector)), buffer, SECTOR_SIZE); + return 0; +} + +int RAMFileSystem::disk_read(uint8_t *buffer, uint64_t sector) { + debug_if(RAMFS_DBG, "read from sector %llu\n", sector); + if (sector >= disk_sectors()) { + return 1; + } + + memcpy(buffer, (uint8_t*)(memStart + SECTOR_SIZE*((uint32_t)sector)), SECTOR_SIZE); + return 0; +} + +int RAMFileSystem::disk_status() { + debug_if(RAMFS_DBG, "disk status %d\n", status); + return status; +} +int RAMFileSystem::disk_sync() { + return 0; +} +uint64_t RAMFileSystem::disk_sectors() { + debug_if(RAMFS_DBG, "returning fs has %u sectors\n", memSize/SECTOR_SIZE); + return memSize/SECTOR_SIZE; +} + +uint64_t RAMFileSystem::disk_size() { + return memSize; +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/RAMFileSystem.h Thu Sep 26 09:21:11 2013 +0000 @@ -0,0 +1,53 @@ +#ifndef RAMFILESYSTEM_H +#define RAMFILESYSTEM_H + +#include "mbed.h" +#include "FATFileSystem.h" +#include "sdram.h" +#include <stdint.h> + +/** Creates a FAT file system in SDRAM + * + * @code + * #include "mbed.h" + * #include "RAMFileSystem.h" + * + * RAMFileSystem ramfs(0xA0000000, 4*1024*1024, "ram"); // 4MB of ram starting at 0xA... + * + * int main() { + * sdram_init(); + * + * FILE *fp = fopen("/ram/myfile.txt", "w"); + * fprintf(fp, "Hello World!\n"); + * fclose(fp); + * } + * @endcode + */ +class RAMFileSystem : public FATFileSystem { +public: + + /** Create the File System in RAM + * + * @param addr Start of memory to use for file system + * @param size Number of bytes to use for file system + * @param name The name used to access the virtual filesystem + */ + RAMFileSystem(uint32_t addr, uint32_t size, const char* name); + virtual int disk_initialize(); + virtual int disk_status(); + virtual int disk_read(uint8_t * buffer, uint64_t sector); + virtual int disk_write(const uint8_t * buffer, uint64_t sector); + virtual int disk_sync(); + virtual uint64_t disk_sectors(); + + uint64_t disk_size(); + +protected: + + uint32_t memStart; + uint32_t memSize; + int status; +}; + +#endif +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBDevice.lib Thu Sep 26 09:21:11 2013 +0000 @@ -0,0 +1,1 @@ +https://mbed.org/users/mbed_official/code/USBDevice/#d495202c90f4
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBMSD_RAMFS.cpp Thu Sep 26 09:21:11 2013 +0000 @@ -0,0 +1,35 @@ +#include "USBMSD_RAMFS.h" + +USBMSD_RAMFS::USBMSD_RAMFS(RAMFileSystem* ramfs, uint16_t vendor_id, uint16_t product_id, uint16_t product_release) : + USBMSD(vendor_id, product_id, product_release) +{ + this->ramfs = ramfs; +} + +int USBMSD_RAMFS::disk_read(uint8_t * data, uint64_t block) +{ + return ramfs->disk_read(data, block); +} + +int USBMSD_RAMFS::disk_write(const uint8_t * data, uint64_t block) +{ + return ramfs->disk_write(data, block); +} + +int USBMSD_RAMFS::disk_initialize() { + return ramfs->disk_initialize(); +} + +uint64_t USBMSD_RAMFS::disk_sectors() { + return ramfs->disk_sectors(); +} + +uint64_t USBMSD_RAMFS::disk_size() { + return ramfs->disk_size(); +} + +int USBMSD_RAMFS::disk_status() { + return ramfs->disk_status(); +} + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBMSD_RAMFS.h Thu Sep 26 09:21:11 2013 +0000 @@ -0,0 +1,78 @@ +#ifndef USBMSDRAMFS_H +#define USBMSDRAMFS_H + +#include "mbed.h" +#include "USBMSD.h" +#include "RAMFileSystem.h" +#include <stdint.h> + +/** + * USBMSD_RAMFS class: Allows the mbed board to expose a FAT file system in SDRAM as a USB memory stick + */ +class USBMSD_RAMFS : public USBMSD { +public: + + /** + * Constructor + * + * @param ramfs The RAM file system + * @param vendor_id Your vendor_id + * @param product_id Your product_id + * @param product_release Your preoduct_release + */ + USBMSD_RAMFS(RAMFileSystem* ramfs, uint16_t vendor_id = 0x0703, uint16_t product_id = 0x0104, uint16_t product_release = 0x0001); + +protected: + + /* + * read a block on a storage chip + * + * @param data pointer where will be stored read data + * @param block block number + * @returns 0 if successful + */ + virtual int disk_read(uint8_t * data, uint64_t block); + + /* + * write a block on a storage chip + * + * @param data data to write + * @param block block number + * @returns 0 if successful + */ + virtual int disk_write(const uint8_t * data, uint64_t block); + + /* + * Disk initilization + */ + virtual int disk_initialize(); + + /* + * Return the number of blocks + * + * @returns number of blocks + */ + virtual uint64_t disk_sectors(); + + /* + * Return memory size + * + * @returns memory size + */ + virtual uint64_t disk_size(); + + + /* + * To check the status of the storage chip + * + * @returns status: 0: OK, 1: disk not initialized, 2: no medium in the drive, 4: write protected + */ + virtual int disk_status(); + +protected: + + RAMFileSystem* ramfs; +}; + +#endif +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/crc.cpp Thu Sep 26 09:21:11 2013 +0000 @@ -0,0 +1,76 @@ +/***************************************************************************** + * + * Copyright(C) 2011, Embedded Artists AB + * All rights reserved. + * + ****************************************************************************** + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * products. This software is supplied "AS IS" without any warranties. + * Embedded Artists AB assumes no responsibility or liability for the + * use of the software, conveys no license or title under any patent, + * copyright, or mask work right to the product. Embedded Artists AB + * reserves the right to make changes in the software without + * notification. Embedded Artists AB also make no representation or + * warranty that such application will be suitable for the specified + * use without further testing or modification. + *****************************************************************************/ + + + +/****************************************************************************** + * Includes + *****************************************************************************/ + +#include "mbed.h" +#include "crc.h" + + +/****************************************************************************** + * Defines and typedefs + *****************************************************************************/ + +#define NUM_CRC_BUFF_ENTRIES (100) + +#define CRC32_INIT() do { LPC_CRC->MODE = 0x00000036; LPC_CRC->SEED = 0xffffffff; } while(0) + +#define CRC32_WRITE8(__val) LPC_CRC->WR_DATA_BYTE.DATA = (uint8_t)(__val) +#define CRC32_WRITE16(__val) LPC_CRC->WR_DATA_WORD.DATA = (uint16_t)(__val) +#define CRC32_WRITE32(__val) LPC_CRC->WR_DATA_DWORD.DATA = (__val) + +#define CRC32_SUM() LPC_CRC->SUM + +/****************************************************************************** + * External global variables + *****************************************************************************/ + +/****************************************************************************** + * Local variables + *****************************************************************************/ + +static uint32_t crcbuff[NUM_CRC_BUFF_ENTRIES]; + +/****************************************************************************** + * Local Functions + *****************************************************************************/ + + +/****************************************************************************** + * Public Functions + *****************************************************************************/ + +uint32_t crc_Read(FILE* f) +{ + CRC32_INIT(); + fseek(f, 0, SEEK_SET); + memset(crcbuff, 0, sizeof(uint32_t)*NUM_CRC_BUFF_ENTRIES); + int numRead = fread(crcbuff, sizeof(uint32_t), 100, f); + while (numRead > 0) { + for (int i = 0; i < numRead; i++) { + CRC32_WRITE32(crcbuff[i]); + } + numRead = fread(crcbuff, sizeof(uint32_t), 100, f); + } + return CRC32_SUM(); +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/crc.h Thu Sep 26 09:21:11 2013 +0000 @@ -0,0 +1,10 @@ +#ifndef __CRC_H +#define __CRC_H + +#include <stdio.h> +#include <stdint.h> + +uint32_t crc_Read(FILE* f); + +#endif /* end __CRC_H */ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Thu Sep 26 09:21:11 2013 +0000 @@ -0,0 +1,539 @@ +/****************************************************************************** + * Includes + *****************************************************************************/ + +#include "mbed.h" + +#include "QSPIFileSystem.h" + +#include "USBMSD_RAMFS.h" +#include "RAMFileSystem.h" +#include "sdram.h" +#include "crc.h" + +/****************************************************************************** + * Typedefs and defines + *****************************************************************************/ + +typedef bool (*syncFunc)(const char* name, bool isDir); + +#define RAM_FS_SIZE (20*1024*1024) //20MB + +/****************************************************************************** + * Local variables + *****************************************************************************/ + +QSPIFileSystem qspi("qspi"); +//RAMFileSystem ramfs(0xA0000000, 20*1024*1024, "ram"); +//USBMSD_RAMFS usbmsd(&ramfs); + +DigitalOut myled1(LED1); +DigitalOut myled2(LED2); +DigitalIn button(p23); + +DigitalOut myled(LED1); +static char lsbuff[NAME_MAX+1]; + +static char image_file_name[128] = { '\0' }; + +/****************************************************************************** + * Local functions + *****************************************************************************/ + +static void ledShowProgress() +{ + static int state = 0; + state = (state + 1) % 2; + switch (state) + { + case 0: + myled1 = 1; + myled2 = 0; + break; + + case 1: + default: + myled1 = 0; + myled2 = 1; + } +} + +static void handleError(const char* msg) +{ + printf(msg); + while(true) { + myled1 = 1; + myled2 = 1; + wait(0.3); + myled1 = 0; + myled2 = 0; + wait(0.3); + } +} + +static void waitForButtonPress() +{ + printf("Press button to sync file systems\n"); + + myled1 = 1; + myled2 = 1; + while(button.read() == 1) { + wait(0.1); + } + myled1 = 0; + printf("Button pressed, now release it\n"); + while(button.read() == 0) { + wait(0.1); + } +} + +static void addNotFormattedFile() +{ + FILE *fp = fopen("/ram/qspi_not_formatted.txt", "w"); + if (fp != NULL) { + fprintf(fp, "The QSPI file system has not be formatted and this program can't do it.\n"); + fprintf(fp, "Format the QSPI file system and then run this program again!\n"); + fclose(fp); + } +} + +static bool recursiveProcessFS(char* buff, const char* name, syncFunc func, bool adding) +{ + uint32_t len = strlen(buff); + if (len > 0) { + if (buff[len - 1] != '/') { + buff[len++] = '/'; + buff[len] = '\0'; + } + } + strcat(buff, name); + len += strlen(name); + + DIR *d = opendir(buff); + bool result = true; // success + if (d != NULL) { + if (adding) { + // when processing in adding mode folders must be created before it's content + result = func(buff, true); + } + struct dirent *p; + while (result && ((p = readdir(d)) != NULL)) { + result = recursiveProcessFS(buff, p->d_name, func, adding); + buff[len] = '\0'; + } + closedir(d); + if (result && !adding) { + // when processing in removing mode folders must be deleted after it's content + result = func(buff, true); + } + } else { + // a file + result = func(buff, false); + } + return result; +} + +static uint32_t fileLen(FILE* f) +{ + uint32_t pos = ftell(f); + fseek(f, 0, SEEK_END); + uint32_t size = ftell(f); + fseek(f, pos, SEEK_SET); + return size; +} + +static bool copy(FILE* fSrc, FILE* fDst) +{ + char buff[512]; + uint32_t left = fileLen(fSrc); + uint32_t num; + uint32_t chunk; + + fseek(fSrc, 0, SEEK_SET); + do { + chunk = (left < 512) ? left : 512; + num = fread(buff, 1, chunk, fSrc); + if (num > 0) { + uint32_t tmp = fwrite(buff, 1, num, fDst); + if (tmp != num) { + // failed to write + return false; + } + left -= num; + ledShowProgress(); + } + } while(num > 0 && left > 0); + + // copied entire file + return true; +} + +static bool identicalFiles(const char* srcName, const char* dstName) +{ + FILE* fSrc = NULL; + FILE* fDst = NULL; + bool identical = false; + do + { + fSrc = fopen(srcName, "r"); + if (fSrc == NULL) { + break; + } + fDst = fopen(dstName, "r"); + if (fDst == NULL) { + break; + } + if (fileLen(fSrc) != fileLen(fDst)) { + break; + } + if (crc_Read(fSrc) != crc_Read(fDst)) { + break; + } + + // All tests passed so the files are identical + identical = true; + + } while(false); + + if (fSrc != NULL) { + fclose(fSrc); + } + if (fDst != NULL) { + fclose(fDst); + } + + return identical; +} + +static bool addExisting(const char* srcName, bool isDir, const char* dstName) +{ + bool result = true; // success + if (isDir) { + DIR *d = opendir(dstName); + if (d == NULL) { + if (dstName[1] != 'r') { printf("%s, new dir, adding\n", dstName); } + if (mkdir(dstName, 0) != 0) { + printf("Failed to create folder %s\n", dstName); + result = false; // dir did not exist and could not be created + } + } else { + closedir(d); + } + } else if (!identicalFiles(srcName, dstName)) { + // Compare the files to avoid replacing with same + FILE* fSrc = fopen(srcName, "r"); + if (fSrc != NULL) { + FILE* fDst = fopen(dstName, "w"); // open and truncate + if (fDst != NULL) { + if (dstName[1] != 'r') { printf("%s, changed, updating\n", dstName); } + result = copy(fSrc, fDst); + if (!result) { + printf("Failed to copy %s to %s\n", srcName, dstName); + } + fclose(fDst); + } else { + printf("Failed to create file %s\n", dstName); + result = false; // unable to create file + } + fclose(fSrc); + } else { + printf("Failed to copen source file file %s\n", srcName); + result = false; // unable to open source + } + } else { + if (dstName[1] != 'r') { printf("%s identical, skipping\n", dstName); } + } + return result; +} + +static bool addExistingToQspi(const char* name, bool isDir) +{ + // create the target file name by replacing /ram/ with /qspi/ + char buff[256]; + buff[0] = '\0'; + strcat(buff, "/qspi/"); + strcat(buff, name+5); + + // Don't add the file created by createImageFile() + if (strcmp(name, image_file_name) == 0) { + return true; + } + + return addExisting(name, isDir, buff); +} + +static bool addExistingToRAM(const char* name, bool isDir) +{ + // create the target file name by replacing /qspi/ with /ram/ + char buff[256]; + buff[0] = '\0'; + strcat(buff, "/ram/"); + strcat(buff, name+6); + return addExisting(name, isDir, buff); +} + +static bool removeIfMissing(const char* toLookFor, const char* toRemove, bool isDir) +{ + int result = 0; //success + if (isDir) { + DIR *d = opendir(toLookFor); + if (d == NULL) { + // dir doesn't exist => delete it + if (toRemove[1] != 'r') { printf("%s, missing, deleting dir\n", toRemove); } + result = remove(toRemove); + ledShowProgress(); + } else { + // dir exist => don't delete + closedir(d); + } + } else { + FILE* f = fopen(toLookFor, "r"); + if (f == NULL) { + // file doesn't exist => delete it + if (toRemove[1] != 'r') { printf("%s, missing, deleting file\n", toRemove); } + result = remove(toRemove); + ledShowProgress(); + } else { + // file exist => don't delete + fclose(f); + } + } + return (result == 0); +} + +static bool removeMissingFromQspi(const char* name, bool isDir) +{ + // create the target file name by replacing /qspi/ with /ram/ + char buff[256]; + buff[0] = '\0'; + strcat(buff, "/ram/"); + strcat(buff, name+6); + removeIfMissing(buff, name, isDir); + return true; +} + +static bool removeMissingFromRAM(const char* name, bool isDir) +{ + // create the target file name by replacing /ram/ with /qspi/ + char buff[256]; + buff[0] = '\0'; + strcat(buff, "/qspi/"); + strcat(buff, name+5); + + // Don't remove the file created by createImageFile() + if (strcmp(name, image_file_name) == 0) { + return true; + } + + removeIfMissing(buff, name, isDir); + return true; +} + +static void syncDir(const char* to, const char* from) +{ + printf("Starting to sync %s on top of %s (This may take time. LED1 & 2 blink for each file)\n", from, to); + + char* buff = (char*)malloc(512); + if (buff != NULL) + { + buff[0] = '\0'; + if (strcmp(to, "/qspi/") == 0) { + if (!recursiveProcessFS(buff, to, removeMissingFromQspi, false)) { + printf("Failed to remove files from %s that were missing on %s\n", to, from); + } else { + buff[0] = '\0'; + if (!recursiveProcessFS(buff, from, addExistingToQspi, true)) { + printf("Failed to add files to %s that existed on %s\n", to, from); + } + } + } else { + if (!recursiveProcessFS(buff, to, removeMissingFromRAM, false)) { + printf("Failed to remove files from %s that were missing on %s\n", to, from); + } else { + buff[0] = '\0'; + if (!recursiveProcessFS(buff, from, addExistingToRAM, true)) { + printf("Failed to add files to %s that existed on %s\n", to, from); + } + } + } + free(buff); + } + printf("Sync completed\n"); +} + + +static void createImageFile() +{ + uint32_t startAddr; + uint32_t endAddr; + uint32_t size; + + printf("Creating image of existing (if any) QSPI file system\n"); + + if (!qspi.getMemoryBoundaries(&startAddr, &endAddr)) + { + handleError("QSPI FS not formatted or impossible to determine it's size\n"); + } + + // Align the start address to an even multiple of 1MB + startAddr = startAddr & 0xfff00000; + + // Update the file to match the size of the file system + size = endAddr - startAddr; + if ((size < 0x00100000) || (size > 0x00800000) || ((size & 0xfffff) > 0)) + { + sprintf(lsbuff, "QSPI FS size is not supported (%u bytes)\n", size); + handleError(lsbuff); + } + sprintf(image_file_name, "/ram/.current/fs_image.fs%d", (size >> 20)); + + // NOTE: The line below is very very !!!! important. For some weird reason the + // RAM file system must have at least one folder on it before USB is connected. + // If the RAM file system doesn't have any folders on it the result is that + // the content of the RAM file system will be the same after USB is disconnected + // as it was before connecting - regardless of what is added. Very strange indeed. + mkdir("/ram/.current", 0); + + printf("QSPI FS max size is %d MB\n", (size >> 20)); + + FILE *fp = fopen(image_file_name, "w"); + if (fp != NULL) + { + while (size > 0) + { + uint32_t written = fwrite((char*)(endAddr - size), 1, size, fp); + size -= written; + if (written == 0) + { + handleError("Failed to create QSPI image file\n"); + } + } + fclose(fp); + } +} + +static bool list(const char* name, bool isDir) +{ + if (isDir) { + printf("d: %s\n", name); + } else { + FILE* f = fopen(name, "r"); + if (f != NULL) { + uint32_t len = fileLen(f); + printf("f: %7u %s\n", len, name); + fclose(f); + } else { + printf("f: ??? %s\n", name); + } + } + return true; +} + +static void recursiveList(const char* dirname) +{ + printf("\nRecursive list of file and folders in %s\n", dirname); + char* buff = (char*)malloc(512); + if (buff != NULL) + { + buff[0] = '\0'; + recursiveProcessFS(buff, dirname, list, true); + free(buff); + } +} + +/****************************************************************************** + * Main function + *****************************************************************************/ +int main() +{ + printf("\n-----------------\n\nWelcome to the QSPI file system tool...\n"); + + // 1) Make sure that the button works + // 2) Init SDRAM and allocate space for the RAM file system + // 3) Setup RAM FS + // 4a) If QSPI FS is not formatted: + // i) Create a "qspi_not_formatted.txt" file in the root of the file system + // 4b) QSPI FS formatted + // i) Create an image file of the QSPI FS + // ii) Sync QSPI FS on top of RAM FS + // 5) Connect USB + // 6a) If QSPI FS is not formatted: Loop forever doing nothing + // 6b) QSPI FS formatted: Wait for button press + // 7) Button pressed, Disconnect USB + // 8) QSPI formatted + // i) Sync RAM FS on top of QSPI FS + // ii) Goto 3) + // + + // 1) + button.mode(PullUp); + + // 2) + if (sdram_init()) { + handleError("Failed to initialize SDRAM\n"); + } + + void* fsmem = malloc(RAM_FS_SIZE); + if (fsmem == NULL) { + handleError("Failed to allocate memory for RAM file system\n"); + } + RAMFileSystem ramfs((uint32_t)fsmem, RAM_FS_SIZE, "ram"); + USBMSD_RAMFS usbmsd(&ramfs); + + while(true) + { + // 3) + ramfs.format(); + + // 4a) + bool qspiFormatted = qspi.isformatted(); + if (!qspiFormatted) + { + addNotFormattedFile(); + } + + // 4b) + else + { + //addTestFile(); + createImageFile(); + + // Copy QSPI FS to RAM FS + syncDir("/ram/", "/qspi/"); + } + + // 5) + printf("Insert the USB cable!\n"); + printf("Starting USB...\n"); + for (int i = 0; i < 10; i++) + { + if (usbmsd.connect()) + { + printf("Connected!\n"); + break; + } + printf("Failed to connect USB, testing again...\n"); + printf("Insert (or remove and then insert) the USB cable!\n"); + wait(1); + } + + // 6b) + if (qspiFormatted) + { + waitForButtonPress(); + } + else + { + // 6a) no point in waiting for buttons if no file system + while (1) {}; + } + + // 7) + usbmsd.disconnect(); + printf("Disconnected!\n"); + + // 8) Copy RAM FS to QSPI FS + recursiveList("/ram/"); + syncDir("/qspi/", "/ram/"); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Thu Sep 26 09:21:11 2013 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed/builds/a9913a65894f \ No newline at end of file