Browse Source

Improve RawHardwareTest

main
PaulStoffregen 9 years ago
parent
commit
6537babe07
1 changed files with 224 additions and 65 deletions
  1. +224
    -65
      examples/RawHardwareTest/RawHardwareTest.ino

+ 224
- 65
examples/RawHardwareTest/RawHardwareTest.ino View File

// RawHardwareTest - Check if a SPI Flash chip is compatible
// with SerialFlash by performing many read and write tests
// to its memory.
//
// The chip should be fully erased before running this test.
// Use the EraseEverything to do a (slow) full chip erase.
//
// Normally you should NOT access the flash memory directly,
// as this test program does. You should create files and
// read and write the files. File creation allocates space
// with program & erase boundaries within the chip, to allow
// reading from any other files while a file is busy writing
// or erasing (if created as erasable).
//
// If you discover an incompatible chip, please report it here:
// https://github.com/PaulStoffregen/SerialFlash/issues
// You MUST post the complete output of this program, and
// the exact part number and manufacturer of the chip.



#include <SerialFlash.h> #include <SerialFlash.h>
#include <SPI.h> #include <SPI.h>


SerialFlashFile file; SerialFlashFile file;


//const unsigned long testIncrement = 4096;
const unsigned long testIncrement = 4194304;
const unsigned long testIncrement = 4096;


void setup() { void setup() {


test(); test();
} }


void print_signature(const unsigned char *data)
{
Serial.print("data=");
for (unsigned char i=0; i < 8; i++) {
Serial.print(data[i]);
Serial.print(" ");
}
Serial.println();
}

void create_signature(unsigned long address, unsigned char *data)
{
data[0] = address >> 24;
data[1] = address >> 16;
data[2] = address >> 8;
data[3] = address;
unsigned long hash = 2166136261ul;
for (unsigned char i=0; i < 4; i++) {
hash ^= data[i];
hash *= 16777619ul;
}
data[4] = hash;
data[5] = hash >> 8;
data[6] = hash >> 16;
data[7] = hash >> 24;
}

bool equal_signatures(const unsigned char *data1, const unsigned char *data2)
{
for (unsigned char i=0; i < 8; i++) {
if (data1[i] != data2[i]) return false;
}
return true;
}



bool test() { bool test() {
unsigned char buf[16], sig[16], erased[16];
unsigned long address, count, chipsize;
unsigned char buf[256], sig[256], buf2[8];
unsigned long address, count, chipsize, blocksize;
unsigned long usec;
bool first; bool first;


// Read the chip identification // Read the chip identification
Serial.print(chipsize); Serial.print(chipsize);
Serial.println(" bytes"); Serial.println(" bytes");
if (chipsize == 0) return false; if (chipsize == 0) return false;

//chipsize = 0x20000;
//Serial.println("erasing a couple small blocks....");
//SerialFlash.eraseBlock(0x00000000);
//SerialFlash.eraseBlock(0x00010000);
//while (!SerialFlash.ready()); // wait

//Serial.println();
//Serial.println("read locations in memory...");
//SerialFlash.read(0x0000000, buf, 12);
//printbuf(buf, 12);
//SerialFlash.read(0x1000000, buf, 12);
//printbuf(buf, 12);
//SerialFlash.read(0x2000000, buf, 12);
//printbuf(buf, 12);
//SerialFlash.read(0x3000000, buf, 12);
//printbuf(buf, 12);
Serial.print(" Block Size: ");
blocksize = SerialFlash.blockSize();
Serial.print(blocksize);
Serial.println(" bytes");




// Read the entire chip. Every test location must be // Read the entire chip. Every test location must be
// erased, or have a previously tested signature // erased, or have a previously tested signature
for (unsigned char i=0; i < 8; i++) {
erased[i] = 255;
}
Serial.println(); Serial.println();
Serial.println("Reading Chip..."); Serial.println("Reading Chip...");
memset(buf, 0, sizeof(buf));
memset(sig, 0, sizeof(sig));
memset(buf2, 0, sizeof(buf2));
address = 0; address = 0;
count = 0; count = 0;
first = true; first = true;
//Serial.print(", data = "); //Serial.print(", data = ");
//printbuf(buf, 8); //printbuf(buf, 8);
create_signature(address, sig); create_signature(address, sig);
if (equal_signatures(buf, erased) == false) {
if (is_erased(buf, 8) == false) {
if (equal_signatures(buf, sig) == false) { if (equal_signatures(buf, sig) == false) {
Serial.print(" Previous data found at address "); Serial.print(" Previous data found at address ");
Serial.println(address); Serial.println(address);
printbuf(buf, 8); printbuf(buf, 8);
Serial.print(" correct: "); Serial.print(" correct: ");
printbuf(sig, 8); printbuf(sig, 8);
Serial.print(" erased: ");
printbuf(erased, 8);
return false; return false;
} }
} else { } else {
} }
} }



