Procházet zdrojové kódy

Improve compatibility with large Micron chips

main
PaulStoffregen před 9 roky
rodič
revize
ce3ba93780
3 změnil soubory, kde provedl 267 přidání a 116 odebrání
  1. +11
    -8
      SerialFlash.h
  2. +239
    -93
      SerialFlashChip.cpp
  3. +17
    -15
      SerialFlashDirectory.cpp

+ 11
- 8
SerialFlash.h Zobrazit soubor

{ {
public: public:
static bool begin(); static bool begin();
static uint32_t capacity();
static uint32_t capacity(const uint8_t *id);
static uint32_t blockSize(); static uint32_t blockSize();
static void readID(uint8_t *buf); static void readID(uint8_t *buf);
static void read(void *buf, uint32_t addr, uint32_t len);
static void read(uint32_t addr, void *buf, uint32_t len);
static bool ready(); static bool ready();
static void wait(); static void wait();
static void write(const void *buf, uint32_t addr, uint32_t len);
static void write(uint32_t addr, const void *buf, uint32_t len);
static void eraseAll(); static void eraseAll();
static void eraseBlock(uint32_t addr); static void eraseBlock(uint32_t addr);


static void opendir() { dirindex = 0; } static void opendir() { dirindex = 0; }
static bool readdir(char *filename, uint32_t strsize, uint32_t &filesize); static bool readdir(char *filename, uint32_t strsize, uint32_t &filesize);
private: private:
static uint16_t dirindex; // current position for readdir()
static uint8_t fourbytemode; // 0=use 24 bit address, 1=use 32 bit address
static uint8_t busy; // 0 = ready, 1 = suspendable busy, 2 = busy for realz
static uint16_t dirindex; // current position for readdir()
static uint8_t flags; // chip features
static uint8_t busy; // 0 = ready
// 1 = suspendable program operation
// 2 = suspendable erase operation
// 3 = busy for realz!!
}; };


extern SerialFlashChip SerialFlash; extern SerialFlashChip SerialFlash;
if (offset >= length) return 0; if (offset >= length) return 0;
rdlen = length - offset; rdlen = length - offset;
} }
SerialFlash.read(buf, address + offset, rdlen);
SerialFlash.read(address + offset, buf, rdlen);
offset += rdlen; offset += rdlen;
return rdlen; return rdlen;
} }
if (offset >= length) return 0; if (offset >= length) return 0;
wrlen = length - offset; wrlen = length - offset;
} }
SerialFlash.write(buf, address + offset, wrlen);
SerialFlash.write(address + offset, buf, wrlen);
offset += wrlen; offset += wrlen;
return wrlen; return wrlen;
} }

+ 239
- 93
SerialFlashChip.cpp Zobrazit soubor

#endif #endif


uint16_t SerialFlashChip::dirindex = 0; uint16_t SerialFlashChip::dirindex = 0;
uint8_t SerialFlashChip::fourbytemode = 0;
uint8_t SerialFlashChip::flags = 0;
uint8_t SerialFlashChip::busy = 0; uint8_t SerialFlashChip::busy = 0;


#define FLAG_32BIT_ADDR 0x01 // larger than 16 MByte address
#define FLAG_STATUS_CMD70 0x02 // requires special busy flag check
#define FLAG_DIFF_SUSPEND 0x04 // uses 2 different suspend commands
#define FLAG_MULTI_DIE 0x08 // multiple die, don't read cross 32M barrier
#define FLAG_256K_BLOCKS 0x10 // has 256K erase blocks
#define FLAG_DIE_MASK 0xC0 // top 2 bits count during multi-die erase

