| 216 | } |
| 217 | |
| 218 | void SerialFlashChip::eraseAll() |
| 219 | { |
| 220 | if (busy) wait(); |
| 221 | uint8_t id[5]; |
| 222 | readID(id); |
| 223 | //Serial.printf("ID: %02X %02X %02X\n", id[0], id[1], id[2]); |
| 224 | if (id[0] == 0x20 && id[2] >= 0x20 && id[2] <= 0x22) { |
| 225 | // Micron's multi-die chips require special die erase commands |
| 226 | // N25Q512A 20 BA 20 2 dies 32 Mbyte/die 65 nm transitors |
| 227 | // N25Q00AA 20 BA 21 4 dies 32 Mbyte/die 65 nm transitors |
| 228 | // MT25QL02GC 20 BA 22 2 dies 128 Mbyte/die 45 nm transitors |
| 229 | uint8_t die_count = 2; |
| 230 | if (id[2] == 0x21) die_count = 4; |
| 231 | uint8_t die_index = flags >> 6; |
| 232 | //Serial.printf("Micron die erase %d\n", die_index); |
| 233 | flags &= 0x3F; |
| 234 | if (die_index >= die_count) return; // all dies erased :-) |
| 235 | uint8_t die_size = 2; // in 16 Mbyte units |
| 236 | if (id[2] == 0x22) die_size = 8; |
| 237 | SPIPORT.beginTransaction(SPICONFIG); |
| 238 | CSASSERT(); |
| 239 | SPIPORT.transfer(0x06); // write enable command |
| 240 | CSRELEASE(); |
| 241 | delayMicroseconds(1); |
| 242 | CSASSERT(); |
| 243 | // die erase command |
| 244 | SPIPORT.transfer(0xC4); |
| 245 | SPIPORT.transfer16((die_index * die_size) << 8); |
| 246 | SPIPORT.transfer16(0x0000); |
| 247 | CSRELEASE(); |
| 248 | //Serial.printf("Micron erase begin\n"); |
| 249 | flags |= (die_index + 1) << 6; |
| 250 | } else { |
| 251 | // All other chips support the bulk erase command |
| 252 | SPIPORT.beginTransaction(SPICONFIG); |
| 253 | CSASSERT(); |
| 254 | // write enable command |
| 255 | SPIPORT.transfer(0x06); |
| 256 | CSRELEASE(); |
| 257 | delayMicroseconds(1); |
| 258 | CSASSERT(); |
| 259 | // bulk erase command |
| 260 | SPIPORT.transfer(0xC7); |
| 261 | CSRELEASE(); |
| 262 | SPIPORT.endTransaction(); |
| 263 | } |
| 264 | busy = 3; |
| 265 | } |
| 266 | |
| 267 | void SerialFlashChip::eraseBlock(uint32_t addr) |
| 268 | { |
nothing calls this directly
no outgoing calls
no test coverage detected