The wait in mci_WaitForEvent will delay all card transactions.

Dependencies:   FATFileSystem

Fork of EALib by EmbeddedArtists AB

Committer:
embeddedartists
Date:
Thu Sep 26 06:37:02 2013 +0000
Revision:
0:0fdadbc3d852
Child:
8:fe3cb3fbb64e
First version

Who changed what in which revision?

UserRevisionLine numberNew contents of line
embeddedartists 0:0fdadbc3d852 1 #include "QSPIFileSystem.h"
embeddedartists 0:0fdadbc3d852 2 #include "mbed_debug.h"
embeddedartists 0:0fdadbc3d852 3
embeddedartists 0:0fdadbc3d852 4 #include "spifi_rom_api.h"
embeddedartists 0:0fdadbc3d852 5
embeddedartists 0:0fdadbc3d852 6 /******************************************************************************
embeddedartists 0:0fdadbc3d852 7 * Defines and typedefs
embeddedartists 0:0fdadbc3d852 8 *****************************************************************************/
embeddedartists 0:0fdadbc3d852 9
embeddedartists 0:0fdadbc3d852 10 #define QSPI_DBG 0
embeddedartists 0:0fdadbc3d852 11
embeddedartists 0:0fdadbc3d852 12 /*
embeddedartists 0:0fdadbc3d852 13 * The SPIFI_ROM_PTR (0x1FFF1FF8) points to an area where the pointers to
embeddedartists 0:0fdadbc3d852 14 * different drivers in ROM are stored.
embeddedartists 0:0fdadbc3d852 15 */
embeddedartists 0:0fdadbc3d852 16 typedef struct {
embeddedartists 0:0fdadbc3d852 17 /*const*/ unsigned p_usbd; // USBROMD
embeddedartists 0:0fdadbc3d852 18 /*const*/ unsigned p_clib;
embeddedartists 0:0fdadbc3d852 19 /*const*/ unsigned p_cand;
embeddedartists 0:0fdadbc3d852 20 /*const*/ unsigned p_pwrd; // PWRROMD
embeddedartists 0:0fdadbc3d852 21 /*const*/ unsigned p_promd; // DIVROMD
embeddedartists 0:0fdadbc3d852 22 /*const*/ SPIFI_RTNS *pSPIFID; // SPIFIROMD
embeddedartists 0:0fdadbc3d852 23 /*const*/ unsigned p_dev3;
embeddedartists 0:0fdadbc3d852 24 /*const*/ unsigned p_dev4;
embeddedartists 0:0fdadbc3d852 25 } ROM;
embeddedartists 0:0fdadbc3d852 26
embeddedartists 0:0fdadbc3d852 27 #define ROM_DRIVERS_PTR ((ROM *)(*((unsigned int *)SPIFI_ROM_PTR)))
embeddedartists 0:0fdadbc3d852 28 #define IS_ADDR_IN_SPIFI(__addr) ( (((uint32_t)(__addr)) & 0xff000000) == SPIFI_MEM_BASE )
embeddedartists 0:0fdadbc3d852 29
embeddedartists 0:0fdadbc3d852 30 #define MEM_SIZE (memInfo.memSize) //(8*1024*1024)
embeddedartists 0:0fdadbc3d852 31 #define ERASE_SIZE (memInfo.eraseBlockSize) //(64*1024)
embeddedartists 0:0fdadbc3d852 32 #define NUM_BLOCKS (memInfo.numEraseBlocks) //(MEM_SIZE/ERASE_SIZE)
embeddedartists 0:0fdadbc3d852 33
embeddedartists 0:0fdadbc3d852 34 typedef uint32_t toc_entry_t;
embeddedartists 0:0fdadbc3d852 35
embeddedartists 0:0fdadbc3d852 36 #define TOC_BLOCK_ADDR (memInfo.tocBlockAddr) //(SPIFI_MEM_BASE + (NUM_BLOCKS - 1)*ERASE_SIZE)
embeddedartists 0:0fdadbc3d852 37 #define TOC_SIZE (memInfo.tocSizeInBytes) //(sizeof(toc_entry_t) * NUM_BLOCKS)
embeddedartists 0:0fdadbc3d852 38 #define NUM_TOCS (memInfo.numTocs) //((int)(ERASE_SIZE/TOC_SIZE))
embeddedartists 0:0fdadbc3d852 39 #define NUM_TOC_BLOCKS ((NUM_TOCS * TOC_SIZE) / ERASE_SIZE)
embeddedartists 0:0fdadbc3d852 40 #define NUM_TOC_ENTRIES ((int)(TOC_SIZE/sizeof(toc_entry_t)))
embeddedartists 0:0fdadbc3d852 41
embeddedartists 0:0fdadbc3d852 42 #define TOC_UNUSED (0xffffffff)
embeddedartists 0:0fdadbc3d852 43 #define TOC_MAX (NUM_BLOCKS - 1)
embeddedartists 0:0fdadbc3d852 44 #define TOC_VALID_MASK (1UL<<31)
embeddedartists 0:0fdadbc3d852 45 #define TOC_RESERVED_MASK (1UL<<30)
embeddedartists 0:0fdadbc3d852 46 #define TOC_USED_MASK (1UL<<29)
embeddedartists 0:0fdadbc3d852 47 #define TOC_FILE_MASK (1UL<<28)
embeddedartists 0:0fdadbc3d852 48 #define TOC_FSIZE_MASK (0x3ffff)
embeddedartists 0:0fdadbc3d852 49 #define TOC_MANDAT_SET_MASK (0x0ffc0000)
embeddedartists 0:0fdadbc3d852 50
embeddedartists 0:0fdadbc3d852 51 #define MANDATORY_BITS_SET(__v) (((__v)&TOC_MANDAT_SET_MASK) == TOC_MANDAT_SET_MASK)
embeddedartists 0:0fdadbc3d852 52
embeddedartists 0:0fdadbc3d852 53 #define VALID_TOC_ENTRY(__v) (((__v)&TOC_VALID_MASK) == 0)
embeddedartists 0:0fdadbc3d852 54 #define USED_TOC_ENTRY(__v) (VALID_TOC_ENTRY(__v) && (((__v)&TOC_USED_MASK) == 0))
embeddedartists 0:0fdadbc3d852 55 #define TOC_IS_FILE(__v) (USED_TOC_ENTRY(__v) && (((__v)&TOC_FILE_MASK) == 0))
embeddedartists 0:0fdadbc3d852 56 #define TOC_IS_RESERVED(__v) (VALID_TOC_ENTRY(__v) && (((__v)&TOC_RESERVED_MASK) == 0))
embeddedartists 0:0fdadbc3d852 57 #define FILESIZE(__v) ((__v) & 0x3ffff)
embeddedartists 0:0fdadbc3d852 58
embeddedartists 0:0fdadbc3d852 59 #define FS_MIN(__a, __b) (((__a) < (__b)) ? (__a) : (__b))
embeddedartists 0:0fdadbc3d852 60
embeddedartists 0:0fdadbc3d852 61 // Mask to compare the different access modes. In LPCXpresso this was defined
embeddedartists 0:0fdadbc3d852 62 // but not in uVision
embeddedartists 0:0fdadbc3d852 63 #ifndef O_ACCMODE
embeddedartists 0:0fdadbc3d852 64 #define O_ACCMODE (O_RDONLY | O_WRONLY | O_RDWR)
embeddedartists 0:0fdadbc3d852 65 #endif
embeddedartists 0:0fdadbc3d852 66
embeddedartists 0:0fdadbc3d852 67
embeddedartists 0:0fdadbc3d852 68 /*
embeddedartists 0:0fdadbc3d852 69 * The file header currently only consists of the filename (including path)
embeddedartists 0:0fdadbc3d852 70 * and the string terminating character, but by separating the file name
embeddedartists 0:0fdadbc3d852 71 * length from the size of the header in the code it allows future additions
embeddedartists 0:0fdadbc3d852 72 * to the header without too much code modification.
embeddedartists 0:0fdadbc3d852 73 */
embeddedartists 0:0fdadbc3d852 74 #define HEADER_DNAME_MAXLEN (250)
embeddedartists 0:0fdadbc3d852 75 #define HEADER_FNAME_STRLEN (HEADER_DNAME_MAXLEN + 5)
embeddedartists 0:0fdadbc3d852 76 #define HEADER_FNAME_LEN (HEADER_FNAME_STRLEN + 1)
embeddedartists 0:0fdadbc3d852 77 #define HEADER_LEN (HEADER_FNAME_LEN) // only filename in header for now
embeddedartists 0:0fdadbc3d852 78
embeddedartists 0:0fdadbc3d852 79 typedef enum
embeddedartists 0:0fdadbc3d852 80 {
embeddedartists 0:0fdadbc3d852 81 FS_OK,
embeddedartists 0:0fdadbc3d852 82 FS_ERR_NOT_FORMATTED,
embeddedartists 0:0fdadbc3d852 83 FS_ERR_NO_FILE,
embeddedartists 0:0fdadbc3d852 84 FS_ERR_FILE_EXIST,
embeddedartists 0:0fdadbc3d852 85 FS_ERR_INVALID_PARAM,
embeddedartists 0:0fdadbc3d852 86 FS_ERR_DISK_FULL,
embeddedartists 0:0fdadbc3d852 87 FS_ERR_SPIFI,
embeddedartists 0:0fdadbc3d852 88 FS_ERR_MALLOC,
embeddedartists 0:0fdadbc3d852 89
embeddedartists 0:0fdadbc3d852 90 // FS_ERR_SPIFI_* return codes are listed in the User's Manual
embeddedartists 0:0fdadbc3d852 91 // as possible return values from spifi_init(), spifi_program()
embeddedartists 0:0fdadbc3d852 92 // and spifi_erase() calls.
embeddedartists 0:0fdadbc3d852 93 FS_ERR_SPIFI_INTERNAL_ERROR = 0x20002, // 0x20002, Internal error in API code
embeddedartists 0:0fdadbc3d852 94 FS_ERR_SPIFI_TIMEOUT = 0x20003, // 0x20003, Time-out waiting for program or erase to begin: protection could not be removed.
embeddedartists 0:0fdadbc3d852 95 FS_ERR_SPIFI_OPERAND = 0x20004, // 0x20004, Operand error (i.e. invalid params)
embeddedartists 0:0fdadbc3d852 96 FS_ERR_SPIFI_STATUS = 0x20005, // 0x20005, Device status error
embeddedartists 0:0fdadbc3d852 97 FS_ERR_SPIFI_EXT_DEVICE_ID = 0x20006, // 0x20006, Unknown extended device ID value
embeddedartists 0:0fdadbc3d852 98 FS_ERR_SPIFI_DEVICE_ID = 0x20007, // 0x20007, Unknown device ID code
embeddedartists 0:0fdadbc3d852 99 FS_ERR_SPIFI_DEVICE_TYPE = 0x20008, // 0x20008, Unknown device type code
embeddedartists 0:0fdadbc3d852 100 FS_ERR_SPIFI_MANUFACTURER = 0x20009, // 0x20009, Unknown manufacturer code
embeddedartists 0:0fdadbc3d852 101 FS_ERR_SPIFI_INVALID_JDEC_ID = 0x2000A, // 0x2000A, No operative serial flash (JEDEC ID all zeroes or all ones)
embeddedartists 0:0fdadbc3d852 102 FS_ERR_SPIFI_ERASE_CONFLICT = 0x2000B, // 0x2000B, S_CALLER_ERASE is included in options, and erasure is required.
embeddedartists 0:0fdadbc3d852 103 FS_ERR_SPIFI_VERIFICATION, // other, Other non-zero values can occur if options selects verification.
embeddedartists 0:0fdadbc3d852 104 // They will be the address in the SPIFI memory area at which the first discrepancy was found.
embeddedartists 0:0fdadbc3d852 105 } fresult;
embeddedartists 0:0fdadbc3d852 106
embeddedartists 0:0fdadbc3d852 107 // The number of times to re-attempt a spifi_program() or spifi_erase()
embeddedartists 0:0fdadbc3d852 108 // if the last one reported a verification error.
embeddedartists 0:0fdadbc3d852 109 #define NUM_VERIFICATION_ATTEMPTS (1)
embeddedartists 0:0fdadbc3d852 110
embeddedartists 0:0fdadbc3d852 111 typedef struct
embeddedartists 0:0fdadbc3d852 112 {
embeddedartists 0:0fdadbc3d852 113 uint32_t memSize;
embeddedartists 0:0fdadbc3d852 114 uint32_t eraseBlockSize;
embeddedartists 0:0fdadbc3d852 115 uint32_t numEraseBlocks;
embeddedartists 0:0fdadbc3d852 116 uint32_t tocBlockAddr;
embeddedartists 0:0fdadbc3d852 117 uint32_t numTocs;
embeddedartists 0:0fdadbc3d852 118 uint32_t tocSizeInBytes;
embeddedartists 0:0fdadbc3d852 119 char memName[30];
embeddedartists 0:0fdadbc3d852 120 } meminfo_t;
embeddedartists 0:0fdadbc3d852 121
embeddedartists 0:0fdadbc3d852 122 typedef struct
embeddedartists 0:0fdadbc3d852 123 {
embeddedartists 0:0fdadbc3d852 124 int tocIdx;
embeddedartists 0:0fdadbc3d852 125 uint32_t size;
embeddedartists 0:0fdadbc3d852 126 uint16_t lastBlock;
embeddedartists 0:0fdadbc3d852 127 } fileHandle_t;
embeddedartists 0:0fdadbc3d852 128
embeddedartists 0:0fdadbc3d852 129 /******************************************************************************
embeddedartists 0:0fdadbc3d852 130 * Local variables
embeddedartists 0:0fdadbc3d852 131 *****************************************************************************/
embeddedartists 0:0fdadbc3d852 132
embeddedartists 0:0fdadbc3d852 133 static toc_entry_t* TOC = NULL;//[NUM_BLOCKS];
embeddedartists 0:0fdadbc3d852 134 static int activeTOC = -1;
embeddedartists 0:0fdadbc3d852 135
embeddedartists 0:0fdadbc3d852 136 static const SPIFI_RTNS *spifi = NULL;
embeddedartists 0:0fdadbc3d852 137 static SPIFIobj obj;
embeddedartists 0:0fdadbc3d852 138 static SPIFIopers opers;
embeddedartists 0:0fdadbc3d852 139
embeddedartists 0:0fdadbc3d852 140 static char addr_conflict_buff[PROG_SIZE];
embeddedartists 0:0fdadbc3d852 141
embeddedartists 0:0fdadbc3d852 142 static meminfo_t memInfo = {0,0,0,0,0,0,{0}};
embeddedartists 0:0fdadbc3d852 143
embeddedartists 0:0fdadbc3d852 144 /******************************************************************************
embeddedartists 0:0fdadbc3d852 145 * Forward Declarations of Local Functions
embeddedartists 0:0fdadbc3d852 146 *****************************************************************************/
embeddedartists 0:0fdadbc3d852 147 static fresult qspifs_init();
embeddedartists 0:0fdadbc3d852 148 static fresult qspifs_translateSpifiError(int rc);
embeddedartists 0:0fdadbc3d852 149 static fresult qspifs_readTOC(void);
embeddedartists 0:0fdadbc3d852 150 static fresult qspifs_saveTOC(void);
embeddedartists 0:0fdadbc3d852 151 static fresult qspifs_findFile(const char* filename, fileHandle_t* fh);
embeddedartists 0:0fdadbc3d852 152 static fresult qspifs_fileSize(int tocIdx, uint32_t* pSize);
embeddedartists 0:0fdadbc3d852 153 static fresult qspifs_eraseBlock(int block);
embeddedartists 0:0fdadbc3d852 154 static fresult qspifs_allocateFile(const char* filename, int neededBlocks, int* pTocIdx);
embeddedartists 0:0fdadbc3d852 155 static void qspifs_deleteFile(fileHandle_t* fh);
embeddedartists 0:0fdadbc3d852 156 static fresult qspifs_allocateSpace(fileHandle_t* fh, uint32_t size);
embeddedartists 0:0fdadbc3d852 157 static fresult qspifs_format(unsigned int minReservedBytes);
embeddedartists 0:0fdadbc3d852 158 static fresult qspifs_write(fileHandle_t* fh, const uint8_t * const pData, uint32_t size);
embeddedartists 0:0fdadbc3d852 159 static bool qspifs_startsWith(const char* prefix, const char* str);
embeddedartists 0:0fdadbc3d852 160
embeddedartists 0:0fdadbc3d852 161 /******************************************************************************
embeddedartists 0:0fdadbc3d852 162 * Local Functions
embeddedartists 0:0fdadbc3d852 163 *****************************************************************************/
embeddedartists 0:0fdadbc3d852 164
embeddedartists 0:0fdadbc3d852 165 /******************************************************************************
embeddedartists 0:0fdadbc3d852 166 *
embeddedartists 0:0fdadbc3d852 167 * Description:
embeddedartists 0:0fdadbc3d852 168 * Initializes spifi, identifies the chip and reads the file system's
embeddedartists 0:0fdadbc3d852 169 * table of content.
embeddedartists 0:0fdadbc3d852 170 *
embeddedartists 0:0fdadbc3d852 171 * Params:
embeddedartists 0:0fdadbc3d852 172 * None
embeddedartists 0:0fdadbc3d852 173 *
embeddedartists 0:0fdadbc3d852 174 * Returns:
embeddedartists 0:0fdadbc3d852 175 * FS_OK or one of the FS_ERR_* error codes
embeddedartists 0:0fdadbc3d852 176 *
embeddedartists 0:0fdadbc3d852 177 *****************************************************************************/
embeddedartists 0:0fdadbc3d852 178 static fresult qspifs_init()
embeddedartists 0:0fdadbc3d852 179 {
embeddedartists 0:0fdadbc3d852 180 if (spifi == NULL) {
embeddedartists 0:0fdadbc3d852 181
embeddedartists 0:0fdadbc3d852 182 // Turn on SPIFI block as it is disabled on reset
embeddedartists 0:0fdadbc3d852 183 LPC_SC->PCONP |= 0x00010000;
embeddedartists 0:0fdadbc3d852 184
embeddedartists 0:0fdadbc3d852 185 // pinsel for SPIFI
embeddedartists 0:0fdadbc3d852 186 LPC_IOCON->P2_7 = 5; /* SPIFI_CSN @ P2.7 */
embeddedartists 0:0fdadbc3d852 187 LPC_IOCON->P0_22 = 5; /* SPIFI_CLK @ P0.22 */
embeddedartists 0:0fdadbc3d852 188 LPC_IOCON->P0_15 = 5; /* SPIFI_IO2 @ P0.15 */
embeddedartists 0:0fdadbc3d852 189 LPC_IOCON->P0_16 = 5; /* SPIFI_IO3 @ P0.16 */
embeddedartists 0:0fdadbc3d852 190 LPC_IOCON->P0_17 = 5; /* SPIFI_IO1 @ P0.17 */
embeddedartists 0:0fdadbc3d852 191 LPC_IOCON->P0_18 = 5; /* SPIFI_IO0 @ P0.18 */
embeddedartists 0:0fdadbc3d852 192
embeddedartists 0:0fdadbc3d852 193 uint32_t spifi_clk_div = (*((volatile uint32_t*)0x400FC1B4)) & 0x1f;
embeddedartists 0:0fdadbc3d852 194 uint32_t spifi_clk_mhz = (SystemCoreClock / spifi_clk_div) / 1000000;
embeddedartists 0:0fdadbc3d852 195
embeddedartists 0:0fdadbc3d852 196 spifi = ROM_DRIVERS_PTR->pSPIFID;
embeddedartists 0:0fdadbc3d852 197
embeddedartists 0:0fdadbc3d852 198 /* Typical time tCS is 20 ns min, we give 200 ns to be on safer side */
embeddedartists 0:0fdadbc3d852 199 int rc = spifi->spifi_init (&obj, spifi_clk_mhz/5, S_FULLCLK+S_RCVCLK, spifi_clk_mhz);
embeddedartists 0:0fdadbc3d852 200 if (rc) {
embeddedartists 0:0fdadbc3d852 201 spifi = NULL;
embeddedartists 0:0fdadbc3d852 202 return qspifs_translateSpifiError(rc);
embeddedartists 0:0fdadbc3d852 203 }
embeddedartists 0:0fdadbc3d852 204
embeddedartists 0:0fdadbc3d852 205 /* Make sure it is a tested flash module */
embeddedartists 0:0fdadbc3d852 206 if ((obj.mfger == 1) && (obj.devType == 0x2) && (obj.devID == 0x15) && (obj.memSize > 0x100000))
embeddedartists 0:0fdadbc3d852 207 {
embeddedartists 0:0fdadbc3d852 208 /* For the Spansion memory the TOC occupies 256bytes and the TOC block will
embeddedartists 0:0fdadbc3d852 209 hold 256 TOCs. */
embeddedartists 0:0fdadbc3d852 210 strcpy(memInfo.memName, "Spansion S25FL032");
embeddedartists 0:0fdadbc3d852 211 memInfo.memSize = obj.memSize;
embeddedartists 0:0fdadbc3d852 212 memInfo.eraseBlockSize = 64*1024;
embeddedartists 0:0fdadbc3d852 213 memInfo.numEraseBlocks = memInfo.memSize / memInfo.eraseBlockSize;
embeddedartists 0:0fdadbc3d852 214 memInfo.tocSizeInBytes = sizeof(toc_entry_t) * memInfo.numEraseBlocks;
embeddedartists 0:0fdadbc3d852 215 memInfo.numTocs = memInfo.eraseBlockSize / memInfo.tocSizeInBytes;
embeddedartists 0:0fdadbc3d852 216 memInfo.tocBlockAddr = SPIFI_MEM_BASE + (NUM_BLOCKS * ERASE_SIZE) - (memInfo.numTocs * memInfo.tocSizeInBytes);
embeddedartists 0:0fdadbc3d852 217 }
embeddedartists 0:0fdadbc3d852 218 else if ((obj.mfger == 0xef) && (obj.devType == 0x40) && (obj.devID == 0x17) && (obj.memSize > 0x100000))
embeddedartists 0:0fdadbc3d852 219 {
embeddedartists 0:0fdadbc3d852 220 /* For the Winbond memory the TOC occupies 8192 bytes and that is bigger than
embeddedartists 0:0fdadbc3d852 221 one erase block (which is 4096 bytes). It is possible to either keep only
embeddedartists 0:0fdadbc3d852 222 one TOC or to create a couple to reduce wear on the memory. In this case
embeddedartists 0:0fdadbc3d852 223 the multiple TOCs option is used. */
embeddedartists 0:0fdadbc3d852 224 strcpy(memInfo.memName, "Winbond W25Q64FV");
embeddedartists 0:0fdadbc3d852 225 memInfo.memSize = obj.memSize;
embeddedartists 0:0fdadbc3d852 226 memInfo.eraseBlockSize = 4*1024;
embeddedartists 0:0fdadbc3d852 227 memInfo.numEraseBlocks = memInfo.memSize / memInfo.eraseBlockSize;
embeddedartists 0:0fdadbc3d852 228 memInfo.tocSizeInBytes = sizeof(toc_entry_t) * memInfo.numEraseBlocks;
embeddedartists 0:0fdadbc3d852 229 memInfo.numTocs = 8;
embeddedartists 0:0fdadbc3d852 230 memInfo.tocBlockAddr = SPIFI_MEM_BASE + (NUM_BLOCKS * ERASE_SIZE) - (memInfo.numTocs * memInfo.tocSizeInBytes);
embeddedartists 0:0fdadbc3d852 231 }
embeddedartists 0:0fdadbc3d852 232 else
embeddedartists 0:0fdadbc3d852 233 {
embeddedartists 0:0fdadbc3d852 234 debug("INIT: Memory is unknown and may not work as expected\n");
embeddedartists 0:0fdadbc3d852 235
embeddedartists 0:0fdadbc3d852 236 // Asuming it has 64Kb erase blocks (i.e. same setup as the Spansion S25FL032
embeddedartists 0:0fdadbc3d852 237 strcpy(memInfo.memName, "Unknown - check ID");
embeddedartists 0:0fdadbc3d852 238 memInfo.memSize = obj.memSize;
embeddedartists 0:0fdadbc3d852 239 memInfo.eraseBlockSize = 64*1024;
embeddedartists 0:0fdadbc3d852 240 memInfo.numEraseBlocks = memInfo.memSize / memInfo.eraseBlockSize;
embeddedartists 0:0fdadbc3d852 241 memInfo.tocSizeInBytes = sizeof(toc_entry_t) * memInfo.numEraseBlocks;
embeddedartists 0:0fdadbc3d852 242 memInfo.numTocs = memInfo.eraseBlockSize / memInfo.tocSizeInBytes;
embeddedartists 0:0fdadbc3d852 243 memInfo.tocBlockAddr = SPIFI_MEM_BASE + (NUM_BLOCKS * ERASE_SIZE) - (memInfo.numTocs * memInfo.tocSizeInBytes);
embeddedartists 0:0fdadbc3d852 244
embeddedartists 0:0fdadbc3d852 245 /*
embeddedartists 0:0fdadbc3d852 246 * If this happens, check the manufacturer and device information
embeddedartists 0:0fdadbc3d852 247 * and compare with the data sheet for your chip. Also make sure
embeddedartists 0:0fdadbc3d852 248 * that the sector sizes are the same (i.e. 64KB) for your chip.
embeddedartists 0:0fdadbc3d852 249 * If everything is the same then add an exception for your chip.
embeddedartists 0:0fdadbc3d852 250 */
embeddedartists 0:0fdadbc3d852 251 }
embeddedartists 0:0fdadbc3d852 252 debug_if(QSPI_DBG, "INIT: Found %dMB %s\n", memInfo.memSize/0x100000, memInfo.memName);
embeddedartists 0:0fdadbc3d852 253
embeddedartists 0:0fdadbc3d852 254 if (TOC != NULL) {
embeddedartists 0:0fdadbc3d852 255 delete TOC;
embeddedartists 0:0fdadbc3d852 256 }
embeddedartists 0:0fdadbc3d852 257 TOC = (toc_entry_t*)malloc(TOC_SIZE);
embeddedartists 0:0fdadbc3d852 258 if (TOC == NULL) {
embeddedartists 0:0fdadbc3d852 259 debug_if(QSPI_DBG, "INIT: Failed to allocate memory for TOC\n");
embeddedartists 0:0fdadbc3d852 260 spifi = NULL;
embeddedartists 0:0fdadbc3d852 261 return FS_ERR_MALLOC;
embeddedartists 0:0fdadbc3d852 262 }
embeddedartists 0:0fdadbc3d852 263 }
embeddedartists 0:0fdadbc3d852 264 if (activeTOC == -1)
embeddedartists 0:0fdadbc3d852 265 {
embeddedartists 0:0fdadbc3d852 266 return qspifs_readTOC();
embeddedartists 0:0fdadbc3d852 267 }
embeddedartists 0:0fdadbc3d852 268 return FS_OK;
embeddedartists 0:0fdadbc3d852 269 }
embeddedartists 0:0fdadbc3d852 270
embeddedartists 0:0fdadbc3d852 271 /******************************************************************************
embeddedartists 0:0fdadbc3d852 272 *
embeddedartists 0:0fdadbc3d852 273 * Description:
embeddedartists 0:0fdadbc3d852 274 * Converts the return value from one of the spifi_init(), spifi_program()
embeddedartists 0:0fdadbc3d852 275 * or spifi_erase() calls into a FS_* error code to simplify it for the
embeddedartists 0:0fdadbc3d852 276 * fs_qspi API user.
embeddedartists 0:0fdadbc3d852 277 * This function also attempts to detect the verification failure error.
embeddedartists 0:0fdadbc3d852 278 * When a verification error occurs the spifi_* functions returns the
embeddedartists 0:0fdadbc3d852 279 * conflicting address and not an error code. As this can be any address
embeddedartists 0:0fdadbc3d852 280 * it is difficult to test but this function converts it into the
embeddedartists 0:0fdadbc3d852 281 * FS_ERR_SPIFI_VERIFICATION error code which can be tested against.
embeddedartists 0:0fdadbc3d852 282 *
embeddedartists 0:0fdadbc3d852 283 * Params:
embeddedartists 0:0fdadbc3d852 284 * [in] rc - The return code from any of the spifi_* functions
embeddedartists 0:0fdadbc3d852 285 *
embeddedartists 0:0fdadbc3d852 286 * Returns:
embeddedartists 0:0fdadbc3d852 287 * FS_OK or one of the FS_ERR_* error codes
embeddedartists 0:0fdadbc3d852 288 *
embeddedartists 0:0fdadbc3d852 289 *****************************************************************************/
embeddedartists 0:0fdadbc3d852 290 static fresult qspifs_translateSpifiError(int rc)
embeddedartists 0:0fdadbc3d852 291 {
embeddedartists 0:0fdadbc3d852 292 fresult res;
embeddedartists 0:0fdadbc3d852 293 if (rc == 0)
embeddedartists 0:0fdadbc3d852 294 {
embeddedartists 0:0fdadbc3d852 295 res = FS_OK;
embeddedartists 0:0fdadbc3d852 296 }
embeddedartists 0:0fdadbc3d852 297 else if ((rc >= FS_ERR_SPIFI_INTERNAL_ERROR) && (rc <= FS_ERR_SPIFI_ERASE_CONFLICT))
embeddedartists 0:0fdadbc3d852 298 {
embeddedartists 0:0fdadbc3d852 299 // This is a known error code
embeddedartists 0:0fdadbc3d852 300 res = (fresult)rc;
embeddedartists 0:0fdadbc3d852 301 }
embeddedartists 0:0fdadbc3d852 302 else if (opers.options & (S_VERIFY_PROG | S_VERIFY_ERASE))
embeddedartists 0:0fdadbc3d852 303 {
embeddedartists 0:0fdadbc3d852 304 // As verification was selected and rc is not in the list of known
embeddedartists 0:0fdadbc3d852 305 // codes this falls into this category in the User's Manual:
embeddedartists 0:0fdadbc3d852 306 //
embeddedartists 0:0fdadbc3d852 307 // "Other non-zero values can occur if options selects verification.
embeddedartists 0:0fdadbc3d852 308 // They will be the address in the SPIFI memory area at which the
embeddedartists 0:0fdadbc3d852 309 // first discrepancy was found."
embeddedartists 0:0fdadbc3d852 310 res = FS_ERR_SPIFI_VERIFICATION;
embeddedartists 0:0fdadbc3d852 311 }
embeddedartists 0:0fdadbc3d852 312 else
embeddedartists 0:0fdadbc3d852 313 {
embeddedartists 0:0fdadbc3d852 314 // Should never happen :-) as all listed error codes are covered but
embeddedartists 0:0fdadbc3d852 315 // to be on the safe side and not interpret this as a success, a generic
embeddedartists 0:0fdadbc3d852 316 // error is set.
embeddedartists 0:0fdadbc3d852 317 res = FS_ERR_SPIFI;
embeddedartists 0:0fdadbc3d852 318 }
embeddedartists 0:0fdadbc3d852 319 return res;
embeddedartists 0:0fdadbc3d852 320 }
embeddedartists 0:0fdadbc3d852 321
embeddedartists 0:0fdadbc3d852 322 /******************************************************************************
embeddedartists 0:0fdadbc3d852 323 *
embeddedartists 0:0fdadbc3d852 324 * Description:
embeddedartists 0:0fdadbc3d852 325 * Reads the table of contents (TOC). The TOC is stored in the last erase
embeddedartists 0:0fdadbc3d852 326 * block on the QSPI flash. As the QSPI flash is not exactly RW (might
embeddedartists 0:0fdadbc3d852 327 * require erasing before writing) the TOC is relocated inside the erase
embeddedartists 0:0fdadbc3d852 328 * block everytime it is saved (see saveTOC()). The currently valid TOC
embeddedartists 0:0fdadbc3d852 329 * is allways the last one stored.
embeddedartists 0:0fdadbc3d852 330 *
embeddedartists 0:0fdadbc3d852 331 * Params:
embeddedartists 0:0fdadbc3d852 332 * None
embeddedartists 0:0fdadbc3d852 333 *
embeddedartists 0:0fdadbc3d852 334 * Returns:
embeddedartists 0:0fdadbc3d852 335 * FS_OK or one of the FS_ERR_* error codes
embeddedartists 0:0fdadbc3d852 336 *
embeddedartists 0:0fdadbc3d852 337 *****************************************************************************/
embeddedartists 0:0fdadbc3d852 338 static fresult qspifs_readTOC(void)
embeddedartists 0:0fdadbc3d852 339 {
embeddedartists 0:0fdadbc3d852 340 int i, j;
embeddedartists 0:0fdadbc3d852 341 toc_entry_t* p;
embeddedartists 0:0fdadbc3d852 342 uint8_t invalid = 0;
embeddedartists 0:0fdadbc3d852 343 int lastValid = -1;
embeddedartists 0:0fdadbc3d852 344
embeddedartists 0:0fdadbc3d852 345 // Search for the first unused TOC, keeping track of the valid
embeddedartists 0:0fdadbc3d852 346 // ones as we go.
embeddedartists 0:0fdadbc3d852 347 for (i = 0; (i < NUM_TOCS) && !invalid; i++)
embeddedartists 0:0fdadbc3d852 348 {
embeddedartists 0:0fdadbc3d852 349 p = (toc_entry_t*)(TOC_BLOCK_ADDR + i*TOC_SIZE);
embeddedartists 0:0fdadbc3d852 350 for (j = 0; j < NUM_BLOCKS; j++)
embeddedartists 0:0fdadbc3d852 351 {
embeddedartists 0:0fdadbc3d852 352 if (!VALID_TOC_ENTRY(*p) || !MANDATORY_BITS_SET(*p))
embeddedartists 0:0fdadbc3d852 353 {
embeddedartists 0:0fdadbc3d852 354 // invalid TOC entry, stop looking
embeddedartists 0:0fdadbc3d852 355 invalid = 1;
embeddedartists 0:0fdadbc3d852 356 break;
embeddedartists 0:0fdadbc3d852 357 }
embeddedartists 0:0fdadbc3d852 358 p++;
embeddedartists 0:0fdadbc3d852 359 }
embeddedartists 0:0fdadbc3d852 360
embeddedartists 0:0fdadbc3d852 361 if (!invalid)
embeddedartists 0:0fdadbc3d852 362 {
embeddedartists 0:0fdadbc3d852 363 // this TOC was ok, but perhaps there is a newer one?
embeddedartists 0:0fdadbc3d852 364 lastValid = i;
embeddedartists 0:0fdadbc3d852 365 }
embeddedartists 0:0fdadbc3d852 366 }
embeddedartists 0:0fdadbc3d852 367
embeddedartists 0:0fdadbc3d852 368 if (lastValid == -1)
embeddedartists 0:0fdadbc3d852 369 {
embeddedartists 0:0fdadbc3d852 370 // no valid TOCs on the flash
embeddedartists 0:0fdadbc3d852 371 return FS_ERR_NOT_FORMATTED;
embeddedartists 0:0fdadbc3d852 372 }
embeddedartists 0:0fdadbc3d852 373 else
embeddedartists 0:0fdadbc3d852 374 {
embeddedartists 0:0fdadbc3d852 375 // previous entry was ok so use that
embeddedartists 0:0fdadbc3d852 376 activeTOC = lastValid;
embeddedartists 0:0fdadbc3d852 377 p = (toc_entry_t*)(TOC_BLOCK_ADDR + activeTOC*TOC_SIZE);
embeddedartists 0:0fdadbc3d852 378 memcpy(TOC, p, TOC_SIZE);
embeddedartists 0:0fdadbc3d852 379 return FS_OK;
embeddedartists 0:0fdadbc3d852 380 }
embeddedartists 0:0fdadbc3d852 381 }
embeddedartists 0:0fdadbc3d852 382
embeddedartists 0:0fdadbc3d852 383 /******************************************************************************
embeddedartists 0:0fdadbc3d852 384 *
embeddedartists 0:0fdadbc3d852 385 * Description:
embeddedartists 0:0fdadbc3d852 386 * Saves the table of contents (TOC). The TOC is stored in the last erase
embeddedartists 0:0fdadbc3d852 387 * block on the QSPI flash. As the QSPI flash is not exactly RW (might
embeddedartists 0:0fdadbc3d852 388 * require erasing before writing) the TOC is first compared with what is
embeddedartists 0:0fdadbc3d852 389 * stored in the QSPI flash and if there are no changes or all changes
embeddedartists 0:0fdadbc3d852 390 * only require bit changes 1->0 then the current TOC can be overwritten.
embeddedartists 0:0fdadbc3d852 391 * If bit value changes 0->1 are required then the current stored TOC
embeddedartists 0:0fdadbc3d852 392 * cannot be overwritten and the new TOC is instead stored in the next
embeddedartists 0:0fdadbc3d852 393 * available space. If the entire last block is filled then it is erased
embeddedartists 0:0fdadbc3d852 394 * and the new TOC is placed at the start of it.
embeddedartists 0:0fdadbc3d852 395 *
embeddedartists 0:0fdadbc3d852 396 * Params:
embeddedartists 0:0fdadbc3d852 397 * None
embeddedartists 0:0fdadbc3d852 398 *
embeddedartists 0:0fdadbc3d852 399 * Returns:
embeddedartists 0:0fdadbc3d852 400 * FS_OK or one of the FS_ERR_* error codes
embeddedartists 0:0fdadbc3d852 401 *
embeddedartists 0:0fdadbc3d852 402 *****************************************************************************/
embeddedartists 0:0fdadbc3d852 403 static fresult qspifs_saveTOC(void)
embeddedartists 0:0fdadbc3d852 404 {
embeddedartists 0:0fdadbc3d852 405 int i, rc = 0;
embeddedartists 0:0fdadbc3d852 406 uint32_t* pSrc;
embeddedartists 0:0fdadbc3d852 407 uint32_t* pDest;
embeddedartists 0:0fdadbc3d852 408 uint32_t tmp;
embeddedartists 0:0fdadbc3d852 409 uint8_t identical = 1;
embeddedartists 0:0fdadbc3d852 410
embeddedartists 0:0fdadbc3d852 411 // active TOC same as the one we want to save?
embeddedartists 0:0fdadbc3d852 412 pSrc = (uint32_t*)TOC;
embeddedartists 0:0fdadbc3d852 413 pDest = (uint32_t*)(TOC_BLOCK_ADDR + activeTOC*TOC_SIZE);
embeddedartists 0:0fdadbc3d852 414 for (i = 0; i < NUM_TOC_ENTRIES; i++)
embeddedartists 0:0fdadbc3d852 415 {
embeddedartists 0:0fdadbc3d852 416 if (*pSrc != *pDest)
embeddedartists 0:0fdadbc3d852 417 {
embeddedartists 0:0fdadbc3d852 418 identical = 0;
embeddedartists 0:0fdadbc3d852 419 tmp = ((*pDest) ^ (*pSrc)) & (*pSrc);
embeddedartists 0:0fdadbc3d852 420 if (tmp > 0)
embeddedartists 0:0fdadbc3d852 421 {
embeddedartists 0:0fdadbc3d852 422 // found a change that contains 0->1 bit modification which
embeddedartists 0:0fdadbc3d852 423 // requires erasing or a new location
embeddedartists 0:0fdadbc3d852 424 activeTOC = (activeTOC + 1)%NUM_TOCS;
embeddedartists 0:0fdadbc3d852 425 if (activeTOC == 0)
embeddedartists 0:0fdadbc3d852 426 {
embeddedartists 0:0fdadbc3d852 427 // no more free TOCs so an erase is needed
embeddedartists 0:0fdadbc3d852 428 #if 0
embeddedartists 0:0fdadbc3d852 429 opers.options &= ~S_CALLER_ERASE;
embeddedartists 0:0fdadbc3d852 430 opers.options |= S_FORCE_ERASE;
embeddedartists 0:0fdadbc3d852 431 #else
embeddedartists 0:0fdadbc3d852 432 opers.dest = (char *) TOC_BLOCK_ADDR;
embeddedartists 0:0fdadbc3d852 433 opers.length = TOC_SIZE * NUM_TOCS;
embeddedartists 0:0fdadbc3d852 434 opers.scratch = NULL;
embeddedartists 0:0fdadbc3d852 435 opers.protect = 0;
embeddedartists 0:0fdadbc3d852 436 opers.options = S_NO_VERIFY;
embeddedartists 0:0fdadbc3d852 437 rc = spifi->spifi_erase(&obj, &opers);
embeddedartists 0:0fdadbc3d852 438 if (rc) {
embeddedartists 0:0fdadbc3d852 439 return qspifs_translateSpifiError(rc);
embeddedartists 0:0fdadbc3d852 440 }
embeddedartists 0:0fdadbc3d852 441 #endif
embeddedartists 0:0fdadbc3d852 442 }
embeddedartists 0:0fdadbc3d852 443 break;
embeddedartists 0:0fdadbc3d852 444 }
embeddedartists 0:0fdadbc3d852 445 }
embeddedartists 0:0fdadbc3d852 446 pSrc++;
embeddedartists 0:0fdadbc3d852 447 pDest++;
embeddedartists 0:0fdadbc3d852 448 }
embeddedartists 0:0fdadbc3d852 449
embeddedartists 0:0fdadbc3d852 450 if (!identical)
embeddedartists 0:0fdadbc3d852 451 {
embeddedartists 0:0fdadbc3d852 452 opers.length = FS_MIN(TOC_SIZE, PROG_SIZE);
embeddedartists 0:0fdadbc3d852 453 opers.scratch = NULL;
embeddedartists 0:0fdadbc3d852 454 opers.protect = 0;
embeddedartists 0:0fdadbc3d852 455 opers.options = S_VERIFY_PROG | S_CALLER_ERASE;
embeddedartists 0:0fdadbc3d852 456 for (int i = 0; i < (TOC_SIZE / PROG_SIZE); i++)
embeddedartists 0:0fdadbc3d852 457 {
embeddedartists 0:0fdadbc3d852 458 opers.dest = (char *)(TOC_BLOCK_ADDR + activeTOC*TOC_SIZE + i*PROG_SIZE);
embeddedartists 0:0fdadbc3d852 459 rc = spifi->spifi_program(&obj, ((char*)TOC)+i*PROG_SIZE, &opers);
embeddedartists 0:0fdadbc3d852 460 if (rc)
embeddedartists 0:0fdadbc3d852 461 {
embeddedartists 0:0fdadbc3d852 462 break;
embeddedartists 0:0fdadbc3d852 463 }
embeddedartists 0:0fdadbc3d852 464 }
embeddedartists 0:0fdadbc3d852 465 return qspifs_translateSpifiError(rc);
embeddedartists 0:0fdadbc3d852 466 }
embeddedartists 0:0fdadbc3d852 467 return FS_OK;
embeddedartists 0:0fdadbc3d852 468 }
embeddedartists 0:0fdadbc3d852 469
embeddedartists 0:0fdadbc3d852 470 /******************************************************************************
embeddedartists 0:0fdadbc3d852 471 *
embeddedartists 0:0fdadbc3d852 472 * Description:
embeddedartists 0:0fdadbc3d852 473 * Searches the file system for a file with the specified name and
embeddedartists 0:0fdadbc3d852 474 * (if found) returns the file's position in the TOC.
embeddedartists 0:0fdadbc3d852 475 *
embeddedartists 0:0fdadbc3d852 476 * Note that the content of fh is only valid if FS_OK is returned.
embeddedartists 0:0fdadbc3d852 477 *
embeddedartists 0:0fdadbc3d852 478 * Params:
embeddedartists 0:0fdadbc3d852 479 * [in] filename - The name of the file to find
embeddedartists 0:0fdadbc3d852 480 * [out] fh - The handle with the file information
embeddedartists 0:0fdadbc3d852 481 *
embeddedartists 0:0fdadbc3d852 482 * Returns:
embeddedartists 0:0fdadbc3d852 483 * FS_OK or one of the FS_ERR_* error codes
embeddedartists 0:0fdadbc3d852 484 *
embeddedartists 0:0fdadbc3d852 485 *****************************************************************************/
embeddedartists 0:0fdadbc3d852 486 static fresult qspifs_findFile(const char* filename, fileHandle_t* fh)
embeddedartists 0:0fdadbc3d852 487 {
embeddedartists 0:0fdadbc3d852 488 int i;
embeddedartists 0:0fdadbc3d852 489
embeddedartists 0:0fdadbc3d852 490 if (activeTOC == -1)
embeddedartists 0:0fdadbc3d852 491 {
embeddedartists 0:0fdadbc3d852 492 return FS_ERR_NOT_FORMATTED;
embeddedartists 0:0fdadbc3d852 493 }
embeddedartists 0:0fdadbc3d852 494
embeddedartists 0:0fdadbc3d852 495 // Look at all blocks except for the reserved ones
embeddedartists 0:0fdadbc3d852 496 for (i = 0; i < NUM_BLOCKS; i++)
embeddedartists 0:0fdadbc3d852 497 {
embeddedartists 0:0fdadbc3d852 498 if (TOC_IS_FILE(TOC[i]) && !TOC_IS_RESERVED(TOC[i]))
embeddedartists 0:0fdadbc3d852 499 {
embeddedartists 0:0fdadbc3d852 500 // found a file, see if name matches
embeddedartists 0:0fdadbc3d852 501 char* p = (char*)(SPIFI_MEM_BASE + i*ERASE_SIZE);
embeddedartists 0:0fdadbc3d852 502 if (strncmp(filename, p, HEADER_FNAME_LEN) == 0)
embeddedartists 0:0fdadbc3d852 503 {
embeddedartists 0:0fdadbc3d852 504 // found a matching name
embeddedartists 0:0fdadbc3d852 505 fh->tocIdx = i;
embeddedartists 0:0fdadbc3d852 506 fresult res = qspifs_fileSize(fh->tocIdx, &fh->size);
embeddedartists 0:0fdadbc3d852 507 if (res == FS_OK) {
embeddedartists 0:0fdadbc3d852 508 fh->lastBlock = fh->tocIdx + ((fh->size + HEADER_LEN)/ ERASE_SIZE);
embeddedartists 0:0fdadbc3d852 509 }
embeddedartists 0:0fdadbc3d852 510 return FS_OK;
embeddedartists 0:0fdadbc3d852 511 }
embeddedartists 0:0fdadbc3d852 512 }
embeddedartists 0:0fdadbc3d852 513 }
embeddedartists 0:0fdadbc3d852 514 return FS_ERR_NO_FILE;
embeddedartists 0:0fdadbc3d852 515 }
embeddedartists 0:0fdadbc3d852 516
embeddedartists 0:0fdadbc3d852 517 /******************************************************************************
embeddedartists 0:0fdadbc3d852 518 *
embeddedartists 0:0fdadbc3d852 519 * Description:
embeddedartists 0:0fdadbc3d852 520 * Calculates and returns the file's size.
embeddedartists 0:0fdadbc3d852 521 *
embeddedartists 0:0fdadbc3d852 522 * Note that the content of pSize is only valid if FS_OK is returned.
embeddedartists 0:0fdadbc3d852 523 *
embeddedartists 0:0fdadbc3d852 524 * Params:
embeddedartists 0:0fdadbc3d852 525 * [in] tocIdx - The file's position in the TOC
embeddedartists 0:0fdadbc3d852 526 * [out] pSize - The file's size
embeddedartists 0:0fdadbc3d852 527 *
embeddedartists 0:0fdadbc3d852 528 * Returns:
embeddedartists 0:0fdadbc3d852 529 * FS_OK or one of the FS_ERR_* error codes
embeddedartists 0:0fdadbc3d852 530 *
embeddedartists 0:0fdadbc3d852 531 *****************************************************************************/
embeddedartists 0:0fdadbc3d852 532 static fresult qspifs_fileSize(int tocIdx, uint32_t* pSize)
embeddedartists 0:0fdadbc3d852 533 {
embeddedartists 0:0fdadbc3d852 534 int i;
embeddedartists 0:0fdadbc3d852 535
embeddedartists 0:0fdadbc3d852 536 if (tocIdx < 0 || tocIdx > NUM_BLOCKS || !TOC_IS_FILE(TOC[tocIdx]))
embeddedartists 0:0fdadbc3d852 537 {
embeddedartists 0:0fdadbc3d852 538 return FS_ERR_NO_FILE;
embeddedartists 0:0fdadbc3d852 539 }
embeddedartists 0:0fdadbc3d852 540
embeddedartists 0:0fdadbc3d852 541 *pSize = 0;
embeddedartists 0:0fdadbc3d852 542
embeddedartists 0:0fdadbc3d852 543 // A file is always stored in sequential blocks so start with the files
embeddedartists 0:0fdadbc3d852 544 // first block and as long as it is full continue sum up the occupied
embeddedartists 0:0fdadbc3d852 545 // block sizes. As soon as a non-full block is found that must be the
embeddedartists 0:0fdadbc3d852 546 // file's last block.
embeddedartists 0:0fdadbc3d852 547 for (i = tocIdx; i < NUM_BLOCKS; i++)
embeddedartists 0:0fdadbc3d852 548 {
embeddedartists 0:0fdadbc3d852 549 *pSize += FILESIZE(TOC[i]);
embeddedartists 0:0fdadbc3d852 550 if (FILESIZE(TOC[i]) < ERASE_SIZE)
embeddedartists 0:0fdadbc3d852 551 {
embeddedartists 0:0fdadbc3d852 552 // last block in chain
embeddedartists 0:0fdadbc3d852 553 break;
embeddedartists 0:0fdadbc3d852 554 }
embeddedartists 0:0fdadbc3d852 555 }
embeddedartists 0:0fdadbc3d852 556
embeddedartists 0:0fdadbc3d852 557 // Remove the filename header from the file's size
embeddedartists 0:0fdadbc3d852 558 *pSize -= HEADER_LEN;
embeddedartists 0:0fdadbc3d852 559
embeddedartists 0:0fdadbc3d852 560 return FS_OK;
embeddedartists 0:0fdadbc3d852 561 }
embeddedartists 0:0fdadbc3d852 562
embeddedartists 0:0fdadbc3d852 563 /******************************************************************************
embeddedartists 0:0fdadbc3d852 564 *
embeddedartists 0:0fdadbc3d852 565 * Description:
embeddedartists 0:0fdadbc3d852 566 * Erases everything in one block on the QSPI flash.
embeddedartists 0:0fdadbc3d852 567 *
embeddedartists 0:0fdadbc3d852 568 * Params:
embeddedartists 0:0fdadbc3d852 569 * [in] block - The block's number
embeddedartists 0:0fdadbc3d852 570 *
embeddedartists 0:0fdadbc3d852 571 * Returns:
embeddedartists 0:0fdadbc3d852 572 * FS_OK or one of the FS_ERR_* error codes
embeddedartists 0:0fdadbc3d852 573 *
embeddedartists 0:0fdadbc3d852 574 *****************************************************************************/
embeddedartists 0:0fdadbc3d852 575 static fresult qspifs_eraseBlock(int block)
embeddedartists 0:0fdadbc3d852 576 {
embeddedartists 0:0fdadbc3d852 577 opers.dest = (char *)(block * ERASE_SIZE);
embeddedartists 0:0fdadbc3d852 578 opers.length = ERASE_SIZE;
embeddedartists 0:0fdadbc3d852 579 opers.scratch = NULL;
embeddedartists 0:0fdadbc3d852 580 opers.protect = 0;
embeddedartists 0:0fdadbc3d852 581 opers.options = S_NO_VERIFY;
embeddedartists 0:0fdadbc3d852 582 return qspifs_translateSpifiError(spifi->spifi_erase (&obj, &opers));
embeddedartists 0:0fdadbc3d852 583 }
embeddedartists 0:0fdadbc3d852 584
embeddedartists 0:0fdadbc3d852 585 /******************************************************************************
embeddedartists 0:0fdadbc3d852 586 *
embeddedartists 0:0fdadbc3d852 587 * Description:
embeddedartists 0:0fdadbc3d852 588 * Creates a new file if there is enough space for it on the file system.
embeddedartists 0:0fdadbc3d852 589 * The TOC is searched for a unused sequence of blocks of at least the
embeddedartists 0:0fdadbc3d852 590 * needed size. That block is marked as used and the file's name is stored
embeddedartists 0:0fdadbc3d852 591 * in the first bytes of the file's first block.
embeddedartists 0:0fdadbc3d852 592 *
embeddedartists 0:0fdadbc3d852 593 * Note: The filename will not be tested for uniqueness.
embeddedartists 0:0fdadbc3d852 594 * Note: The value of pTocIdx will only be valid if FS_OK is returned.
embeddedartists 0:0fdadbc3d852 595 *
embeddedartists 0:0fdadbc3d852 596 * Params:
embeddedartists 0:0fdadbc3d852 597 * [in] filename - The name of the new file
embeddedartists 0:0fdadbc3d852 598 * [in] neededBlocks - The number of blocks (in sequence) to allocate
embeddedartists 0:0fdadbc3d852 599 * [out] pTocIdx - The new file's position in the TOC
embeddedartists 0:0fdadbc3d852 600 *
embeddedartists 0:0fdadbc3d852 601 * Returns:
embeddedartists 0:0fdadbc3d852 602 * FS_OK or one of the FS_ERR_* error codes
embeddedartists 0:0fdadbc3d852 603 *
embeddedartists 0:0fdadbc3d852 604 *****************************************************************************/
embeddedartists 0:0fdadbc3d852 605 static fresult qspifs_allocateFile(const char* filename, int neededBlocks, int* pTocIdx)
embeddedartists 0:0fdadbc3d852 606 {
embeddedartists 0:0fdadbc3d852 607 int i, rc;
embeddedartists 0:0fdadbc3d852 608
embeddedartists 0:0fdadbc3d852 609 if (activeTOC == -1)
embeddedartists 0:0fdadbc3d852 610 {
embeddedartists 0:0fdadbc3d852 611 return FS_ERR_NOT_FORMATTED;
embeddedartists 0:0fdadbc3d852 612 }
embeddedartists 0:0fdadbc3d852 613
embeddedartists 0:0fdadbc3d852 614 // Look at all blocks except for the reserved ones
embeddedartists 0:0fdadbc3d852 615 for (i = 0; i < NUM_BLOCKS; i++)
embeddedartists 0:0fdadbc3d852 616 {
embeddedartists 0:0fdadbc3d852 617 //TODO: Improve search to use gaps to avoid having to move files
embeddedartists 0:0fdadbc3d852 618 // that are written to
embeddedartists 0:0fdadbc3d852 619 if (!USED_TOC_ENTRY(TOC[i]) && !TOC_IS_RESERVED(TOC[i]))
embeddedartists 0:0fdadbc3d852 620 {
embeddedartists 0:0fdadbc3d852 621 int j;
embeddedartists 0:0fdadbc3d852 622 for (j = 1; j < neededBlocks; j++)
embeddedartists 0:0fdadbc3d852 623 {
embeddedartists 0:0fdadbc3d852 624 if (USED_TOC_ENTRY(TOC[i+j]) || TOC_IS_RESERVED(TOC[i+j]))
embeddedartists 0:0fdadbc3d852 625 {
embeddedartists 0:0fdadbc3d852 626 // not enough free blocks in sequence, skip past these
embeddedartists 0:0fdadbc3d852 627 // tested entries and continue searching
embeddedartists 0:0fdadbc3d852 628 i += j;
embeddedartists 0:0fdadbc3d852 629 break;
embeddedartists 0:0fdadbc3d852 630 }
embeddedartists 0:0fdadbc3d852 631 }
embeddedartists 0:0fdadbc3d852 632
embeddedartists 0:0fdadbc3d852 633 if (j == neededBlocks)
embeddedartists 0:0fdadbc3d852 634 {
embeddedartists 0:0fdadbc3d852 635 const char* pSrc = filename;
embeddedartists 0:0fdadbc3d852 636 if (IS_ADDR_IN_SPIFI(filename))
embeddedartists 0:0fdadbc3d852 637 {
embeddedartists 0:0fdadbc3d852 638 // The SPIFI ROM driver cannot write data from SPIFI into
embeddedartists 0:0fdadbc3d852 639 // SPIFI (i.e. cannot read and write at the same time).
embeddedartists 0:0fdadbc3d852 640 // The workaround is to copy the source data into a buffer
embeddedartists 0:0fdadbc3d852 641 // in local memory and use that as source for the write
embeddedartists 0:0fdadbc3d852 642 // instead.
embeddedartists 0:0fdadbc3d852 643 memcpy(addr_conflict_buff, filename, strlen(filename)+1);
embeddedartists 0:0fdadbc3d852 644 pSrc = addr_conflict_buff;
embeddedartists 0:0fdadbc3d852 645 }
embeddedartists 0:0fdadbc3d852 646
embeddedartists 0:0fdadbc3d852 647 // Erase the new file's first block and store the filename at the
embeddedartists 0:0fdadbc3d852 648 // start of it
embeddedartists 0:0fdadbc3d852 649 opers.length = strlen(pSrc)+1;
embeddedartists 0:0fdadbc3d852 650 opers.scratch = NULL;
embeddedartists 0:0fdadbc3d852 651 opers.protect = 0;
embeddedartists 0:0fdadbc3d852 652 opers.options = S_VERIFY_PROG | S_FORCE_ERASE;// S_CALLER_ERASE;
embeddedartists 0:0fdadbc3d852 653 opers.dest = (char *)(i*ERASE_SIZE);
embeddedartists 0:0fdadbc3d852 654 rc = spifi->spifi_program(&obj, (char*)pSrc, &opers);
embeddedartists 0:0fdadbc3d852 655 if (rc) {
embeddedartists 0:0fdadbc3d852 656 return qspifs_translateSpifiError(rc);
embeddedartists 0:0fdadbc3d852 657 }
embeddedartists 0:0fdadbc3d852 658
embeddedartists 0:0fdadbc3d852 659 TOC[i] &= ~(TOC_VALID_MASK | TOC_USED_MASK | TOC_FILE_MASK | TOC_FSIZE_MASK);
embeddedartists 0:0fdadbc3d852 660 TOC[i] |= HEADER_LEN;
embeddedartists 0:0fdadbc3d852 661
embeddedartists 0:0fdadbc3d852 662 *pTocIdx = i;
embeddedartists 0:0fdadbc3d852 663 return FS_OK;
embeddedartists 0:0fdadbc3d852 664 }
embeddedartists 0:0fdadbc3d852 665 }
embeddedartists 0:0fdadbc3d852 666 }
embeddedartists 0:0fdadbc3d852 667 return FS_ERR_DISK_FULL;
embeddedartists 0:0fdadbc3d852 668 }
embeddedartists 0:0fdadbc3d852 669
embeddedartists 0:0fdadbc3d852 670 /******************************************************************************
embeddedartists 0:0fdadbc3d852 671 *
embeddedartists 0:0fdadbc3d852 672 * Description:
embeddedartists 0:0fdadbc3d852 673 * Deletes the specified file by marking all its blocks as unused in
embeddedartists 0:0fdadbc3d852 674 * the TOC.
embeddedartists 0:0fdadbc3d852 675 *
embeddedartists 0:0fdadbc3d852 676 * Note: The deleted blocks are not erased here - that is done when they
embeddedartists 0:0fdadbc3d852 677 * are allocated the next time.
embeddedartists 0:0fdadbc3d852 678 *
embeddedartists 0:0fdadbc3d852 679 * Params:
embeddedartists 0:0fdadbc3d852 680 * [in] fh - The file handle with information about what to delete
embeddedartists 0:0fdadbc3d852 681 *
embeddedartists 0:0fdadbc3d852 682 * Returns:
embeddedartists 0:0fdadbc3d852 683 * None
embeddedartists 0:0fdadbc3d852 684 *
embeddedartists 0:0fdadbc3d852 685 *****************************************************************************/
embeddedartists 0:0fdadbc3d852 686 static void qspifs_deleteFile(fileHandle_t* fh)
embeddedartists 0:0fdadbc3d852 687 {
embeddedartists 0:0fdadbc3d852 688 int i;
embeddedartists 0:0fdadbc3d852 689
embeddedartists 0:0fdadbc3d852 690 for (i = fh->lastBlock; i >= fh->tocIdx; i--)
embeddedartists 0:0fdadbc3d852 691 {
embeddedartists 0:0fdadbc3d852 692 TOC[i] = ~TOC_VALID_MASK;
embeddedartists 0:0fdadbc3d852 693 }
embeddedartists 0:0fdadbc3d852 694 }
embeddedartists 0:0fdadbc3d852 695
embeddedartists 0:0fdadbc3d852 696 /******************************************************************************
embeddedartists 0:0fdadbc3d852 697 *
embeddedartists 0:0fdadbc3d852 698 * Description:
embeddedartists 0:0fdadbc3d852 699 * Ensures that the specified file can grow to the wanted size.
embeddedartists 0:0fdadbc3d852 700 * If the file size will increase enough to need one or more new blocks
embeddedartists 0:0fdadbc3d852 701 * and there isn't enough space then an attempt is made to move the
embeddedartists 0:0fdadbc3d852 702 * current file to a large enough space somewhere else.
embeddedartists 0:0fdadbc3d852 703 *
embeddedartists 0:0fdadbc3d852 704 * If there are more free block(s) at the end of the file then it is not
embeddedartists 0:0fdadbc3d852 705 * moved and instead those blocks are marked as used.
embeddedartists 0:0fdadbc3d852 706 *
embeddedartists 0:0fdadbc3d852 707 * Note: The filename will not be tested for uniqueness.
embeddedartists 0:0fdadbc3d852 708 * Note: The value of pTocIdx will only be valid if FS_OK is returned.
embeddedartists 0:0fdadbc3d852 709 *
embeddedartists 0:0fdadbc3d852 710 * Params:
embeddedartists 0:0fdadbc3d852 711 * [in/out] fh - The current file handle, might be updated after a move
embeddedartists 0:0fdadbc3d852 712 * [in] size - The wanted new size
embeddedartists 0:0fdadbc3d852 713 *
embeddedartists 0:0fdadbc3d852 714 * Returns:
embeddedartists 0:0fdadbc3d852 715 * FS_OK or one of the FS_ERR_* error codes
embeddedartists 0:0fdadbc3d852 716 *
embeddedartists 0:0fdadbc3d852 717 *****************************************************************************/
embeddedartists 0:0fdadbc3d852 718 static fresult qspifs_allocateSpace(fileHandle_t* fh, uint32_t size)
embeddedartists 0:0fdadbc3d852 719 {
embeddedartists 0:0fdadbc3d852 720 uint16_t oldNumBlocks = (fh->size + HEADER_LEN) / ERASE_SIZE;
embeddedartists 0:0fdadbc3d852 721 uint16_t newNumBlocks = (fh->size + HEADER_LEN + size) / ERASE_SIZE;
embeddedartists 0:0fdadbc3d852 722 uint16_t numNeeded = newNumBlocks - oldNumBlocks;
embeddedartists 0:0fdadbc3d852 723 fresult res = FS_OK;
embeddedartists 0:0fdadbc3d852 724
embeddedartists 0:0fdadbc3d852 725 if (numNeeded > 0)
embeddedartists 0:0fdadbc3d852 726 {
embeddedartists 0:0fdadbc3d852 727 uint16_t i;
embeddedartists 0:0fdadbc3d852 728 for (i = 0; i < numNeeded; i++)
embeddedartists 0:0fdadbc3d852 729 {
embeddedartists 0:0fdadbc3d852 730 if (USED_TOC_ENTRY(TOC[fh->tocIdx + oldNumBlocks + 1 + i]) ||
embeddedartists 0:0fdadbc3d852 731 TOC_IS_RESERVED(TOC[fh->tocIdx + oldNumBlocks + 1 + i]))
embeddedartists 0:0fdadbc3d852 732 {
embeddedartists 0:0fdadbc3d852 733 fileHandle_t fhNew;
embeddedartists 0:0fdadbc3d852 734
embeddedartists 0:0fdadbc3d852 735 // have to move the chain
embeddedartists 0:0fdadbc3d852 736 char* filename = (char*)(SPIFI_MEM_BASE + fh->tocIdx * ERASE_SIZE);
embeddedartists 0:0fdadbc3d852 737 res = qspifs_allocateFile(filename, newNumBlocks, &(fhNew.tocIdx));
embeddedartists 0:0fdadbc3d852 738 if (res == FS_OK)
embeddedartists 0:0fdadbc3d852 739 {
embeddedartists 0:0fdadbc3d852 740 // copy data
embeddedartists 0:0fdadbc3d852 741 fhNew.lastBlock = fhNew.tocIdx;
embeddedartists 0:0fdadbc3d852 742 fhNew.size = 0;
embeddedartists 0:0fdadbc3d852 743 res = qspifs_write(&fhNew, (uint8_t*)(SPIFI_MEM_BASE + fh->tocIdx * ERASE_SIZE + HEADER_LEN), fh->size);
embeddedartists 0:0fdadbc3d852 744 }
embeddedartists 0:0fdadbc3d852 745 if (res == FS_OK)
embeddedartists 0:0fdadbc3d852 746 {
embeddedartists 0:0fdadbc3d852 747 // remove old entries
embeddedartists 0:0fdadbc3d852 748 qspifs_deleteFile(fh);
embeddedartists 0:0fdadbc3d852 749
embeddedartists 0:0fdadbc3d852 750 // modify old handle to point to new information
embeddedartists 0:0fdadbc3d852 751 fh->lastBlock = fhNew.lastBlock;
embeddedartists 0:0fdadbc3d852 752 fh->size = fhNew.size;
embeddedartists 0:0fdadbc3d852 753 fh->tocIdx = fhNew.tocIdx;
embeddedartists 0:0fdadbc3d852 754 }
embeddedartists 0:0fdadbc3d852 755 if (res != FS_OK)
embeddedartists 0:0fdadbc3d852 756 {
embeddedartists 0:0fdadbc3d852 757 // not possible to relocate the file => abort
embeddedartists 0:0fdadbc3d852 758 return res;
embeddedartists 0:0fdadbc3d852 759 }
embeddedartists 0:0fdadbc3d852 760 break;
embeddedartists 0:0fdadbc3d852 761 }
embeddedartists 0:0fdadbc3d852 762 }
embeddedartists 0:0fdadbc3d852 763
embeddedartists 0:0fdadbc3d852 764 // have space that is unused, so mark as used
embeddedartists 0:0fdadbc3d852 765 for (i = 0; i < numNeeded; i++)
embeddedartists 0:0fdadbc3d852 766 {
embeddedartists 0:0fdadbc3d852 767 int tocIdx = fh->tocIdx + oldNumBlocks + 1 + i;
embeddedartists 0:0fdadbc3d852 768 TOC[tocIdx] &= ~TOC_USED_MASK;
embeddedartists 0:0fdadbc3d852 769 qspifs_eraseBlock(tocIdx);
embeddedartists 0:0fdadbc3d852 770 }
embeddedartists 0:0fdadbc3d852 771 }
embeddedartists 0:0fdadbc3d852 772
embeddedartists 0:0fdadbc3d852 773 return res;
embeddedartists 0:0fdadbc3d852 774 }
embeddedartists 0:0fdadbc3d852 775
embeddedartists 0:0fdadbc3d852 776 /******************************************************************************
embeddedartists 0:0fdadbc3d852 777 *
embeddedartists 0:0fdadbc3d852 778 * Description:
embeddedartists 0:0fdadbc3d852 779 * Adds a file system to the QSPI flash. The entire flash will be erase
embeddedartists 0:0fdadbc3d852 780 * except for the minReservedBytes first bytes. That reserved area (rounded
embeddedartists 0:0fdadbc3d852 781 * up to the closest even multiple of the erase block size) can be used
embeddedartists 0:0fdadbc3d852 782 * for anything and will never be touched by the file system. That area is
embeddedartists 0:0fdadbc3d852 783 * typically used for executing programs from when the internal flash is
embeddedartists 0:0fdadbc3d852 784 * full.
embeddedartists 0:0fdadbc3d852 785 *
embeddedartists 0:0fdadbc3d852 786 * The file system will have a table of content (TOC) placed at the start
embeddedartists 0:0fdadbc3d852 787 * of the last erase block on the flash.
embeddedartists 0:0fdadbc3d852 788 *
embeddedartists 0:0fdadbc3d852 789 * Params:
embeddedartists 0:0fdadbc3d852 790 * [in] minReservedBytes - The number of bytes to ignore at the start of
embeddedartists 0:0fdadbc3d852 791 * the flash.
embeddedartists 0:0fdadbc3d852 792 *
embeddedartists 0:0fdadbc3d852 793 * Returns:
embeddedartists 0:0fdadbc3d852 794 * FS_OK on success or one of the FS_ERR_* on failure
embeddedartists 0:0fdadbc3d852 795 *
embeddedartists 0:0fdadbc3d852 796 *****************************************************************************/
embeddedartists 0:0fdadbc3d852 797 static fresult qspifs_format(unsigned int minReservedBytes)
embeddedartists 0:0fdadbc3d852 798 {
embeddedartists 0:0fdadbc3d852 799 int i, rc;
embeddedartists 0:0fdadbc3d852 800 int numReserved = 0;
embeddedartists 0:0fdadbc3d852 801
embeddedartists 0:0fdadbc3d852 802 if (minReservedBytes > 0) {
embeddedartists 0:0fdadbc3d852 803 numReserved = (minReservedBytes + ERASE_SIZE - 1) / ERASE_SIZE;
embeddedartists 0:0fdadbc3d852 804 if (numReserved >= (NUM_BLOCKS - 2)) {
embeddedartists 0:0fdadbc3d852 805 // Too many of the erase blocks are reserved - not even room for one file
embeddedartists 0:0fdadbc3d852 806 return FS_ERR_INVALID_PARAM;
embeddedartists 0:0fdadbc3d852 807 }
embeddedartists 0:0fdadbc3d852 808 }
embeddedartists 0:0fdadbc3d852 809
embeddedartists 0:0fdadbc3d852 810 #if 0 // works but is really slow
embeddedartists 0:0fdadbc3d852 811 // Erase all non-reserved blocks
embeddedartists 0:0fdadbc3d852 812 for (i = numReserved; i < NUM_BLOCKS; i++) {
embeddedartists 0:0fdadbc3d852 813 opers.dest = (char *) (i * ERASE_SIZE);
embeddedartists 0:0fdadbc3d852 814 opers.length = ERASE_SIZE;
embeddedartists 0:0fdadbc3d852 815 opers.scratch = NULL;
embeddedartists 0:0fdadbc3d852 816 opers.protect = 0;
embeddedartists 0:0fdadbc3d852 817 opers.options = S_NO_VERIFY;
embeddedartists 0:0fdadbc3d852 818 rc = spifi->spifi_erase(&obj, &opers);
embeddedartists 0:0fdadbc3d852 819 if (rc) {
embeddedartists 0:0fdadbc3d852 820 return qspifs_translateSpifiError(rc);
embeddedartists 0:0fdadbc3d852 821 }
embeddedartists 0:0fdadbc3d852 822 }
embeddedartists 0:0fdadbc3d852 823 #else
embeddedartists 0:0fdadbc3d852 824 // Erase all non-reserved blocks
embeddedartists 0:0fdadbc3d852 825 opers.dest = (char *) (numReserved * ERASE_SIZE);
embeddedartists 0:0fdadbc3d852 826 opers.length = MEM_SIZE - (numReserved * ERASE_SIZE);
embeddedartists 0:0fdadbc3d852 827 opers.scratch = NULL;
embeddedartists 0:0fdadbc3d852 828 opers.protect = 0;
embeddedartists 0:0fdadbc3d852 829 opers.options = S_NO_VERIFY;
embeddedartists 0:0fdadbc3d852 830 rc = spifi->spifi_erase(&obj, &opers);
embeddedartists 0:0fdadbc3d852 831 if (rc) {
embeddedartists 0:0fdadbc3d852 832 return qspifs_translateSpifiError(rc);
embeddedartists 0:0fdadbc3d852 833 }
embeddedartists 0:0fdadbc3d852 834 #endif
embeddedartists 0:0fdadbc3d852 835
embeddedartists 0:0fdadbc3d852 836 // Create the TOC, mark requested blocks as reserved and mark the TOC's
embeddedartists 0:0fdadbc3d852 837 // block(s) as reserved as well.
embeddedartists 0:0fdadbc3d852 838 for (i = 0; i < numReserved; i++) {
embeddedartists 0:0fdadbc3d852 839 TOC[i] = ~(TOC_VALID_MASK | TOC_RESERVED_MASK);
embeddedartists 0:0fdadbc3d852 840 }
embeddedartists 0:0fdadbc3d852 841 for (; i < (NUM_BLOCKS - NUM_TOC_BLOCKS); i++) {
embeddedartists 0:0fdadbc3d852 842 TOC[i] = ~TOC_VALID_MASK;
embeddedartists 0:0fdadbc3d852 843 }
embeddedartists 0:0fdadbc3d852 844 for (; i < NUM_BLOCKS; i++) {
embeddedartists 0:0fdadbc3d852 845 TOC[i] = ~(TOC_VALID_MASK | TOC_RESERVED_MASK);
embeddedartists 0:0fdadbc3d852 846 }
embeddedartists 0:0fdadbc3d852 847
embeddedartists 0:0fdadbc3d852 848 // Save the TOC in the last block
embeddedartists 0:0fdadbc3d852 849 activeTOC = 0;
embeddedartists 0:0fdadbc3d852 850 fresult res = qspifs_saveTOC();
embeddedartists 0:0fdadbc3d852 851 if (res != FS_OK) {
embeddedartists 0:0fdadbc3d852 852 activeTOC = -1;
embeddedartists 0:0fdadbc3d852 853 return res;
embeddedartists 0:0fdadbc3d852 854 }
embeddedartists 0:0fdadbc3d852 855 // opers.dest = (char *) TOC_BLOCK_ADDR;
embeddedartists 0:0fdadbc3d852 856 // opers.length = TOC_SIZE;
embeddedartists 0:0fdadbc3d852 857 // opers.scratch = NULL;
embeddedartists 0:0fdadbc3d852 858 // opers.protect = 0;
embeddedartists 0:0fdadbc3d852 859 // opers.options = S_VERIFY_PROG | S_CALLER_ERASE;
embeddedartists 0:0fdadbc3d852 860 // rc = spifi->spifi_program(&obj, (char*) TOC, &opers);
embeddedartists 0:0fdadbc3d852 861 // if (rc) {
embeddedartists 0:0fdadbc3d852 862 // return qspifs_translateSpifiError(rc);
embeddedartists 0:0fdadbc3d852 863 // }
embeddedartists 0:0fdadbc3d852 864
embeddedartists 0:0fdadbc3d852 865 // Read back TOC to be sure it worked
embeddedartists 0:0fdadbc3d852 866 return qspifs_readTOC();
embeddedartists 0:0fdadbc3d852 867 }
embeddedartists 0:0fdadbc3d852 868
embeddedartists 0:0fdadbc3d852 869 /******************************************************************************
embeddedartists 0:0fdadbc3d852 870 *
embeddedartists 0:0fdadbc3d852 871 * Description:
embeddedartists 0:0fdadbc3d852 872 * Deletes all files on the file system. This is a "quick format" that
embeddedartists 0:0fdadbc3d852 873 * leaves all blocks untouched and only modifies the TOC. Any reserved
embeddedartists 0:0fdadbc3d852 874 * blocks are kept reserved.
embeddedartists 0:0fdadbc3d852 875 *
embeddedartists 0:0fdadbc3d852 876 * The purpose of this function is to make it easy to clear the file system
embeddedartists 0:0fdadbc3d852 877 * without going through a time consuming complete erase every time.
embeddedartists 0:0fdadbc3d852 878 *
embeddedartists 0:0fdadbc3d852 879 * Params:
embeddedartists 0:0fdadbc3d852 880 * None
embeddedartists 0:0fdadbc3d852 881 *
embeddedartists 0:0fdadbc3d852 882 * Returns:
embeddedartists 0:0fdadbc3d852 883 * FS_OK on success or one of the FS_ERR_* on failure
embeddedartists 0:0fdadbc3d852 884 *
embeddedartists 0:0fdadbc3d852 885 *****************************************************************************/
embeddedartists 0:0fdadbc3d852 886 // static fresult qspifs_deleteAllFiles(void)
embeddedartists 0:0fdadbc3d852 887 // {
embeddedartists 0:0fdadbc3d852 888 // for (int i = 0; i < NUM_BLOCKS; i++)
embeddedartists 0:0fdadbc3d852 889 // {
embeddedartists 0:0fdadbc3d852 890 // if (!TOC_IS_RESERVED(TOC[i])) {
embeddedartists 0:0fdadbc3d852 891 // TOC[i] = ~TOC_VALID_MASK;
embeddedartists 0:0fdadbc3d852 892 // }
embeddedartists 0:0fdadbc3d852 893 // }
embeddedartists 0:0fdadbc3d852 894 //
embeddedartists 0:0fdadbc3d852 895 // return qspifs_saveTOC();
embeddedartists 0:0fdadbc3d852 896 // }
embeddedartists 0:0fdadbc3d852 897
embeddedartists 0:0fdadbc3d852 898 /******************************************************************************
embeddedartists 0:0fdadbc3d852 899 *
embeddedartists 0:0fdadbc3d852 900 * Description:
embeddedartists 0:0fdadbc3d852 901 * Appends the data to the end of the file.
embeddedartists 0:0fdadbc3d852 902 *
embeddedartists 0:0fdadbc3d852 903 * Params:
embeddedartists 0:0fdadbc3d852 904 * [in] fh - The handle to the file as returned from fs_open_append()
embeddedartists 0:0fdadbc3d852 905 * [in] pData - The data to save
embeddedartists 0:0fdadbc3d852 906 * [in] size - Number of bytes to save
embeddedartists 0:0fdadbc3d852 907 *
embeddedartists 0:0fdadbc3d852 908 * Returns:
embeddedartists 0:0fdadbc3d852 909 * FS_OK on success or one of the FS_ERR_* on failure
embeddedartists 0:0fdadbc3d852 910 *
embeddedartists 0:0fdadbc3d852 911 *****************************************************************************/
embeddedartists 0:0fdadbc3d852 912 static fresult qspifs_write(fileHandle_t* fh, const uint8_t * const pData, uint32_t size)
embeddedartists 0:0fdadbc3d852 913 {
embeddedartists 0:0fdadbc3d852 914 uint32_t left = size;
embeddedartists 0:0fdadbc3d852 915 const uint8_t* pSrc = pData;
embeddedartists 0:0fdadbc3d852 916 int rc, i;
embeddedartists 0:0fdadbc3d852 917 fresult res;
embeddedartists 0:0fdadbc3d852 918 int failed_attempts = 0;
embeddedartists 0:0fdadbc3d852 919
embeddedartists 0:0fdadbc3d852 920 do {
embeddedartists 0:0fdadbc3d852 921 res = qspifs_allocateSpace(fh, size);
embeddedartists 0:0fdadbc3d852 922 if (res != FS_OK) {
embeddedartists 0:0fdadbc3d852 923 break;
embeddedartists 0:0fdadbc3d852 924 }
embeddedartists 0:0fdadbc3d852 925
embeddedartists 0:0fdadbc3d852 926 opers.dest = (char *) (SPIFI_MEM_BASE + fh->tocIdx * ERASE_SIZE
embeddedartists 0:0fdadbc3d852 927 + HEADER_LEN + fh->size);
embeddedartists 0:0fdadbc3d852 928 opers.scratch = NULL;
embeddedartists 0:0fdadbc3d852 929 opers.protect = 0;
embeddedartists 0:0fdadbc3d852 930 opers.options = S_VERIFY_PROG; // | S_FORCE_ERASE;
embeddedartists 0:0fdadbc3d852 931
embeddedartists 0:0fdadbc3d852 932 while ((res == FS_OK) && (left > 0)) {
embeddedartists 0:0fdadbc3d852 933 if (left >= PROG_SIZE) {
embeddedartists 0:0fdadbc3d852 934 opers.length = PROG_SIZE;
embeddedartists 0:0fdadbc3d852 935 } else {
embeddedartists 0:0fdadbc3d852 936 opers.length = left;
embeddedartists 0:0fdadbc3d852 937 }
embeddedartists 0:0fdadbc3d852 938 if (IS_ADDR_IN_SPIFI(pData)) {
embeddedartists 0:0fdadbc3d852 939 memcpy(addr_conflict_buff, pSrc, opers.length);
embeddedartists 0:0fdadbc3d852 940 rc = spifi->spifi_program(&obj, addr_conflict_buff, &opers);
embeddedartists 0:0fdadbc3d852 941 } else {
embeddedartists 0:0fdadbc3d852 942 rc = spifi->spifi_program(&obj, (char*) pSrc, &opers);
embeddedartists 0:0fdadbc3d852 943 }
embeddedartists 0:0fdadbc3d852 944 res = qspifs_translateSpifiError(rc);
embeddedartists 0:0fdadbc3d852 945 if ((res == FS_ERR_SPIFI_VERIFICATION)
embeddedartists 0:0fdadbc3d852 946 && (++failed_attempts <= NUM_VERIFICATION_ATTEMPTS)) {
embeddedartists 0:0fdadbc3d852 947 // The verification process failed.
embeddedartists 0:0fdadbc3d852 948 // In all the observed occasions re-running the exact same
embeddedartists 0:0fdadbc3d852 949 // spifi_program command again yielded a 0 as a return value
embeddedartists 0:0fdadbc3d852 950 // the second time.
embeddedartists 0:0fdadbc3d852 951 // The quick'N'dirty fix is to re-run that program instruction
embeddedartists 0:0fdadbc3d852 952 // NUM_VERIFICATION_ATTEMPTS more time(s) when this happens.
embeddedartists 0:0fdadbc3d852 953 res = FS_OK;
embeddedartists 0:0fdadbc3d852 954 continue;
embeddedartists 0:0fdadbc3d852 955 }
embeddedartists 0:0fdadbc3d852 956 if (res != FS_OK) {
embeddedartists 0:0fdadbc3d852 957 // Got an error but cannot exit this function here as parts of the data
embeddedartists 0:0fdadbc3d852 958 // (previous loops?) may have been written so the TOC must be updated.
embeddedartists 0:0fdadbc3d852 959 break;
embeddedartists 0:0fdadbc3d852 960 }
embeddedartists 0:0fdadbc3d852 961 pSrc += opers.length;
embeddedartists 0:0fdadbc3d852 962 opers.dest += opers.length;
embeddedartists 0:0fdadbc3d852 963 left -= opers.length;
embeddedartists 0:0fdadbc3d852 964 failed_attempts = 0;
embeddedartists 0:0fdadbc3d852 965 }
embeddedartists 0:0fdadbc3d852 966
embeddedartists 0:0fdadbc3d852 967 // update file information
embeddedartists 0:0fdadbc3d852 968 fh->size = fh->size + size - left;
embeddedartists 0:0fdadbc3d852 969 fh->lastBlock = fh->tocIdx + ((fh->size + HEADER_LEN)/ ERASE_SIZE);
embeddedartists 0:0fdadbc3d852 970 left = fh->size + HEADER_LEN;
embeddedartists 0:0fdadbc3d852 971 for (i = 0; i <= (fh->lastBlock - fh->tocIdx); i++) {
embeddedartists 0:0fdadbc3d852 972 TOC[fh->tocIdx + i] &= ~TOC_FSIZE_MASK;
embeddedartists 0:0fdadbc3d852 973 TOC[fh->tocIdx + i] |= FS_MIN(ERASE_SIZE, left);
embeddedartists 0:0fdadbc3d852 974 left -= FILESIZE(TOC[fh->tocIdx + i]);
embeddedartists 0:0fdadbc3d852 975 }
embeddedartists 0:0fdadbc3d852 976
embeddedartists 0:0fdadbc3d852 977 if (res == FS_OK) {
embeddedartists 0:0fdadbc3d852 978 res = qspifs_saveTOC();
embeddedartists 0:0fdadbc3d852 979 } else {
embeddedartists 0:0fdadbc3d852 980 // Want to save the TOC but not overwrite the previous error with
embeddedartists 0:0fdadbc3d852 981 // a possibly successful TOC saving thus making it seem like there
embeddedartists 0:0fdadbc3d852 982 // was no error
embeddedartists 0:0fdadbc3d852 983 qspifs_saveTOC();
embeddedartists 0:0fdadbc3d852 984 }
embeddedartists 0:0fdadbc3d852 985 } while (0);
embeddedartists 0:0fdadbc3d852 986
embeddedartists 0:0fdadbc3d852 987 return res;
embeddedartists 0:0fdadbc3d852 988 }
embeddedartists 0:0fdadbc3d852 989
embeddedartists 0:0fdadbc3d852 990 /******************************************************************************
embeddedartists 0:0fdadbc3d852 991 *
embeddedartists 0:0fdadbc3d852 992 * Description:
embeddedartists 0:0fdadbc3d852 993 * Tests if str starts with prefix. A prefix of NULL or an empty string
embeddedartists 0:0fdadbc3d852 994 * results in a positive result regardless of the content of str.
embeddedartists 0:0fdadbc3d852 995 *
embeddedartists 0:0fdadbc3d852 996 * Params:
embeddedartists 0:0fdadbc3d852 997 * [in] prefix - The prefix to look for
embeddedartists 0:0fdadbc3d852 998 * [in] str - The string to search for prefix
embeddedartists 0:0fdadbc3d852 999 *
embeddedartists 0:0fdadbc3d852 1000 * Returns:
embeddedartists 0:0fdadbc3d852 1001 * True if the specified string starts with prefix
embeddedartists 0:0fdadbc3d852 1002 *
embeddedartists 0:0fdadbc3d852 1003 *****************************************************************************/
embeddedartists 0:0fdadbc3d852 1004 static bool qspifs_startsWith(const char* prefix, const char* str)
embeddedartists 0:0fdadbc3d852 1005 {
embeddedartists 0:0fdadbc3d852 1006 const char* pA = prefix;
embeddedartists 0:0fdadbc3d852 1007 const char* pB = str;
embeddedartists 0:0fdadbc3d852 1008
embeddedartists 0:0fdadbc3d852 1009 if (pA == NULL)
embeddedartists 0:0fdadbc3d852 1010 {
embeddedartists 0:0fdadbc3d852 1011 return true;
embeddedartists 0:0fdadbc3d852 1012 }
embeddedartists 0:0fdadbc3d852 1013 for (; *pA != '\0'; pA++, pB++)
embeddedartists 0:0fdadbc3d852 1014 {
embeddedartists 0:0fdadbc3d852 1015 if (*pB != *pA)
embeddedartists 0:0fdadbc3d852 1016 {
embeddedartists 0:0fdadbc3d852 1017 return false;
embeddedartists 0:0fdadbc3d852 1018 }
embeddedartists 0:0fdadbc3d852 1019 }
embeddedartists 0:0fdadbc3d852 1020
embeddedartists 0:0fdadbc3d852 1021 return true;
embeddedartists 0:0fdadbc3d852 1022 }
embeddedartists 0:0fdadbc3d852 1023
embeddedartists 0:0fdadbc3d852 1024 /******************************************************************************
embeddedartists 0:0fdadbc3d852 1025 * Class Declarations
embeddedartists 0:0fdadbc3d852 1026 *****************************************************************************/
embeddedartists 0:0fdadbc3d852 1027
embeddedartists 0:0fdadbc3d852 1028 class QSPIFileHandle : public FileHandle {
embeddedartists 0:0fdadbc3d852 1029
embeddedartists 0:0fdadbc3d852 1030 public:
embeddedartists 0:0fdadbc3d852 1031 QSPIFileHandle(fileHandle_t* handle, int flags);
embeddedartists 0:0fdadbc3d852 1032
embeddedartists 0:0fdadbc3d852 1033 virtual int close();
embeddedartists 0:0fdadbc3d852 1034
embeddedartists 0:0fdadbc3d852 1035 virtual ssize_t write(const void *buffer, size_t length);
embeddedartists 0:0fdadbc3d852 1036
embeddedartists 0:0fdadbc3d852 1037 virtual ssize_t read(void *buffer, size_t length);
embeddedartists 0:0fdadbc3d852 1038
embeddedartists 0:0fdadbc3d852 1039 virtual int isatty();
embeddedartists 0:0fdadbc3d852 1040
embeddedartists 0:0fdadbc3d852 1041 virtual off_t lseek(off_t position, int whence);
embeddedartists 0:0fdadbc3d852 1042
embeddedartists 0:0fdadbc3d852 1043 virtual int fsync();
embeddedartists 0:0fdadbc3d852 1044
embeddedartists 0:0fdadbc3d852 1045 virtual off_t flen();
embeddedartists 0:0fdadbc3d852 1046
embeddedartists 0:0fdadbc3d852 1047 protected:
embeddedartists 0:0fdadbc3d852 1048
embeddedartists 0:0fdadbc3d852 1049 fileHandle_t fh;
embeddedartists 0:0fdadbc3d852 1050 bool allowReading;
embeddedartists 0:0fdadbc3d852 1051 bool allowWriting;
embeddedartists 0:0fdadbc3d852 1052 uint32_t pos;
embeddedartists 0:0fdadbc3d852 1053 };
embeddedartists 0:0fdadbc3d852 1054
embeddedartists 0:0fdadbc3d852 1055 class QSPIDirHandle : public DirHandle {
embeddedartists 0:0fdadbc3d852 1056
embeddedartists 0:0fdadbc3d852 1057 public:
embeddedartists 0:0fdadbc3d852 1058 static QSPIDirHandle* openDir(const char* dirname);
embeddedartists 0:0fdadbc3d852 1059
embeddedartists 0:0fdadbc3d852 1060 virtual ~QSPIDirHandle();
embeddedartists 0:0fdadbc3d852 1061
embeddedartists 0:0fdadbc3d852 1062 virtual int closedir();
embeddedartists 0:0fdadbc3d852 1063 virtual struct dirent *readdir();
embeddedartists 0:0fdadbc3d852 1064 virtual void rewinddir();
embeddedartists 0:0fdadbc3d852 1065
embeddedartists 0:0fdadbc3d852 1066 private:
embeddedartists 0:0fdadbc3d852 1067 QSPIDirHandle(const char* dirname);
embeddedartists 0:0fdadbc3d852 1068
embeddedartists 0:0fdadbc3d852 1069 int findFileWithPrefix(const char* prefix, int startTOCIdx, int maxTOCIdx) const;
embeddedartists 0:0fdadbc3d852 1070
embeddedartists 0:0fdadbc3d852 1071 protected:
embeddedartists 0:0fdadbc3d852 1072
embeddedartists 0:0fdadbc3d852 1073 char* dirname;
embeddedartists 0:0fdadbc3d852 1074 int nextTocIdx;
embeddedartists 0:0fdadbc3d852 1075
embeddedartists 0:0fdadbc3d852 1076 bool isRoot;
embeddedartists 0:0fdadbc3d852 1077
embeddedartists 0:0fdadbc3d852 1078 struct dirent cur_entry;
embeddedartists 0:0fdadbc3d852 1079 };
embeddedartists 0:0fdadbc3d852 1080
embeddedartists 0:0fdadbc3d852 1081 /******************************************************************************
embeddedartists 0:0fdadbc3d852 1082 * Class Implementations
embeddedartists 0:0fdadbc3d852 1083 *****************************************************************************/
embeddedartists 0:0fdadbc3d852 1084
embeddedartists 0:0fdadbc3d852 1085 QSPIFileHandle::QSPIFileHandle(fileHandle_t* handle, int flags)
embeddedartists 0:0fdadbc3d852 1086 {
embeddedartists 0:0fdadbc3d852 1087 fh = *handle;
embeddedartists 0:0fdadbc3d852 1088 int accmode = (flags & O_ACCMODE);
embeddedartists 0:0fdadbc3d852 1089 allowReading = (accmode == O_RDONLY) || (accmode == O_RDWR);
embeddedartists 0:0fdadbc3d852 1090 allowWriting = (accmode == O_WRONLY) || (accmode == O_RDWR) || (flags & O_APPEND);
embeddedartists 0:0fdadbc3d852 1091 pos = 0;
embeddedartists 0:0fdadbc3d852 1092 }
embeddedartists 0:0fdadbc3d852 1093
embeddedartists 0:0fdadbc3d852 1094 int QSPIFileHandle::close()
embeddedartists 0:0fdadbc3d852 1095 {
embeddedartists 0:0fdadbc3d852 1096 delete this;
embeddedartists 0:0fdadbc3d852 1097 return 0;
embeddedartists 0:0fdadbc3d852 1098 }
embeddedartists 0:0fdadbc3d852 1099
embeddedartists 0:0fdadbc3d852 1100 ssize_t QSPIFileHandle::write(const void *buffer, size_t length)
embeddedartists 0:0fdadbc3d852 1101 {
embeddedartists 0:0fdadbc3d852 1102 if (!allowWriting) {
embeddedartists 0:0fdadbc3d852 1103 return -1;
embeddedartists 0:0fdadbc3d852 1104 }
embeddedartists 0:0fdadbc3d852 1105 fresult res = qspifs_write(&fh, (const uint8_t*)buffer, length);
embeddedartists 0:0fdadbc3d852 1106 if (res == FS_OK) {
embeddedartists 0:0fdadbc3d852 1107 // A write is always 'append' in this file system so the file
embeddedartists 0:0fdadbc3d852 1108 // position is always end of file after a write
embeddedartists 0:0fdadbc3d852 1109 pos = fh.size;
embeddedartists 0:0fdadbc3d852 1110 return length;
embeddedartists 0:0fdadbc3d852 1111 }
embeddedartists 0:0fdadbc3d852 1112 return -1;
embeddedartists 0:0fdadbc3d852 1113 }
embeddedartists 0:0fdadbc3d852 1114
embeddedartists 0:0fdadbc3d852 1115 ssize_t QSPIFileHandle::read(void *buffer, size_t length)
embeddedartists 0:0fdadbc3d852 1116 {
embeddedartists 0:0fdadbc3d852 1117 if (!allowReading) {
embeddedartists 0:0fdadbc3d852 1118 return -1;
embeddedartists 0:0fdadbc3d852 1119 }
embeddedartists 0:0fdadbc3d852 1120 if (pos >= fh.size) {
embeddedartists 0:0fdadbc3d852 1121 return 0;
embeddedartists 0:0fdadbc3d852 1122 }
embeddedartists 0:0fdadbc3d852 1123 uint32_t len = FS_MIN(length, fh.size - pos);
embeddedartists 0:0fdadbc3d852 1124 const char* pData = (const char*)(SPIFI_MEM_BASE + fh.tocIdx*ERASE_SIZE + HEADER_LEN + pos);
embeddedartists 0:0fdadbc3d852 1125 memcpy(buffer, pData, len);
embeddedartists 0:0fdadbc3d852 1126 pos += len;
embeddedartists 0:0fdadbc3d852 1127 return len;
embeddedartists 0:0fdadbc3d852 1128 }
embeddedartists 0:0fdadbc3d852 1129
embeddedartists 0:0fdadbc3d852 1130 int QSPIFileHandle::isatty()
embeddedartists 0:0fdadbc3d852 1131 {
embeddedartists 0:0fdadbc3d852 1132 return 0;
embeddedartists 0:0fdadbc3d852 1133 }
embeddedartists 0:0fdadbc3d852 1134
embeddedartists 0:0fdadbc3d852 1135 off_t QSPIFileHandle::lseek(off_t position, int whence)
embeddedartists 0:0fdadbc3d852 1136 {
embeddedartists 0:0fdadbc3d852 1137 switch (whence) {
embeddedartists 0:0fdadbc3d852 1138 case SEEK_SET:
embeddedartists 0:0fdadbc3d852 1139 pos = position;
embeddedartists 0:0fdadbc3d852 1140 break;
embeddedartists 0:0fdadbc3d852 1141
embeddedartists 0:0fdadbc3d852 1142 case SEEK_CUR:
embeddedartists 0:0fdadbc3d852 1143 pos += position;
embeddedartists 0:0fdadbc3d852 1144 break;
embeddedartists 0:0fdadbc3d852 1145
embeddedartists 0:0fdadbc3d852 1146 case SEEK_END:
embeddedartists 0:0fdadbc3d852 1147 pos = fh.size + position;
embeddedartists 0:0fdadbc3d852 1148 break;
embeddedartists 0:0fdadbc3d852 1149
embeddedartists 0:0fdadbc3d852 1150 default:
embeddedartists 0:0fdadbc3d852 1151 return -1;
embeddedartists 0:0fdadbc3d852 1152 }
embeddedartists 0:0fdadbc3d852 1153 return pos;
embeddedartists 0:0fdadbc3d852 1154 }
embeddedartists 0:0fdadbc3d852 1155
embeddedartists 0:0fdadbc3d852 1156 int QSPIFileHandle::fsync()
embeddedartists 0:0fdadbc3d852 1157 {
embeddedartists 0:0fdadbc3d852 1158 return 0; // always synced
embeddedartists 0:0fdadbc3d852 1159 }
embeddedartists 0:0fdadbc3d852 1160
embeddedartists 0:0fdadbc3d852 1161 off_t QSPIFileHandle::flen()
embeddedartists 0:0fdadbc3d852 1162 {
embeddedartists 0:0fdadbc3d852 1163 return fh.size;
embeddedartists 0:0fdadbc3d852 1164 }
embeddedartists 0:0fdadbc3d852 1165
embeddedartists 0:0fdadbc3d852 1166 QSPIDirHandle::QSPIDirHandle(const char* dirname) {
embeddedartists 0:0fdadbc3d852 1167 size_t len = strlen(dirname);
embeddedartists 0:0fdadbc3d852 1168 this->dirname = (char*)malloc(len + 2); // null termination and possible ending '/'
embeddedartists 0:0fdadbc3d852 1169 if (this->dirname != NULL) {
embeddedartists 0:0fdadbc3d852 1170 if (len == 0 || ((len == 1) && (dirname[0] == '/'))) {
embeddedartists 0:0fdadbc3d852 1171 isRoot = true;
embeddedartists 0:0fdadbc3d852 1172 this->dirname[0] = '\0';
embeddedartists 0:0fdadbc3d852 1173 } else {
embeddedartists 0:0fdadbc3d852 1174 isRoot = false;
embeddedartists 0:0fdadbc3d852 1175 memcpy(this->dirname, dirname, len+1);
embeddedartists 0:0fdadbc3d852 1176 if (dirname[len - 1] != '/') {
embeddedartists 0:0fdadbc3d852 1177 this->dirname[len] = '/';
embeddedartists 0:0fdadbc3d852 1178 this->dirname[len+1] = '\0';
embeddedartists 0:0fdadbc3d852 1179 }
embeddedartists 0:0fdadbc3d852 1180 }
embeddedartists 0:0fdadbc3d852 1181 cur_entry.d_name[HEADER_FNAME_STRLEN] = '\0';
embeddedartists 0:0fdadbc3d852 1182 rewinddir();
embeddedartists 0:0fdadbc3d852 1183 }
embeddedartists 0:0fdadbc3d852 1184 }
embeddedartists 0:0fdadbc3d852 1185
embeddedartists 0:0fdadbc3d852 1186 QSPIDirHandle::~QSPIDirHandle()
embeddedartists 0:0fdadbc3d852 1187 {
embeddedartists 0:0fdadbc3d852 1188 if (dirname != NULL) {
embeddedartists 0:0fdadbc3d852 1189 delete dirname;
embeddedartists 0:0fdadbc3d852 1190 dirname = NULL;
embeddedartists 0:0fdadbc3d852 1191 }
embeddedartists 0:0fdadbc3d852 1192 }
embeddedartists 0:0fdadbc3d852 1193
embeddedartists 0:0fdadbc3d852 1194 QSPIDirHandle* QSPIDirHandle::openDir(const char* dirname)
embeddedartists 0:0fdadbc3d852 1195 {
embeddedartists 0:0fdadbc3d852 1196 QSPIDirHandle* d = new QSPIDirHandle(dirname);
embeddedartists 0:0fdadbc3d852 1197 if (d->dirname == NULL) {
embeddedartists 0:0fdadbc3d852 1198 // failed to allocate memory for the folder name
embeddedartists 0:0fdadbc3d852 1199 delete d;
embeddedartists 0:0fdadbc3d852 1200 d = NULL;
embeddedartists 0:0fdadbc3d852 1201 } else if (!d->isRoot) {
embeddedartists 0:0fdadbc3d852 1202 if (d->findFileWithPrefix(d->dirname, 0, NUM_BLOCKS) == NUM_BLOCKS) {
embeddedartists 0:0fdadbc3d852 1203 // There are no files in this directory, i.e. it does not exist
embeddedartists 0:0fdadbc3d852 1204 delete d;
embeddedartists 0:0fdadbc3d852 1205 d = NULL;
embeddedartists 0:0fdadbc3d852 1206 }
embeddedartists 0:0fdadbc3d852 1207 }
embeddedartists 0:0fdadbc3d852 1208 return d;
embeddedartists 0:0fdadbc3d852 1209 }
embeddedartists 0:0fdadbc3d852 1210
embeddedartists 0:0fdadbc3d852 1211 int QSPIDirHandle::closedir() {
embeddedartists 0:0fdadbc3d852 1212 delete this;
embeddedartists 0:0fdadbc3d852 1213 return 0;
embeddedartists 0:0fdadbc3d852 1214 }
embeddedartists 0:0fdadbc3d852 1215
embeddedartists 0:0fdadbc3d852 1216 int QSPIDirHandle::findFileWithPrefix(const char* prefix, int startTOCIdx, int maxTOCIdx) const
embeddedartists 0:0fdadbc3d852 1217 {
embeddedartists 0:0fdadbc3d852 1218 for (int i = startTOCIdx; i < maxTOCIdx; i++) {
embeddedartists 0:0fdadbc3d852 1219 if (TOC_IS_FILE(TOC[i])) {
embeddedartists 0:0fdadbc3d852 1220 const char* filename = (const char*) (SPIFI_MEM_BASE + i * ERASE_SIZE);
embeddedartists 0:0fdadbc3d852 1221 if (qspifs_startsWith(prefix, filename)) {
embeddedartists 0:0fdadbc3d852 1222 return i;
embeddedartists 0:0fdadbc3d852 1223 }
embeddedartists 0:0fdadbc3d852 1224 }
embeddedartists 0:0fdadbc3d852 1225 }
embeddedartists 0:0fdadbc3d852 1226 return NUM_BLOCKS; // no match
embeddedartists 0:0fdadbc3d852 1227 }
embeddedartists 0:0fdadbc3d852 1228
embeddedartists 0:0fdadbc3d852 1229
embeddedartists 0:0fdadbc3d852 1230 struct dirent *QSPIDirHandle::readdir() {
embeddedartists 0:0fdadbc3d852 1231 if (nextTocIdx < NUM_BLOCKS) {
embeddedartists 0:0fdadbc3d852 1232 for (int i = nextTocIdx; i < NUM_BLOCKS; i++) {
embeddedartists 0:0fdadbc3d852 1233 int possible = findFileWithPrefix(dirname, i, NUM_BLOCKS);
embeddedartists 0:0fdadbc3d852 1234 if (possible < NUM_BLOCKS) {
embeddedartists 0:0fdadbc3d852 1235 const char* fullfilename = (const char*) (SPIFI_MEM_BASE + possible * ERASE_SIZE);
embeddedartists 0:0fdadbc3d852 1236 const char* filename = fullfilename + strlen(dirname);
embeddedartists 0:0fdadbc3d852 1237
embeddedartists 0:0fdadbc3d852 1238 if (strchr(filename, '/') == NULL) {
embeddedartists 0:0fdadbc3d852 1239 // file is not in any sub folder so it is truly in the wanted dir
embeddedartists 0:0fdadbc3d852 1240 nextTocIdx = possible + 1;
embeddedartists 0:0fdadbc3d852 1241 strcpy(cur_entry.d_name, filename);
embeddedartists 0:0fdadbc3d852 1242 return &cur_entry;
embeddedartists 0:0fdadbc3d852 1243 }
embeddedartists 0:0fdadbc3d852 1244
embeddedartists 0:0fdadbc3d852 1245 // this is a file in a subfolder and should not be reported,
embeddedartists 0:0fdadbc3d852 1246 // but the folder name itself should
embeddedartists 0:0fdadbc3d852 1247 strcpy(cur_entry.d_name, fullfilename);
embeddedartists 0:0fdadbc3d852 1248 char* pSlash = strchr(cur_entry.d_name + strlen(dirname), '/');
embeddedartists 0:0fdadbc3d852 1249 pSlash++;
embeddedartists 0:0fdadbc3d852 1250 *pSlash = '\0';
embeddedartists 0:0fdadbc3d852 1251
embeddedartists 0:0fdadbc3d852 1252 // now that cur_entry.d_name contains the folder's complete
embeddedartists 0:0fdadbc3d852 1253 // path with a trailing '/', see if it has occurred earlier
embeddedartists 0:0fdadbc3d852 1254 int older = findFileWithPrefix(cur_entry.d_name, 0, i);
embeddedartists 0:0fdadbc3d852 1255 if (older < possible) {
embeddedartists 0:0fdadbc3d852 1256 // already reported, move past this entry
embeddedartists 0:0fdadbc3d852 1257 i = possible;
embeddedartists 0:0fdadbc3d852 1258 } else {
embeddedartists 0:0fdadbc3d852 1259 // found a new subfolder
embeddedartists 0:0fdadbc3d852 1260 nextTocIdx = possible + 1;
embeddedartists 0:0fdadbc3d852 1261 strcpy(cur_entry.d_name, filename);
embeddedartists 0:0fdadbc3d852 1262 char* pSlash = strchr(cur_entry.d_name, '/');
embeddedartists 0:0fdadbc3d852 1263 // pSlash++; //with ++ the returned dir name is "mydir/" without ++ "mydir" is returned
embeddedartists 0:0fdadbc3d852 1264 *pSlash = '\0';
embeddedartists 0:0fdadbc3d852 1265 return &cur_entry;
embeddedartists 0:0fdadbc3d852 1266 }
embeddedartists 0:0fdadbc3d852 1267 }
embeddedartists 0:0fdadbc3d852 1268 }
embeddedartists 0:0fdadbc3d852 1269 }
embeddedartists 0:0fdadbc3d852 1270 return NULL;
embeddedartists 0:0fdadbc3d852 1271 }
embeddedartists 0:0fdadbc3d852 1272
embeddedartists 0:0fdadbc3d852 1273 void QSPIDirHandle::rewinddir() {
embeddedartists 0:0fdadbc3d852 1274 nextTocIdx = 0;
embeddedartists 0:0fdadbc3d852 1275 }
embeddedartists 0:0fdadbc3d852 1276
embeddedartists 0:0fdadbc3d852 1277
embeddedartists 0:0fdadbc3d852 1278 QSPIFileSystem::QSPIFileSystem(const char* name) :
embeddedartists 0:0fdadbc3d852 1279 FileSystemLike(name) {
embeddedartists 0:0fdadbc3d852 1280
embeddedartists 0:0fdadbc3d852 1281 // Turn on SPIFI block as it is disabled on reset
embeddedartists 0:0fdadbc3d852 1282 LPC_SC->PCONP |= 0x00010000;
embeddedartists 0:0fdadbc3d852 1283
embeddedartists 0:0fdadbc3d852 1284 // pinsel for SPIFI
embeddedartists 0:0fdadbc3d852 1285 LPC_IOCON->P2_7 &= ~0x07;
embeddedartists 0:0fdadbc3d852 1286 LPC_IOCON->P2_7 |= 0x05; /* SPIFI_CSN @ P2.7 */
embeddedartists 0:0fdadbc3d852 1287 LPC_IOCON->P0_22 &= ~0x07;
embeddedartists 0:0fdadbc3d852 1288 LPC_IOCON->P0_22 |= 0x05; /* SPIFI_CLK @ P0.22 */
embeddedartists 0:0fdadbc3d852 1289 LPC_IOCON->P0_15 &= ~0x07;
embeddedartists 0:0fdadbc3d852 1290 LPC_IOCON->P0_15 |= 0x5; /* SPIFI_IO2 @ P0.15 */
embeddedartists 0:0fdadbc3d852 1291 LPC_IOCON->P0_16 &= ~0x07;
embeddedartists 0:0fdadbc3d852 1292 LPC_IOCON->P0_16 |= 0x5; /* SPIFI_IO3 @ P0.16 */
embeddedartists 0:0fdadbc3d852 1293 LPC_IOCON->P0_17 &= ~0x07;
embeddedartists 0:0fdadbc3d852 1294 LPC_IOCON->P0_17 |= 0x5; /* SPIFI_IO1 @ P0.17 */
embeddedartists 0:0fdadbc3d852 1295 LPC_IOCON->P0_18 &= ~0x07;
embeddedartists 0:0fdadbc3d852 1296 LPC_IOCON->P0_18 |= 0x5; /* SPIFI_IO0 @ P0.18 */
embeddedartists 0:0fdadbc3d852 1297
embeddedartists 0:0fdadbc3d852 1298 activeTOC = -1;
embeddedartists 0:0fdadbc3d852 1299 spifi = NULL;
embeddedartists 0:0fdadbc3d852 1300 }
embeddedartists 0:0fdadbc3d852 1301
embeddedartists 0:0fdadbc3d852 1302 // All modes are supported but:
embeddedartists 0:0fdadbc3d852 1303 //
embeddedartists 0:0fdadbc3d852 1304 // 1) All writes are treated as appends
embeddedartists 0:0fdadbc3d852 1305 // 2) Truncation is only to size 0, i.e. effectively a delete
embeddedartists 0:0fdadbc3d852 1306 // 3) File position operations work like this:
embeddedartists 0:0fdadbc3d852 1307 // ReadOnly - dictates where to read from
embeddedartists 0:0fdadbc3d852 1308 // WriteOnly - ignored, writes are always at the end
embeddedartists 0:0fdadbc3d852 1309 // ReadWrite - dictates where to read from, writes ignore it but
embeddedartists 0:0fdadbc3d852 1310 // sets the position to the end afterwards
embeddedartists 0:0fdadbc3d852 1311 //
embeddedartists 0:0fdadbc3d852 1312 FileHandle *QSPIFileSystem::open(const char *filename, int flags)
embeddedartists 0:0fdadbc3d852 1313 {
embeddedartists 0:0fdadbc3d852 1314 fresult res = qspifs_init();
embeddedartists 0:0fdadbc3d852 1315 // if (res == FS_OK) {
embeddedartists 0:0fdadbc3d852 1316 // if ((flags & O_ACCMODE) == O_RDONLY) {
embeddedartists 0:0fdadbc3d852 1317 // // ok
embeddedartists 0:0fdadbc3d852 1318 // } else if (flags & O_APPEND) {
embeddedartists 0:0fdadbc3d852 1319 // // ok
embeddedartists 0:0fdadbc3d852 1320 // } else {
embeddedartists 0:0fdadbc3d852 1321 // // not supported yet, this includes all combination of flags
embeddedartists 0:0fdadbc3d852 1322 // // allowing writing at specific positions in the file. This file system
embeddedartists 0:0fdadbc3d852 1323 // // only allows appending
embeddedartists 0:0fdadbc3d852 1324 // res = FS_ERR_INVALID_PARAM;
embeddedartists 0:0fdadbc3d852 1325 // }
embeddedartists 0:0fdadbc3d852 1326 // }
embeddedartists 0:0fdadbc3d852 1327 if (res == FS_OK) {
embeddedartists 0:0fdadbc3d852 1328 if (strlen(filename) > HEADER_FNAME_STRLEN) {
embeddedartists 0:0fdadbc3d852 1329 // Filename is too long
embeddedartists 0:0fdadbc3d852 1330 res = FS_ERR_INVALID_PARAM;
embeddedartists 0:0fdadbc3d852 1331 }
embeddedartists 0:0fdadbc3d852 1332 }
embeddedartists 0:0fdadbc3d852 1333 if (res == FS_OK) {
embeddedartists 0:0fdadbc3d852 1334 // Handle truncation by silently deleting the file before
embeddedartists 0:0fdadbc3d852 1335 // attempting to open it
embeddedartists 0:0fdadbc3d852 1336 if (flags & O_TRUNC) {
embeddedartists 0:0fdadbc3d852 1337 remove(filename);
embeddedartists 0:0fdadbc3d852 1338 }
embeddedartists 0:0fdadbc3d852 1339 }
embeddedartists 0:0fdadbc3d852 1340 if (res == FS_OK) {
embeddedartists 0:0fdadbc3d852 1341 fileHandle_t fh = {0,0,0};
embeddedartists 0:0fdadbc3d852 1342 res = qspifs_findFile(filename, &fh);
embeddedartists 0:0fdadbc3d852 1343 if ((res == FS_ERR_NO_FILE) && (flags & O_CREAT)) {
embeddedartists 0:0fdadbc3d852 1344 res = qspifs_allocateFile(filename, 1, &fh.tocIdx);
embeddedartists 0:0fdadbc3d852 1345 }
embeddedartists 0:0fdadbc3d852 1346 if (res == FS_OK) {
embeddedartists 0:0fdadbc3d852 1347 res = qspifs_saveTOC();
embeddedartists 0:0fdadbc3d852 1348 }
embeddedartists 0:0fdadbc3d852 1349 if (res == FS_OK) {
embeddedartists 0:0fdadbc3d852 1350 return new QSPIFileHandle(&fh, flags);
embeddedartists 0:0fdadbc3d852 1351 }
embeddedartists 0:0fdadbc3d852 1352 }
embeddedartists 0:0fdadbc3d852 1353 debug_if(QSPI_DBG, "QSPIFS: Failed to open: %d\n", res);
embeddedartists 0:0fdadbc3d852 1354 return NULL;
embeddedartists 0:0fdadbc3d852 1355 }
embeddedartists 0:0fdadbc3d852 1356
embeddedartists 0:0fdadbc3d852 1357 int QSPIFileSystem::remove(const char *filename)
embeddedartists 0:0fdadbc3d852 1358 {
embeddedartists 0:0fdadbc3d852 1359 fileHandle_t fh = {0,0,0};
embeddedartists 0:0fdadbc3d852 1360 fresult res = qspifs_init();
embeddedartists 0:0fdadbc3d852 1361 if (res == FS_OK) {
embeddedartists 0:0fdadbc3d852 1362 res = qspifs_findFile(filename, &fh);
embeddedartists 0:0fdadbc3d852 1363 }
embeddedartists 0:0fdadbc3d852 1364 if (res == FS_OK) {
embeddedartists 0:0fdadbc3d852 1365 qspifs_deleteFile(&fh);
embeddedartists 0:0fdadbc3d852 1366 res = qspifs_saveTOC();
embeddedartists 0:0fdadbc3d852 1367 }
embeddedartists 0:0fdadbc3d852 1368 else if (res == FS_ERR_NO_FILE) {
embeddedartists 0:0fdadbc3d852 1369 // file does not exist so treat it as a successful deletion
embeddedartists 0:0fdadbc3d852 1370 res = FS_OK;
embeddedartists 0:0fdadbc3d852 1371 }
embeddedartists 0:0fdadbc3d852 1372 if (res != FS_OK) {
embeddedartists 0:0fdadbc3d852 1373 debug_if(QSPI_DBG, "QSPIFS: Failed to delete %s: %d\n", filename, res);
embeddedartists 0:0fdadbc3d852 1374 return -1;
embeddedartists 0:0fdadbc3d852 1375 }
embeddedartists 0:0fdadbc3d852 1376 return 0;
embeddedartists 0:0fdadbc3d852 1377 }
embeddedartists 0:0fdadbc3d852 1378
embeddedartists 0:0fdadbc3d852 1379 int QSPIFileSystem::rename(const char *oldname, const char *newname)
embeddedartists 0:0fdadbc3d852 1380 {
embeddedartists 0:0fdadbc3d852 1381 fileHandle_t fhOld = {0,0,0};
embeddedartists 0:0fdadbc3d852 1382 fileHandle_t fhNew = {0,0,0};
embeddedartists 0:0fdadbc3d852 1383
embeddedartists 0:0fdadbc3d852 1384 fresult res = qspifs_init();
embeddedartists 0:0fdadbc3d852 1385 if (res == FS_OK) {
embeddedartists 0:0fdadbc3d852 1386 res = qspifs_findFile(oldname, &fhOld);
embeddedartists 0:0fdadbc3d852 1387 }
embeddedartists 0:0fdadbc3d852 1388 if (res == FS_OK) {
embeddedartists 0:0fdadbc3d852 1389 // Make sure the destination file doesn't exist
embeddedartists 0:0fdadbc3d852 1390 res = qspifs_findFile(newname, &fhNew);
embeddedartists 0:0fdadbc3d852 1391 if (res == FS_OK) {
embeddedartists 0:0fdadbc3d852 1392 res = FS_ERR_FILE_EXIST;
embeddedartists 0:0fdadbc3d852 1393 } else if (res == FS_ERR_NO_FILE) {
embeddedartists 0:0fdadbc3d852 1394 res = FS_OK;
embeddedartists 0:0fdadbc3d852 1395 }
embeddedartists 0:0fdadbc3d852 1396 }
embeddedartists 0:0fdadbc3d852 1397 if (res == FS_OK) {
embeddedartists 0:0fdadbc3d852 1398 int numNeededBlocks = 1 + ((fhOld.size + HEADER_LEN) / ERASE_SIZE);
embeddedartists 0:0fdadbc3d852 1399 res = qspifs_allocateFile(newname, numNeededBlocks, &fhNew.tocIdx);
embeddedartists 0:0fdadbc3d852 1400 if (res == FS_OK) {
embeddedartists 0:0fdadbc3d852 1401 const uint8_t* pData = (const uint8_t*)(SPIFI_MEM_BASE + fhOld.tocIdx*ERASE_SIZE + HEADER_LEN);
embeddedartists 0:0fdadbc3d852 1402 res = qspifs_write(&fhNew, pData, fhOld.size);
embeddedartists 0:0fdadbc3d852 1403 if (res == FS_OK) {
embeddedartists 0:0fdadbc3d852 1404 qspifs_deleteFile(&fhOld);
embeddedartists 0:0fdadbc3d852 1405 } else {
embeddedartists 0:0fdadbc3d852 1406 qspifs_deleteFile(&fhNew);
embeddedartists 0:0fdadbc3d852 1407 }
embeddedartists 0:0fdadbc3d852 1408 }
embeddedartists 0:0fdadbc3d852 1409 qspifs_saveTOC();
embeddedartists 0:0fdadbc3d852 1410 }
embeddedartists 0:0fdadbc3d852 1411 if (res != FS_OK) {
embeddedartists 0:0fdadbc3d852 1412 debug_if(QSPI_DBG, "QSPIFS: Failed to rename '%s' to '%s': %d\n", oldname, newname, res);
embeddedartists 0:0fdadbc3d852 1413 return -1;
embeddedartists 0:0fdadbc3d852 1414 }
embeddedartists 0:0fdadbc3d852 1415 return 0;
embeddedartists 0:0fdadbc3d852 1416 }
embeddedartists 0:0fdadbc3d852 1417
embeddedartists 0:0fdadbc3d852 1418 DirHandle *QSPIFileSystem::opendir(const char *name)
embeddedartists 0:0fdadbc3d852 1419 {
embeddedartists 0:0fdadbc3d852 1420 FileHandle* fh = open(name, O_RDONLY);
embeddedartists 0:0fdadbc3d852 1421 if (fh != NULL) {
embeddedartists 0:0fdadbc3d852 1422 // Attempting to open a file as a dir
embeddedartists 0:0fdadbc3d852 1423 delete fh;
embeddedartists 0:0fdadbc3d852 1424 return NULL;
embeddedartists 0:0fdadbc3d852 1425 }
embeddedartists 0:0fdadbc3d852 1426
embeddedartists 0:0fdadbc3d852 1427 // printf("opendir: name '%s'\n", name);
embeddedartists 0:0fdadbc3d852 1428 if (strlen(name) <= HEADER_DNAME_MAXLEN) {
embeddedartists 0:0fdadbc3d852 1429 return QSPIDirHandle::openDir(name);
embeddedartists 0:0fdadbc3d852 1430 }
embeddedartists 0:0fdadbc3d852 1431 return NULL;
embeddedartists 0:0fdadbc3d852 1432 }
embeddedartists 0:0fdadbc3d852 1433
embeddedartists 0:0fdadbc3d852 1434 int QSPIFileSystem::mkdir(const char *name, mode_t mode)
embeddedartists 0:0fdadbc3d852 1435 {
embeddedartists 0:0fdadbc3d852 1436 // Creating folders is always successful as there are no folders in this filesystem
embeddedartists 0:0fdadbc3d852 1437 return 0;
embeddedartists 0:0fdadbc3d852 1438 }
embeddedartists 0:0fdadbc3d852 1439
embeddedartists 0:0fdadbc3d852 1440 int QSPIFileSystem::format(unsigned int fsSizeInMB)
embeddedartists 0:0fdadbc3d852 1441 {
embeddedartists 0:0fdadbc3d852 1442 fresult res = qspifs_init();
embeddedartists 0:0fdadbc3d852 1443 if (res == FS_OK || res == FS_ERR_NOT_FORMATTED) {
embeddedartists 0:0fdadbc3d852 1444 if (((fsSizeInMB<<20) > memInfo.memSize) || (fsSizeInMB < 1)) {
embeddedartists 0:0fdadbc3d852 1445 debug_if(QSPI_DBG, "QSPIFS: Failed to format to size %d MByte: error %d\n", fsSizeInMB, res);
embeddedartists 0:0fdadbc3d852 1446 return -1;
embeddedartists 0:0fdadbc3d852 1447 }
embeddedartists 0:0fdadbc3d852 1448 activeTOC = -1;
embeddedartists 0:0fdadbc3d852 1449 res = qspifs_format(memInfo.memSize - (fsSizeInMB<<20));
embeddedartists 0:0fdadbc3d852 1450 }
embeddedartists 0:0fdadbc3d852 1451
embeddedartists 0:0fdadbc3d852 1452 if (res != FS_OK) {
embeddedartists 0:0fdadbc3d852 1453 debug_if(QSPI_DBG, "QSPIFS: Failed to format: %d\n", res);
embeddedartists 0:0fdadbc3d852 1454 return -1;
embeddedartists 0:0fdadbc3d852 1455 }
embeddedartists 0:0fdadbc3d852 1456 return 0;
embeddedartists 0:0fdadbc3d852 1457 }
embeddedartists 0:0fdadbc3d852 1458
embeddedartists 0:0fdadbc3d852 1459 bool QSPIFileSystem::isformatted()
embeddedartists 0:0fdadbc3d852 1460 {
embeddedartists 0:0fdadbc3d852 1461 fresult res = qspifs_init();
embeddedartists 0:0fdadbc3d852 1462 if (res == FS_OK) {
embeddedartists 0:0fdadbc3d852 1463 return true;
embeddedartists 0:0fdadbc3d852 1464 } else if (res == FS_ERR_NOT_FORMATTED) {
embeddedartists 0:0fdadbc3d852 1465 return false;
embeddedartists 0:0fdadbc3d852 1466 }
embeddedartists 0:0fdadbc3d852 1467 debug_if(QSPI_DBG, "QSPIFS: Failed to detect status: %d\n", res);
embeddedartists 0:0fdadbc3d852 1468 return false;
embeddedartists 0:0fdadbc3d852 1469 }
embeddedartists 0:0fdadbc3d852 1470
embeddedartists 0:0fdadbc3d852 1471 bool QSPIFileSystem::getMemoryBoundaries(uint32_t* pStartAddr, uint32_t* pEndAddr)
embeddedartists 0:0fdadbc3d852 1472 {
embeddedartists 0:0fdadbc3d852 1473 if (isformatted())
embeddedartists 0:0fdadbc3d852 1474 {
embeddedartists 0:0fdadbc3d852 1475 *pEndAddr = 0x28000000 + memInfo.memSize;
embeddedartists 0:0fdadbc3d852 1476
embeddedartists 0:0fdadbc3d852 1477 // Look at all blocks except for the reserved ones
embeddedartists 0:0fdadbc3d852 1478 for (int i = 0; i < NUM_BLOCKS; i++)
embeddedartists 0:0fdadbc3d852 1479 {
embeddedartists 0:0fdadbc3d852 1480 if (!TOC_IS_RESERVED(TOC[i]))
embeddedartists 0:0fdadbc3d852 1481 {
embeddedartists 0:0fdadbc3d852 1482 // Found first non-reserved erase block, indicating the start of
embeddedartists 0:0fdadbc3d852 1483 // the file system.
embeddedartists 0:0fdadbc3d852 1484 *pStartAddr = SPIFI_MEM_BASE + i*ERASE_SIZE;
embeddedartists 0:0fdadbc3d852 1485 return true;
embeddedartists 0:0fdadbc3d852 1486 }
embeddedartists 0:0fdadbc3d852 1487 }
embeddedartists 0:0fdadbc3d852 1488
embeddedartists 0:0fdadbc3d852 1489 // The entire file system seems to be reserved which should never happen
embeddedartists 0:0fdadbc3d852 1490 // but just in case, report it as beeing 1MB in size.
embeddedartists 0:0fdadbc3d852 1491 *pStartAddr = *pEndAddr - 1024*1024;
embeddedartists 0:0fdadbc3d852 1492 return true;
embeddedartists 0:0fdadbc3d852 1493 }
embeddedartists 0:0fdadbc3d852 1494 return false;
embeddedartists 0:0fdadbc3d852 1495 }
embeddedartists 0:0fdadbc3d852 1496
embeddedartists 0:0fdadbc3d852 1497
embeddedartists 0:0fdadbc3d852 1498
embeddedartists 0:0fdadbc3d852 1499