void SerialFlashChip::wait(void) void SerialFlashChip::wait(void)
{ {
uint32_t status; uint32_t status;
do {
//Serial.print("wait-");
while (1) {
SPI.beginTransaction(SPICONFIG); SPI.beginTransaction(SPICONFIG);
CSASSERT(); CSASSERT();
status = SPI.transfer16(0x0500);
CSRELEASE();
SPI.endTransaction();
} while ((status & 1));
if (flags & FLAG_STATUS_CMD70) {
// some Micron chips require this different
// command to detect program and erase completion
SPI.transfer(0x70);
status = SPI.transfer(0);
CSRELEASE();
SPI.endTransaction();
//Serial.printf("b=%02x.", status & 0xFF);
if ((status & 0x80)) break;
} else {
// all others work by simply reading the status reg
SPI.transfer(0x05);
status = SPI.transfer(0);
CSRELEASE();
SPI.endTransaction();
//Serial.printf("b=%02x.", status & 0xFF);
if (!(status & 1)) break;
}
}
busy = 0; busy = 0;
//Serial.println();
} }


void SerialFlashChip::read(void *buf, uint32_t addr, uint32_t len)
void SerialFlashChip::read(uint32_t addr, void *buf, uint32_t len)
{ {
uint8_t *p = (uint8_t *)buf; uint8_t *p = (uint8_t *)buf;
uint8_t b;
uint8_t b, f;


memset(p, 0, len); memset(p, 0, len);
f = flags;
b = busy; b = busy;
if (b) { if (b) {
if (b == 1) {
if (b < 3) {
// TODO: this may not work on Spansion chips // TODO: this may not work on Spansion chips
// which apparently have 2 different suspend // which apparently have 2 different suspend
// commands, for program vs erase // commands, for program vs erase
delayMicroseconds(20); // Tsus = 20us delayMicroseconds(20); // Tsus = 20us
} else { } else {
wait(); wait();
b = 0;
} }
} }
SPI.beginTransaction(SPICONFIG); SPI.beginTransaction(SPICONFIG);
CSASSERT();
// TODO: FIFO optimize....
if (fourbytemode) {
SPI.transfer(0x13);
SPI.transfer16(addr >> 16);
SPI.transfer16(addr);
} else {
SPI.transfer16(0x0300 | ((addr >> 16) & 255));
SPI.transfer16(addr);
}
SPI.transfer(p, len);
CSRELEASE();
do {
uint32_t rdlen = len;
if (f & FLAG_MULTI_DIE) {
if ((addr & 0xFE000000) != ((addr + len - 1) & 0xFE000000)) {
rdlen = 0x2000000 - (addr & 0x1FFFFFF);
}
}
CSASSERT();
// TODO: FIFO optimize....
if (f & FLAG_32BIT_ADDR) {
SPI.transfer(0x03);
SPI.transfer16(addr >> 16);
SPI.transfer16(addr);
} else {
SPI.transfer16(0x0300 | ((addr >> 16) & 255));
SPI.transfer16(addr);
}
SPI.transfer(p, rdlen);
CSRELEASE();
p += rdlen;
addr += rdlen;
len -= rdlen;
} while (len > 0);
SPI.endTransaction(); SPI.endTransaction();
if (b == 1) {
if (b) {
SPI.beginTransaction(SPICONFIG); SPI.beginTransaction(SPICONFIG);
CSASSERT(); CSASSERT();
SPI.transfer(0x7A); // Resume program/erase SPI.transfer(0x7A); // Resume program/erase
} }
} }


