|
|
@@ -80,28 +80,58 @@ void SerialFlashChip::wait(void) |
|
|
|
void SerialFlashChip::read(uint32_t addr, void *buf, uint32_t len) |
|
|
|
{ |
|
|
|
uint8_t *p = (uint8_t *)buf; |
|
|
|
uint8_t b, f; |
|
|
|
uint8_t b, f, status; |
|
|
|
|
|
|
|
memset(p, 0, len); |
|
|
|
f = flags; |
|
|
|
SPI.beginTransaction(SPICONFIG); |
|
|
|
b = busy; |
|
|
|
if (b) { |
|
|
|
if (b < 3) { |
|
|
|
// read status register ... chip may no longer be busy |
|
|
|
CSASSERT(); |
|
|
|
if (flags & FLAG_STATUS_CMD70) { |
|
|
|
SPI.transfer(0x70); |
|
|
|
status = SPI.transfer(0); |
|
|
|
if ((status & 0x80)) b = 0; |
|
|
|
} else { |
|
|
|
SPI.transfer(0x05); |
|
|
|
status = SPI.transfer(0); |
|
|
|
if (!(status & 1)) b = 0; |
|
|
|
} |
|
|
|
CSRELEASE(); |
|
|
|
if (b == 0) { |
|
|
|
// chip is no longer busy :-) |
|
|
|
busy = 0; |
|
|
|
} else if (b < 3) { |
|
|
|
// TODO: this may not work on Spansion chips |
|
|
|
// which apparently have 2 different suspend |
|
|
|
// commands, for program vs erase |
|
|
|
SPI.beginTransaction(SPICONFIG); |
|
|
|
CSASSERT(); |
|
|
|
SPI.transfer(0x06); // write enable (Micron req'd) |
|
|
|
CSRELEASE(); |
|
|
|
delayMicroseconds(1); |
|
|
|
CSASSERT(); |
|
|
|
SPI.transfer(0x75); // Suspend program/erase |
|
|
|
CSRELEASE(); |
|
|
|
SPI.endTransaction(); |
|
|
|
delayMicroseconds(20); // Tsus = 20us |
|
|
|
if (f & FLAG_STATUS_CMD70) { |
|
|
|
// Micron chips don't actually suspend until flags read |
|
|
|
CSASSERT(); |
|
|
|
SPI.transfer(0x70); |
|
|
|
do { |
|
|
|
status = SPI.transfer(0); |
|
|
|
} while (!(status & 0x80)); |
|
|
|
CSRELEASE(); |
|
|
|
} else { |
|
|
|
delayMicroseconds(20); // Tsus = 20us (Winbond) |
|
|
|
} |
|
|
|
} else { |
|
|
|
wait(); |
|
|
|
b = 0; |
|
|
|
// chip is busy with an operation that can not suspend |
|
|
|
SPI.endTransaction(); // is this a good idea? |
|
|
|
wait(); // should we wait without ending |
|
|
|
b = 0; // the transaction?? |
|
|
|
SPI.beginTransaction(SPICONFIG); |
|
|
|
} |
|
|
|
} |
|
|
|
SPI.beginTransaction(SPICONFIG); |
|
|
|
do { |
|
|
|
uint32_t rdlen = len; |
|
|
|
if (f & FLAG_MULTI_DIE) { |
|
|
@@ -125,14 +155,16 @@ void SerialFlashChip::read(uint32_t addr, void *buf, uint32_t len) |
|
|
|
addr += rdlen; |
|
|
|
len -= rdlen; |
|
|
|
} while (len > 0); |
|
|
|
SPI.endTransaction(); |
|
|
|
if (b) { |
|
|
|
SPI.beginTransaction(SPICONFIG); |
|
|
|
CSASSERT(); |
|
|
|
SPI.transfer(0x06); // write enable (Micro req'd) |
|
|
|
CSRELEASE(); |
|
|
|
delayMicroseconds(1); |
|
|
|
CSASSERT(); |
|
|
|
SPI.transfer(0x7A); // Resume program/erase |
|
|
|
CSRELEASE(); |
|
|
|
SPI.endTransaction(); |
|
|
|
} |
|
|
|
SPI.endTransaction(); |
|
|
|
} |
|
|
|
|
|
|
|
void SerialFlashChip::write(uint32_t addr, const void *buf, uint32_t len) |