port of teensy SerialFlash library for SPI serial flash like winbond from https://github.com/PaulStoffregen/SerialFlash

Dependents:   spiserialtst

Committer:
manitou
Date:
Thu Apr 14 12:05:15 2016 +0000
Revision:
0:e5c9fd5789d7
initial port of teensy SerialFlash library

Who changed what in which revision?

UserRevisionLine numberNew contents of line
manitou 0:e5c9fd5789d7 1 /* SerialFlash Library - for filesystem-like access to SPI Serial Flash memory
manitou 0:e5c9fd5789d7 2 * https://github.com/PaulStoffregen/SerialFlash
manitou 0:e5c9fd5789d7 3 * Copyright (C) 2015, Paul Stoffregen, paul@pjrc.com
manitou 0:e5c9fd5789d7 4 *
manitou 0:e5c9fd5789d7 5 * Development of this library was funded by PJRC.COM, LLC by sales of Teensy.
manitou 0:e5c9fd5789d7 6 * Please support PJRC's efforts to develop open source software by purchasing
manitou 0:e5c9fd5789d7 7 * Teensy or other genuine PJRC products.
manitou 0:e5c9fd5789d7 8 *
manitou 0:e5c9fd5789d7 9 * Permission is hereby granted, free of charge, to any person obtaining a copy
manitou 0:e5c9fd5789d7 10 * of this software and associated documentation files (the "Software"), to deal
manitou 0:e5c9fd5789d7 11 * in the Software without restriction, including without limitation the rights
manitou 0:e5c9fd5789d7 12 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
manitou 0:e5c9fd5789d7 13 * copies of the Software, and to permit persons to whom the Software is
manitou 0:e5c9fd5789d7 14 * furnished to do so, subject to the following conditions:
manitou 0:e5c9fd5789d7 15 *
manitou 0:e5c9fd5789d7 16 * The above copyright notice, development funding notice, and this permission
manitou 0:e5c9fd5789d7 17 * notice shall be included in all copies or substantial portions of the Software.
manitou 0:e5c9fd5789d7 18 *
manitou 0:e5c9fd5789d7 19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
manitou 0:e5c9fd5789d7 20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
manitou 0:e5c9fd5789d7 21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
manitou 0:e5c9fd5789d7 22 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
manitou 0:e5c9fd5789d7 23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
manitou 0:e5c9fd5789d7 24 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
manitou 0:e5c9fd5789d7 25 * THE SOFTWARE.
manitou 0:e5c9fd5789d7 26 */
manitou 0:e5c9fd5789d7 27 #include "mbed.h"
manitou 0:e5c9fd5789d7 28 #include "SerialFlash.h"
manitou 0:e5c9fd5789d7 29 //#include "util/crc16.h"
manitou 0:e5c9fd5789d7 30
manitou 0:e5c9fd5789d7 31 /* On-chip SerialFlash file allocation data structures:
manitou 0:e5c9fd5789d7 32
manitou 0:e5c9fd5789d7 33 uint32_t signature = 0xFA96554C;
manitou 0:e5c9fd5789d7 34 uint16_t maxfiles
manitou 0:e5c9fd5789d7 35 uint16_t stringssize // div by 4
manitou 0:e5c9fd5789d7 36 uint16_t hashes[maxfiles]
manitou 0:e5c9fd5789d7 37 struct {
manitou 0:e5c9fd5789d7 38 uint32_t file_begin
manitou 0:e5c9fd5789d7 39 uint32_t file_length
manitou 0:e5c9fd5789d7 40 uint16_t string_index // div4
manitou 0:e5c9fd5789d7 41 } fileinfo[maxfiles]
manitou 0:e5c9fd5789d7 42 char strings[stringssize]
manitou 0:e5c9fd5789d7 43
manitou 0:e5c9fd5789d7 44 A 32 bit signature is stored at the beginning of the flash memory.
manitou 0:e5c9fd5789d7 45 If 0xFFFFFFFF is seen, the entire chip should be assumed blank.
manitou 0:e5c9fd5789d7 46 If any value other than 0xFA96554C is found, a different data format
manitou 0:e5c9fd5789d7 47 is stored. This could should refuse to access the flash.
manitou 0:e5c9fd5789d7 48
manitou 0:e5c9fd5789d7 49 The next 4 bytes store number of files and size of the strings
manitou 0:e5c9fd5789d7 50 section, which allow the position of every other item to be found.
manitou 0:e5c9fd5789d7 51 The string section size is the 16 bit integer times 4, which allows
manitou 0:e5c9fd5789d7 52 up to 262140 bytes for string data.
manitou 0:e5c9fd5789d7 53
manitou 0:e5c9fd5789d7 54 An array of 16 bit filename hashes allows for quick linear search
manitou 0:e5c9fd5789d7 55 for potentially matching filenames. A hash value of 0xFFFF indicates
manitou 0:e5c9fd5789d7 56 no file is allocated for the remainder of the array.
manitou 0:e5c9fd5789d7 57
manitou 0:e5c9fd5789d7 58 Following the hashes, and array of 10 byte structs give the location
manitou 0:e5c9fd5789d7 59 and length of the file's actual data, and the offset of its filename
manitou 0:e5c9fd5789d7 60 in the strings section.
manitou 0:e5c9fd5789d7 61
manitou 0:e5c9fd5789d7 62 Strings are null terminated. The remainder of the chip is file data.
manitou 0:e5c9fd5789d7 63 */
manitou 0:e5c9fd5789d7 64
manitou 0:e5c9fd5789d7 65 #define DEFAULT_MAXFILES 600
manitou 0:e5c9fd5789d7 66 #define DEFAULT_STRINGS_SIZE 25560
manitou 0:e5c9fd5789d7 67
manitou 0:e5c9fd5789d7 68
manitou 0:e5c9fd5789d7 69 static uint32_t check_signature(void)
manitou 0:e5c9fd5789d7 70 {
manitou 0:e5c9fd5789d7 71 uint32_t sig[2];
manitou 0:e5c9fd5789d7 72
manitou 0:e5c9fd5789d7 73 SerialFlash.read(0, sig, 8);
manitou 0:e5c9fd5789d7 74 //Serial.printf("sig: %08X %08X\n", sig[0], sig[1]);
manitou 0:e5c9fd5789d7 75 if (sig[0] == 0xFA96554C) return sig[1];
manitou 0:e5c9fd5789d7 76 if (sig[0] == 0xFFFFFFFF) {
manitou 0:e5c9fd5789d7 77 sig[0] = 0xFA96554C;
manitou 0:e5c9fd5789d7 78 sig[1] = ((uint32_t)(DEFAULT_STRINGS_SIZE/4) << 16) | DEFAULT_MAXFILES;
manitou 0:e5c9fd5789d7 79 SerialFlash.write(0, sig, 8);
manitou 0:e5c9fd5789d7 80 while (!SerialFlash.ready()) ; // TODO: timeout
manitou 0:e5c9fd5789d7 81 SerialFlash.read(0, sig, 8);
manitou 0:e5c9fd5789d7 82 if (sig[0] == 0xFA96554C) return sig[1];
manitou 0:e5c9fd5789d7 83 }
manitou 0:e5c9fd5789d7 84 return 0;
manitou 0:e5c9fd5789d7 85 }
manitou 0:e5c9fd5789d7 86
manitou 0:e5c9fd5789d7 87 static uint16_t filename_hash(const char *filename)
manitou 0:e5c9fd5789d7 88 {
manitou 0:e5c9fd5789d7 89 // http://isthe.com/chongo/tech/comp/fnv/
manitou 0:e5c9fd5789d7 90 uint32_t hash = 2166136261;
manitou 0:e5c9fd5789d7 91 const char *p;
manitou 0:e5c9fd5789d7 92
manitou 0:e5c9fd5789d7 93 for (p=filename; *p; p++) {
manitou 0:e5c9fd5789d7 94 hash ^= *p;
manitou 0:e5c9fd5789d7 95 hash *= 16777619;
manitou 0:e5c9fd5789d7 96 }
manitou 0:e5c9fd5789d7 97 hash = (hash % (uint32_t)0xFFFE) + 1; // all values except 0000 & FFFF
manitou 0:e5c9fd5789d7 98 return hash;
manitou 0:e5c9fd5789d7 99 }
manitou 0:e5c9fd5789d7 100
manitou 0:e5c9fd5789d7 101 static bool filename_compare(const char *filename, uint32_t straddr)
manitou 0:e5c9fd5789d7 102 {
manitou 0:e5c9fd5789d7 103 unsigned int i;
manitou 0:e5c9fd5789d7 104 const char *p;
manitou 0:e5c9fd5789d7 105 char buf[16];
manitou 0:e5c9fd5789d7 106
manitou 0:e5c9fd5789d7 107 p = filename;
manitou 0:e5c9fd5789d7 108 while (1) {
manitou 0:e5c9fd5789d7 109 SerialFlash.read(straddr, buf, sizeof(buf));
manitou 0:e5c9fd5789d7 110 straddr += sizeof(buf);
manitou 0:e5c9fd5789d7 111 for (i=0; i < sizeof(buf); i++) {
manitou 0:e5c9fd5789d7 112 if (*p++ != buf[i]) return false;
manitou 0:e5c9fd5789d7 113 if (buf[i] == 0) return true;
manitou 0:e5c9fd5789d7 114 }
manitou 0:e5c9fd5789d7 115 }
manitou 0:e5c9fd5789d7 116 }
manitou 0:e5c9fd5789d7 117
manitou 0:e5c9fd5789d7 118 #if 0
manitou 0:e5c9fd5789d7 119 void pbuf(const void *buf, uint32_t len)
manitou 0:e5c9fd5789d7 120 {
manitou 0:e5c9fd5789d7 121 const uint8_t *p = (const uint8_t *)buf;
manitou 0:e5c9fd5789d7 122 do {
manitou 0:e5c9fd5789d7 123 Serial.printf("%02X ", *p++);
manitou 0:e5c9fd5789d7 124 } while (--len > 0);
manitou 0:e5c9fd5789d7 125 Serial.println();
manitou 0:e5c9fd5789d7 126 }
manitou 0:e5c9fd5789d7 127 #endif
manitou 0:e5c9fd5789d7 128
manitou 0:e5c9fd5789d7 129 SerialFlashFile SerialFlashChip::open(const char *filename)
manitou 0:e5c9fd5789d7 130 {
manitou 0:e5c9fd5789d7 131 uint32_t maxfiles, straddr;
manitou 0:e5c9fd5789d7 132 uint16_t hash, hashtable[8];
manitou 0:e5c9fd5789d7 133 uint32_t i, n, index=0;
manitou 0:e5c9fd5789d7 134 uint32_t buf[3];
manitou 0:e5c9fd5789d7 135 SerialFlashFile file;
manitou 0:e5c9fd5789d7 136
manitou 0:e5c9fd5789d7 137 maxfiles = check_signature();
manitou 0:e5c9fd5789d7 138 //Serial.printf("sig: %08X\n", maxfiles);
manitou 0:e5c9fd5789d7 139 if (!maxfiles) return file;
manitou 0:e5c9fd5789d7 140 maxfiles &= 0xFFFF;
manitou 0:e5c9fd5789d7 141 hash = filename_hash(filename);
manitou 0:e5c9fd5789d7 142 //Serial.printf("hash %04X for \"%s\"\n", hash, filename);
manitou 0:e5c9fd5789d7 143 while (index < maxfiles) {
manitou 0:e5c9fd5789d7 144 n = 8;
manitou 0:e5c9fd5789d7 145 if (n > maxfiles - index) n = maxfiles - index;
manitou 0:e5c9fd5789d7 146 SerialFlash.read(8 + index * 2, hashtable, n * 2);
manitou 0:e5c9fd5789d7 147 //Serial.printf(" read %u: ", 8 + index * 2);
manitou 0:e5c9fd5789d7 148 //pbuf(hashtable, n * 2);
manitou 0:e5c9fd5789d7 149 for (i=0; i < n; i++) {
manitou 0:e5c9fd5789d7 150 if (hashtable[i] == hash) {
manitou 0:e5c9fd5789d7 151 //Serial.printf(" hash match at index %u\n", index+i);
manitou 0:e5c9fd5789d7 152 buf[2] = 0;
manitou 0:e5c9fd5789d7 153 SerialFlash.read(8 + maxfiles * 2 + (index+i) * 10, buf, 10);
manitou 0:e5c9fd5789d7 154
manitou 0:e5c9fd5789d7 155 //Serial.printf(" maxf=%d, index=%d, i=%d\n", maxfiles, index, i);
manitou 0:e5c9fd5789d7 156 //Serial.printf(" read %u: ", 8 + maxfiles * 2 + (index+i) * 10);
manitou 0:e5c9fd5789d7 157 //pbuf(buf, 10);
manitou 0:e5c9fd5789d7 158 straddr = 8 + maxfiles * 12 + buf[2] * 4;
manitou 0:e5c9fd5789d7 159 //Serial.printf(" straddr = %u\n", straddr);
manitou 0:e5c9fd5789d7 160 if (filename_compare(filename, straddr)) {
manitou 0:e5c9fd5789d7 161 //Serial.printf(" match!\n");
manitou 0:e5c9fd5789d7 162 //Serial.printf(" addr = %u\n", buf[0]);
manitou 0:e5c9fd5789d7 163 //Serial.printf(" len = %u\n", buf[1]);
manitou 0:e5c9fd5789d7 164 file.address = buf[0];
manitou 0:e5c9fd5789d7 165 file.length = buf[1];
manitou 0:e5c9fd5789d7 166 file.offset = 0;
manitou 0:e5c9fd5789d7 167 file.dirindex = index + i;
manitou 0:e5c9fd5789d7 168 return file;
manitou 0:e5c9fd5789d7 169 }
manitou 0:e5c9fd5789d7 170 } else if (hashtable[i] == 0xFFFF) {
manitou 0:e5c9fd5789d7 171 return file;
manitou 0:e5c9fd5789d7 172 }
manitou 0:e5c9fd5789d7 173 }
manitou 0:e5c9fd5789d7 174 index += n;
manitou 0:e5c9fd5789d7 175 }
manitou 0:e5c9fd5789d7 176 return file;
manitou 0:e5c9fd5789d7 177 }
manitou 0:e5c9fd5789d7 178
manitou 0:e5c9fd5789d7 179 bool SerialFlashChip::exists(const char *filename)
manitou 0:e5c9fd5789d7 180 {
manitou 0:e5c9fd5789d7 181 SerialFlashFile file = open(filename);
manitou 0:e5c9fd5789d7 182 return (bool)file;
manitou 0:e5c9fd5789d7 183 }
manitou 0:e5c9fd5789d7 184
manitou 0:e5c9fd5789d7 185 bool SerialFlashChip::remove(const char *filename)
manitou 0:e5c9fd5789d7 186 {
manitou 0:e5c9fd5789d7 187 SerialFlashFile file = open(filename);
manitou 0:e5c9fd5789d7 188 return remove(file);
manitou 0:e5c9fd5789d7 189 }
manitou 0:e5c9fd5789d7 190
manitou 0:e5c9fd5789d7 191 bool SerialFlashChip::remove(SerialFlashFile &file)
manitou 0:e5c9fd5789d7 192 {
manitou 0:e5c9fd5789d7 193 // To "remove" a file, we simply zero its hash in the lookup
manitou 0:e5c9fd5789d7 194 // table, so it can't be found by open(). The space on the
manitou 0:e5c9fd5789d7 195 // flash memory is not freed.
manitou 0:e5c9fd5789d7 196 if (!file) return false;
manitou 0:e5c9fd5789d7 197 uint16_t hash;
manitou 0:e5c9fd5789d7 198 SerialFlash.read(8 + file.dirindex * 2, &hash, 2);
manitou 0:e5c9fd5789d7 199 //Serial.printf("remove hash %04X at %d index\n", hash, file.dirindex);
manitou 0:e5c9fd5789d7 200 hash ^= 0xFFFF; // write zeros to all ones
manitou 0:e5c9fd5789d7 201 SerialFlash.write(8 + file.dirindex * 2, &hash, 2);
manitou 0:e5c9fd5789d7 202 while (!SerialFlash.ready()) ; // wait... TODO: timeout
manitou 0:e5c9fd5789d7 203 SerialFlash.read(8 + file.dirindex * 2, &hash, 2);
manitou 0:e5c9fd5789d7 204 if (hash != 0) {
manitou 0:e5c9fd5789d7 205 //Serial.printf("remove failed, hash %04X\n", hash);
manitou 0:e5c9fd5789d7 206 return false;
manitou 0:e5c9fd5789d7 207 }
manitou 0:e5c9fd5789d7 208 file.address = 0;
manitou 0:e5c9fd5789d7 209 file.length = 0;
manitou 0:e5c9fd5789d7 210 return true;
manitou 0:e5c9fd5789d7 211 }
manitou 0:e5c9fd5789d7 212
manitou 0:e5c9fd5789d7 213 static uint32_t find_first_unallocated_file_index(uint32_t maxfiles)
manitou 0:e5c9fd5789d7 214 {
manitou 0:e5c9fd5789d7 215 uint16_t hashtable[8];
manitou 0:e5c9fd5789d7 216 uint32_t i, n, index=0;
manitou 0:e5c9fd5789d7 217
manitou 0:e5c9fd5789d7 218 do {
manitou 0:e5c9fd5789d7 219 n = 8;
manitou 0:e5c9fd5789d7 220 if (index + n > maxfiles) n = maxfiles - index;
manitou 0:e5c9fd5789d7 221 SerialFlash.read(8 + index * 2, hashtable, n * 2);
manitou 0:e5c9fd5789d7 222 for (i=0; i < n; i++) {
manitou 0:e5c9fd5789d7 223 if (hashtable[i] == 0xFFFF) return index + i;
manitou 0:e5c9fd5789d7 224 }
manitou 0:e5c9fd5789d7 225 index += n;
manitou 0:e5c9fd5789d7 226 } while (index < maxfiles);
manitou 0:e5c9fd5789d7 227 return 0xFFFFFFFF;
manitou 0:e5c9fd5789d7 228 }
manitou 0:e5c9fd5789d7 229
manitou 0:e5c9fd5789d7 230 static uint32_t string_length(uint32_t addr)
manitou 0:e5c9fd5789d7 231 {
manitou 0:e5c9fd5789d7 232 char buf[16];
manitou 0:e5c9fd5789d7 233 const char *p;
manitou 0:e5c9fd5789d7 234 uint32_t len=0;
manitou 0:e5c9fd5789d7 235
manitou 0:e5c9fd5789d7 236 while (1) {
manitou 0:e5c9fd5789d7 237 SerialFlash.read(addr, buf, sizeof(buf));
manitou 0:e5c9fd5789d7 238 for (p=buf; p < buf + sizeof(buf); p++) {
manitou 0:e5c9fd5789d7 239 len++;
manitou 0:e5c9fd5789d7 240 if (*p == 0) return len;
manitou 0:e5c9fd5789d7 241 }
manitou 0:e5c9fd5789d7 242 addr += sizeof(buf);
manitou 0:e5c9fd5789d7 243 }
manitou 0:e5c9fd5789d7 244 }
manitou 0:e5c9fd5789d7 245
manitou 0:e5c9fd5789d7 246 // uint32_t signature = 0xFA96554C;
manitou 0:e5c9fd5789d7 247 // uint16_t maxfiles
manitou 0:e5c9fd5789d7 248 // uint16_t stringssize // div by 4
manitou 0:e5c9fd5789d7 249 // uint16_t hashes[maxfiles]
manitou 0:e5c9fd5789d7 250 // struct {
manitou 0:e5c9fd5789d7 251 // uint32_t file_begin
manitou 0:e5c9fd5789d7 252 // uint32_t file_length
manitou 0:e5c9fd5789d7 253 // uint16_t string_index // div 4
manitou 0:e5c9fd5789d7 254 // } fileinfo[maxfiles]
manitou 0:e5c9fd5789d7 255 // char strings[stringssize]
manitou 0:e5c9fd5789d7 256
manitou 0:e5c9fd5789d7 257 bool SerialFlashChip::create(const char *filename, uint32_t length, uint32_t align)
manitou 0:e5c9fd5789d7 258 {
manitou 0:e5c9fd5789d7 259 uint32_t maxfiles, stringsize;
manitou 0:e5c9fd5789d7 260 uint32_t index, buf[3];
manitou 0:e5c9fd5789d7 261 uint32_t address, straddr, len;
manitou 0:e5c9fd5789d7 262 SerialFlashFile file;
manitou 0:e5c9fd5789d7 263
manitou 0:e5c9fd5789d7 264 // check if the file already exists
manitou 0:e5c9fd5789d7 265 if (exists(filename)) return false;
manitou 0:e5c9fd5789d7 266
manitou 0:e5c9fd5789d7 267 // first, get the filesystem parameters
manitou 0:e5c9fd5789d7 268 maxfiles = check_signature();
manitou 0:e5c9fd5789d7 269 if (!maxfiles) return false;
manitou 0:e5c9fd5789d7 270 stringsize = (maxfiles & 0xFFFF0000) >> 14;
manitou 0:e5c9fd5789d7 271 maxfiles &= 0xFFFF;
manitou 0:e5c9fd5789d7 272
manitou 0:e5c9fd5789d7 273 // find the first unused slot for this file
manitou 0:e5c9fd5789d7 274 index = find_first_unallocated_file_index(maxfiles);
manitou 0:e5c9fd5789d7 275 if (index >= maxfiles) return false;
manitou 0:e5c9fd5789d7 276 //Serial.printf("index = %u\n", index);
manitou 0:e5c9fd5789d7 277 // compute where to store the filename and actual data
manitou 0:e5c9fd5789d7 278 straddr = 8 + maxfiles * 12;
manitou 0:e5c9fd5789d7 279 if (index == 0) {
manitou 0:e5c9fd5789d7 280 address = straddr + stringsize;
manitou 0:e5c9fd5789d7 281 } else {
manitou 0:e5c9fd5789d7 282 buf[2] = 0;
manitou 0:e5c9fd5789d7 283 SerialFlash.read(8 + maxfiles * 2 + (index-1) * 10, buf, 10);
manitou 0:e5c9fd5789d7 284 address = buf[0] + buf[1];
manitou 0:e5c9fd5789d7 285 straddr += buf[2] * 4;
manitou 0:e5c9fd5789d7 286 straddr += string_length(straddr);
manitou 0:e5c9fd5789d7 287 straddr = (straddr + 3) & 0x0003FFFC;
manitou 0:e5c9fd5789d7 288 }
manitou 0:e5c9fd5789d7 289 //Serial.printf("straddr = %u\n", straddr);
manitou 0:e5c9fd5789d7 290 //Serial.printf("address = %u\n", address);
manitou 0:e5c9fd5789d7 291 //Serial.printf("length = %u\n", length);
manitou 0:e5c9fd5789d7 292 if (align > 0) {
manitou 0:e5c9fd5789d7 293 // for files aligned to sectors, adjust addr & len
manitou 0:e5c9fd5789d7 294 address += align - 1;
manitou 0:e5c9fd5789d7 295 address /= align;
manitou 0:e5c9fd5789d7 296 address *= align;
manitou 0:e5c9fd5789d7 297 //Serial.printf("align address = %u\n", address);
manitou 0:e5c9fd5789d7 298 length += align - 1;
manitou 0:e5c9fd5789d7 299 length /= align;
manitou 0:e5c9fd5789d7 300 length *= align;
manitou 0:e5c9fd5789d7 301 //Serial.printf("align length = %u\n", length);
manitou 0:e5c9fd5789d7 302 } else {
manitou 0:e5c9fd5789d7 303 // always align every file to a page boundary
manitou 0:e5c9fd5789d7 304 // for predictable write latency and to guarantee
manitou 0:e5c9fd5789d7 305 // write suspend for reading another file can't
manitou 0:e5c9fd5789d7 306 // conflict on the same page (2 files never share
manitou 0:e5c9fd5789d7 307 // a write page).
manitou 0:e5c9fd5789d7 308 address = (address + 255) & 0xFFFFFF00;
manitou 0:e5c9fd5789d7 309 }
manitou 0:e5c9fd5789d7 310 //Serial.printf("address = %u\n", address);
manitou 0:e5c9fd5789d7 311 // last check, if enough space exists...
manitou 0:e5c9fd5789d7 312 len = strlen(filename);
manitou 0:e5c9fd5789d7 313 // TODO: check for enough string space for filename
manitou 0:e5c9fd5789d7 314 uint8_t id[3];
manitou 0:e5c9fd5789d7 315 SerialFlash.readID(id);
manitou 0:e5c9fd5789d7 316 if (address + length > SerialFlash.capacity(id)) return false;
manitou 0:e5c9fd5789d7 317
manitou 0:e5c9fd5789d7 318 SerialFlash.write(straddr, filename, len+1);
manitou 0:e5c9fd5789d7 319 buf[0] = address;
manitou 0:e5c9fd5789d7 320 buf[1] = length;
manitou 0:e5c9fd5789d7 321 buf[2] = (straddr - (8 + maxfiles * 12)) / 4;
manitou 0:e5c9fd5789d7 322 SerialFlash.write(8 + maxfiles * 2 + index * 10, buf, 10);
manitou 0:e5c9fd5789d7 323 //Serial.printf(" write %u: ", 8 + maxfiles * 2 + index * 10);
manitou 0:e5c9fd5789d7 324 //pbuf(buf, 10);
manitou 0:e5c9fd5789d7 325 while (!SerialFlash.ready()) ; // TODO: timeout
manitou 0:e5c9fd5789d7 326
manitou 0:e5c9fd5789d7 327 buf[0] = filename_hash(filename);
manitou 0:e5c9fd5789d7 328 //Serial.printf("hash = %04X\n", buf[0]);
manitou 0:e5c9fd5789d7 329 SerialFlash.write(8 + index * 2, buf, 2);
manitou 0:e5c9fd5789d7 330 while (!SerialFlash.ready()) ; // TODO: timeout
manitou 0:e5c9fd5789d7 331 return true;
manitou 0:e5c9fd5789d7 332 }
manitou 0:e5c9fd5789d7 333
manitou 0:e5c9fd5789d7 334 bool SerialFlashChip::readdir(char *filename, uint32_t strsize, uint32_t &filesize)
manitou 0:e5c9fd5789d7 335 {
manitou 0:e5c9fd5789d7 336 uint32_t maxfiles, index, straddr;
manitou 0:e5c9fd5789d7 337 uint32_t i, n;
manitou 0:e5c9fd5789d7 338 uint32_t buf[2];
manitou 0:e5c9fd5789d7 339 uint16_t hash;
manitou 0:e5c9fd5789d7 340 char str[16], *p=filename;
manitou 0:e5c9fd5789d7 341
manitou 0:e5c9fd5789d7 342 filename[0] = 0;
manitou 0:e5c9fd5789d7 343 maxfiles = check_signature();
manitou 0:e5c9fd5789d7 344 if (!maxfiles) return false;
manitou 0:e5c9fd5789d7 345 maxfiles &= 0xFFFF;
manitou 0:e5c9fd5789d7 346 index = dirindex;
manitou 0:e5c9fd5789d7 347 while (1) {
manitou 0:e5c9fd5789d7 348 if (index >= maxfiles) return false;
manitou 0:e5c9fd5789d7 349 //Serial.printf("readdir, index = %u\n", index);
manitou 0:e5c9fd5789d7 350 SerialFlash.read(8 + index * 2, &hash, 2);
manitou 0:e5c9fd5789d7 351 if (hash != 0) break;
manitou 0:e5c9fd5789d7 352 index++; // skip deleted entries
manitou 0:e5c9fd5789d7 353 }
manitou 0:e5c9fd5789d7 354 dirindex = index + 1;
manitou 0:e5c9fd5789d7 355 buf[1] = 0;
manitou 0:e5c9fd5789d7 356 SerialFlash.read(8 + 4 + maxfiles * 2 + index * 10, buf, 6);
manitou 0:e5c9fd5789d7 357 if (buf[0] == 0xFFFFFFFF) return false;
manitou 0:e5c9fd5789d7 358 filesize = buf[0];
manitou 0:e5c9fd5789d7 359 straddr = 8 + maxfiles * 12 + buf[1] * 4;
manitou 0:e5c9fd5789d7 360 //Serial.printf(" length = %u\n", buf[0]);
manitou 0:e5c9fd5789d7 361 //Serial.printf(" straddr = %u\n", straddr);
manitou 0:e5c9fd5789d7 362
manitou 0:e5c9fd5789d7 363 while (strsize) {
manitou 0:e5c9fd5789d7 364 n = strsize;
manitou 0:e5c9fd5789d7 365 if (n > sizeof(str)) n = sizeof(str);
manitou 0:e5c9fd5789d7 366 SerialFlash.read(straddr, str, n);
manitou 0:e5c9fd5789d7 367 for (i=0; i < n; i++) {
manitou 0:e5c9fd5789d7 368 *p++ = str[i];
manitou 0:e5c9fd5789d7 369 if (str[i] == 0) {
manitou 0:e5c9fd5789d7 370 //Serial.printf(" name = %s\n", filename);
manitou 0:e5c9fd5789d7 371 return true;
manitou 0:e5c9fd5789d7 372 }
manitou 0:e5c9fd5789d7 373 }
manitou 0:e5c9fd5789d7 374 strsize -= n;
manitou 0:e5c9fd5789d7 375 straddr += n;
manitou 0:e5c9fd5789d7 376 }
manitou 0:e5c9fd5789d7 377 *(p - 1) = 0;
manitou 0:e5c9fd5789d7 378 //Serial.printf(" name(overflow) = %s\n", filename);
manitou 0:e5c9fd5789d7 379 return true;
manitou 0:e5c9fd5789d7 380 }
manitou 0:e5c9fd5789d7 381
manitou 0:e5c9fd5789d7 382
manitou 0:e5c9fd5789d7 383 void SerialFlashFile::erase()
manitou 0:e5c9fd5789d7 384 {
manitou 0:e5c9fd5789d7 385 uint32_t i, blocksize;
manitou 0:e5c9fd5789d7 386
manitou 0:e5c9fd5789d7 387 blocksize = SerialFlash.blockSize();
manitou 0:e5c9fd5789d7 388 if (address & (blocksize - 1)) return; // must begin on a block boundary
manitou 0:e5c9fd5789d7 389 if (length & (blocksize - 1)) return; // must be exact number of blocks
manitou 0:e5c9fd5789d7 390 for (i=0; i < length; i += blocksize) {
manitou 0:e5c9fd5789d7 391 SerialFlash.eraseBlock(address + i);
manitou 0:e5c9fd5789d7 392 }
manitou 0:e5c9fd5789d7 393 }
manitou 0:e5c9fd5789d7 394