void SerialFlashChip::write(const void *buf, uint32_t addr, uint32_t len)
void SerialFlashChip::write(uint32_t addr, const void *buf, uint32_t len)
{ {
const uint8_t *p = (const uint8_t *)buf; const uint8_t *p = (const uint8_t *)buf;
uint32_t max, pagelen; uint32_t max, pagelen;


//Serial.println("write");
do { do {
if (busy) wait(); if (busy) wait();
//Serial.printf("pagelen=%d\n", pagelen);
SPI.beginTransaction(SPICONFIG); SPI.beginTransaction(SPICONFIG);
CSASSERT(); CSASSERT();
// write enable command
SPI.transfer(0x06); SPI.transfer(0x06);
CSRELEASE(); CSRELEASE();
//delayMicroseconds(1);
max = 256 - (addr & 0xFF); max = 256 - (addr & 0xFF);
pagelen = (len <= max) ? len : max; pagelen = (len <= max) ? len : max;
len -= pagelen; len -= pagelen;
CSASSERT(); CSASSERT();
if (fourbytemode) {
// TODO: Winbond doesn't implement 0x12 on W25Q256FV
SPI.transfer(0x12);
if (flags & FLAG_32BIT_ADDR) {
//Serial.printf("write 32 bit addr %08X %02X\n", addr, addr >> 24);
SPI.transfer(0x02);
SPI.transfer16(addr >> 16); SPI.transfer16(addr >> 16);
SPI.transfer16(addr); SPI.transfer16(addr);
} else { } else {
SPI.transfer16(0x0200 | ((addr >> 16) & 255)); SPI.transfer16(0x0200 | ((addr >> 16) & 255));
SPI.transfer16(addr); SPI.transfer16(addr);
} }
// program page command
do { do {
SPI.transfer(*p++); SPI.transfer(*p++);
} while (--pagelen > 0); } while (--pagelen > 0);
CSRELEASE(); CSRELEASE();
SPI.endTransaction(); SPI.endTransaction();
busy = 1; busy = 1;
//Serial.printf("busy=%d\n", busy);
} while (len > 0); } while (len > 0);
} }


void SerialFlashChip::eraseAll() void SerialFlashChip::eraseAll()
{ {
if (busy) wait(); if (busy) wait();
SPI.beginTransaction(SPICONFIG);
CSASSERT();
SPI.transfer(0x06);
CSRELEASE();
CSASSERT();
SPI.transfer(0xC7);
CSRELEASE();
SPI.endTransaction();
busy = 2;
uint8_t id[3];
readID(id);
//Serial.printf("ID: %02X %02X %02X\n", id[0], id[1], id[2]);
if (id[0] == 0x20 && id[2] >= 0x20 && id[2] <= 0x22) {
// Micron's multi-die chips require special die erase commands
// N25Q512A 20 BA 20 2 dies 32 Mbyte/die 65 nm transitors
// N25Q00AA 20 BA 21 4 dies 32 Mbyte/die 65 nm transitors
// MT25QL02GC 20 BA 22 2 dies 128 Mbyte/die 45 nm transitors
uint8_t die_count = 2;
if (id[2] == 0x21) die_count = 4;
uint8_t die_index = flags >> 6;
//Serial.printf("Micron die erase %d\n", die_index);
flags &= 0x3F;
if (die_index >= die_count) return; // all dies erased :-)
uint8_t die_size = 2; // in 16 Mbyte units
if (id[2] == 0x22) die_size = 8;
SPI.beginTransaction(SPICONFIG);
CSASSERT();
SPI.transfer(0x06); // write enable command
CSRELEASE();
delayMicroseconds(1);
CSASSERT();
// die erase command
SPI.transfer(0xC4);
SPI.transfer16((die_index * die_size) << 8);
SPI.transfer16(0x0000);
CSRELEASE();
//Serial.printf("Micron erase begin\n");
flags |= (die_index + 1) << 6;
} else {
// All other chips support the bulk erase command
SPI.beginTransaction(SPICONFIG);
CSASSERT();
// write enable command
SPI.transfer(0x06);
CSRELEASE();
delayMicroseconds(1);
CSASSERT();
// bulk erase command
SPI.transfer(0xC7);
CSRELEASE();
SPI.endTransaction();
}
busy = 3;
} }


