111 lines
2.9 KiB
C++
111 lines
2.9 KiB
C++
#include <SPI.h>
|
|
#include <SPIMemory.h>
|
|
|
|
#define FLASH_CS_PIN 4
|
|
SPIFlash flash(FLASH_CS_PIN);
|
|
|
|
void setup() {
|
|
pinMode(LED_BUILTIN, OUTPUT);
|
|
digitalWrite(LED_BUILTIN, LOW);
|
|
|
|
Serial.begin(115200);
|
|
while (!Serial) delay(10);
|
|
|
|
delay(4000); // Allow boot garbage to clear
|
|
digitalWrite(LED_BUILTIN, HIGH);
|
|
|
|
flash.setClock(5000000); // Cap SPI clock speed at 5 MHz for stability
|
|
//flash.error(true); // Enable error reporting for troubleshooting
|
|
|
|
delay(500); // Allow time to adjust
|
|
|
|
if (!flash.begin()) {
|
|
digitalWrite(LED_BUILTIN, LOW);
|
|
Serial.write("ABORTED_DUMP_FAILURE"); // Mark end of failed dump
|
|
// Stop if flash initialization fails and blink error sequence
|
|
blinkError();
|
|
}
|
|
|
|
sendFlashInformation(); // Send flash info before the dump
|
|
delay(4000); // Wait before starting the dump
|
|
Serial.write("START_OF_DUMP\n"); // Mark start of dump
|
|
|
|
dumpFlashContents();
|
|
|
|
// If dumpFlashContents exits, something went wrong and we should blink error sequence
|
|
blinkError();
|
|
}
|
|
|
|
void loop() {
|
|
// Do nothing
|
|
}
|
|
|
|
void sendFlashInformation() {
|
|
Serial.write("START_OF_INFORM\n");
|
|
Serial.print("JEDEC ID: 0x");
|
|
Serial.println(flash.getJEDECID(), HEX);
|
|
Serial.print("Capacity: ");
|
|
Serial.println(flash.getCapacity());
|
|
Serial.print("Max Page: ");
|
|
Serial.println(flash.getMaxPage());
|
|
Serial.write("END_OF_INFORM\n");
|
|
}
|
|
|
|
void dumpFlashContents() {
|
|
const size_t blockSize = 256;
|
|
uint8_t bufferA[blockSize]; // Two buffers, for reading each block twice
|
|
uint8_t bufferB[blockSize];
|
|
uint32_t address = 0;
|
|
|
|
while (address < flash.getCapacity()) {
|
|
bool success = false;
|
|
|
|
// Retry reading the block until both reads match or max retries reached
|
|
for (int retries = 0; retries < 5; retries++) {
|
|
if (flash.readByteArray(address, bufferA, blockSize) && flash.readByteArray(address, bufferB, blockSize)) {
|
|
|
|
// Compare the two buffers
|
|
if (memcmp(bufferA, bufferB, blockSize) == 0) {
|
|
success = true;
|
|
break; // Matching reads, exit retry loop
|
|
}
|
|
}
|
|
}
|
|
|
|
if (success) {
|
|
Serial.write(bufferA, blockSize);
|
|
} else {
|
|
// If unable to get consistent reads, indicate failure and stop
|
|
Serial.write("READ_ERROR_AT_ADDRESS\n");
|
|
Serial.print(address);
|
|
break;
|
|
}
|
|
address += blockSize;
|
|
delay(10);
|
|
}
|
|
|
|
Serial.write("END_OF_DUMP"); // Mark end of dump
|
|
|
|
// Blink builtin led forever (until reset) to indicate finished dumping
|
|
blinkSuccess();
|
|
}
|
|
|
|
void blinkError() {
|
|
// Forever (until reset) blink builtin led in the error sequence
|
|
while (true) {
|
|
digitalWrite(LED_BUILTIN, LOW);
|
|
delay(400);
|
|
digitalWrite(LED_BUILTIN, HIGH);
|
|
delay(400);
|
|
}
|
|
}
|
|
|
|
void blinkSuccess() {
|
|
// Forever (until reset) blink builtin led in the success sequence
|
|
while (true) {
|
|
digitalWrite(LED_BUILTIN, LOW);
|
|
delay(800);
|
|
digitalWrite(LED_BUILTIN, HIGH);
|
|
delay(1500);
|
|
}
|
|
}
|