// Write any signatures that were blank on the original check // Write any signatures that were blank on the original check
if (count > 0) { if (count > 0) {
Serial.println(); Serial.println();
Serial.print("Writing "); Serial.print("Writing ");
Serial.print(count); Serial.print(count);
Serial.println(" signatures"); Serial.println(" signatures");
memset(buf, 0, sizeof(buf));
memset(sig, 0, sizeof(sig));
memset(buf2, 0, sizeof(buf2));
address = 0; address = 0;
first = true; first = true;
while (address < chipsize) { while (address < chipsize) {
SerialFlash.read(address, buf, 8); SerialFlash.read(address, buf, 8);
if (equal_signatures(buf, erased)) {
if (is_erased(buf, 8)) {
create_signature(address, sig); create_signature(address, sig);
Serial.printf("write %08X: data: ", address);
printbuf(sig, 8);
//Serial.printf("write %08X: data: ", address);
//printbuf(sig, 8);
SerialFlash.write(address, sig, 8); SerialFlash.write(address, sig, 8);
while (!SerialFlash.ready()) ; // wait while (!SerialFlash.ready()) ; // wait
SerialFlash.read(address, buf, 8); SerialFlash.read(address, buf, 8);
Serial.println(" all signatures present from prior tests"); Serial.println(" all signatures present from prior tests");
} }



// Read all the signatures again, just to be sure // Read all the signatures again, just to be sure
// checks prior writing didn't corrupt any other data
Serial.println(); Serial.println();
Serial.println("Double Checking All Signatures:"); Serial.println("Double Checking All Signatures:");
memset(buf, 0, sizeof(buf));
memset(sig, 0, sizeof(sig));
memset(buf2, 0, sizeof(buf2));
count = 0; count = 0;
address = 0; address = 0;
first = true; first = true;
Serial.print(count); Serial.print(count);
Serial.println(" signatures read ok"); Serial.println(" signatures read ok");



// Read pairs of adjacent signatures // Read pairs of adjacent signatures
// check read works across boundaries
Serial.println(); Serial.println();
Serial.println("Checking Signature Pairs"); Serial.println("Checking Signature Pairs");
memset(buf, 0, sizeof(buf));
memset(sig, 0, sizeof(sig));
memset(buf2, 0, sizeof(buf2));
count = 0; count = 0;
address = testIncrement - 8; address = testIncrement - 8;
first = true; first = true;
Serial.println(" signature pairs read ok"); Serial.println(" signature pairs read ok");




// Write data and read while write in progress
Serial.println();
Serial.println("Checking Read-While-Write (Program Suspend)");
address = 256;
while (address < chipsize) { // find a blank space
SerialFlash.read(address, buf, 256);
if (is_erased(buf, 256)) break;
address = address + 256;
}
if (address >= chipsize) {
Serial.println(" error, unable to find any blank space!");
return false;
}
for (int i=0; i < 256; i += 8) {
create_signature(address + i, sig + i);
}
Serial.print(" write 256 bytes at ");
Serial.println(address);
Serial.flush();
SerialFlash.write(address, sig, 256);
usec = micros();
if (SerialFlash.ready()) {
Serial.println(" error, chip did not become busy after write");
return false;
}
SerialFlash.read(0, buf2, 8); // read while busy writing
while (!SerialFlash.ready()) ; // wait
usec = micros() - usec;
Serial.print(" write time was ");
Serial.print(usec);
Serial.println(" microseconds.");
SerialFlash.read(address, buf, 256);
if (memcmp(buf, sig, 256) != 0) {
Serial.println(" error writing to flash");
Serial.print(" Read this: ");
printbuf(buf, 256);
Serial.print(" Expected: ");
printbuf(sig, 256);
return false;
}
create_signature(0, sig);
if (memcmp(buf2, sig, 8) != 0) {
Serial.println(" error, incorrect read while writing");
Serial.print(" Read this: ");
printbuf(buf2, 256);
Serial.print(" Expected: ");
printbuf(sig, 256);
return false;
}
Serial.print(" read-while-writing: ");
printbuf(buf2, 8);
Serial.println(" test passed, good read while writing");



// Erase a block and read while erase in progress
if (chipsize >= 262144 + blocksize + testIncrement) {
Serial.println();
Serial.println("Checking Read-While-Erase (Erase Suspend)");
memset(buf, 0, sizeof(buf));
memset(sig, 0, sizeof(sig));
memset(buf2, 0, sizeof(buf2));
SerialFlash.eraseBlock(262144);
usec = micros();
delayMicroseconds(50);
if (SerialFlash.ready()) {
Serial.println(" error, chip did not become busy after erase");
return false;
}
SerialFlash.read(0, buf2, 8); // read while busy writing
while (!SerialFlash.ready()) ; // wait
usec = micros() - usec;
Serial.print(" erase time was ");
Serial.print(usec);
Serial.println(" microseconds.");
// read all signatures, check ones in this block got
// erased, and all the others are still intact
address = 0;
first = true;
while (address < chipsize) {
SerialFlash.read(address, buf, 8);
if (address >= 262144 && address < 262144 + blocksize) {
if (is_erased(buf, 8) == false) {
Serial.print(" error in erasing at ");
Serial.println(address);
Serial.print(" Read this: ");
printbuf(buf, 8);
return false;
}
} else {
create_signature(address, sig);
if (equal_signatures(buf, sig) == false) {
Serial.print(" error in signature at ");
Serial.println(address);
Serial.print(" Read this: ");
printbuf(buf, 8);
Serial.print(" Expected: ");
printbuf(sig, 8);
return false;
}
}
if (first) {
address = address + (testIncrement - 8);
first = false;
} else {
address = address + 8;
first = true;
}
}
Serial.print(" erase correctly erased ");
Serial.print(blocksize);
Serial.println(" bytes");
// now check if the data we read during erase is good
create_signature(0, sig);
if (memcmp(buf2, sig, 8) != 0) {
Serial.println(" error, incorrect read while erasing");
Serial.print(" Read this: ");
printbuf(buf2, 256);
Serial.print(" Expected: ");
printbuf(sig, 256);
return false;
}
Serial.print(" read-while-erasing: ");
printbuf(buf2, 8);
Serial.println(" test passed, good read while erasing");

} else {
Serial.println("Skip Read-While-Erase, this chip is too small");
}







return "(unknown chip)"; return "(unknown chip)";
} }


void print_signature(const unsigned char *data)
{
Serial.print("data=");
for (unsigned char i=0; i < 8; i++) {
Serial.print(data[i]);
Serial.print(" ");
}
Serial.println();
}

void create_signature(unsigned long address, unsigned char *data)
{
data[0] = address >> 24;
data[1] = address >> 16;
data[2] = address >> 8;
data[3] = address;
unsigned long hash = 2166136261ul;
for (unsigned char i=0; i < 4; i++) {
hash ^= data[i];
hash *= 16777619ul;
}
data[4] = hash;
data[5] = hash >> 8;
data[6] = hash >> 16;
data[7] = hash >> 24;
}

bool equal_signatures(const unsigned char *data1, const unsigned char *data2)
{
for (unsigned char i=0; i < 8; i++) {
if (data1[i] != data2[i]) return false;
}
return true;
}

bool is_erased(const unsigned char *data, unsigned int len)
{
while (len > 0) {
if (*data++ != 255) return false;
len = len - 1;
}
return true;
}



void printbuf(const void *buf, uint32_t len) void printbuf(const void *buf, uint32_t len)
{ {

Loading…
Cancel
Save