void SerialFlashChip::eraseBlock(uint32_t addr) void SerialFlashChip::eraseBlock(uint32_t addr)
{ {
uint8_t f = flags;
if (busy) wait(); if (busy) wait();
SPI.beginTransaction(SPICONFIG); SPI.beginTransaction(SPICONFIG);
CSASSERT(); CSASSERT();
if (fourbytemode) {
// TODO: Winbond doesn't implement 0xDC on W25Q256FV
SPI.transfer(0xDC);
SPI.transfer(0x06); // write enable command
CSRELEASE();
delayMicroseconds(1);
CSASSERT();
if (f & FLAG_32BIT_ADDR) {
SPI.transfer(0xD8);
SPI.transfer16(addr >> 16); SPI.transfer16(addr >> 16);
SPI.transfer16(addr); SPI.transfer16(addr);
} else { } else {
} }
CSRELEASE(); CSRELEASE();
SPI.endTransaction(); SPI.endTransaction();
busy = 1;
busy = 2;
} }




if (!busy) return true; if (!busy) return true;
SPI.beginTransaction(SPICONFIG); SPI.beginTransaction(SPICONFIG);
CSASSERT(); CSASSERT();
status = SPI.transfer16(0x0500);
CSRELEASE();
SPI.endTransaction();
if ((status & 1)) return false;
if (flags & FLAG_STATUS_CMD70) {
// some Micron chips require this different
// command to detect program and erase completion
SPI.transfer(0x70);
status = SPI.transfer(0);
CSRELEASE();
SPI.endTransaction();
//Serial.printf("ready=%02x\n", status & 0xFF);
if ((status & 0x80) == 0) return false;
} else {
// all others work by simply reading the status reg
SPI.transfer(0x05);
status = SPI.transfer(0);
CSRELEASE();
SPI.endTransaction();
//Serial.printf("ready=%02x\n", status & 0xFF);
if ((status & 1)) return false;
}
busy = 0; busy = 0;
if (flags & 0xC0) {
// continue a multi-die erase
eraseAll();
return false;
}
return true; return true;
} }




#define ID0_WINBOND 0xEF
#define ID0_SPANSION 0x01
#define ID0_MICRON 0x20
#define ID0_MACRONIX 0xC2
#define ID0_SST 0xBF

//#define FLAG_32BIT_ADDR 0x01 // larger than 16 MByte address
//#define FLAG_STATUS_CMD70 0x02 // requires special busy flag check
//#define FLAG_DIFF_SUSPEND 0x04 // uses 2 different suspend commands
//#define FLAG_256K_BLOCKS 0x10 // has 256K erase blocks

bool SerialFlashChip::begin() bool SerialFlashChip::begin()
{ {
uint8_t id[3];
uint8_t f;
uint32_t size;

SPI.begin(); SPI.begin();
CSCONFIG(); CSCONFIG();
CSRELEASE(); CSRELEASE();
if (capacity() <= 16777216) {
fourbytemode = 0;
} else {
fourbytemode = 1; // chip larger than 16 MByte
// TODO: need to configure for 32 bit address mode
// because Winbond doesn't implement 0x12 & 0xDC
readID(id);
f = 0;
size = capacity(id);
if (size > 16777216) {
// more than 16 Mbyte requires 32 bit addresses
f |= FLAG_32BIT_ADDR;
SPI.beginTransaction(SPICONFIG);
if (id[0] == ID0_SPANSION) {
// spansion uses MSB of bank register
CSASSERT();
SPI.transfer16(0x1780); // bank register write
CSRELEASE();
} else {
// micron & winbond & macronix use command
CSASSERT();
SPI.transfer(0x06); // write enable
CSRELEASE();
delayMicroseconds(1);
CSASSERT();
SPI.transfer(0xB7); // enter 4 byte addr mode
CSRELEASE();
}
SPI.endTransaction();
if (id[0] == ID0_MICRON) f |= FLAG_MULTI_DIE;
}
if (id[0] == ID0_SPANSION) {
// Spansion has separate suspend commands
f |= FLAG_DIFF_SUSPEND;
if (size >= 67108864) {
// Spansion chips >= 512 mbit use 256K sectors
f |= FLAG_256K_BLOCKS;
}
}
if (id[0] == ID0_MICRON) {
// Micron requires busy checks with a different command
f |= FLAG_STATUS_CMD70; // TODO: all or just multi-die chips?
} }
flags = f;
readID(id);
return true; return true;
} }


