Browse Source

Fix program/erase suspend on Micron chips

main
PaulStoffregen 10 years ago
parent
commit
30659694ce
1 changed files with 43 additions and 11 deletions
  1. +43
    -11
      SerialFlashChip.cpp

+ 43
- 11
SerialFlashChip.cpp View File

void SerialFlashChip::read(uint32_t addr, void *buf, 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, f;
uint8_t b, f, status;


memset(p, 0, len); memset(p, 0, len);
f = flags; f = flags;
SPI.beginTransaction(SPICONFIG);
b = busy; b = busy;
if (b) { 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 // 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
SPI.beginTransaction(SPICONFIG);
CSASSERT();
SPI.transfer(0x06); // write enable (Micron req'd)
CSRELEASE();
delayMicroseconds(1);
CSASSERT(); CSASSERT();
SPI.transfer(0x75); // Suspend program/erase SPI.transfer(0x75); // Suspend program/erase
CSRELEASE(); 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 { } 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 { do {
uint32_t rdlen = len; uint32_t rdlen = len;
if (f & FLAG_MULTI_DIE) { if (f & FLAG_MULTI_DIE) {
addr += rdlen; addr += rdlen;
len -= rdlen; len -= rdlen;
} while (len > 0); } while (len > 0);
SPI.endTransaction();
if (b) { if (b) {
SPI.beginTransaction(SPICONFIG);
CSASSERT();
SPI.transfer(0x06); // write enable (Micro req'd)
CSRELEASE();
delayMicroseconds(1);
CSASSERT(); CSASSERT();
SPI.transfer(0x7A); // Resume program/erase SPI.transfer(0x7A); // Resume program/erase
CSRELEASE(); CSRELEASE();
SPI.endTransaction();
} }
SPI.endTransaction();
} }


void SerialFlashChip::write(uint32_t addr, const void *buf, uint32_t len) void SerialFlashChip::write(uint32_t addr, const void *buf, uint32_t len)

Loading…
Cancel
Save