buf[2] = SPI.transfer(0); // capacity buf[2] = SPI.transfer(0); // capacity
CSRELEASE(); CSRELEASE();
SPI.endTransaction(); SPI.endTransaction();
//Serial.printf("ID: %02X %02X %02X\n", buf[0], buf[1], buf[2]);
} }


uint32_t SerialFlashChip::capacity()
uint32_t SerialFlashChip::capacity(const uint8_t *id)
{ {
uint8_t id[3];
uint32_t n = 1048576; // unknown chips, default to 1 MByte


readID(id);
//Serial.print("capacity ");
//Serial.println(id[3], HEX);
if (id[2] >= 16 && id[2] <= 31) { if (id[2] >= 16 && id[2] <= 31) {
return 1 << id[2];
}
n = 1ul << id[2];
} else
if (id[2] >= 32 && id[2] <= 37) { if (id[2] >= 32 && id[2] <= 37) {
return 1 << (id[2] - 6);
n = 1ul << (id[2] - 6);
} }
return 1048576; // unknown, guess 1 MByte
//Serial.printf("capacity %lu\n", n);
return n;
} }


uint32_t SerialFlashChip::blockSize() uint32_t SerialFlashChip::blockSize()
{ {
uint8_t id[3];

readID(id);
if (id[0] == 1 && id[2] > 0x19) {
// Spansion chips >= 512 mbit use 256K sectors
return 262144;
}
// Spansion chips >= 512 mbit use 256K sectors
if (flags & FLAG_256K_BLOCKS) return 262144;
// everything else seems to have 64K sectors // everything else seems to have 64K sectors
return 65536; return 65536;
} }





/* /*
Chip Uniform Sector Erase Chip Uniform Sector Erase
20/21 52 D8/DC 20/21 52 D8/DC
SST26VF032 4 SST26VF032 4
*/ */


// size sector
// Part Mbit kbyte ID bytes Digikey
// ---- ---- ----- -------- -------
// Winbond W25Q64CV 64 4/32/64 EF 40 17 W25Q128FVSIG-ND
// Winbond W25Q128FV 128 4/32/64 EF 40 18 W25Q128FVSIG-ND
// Winbond W25Q256FV 256 64 EF 40 19
// Spansion S25FL064A 64 01 02 16 ?
// Spansion S25FL127S 128 64 01 20 18 1274-1045-ND
// Spansion S25FL128P 128 64 01 20 18
// Spansion S25FL256S 256 64 01 02 19
// Spansion S25FL512S 512 256 01 02 20
// Macronix MX25L12805D 128 C2 20 18
// Numonyx M25P128 128 20 20 18
// Micron M25P80 8 20 20 14
// Micron N25Q512A 512 4 20 BA 20 557-1569-ND
// Micron N25Q00AA 1024 4/64 20 BA 21 557-1571-5-ND
// Micron MT25QL02GC 2048 4/64 20 BB 22
// SST SST25WF512 0.5 BF 25 01
// SST SST25WF010 1 BF 25 02
// SST SST25WF020 2 BF 25 03
// SST SST25WF040 4 BF 25 04
// SST SST25VF016B 16 BF 25 41
// SST26VF016 BF 26 01
// SST26VF032 BF 26 02
// SST25VF032 32 4/32/64 BF 25 4A
// SST26VF064 64 BF 26 43
// LE25U40CMC 4 4/64 62 06 13


// size sector busy pgm/erase chip
// Part Mbyte kbyte ID bytes cmd suspend erase
// ---- ---- ----- -------- --- ------- -----
// Winbond W25Q64CV 8 64 EF 40 17
// Winbond W25Q128FV 16 64 EF 40 18 05 single 60 & C7
// Winbond W25Q256FV 32 64 EF 40 19
// Spansion S25FL064A 8 ? 01 02 16
// Spansion S25FL127S 16 64 01 20 18 05
// Spansion S25FL128P 16 64 01 20 18
// Spansion S25FL256S 32 64 01 02 19 05 60 & C7
// Spansion S25FL512S 64 256 01 02 20
// Macronix MX25L12805D 16 ? C2 20 18
// Macronix MX66L51235F 64 C2 20 1A
// Numonyx M25P128 16 ? 20 20 18
// Micron M25P80 1 ? 20 20 14
// Micron N25Q128A 16 64 20 BA 18
// Micron N25Q512A 64 ? 20 BA 20 70 single C4 x2
// Micron N25Q00AA 128 64 20 BA 21 single C4 x4
// Micron MT25QL02GC 256 64 20 BA 22 70 C4 x2
// SST SST25WF010 1/8 ? BF 25 02
// SST SST25WF020 1/4 ? BF 25 03
// SST SST25WF040 1/2 ? BF 25 04
// SST SST25VF016B 1 ? BF 25 41
// SST26VF016 ? BF 26 01
// SST26VF032 ? BF 26 02
// SST25VF032 4 64 BF 25 4A
// SST26VF064 8 ? BF 26 43
// LE25U40CMC 1/2 64 62 06 13


SerialFlashChip SerialFlash; SerialFlashChip SerialFlash;

+ 17
- 15
SerialFlashDirectory.cpp Zobrazit soubor

{ {
uint32_t sig[2]; uint32_t sig[2];


SerialFlash.read(sig, 0, 8);
SerialFlash.read(0, sig, 8);
if (sig[0] == 0xFA96554C) return sig[1]; if (sig[0] == 0xFA96554C) return sig[1];
if (sig[0] == 0xFFFFFFFF) { if (sig[0] == 0xFFFFFFFF) {
sig[0] = 0xFA96554C; sig[0] = 0xFA96554C;
sig[1] = ((DEFAULT_STRINGS_SIZE/4) << 16) | DEFAULT_MAXFILES; sig[1] = ((DEFAULT_STRINGS_SIZE/4) << 16) | DEFAULT_MAXFILES;
SerialFlash.write(sig, 0, 8);
SerialFlash.write(0, sig, 8);
while (!SerialFlash.ready()) ; // TODO: timeout while (!SerialFlash.ready()) ; // TODO: timeout
SerialFlash.read(sig, 0, 8);
SerialFlash.read(0, sig, 8);
if (sig[0] == 0xFA96554C) return sig[1]; if (sig[0] == 0xFA96554C) return sig[1];
} }
return 0; return 0;


p = filename; p = filename;
while (1) { while (1) {
SerialFlash.read(buf, straddr, sizeof(buf));
SerialFlash.read(straddr, buf, sizeof(buf));
straddr += sizeof(buf); straddr += sizeof(buf);
for (i=0; i < sizeof(buf); i++) { for (i=0; i < sizeof(buf); i++) {
if (*p++ != buf[i]) return false; if (*p++ != buf[i]) return false;
while (index < maxfiles) { while (index < maxfiles) {
n = 8; n = 8;
if (n > maxfiles - index) n = maxfiles - index; if (n > maxfiles - index) n = maxfiles - index;
SerialFlash.read(hashtable, 8 + index * 2, n * 2);
SerialFlash.read(8 + index * 2, hashtable, n * 2);
for (i=0; i < n; i++) { for (i=0; i < n; i++) {
if (hashtable[i] == hash) { if (hashtable[i] == hash) {
buf[2] = 0; buf[2] = 0;
SerialFlash.read(buf, 8 + maxfiles * 2 + (index+i) * 10, 10);
SerialFlash.read(8 + maxfiles * 2 + (index+i) * 10, buf, 10);
straddr = 8 + maxfiles * 12 + buf[2] * 4; straddr = 8 + maxfiles * 12 + buf[2] * 4;
if (filename_compare(filename, straddr)) { if (filename_compare(filename, straddr)) {
file.address = buf[0]; file.address = buf[0];
do { do {
n = 8; n = 8;
if (index + n > maxfiles) n = maxfiles - index; if (index + n > maxfiles) n = maxfiles - index;
SerialFlash.read(hashtable, 8 + index * 2, n * 2);
SerialFlash.read(8 + index * 2, hashtable, n * 2);
for (i=0; i < n; i++) { for (i=0; i < n; i++) {
if (hashtable[i] == 0xFFFF) return index + i; if (hashtable[i] == 0xFFFF) return index + i;
} }
uint32_t len=0; uint32_t len=0;


while (1) { while (1) {
SerialFlash.read(buf, addr, sizeof(buf));
SerialFlash.read(addr, buf, sizeof(buf));
for (p=buf; p < buf + sizeof(buf); p++) { for (p=buf; p < buf + sizeof(buf); p++) {
if (*p == 0) return len; if (*p == 0) return len;
len++; len++;
address = straddr + stringsize; address = straddr + stringsize;
} else { } else {
buf[2] = 0; buf[2] = 0;
SerialFlash.read(buf, 8 + maxfiles * 2 + (index-1) * 10, 10);
SerialFlash.read(8 + maxfiles * 2 + (index-1) * 10, buf, 10);
address = buf[0] + buf[1]; address = buf[0] + buf[1];
straddr += buf[2] * 4; straddr += buf[2] * 4;
straddr += string_length(straddr); straddr += string_length(straddr);
// last check, if enough space exists... // last check, if enough space exists...
len = strlen(filename); len = strlen(filename);
// TODO: check for enough string space for filename // TODO: check for enough string space for filename
if (address + length > SerialFlash.capacity()) return false;
uint8_t id[3];
SerialFlash.readID(id);
if (address + length > SerialFlash.capacity(id)) return false;


SerialFlash.write(filename, straddr, len+1);
SerialFlash.write(straddr, filename, len+1);
buf[0] = address; buf[0] = address;
buf[1] = length; buf[1] = length;
buf[2] = (straddr - (8 + maxfiles * 12)) / 4; buf[2] = (straddr - (8 + maxfiles * 12)) / 4;
SerialFlash.write(buf, 8 + maxfiles * 2 + index * 10, 10);
SerialFlash.write(8 + maxfiles * 2 + index * 10, buf, 10);
buf[0] = filename_hash(filename); buf[0] = filename_hash(filename);
SerialFlash.write(buf, 8 + index * 2, 2);
SerialFlash.write(8 + index * 2, buf, 2);
while (!SerialFlash.ready()) ; // TODO: timeout while (!SerialFlash.ready()) ; // TODO: timeout
return true; return true;
} }
dirindex = index + 1; dirindex = index + 1;


buf[1] = 0; buf[1] = 0;
SerialFlash.read(buf, 8 + 4 + maxfiles * 2 + index * 10, 6);
SerialFlash.read(8 + 4 + maxfiles * 2 + index * 10, buf, 6);
if (buf[0] == 0xFFFFFFFF) return false; if (buf[0] == 0xFFFFFFFF) return false;
filesize = buf[0]; filesize = buf[0];
straddr = 8 + maxfiles * 12 + buf[1] * 4; straddr = 8 + maxfiles * 12 + buf[1] * 4;
while (strsize) { while (strsize) {
n = strsize; n = strsize;
if (n > sizeof(str)) n = sizeof(str); if (n > sizeof(str)) n = sizeof(str);
SerialFlash.read(str, straddr, n);
SerialFlash.read(straddr, str, n);
for (i=0; i < n; i++) { for (i=0; i < n; i++) {
*p++ = str[i]; *p++ = str[i];
if (str[i] == 0) { if (str[i] == 0) {

Načítá se…
Zrušit
Uložit