#include #include "FS.h" #include "SPIFFS.h" #define CS 5 #define FORMAT false SPIClass * vspi = NULL; SPISettings settings(10000000, MSBFIRST, SPI_MODE0); //SPISettings settings(1000000, MSBFIRST, SPI_MODE0); byte jedec[3]; void readBuffer(uint32_t addr, uint8_t *buff, uint32_t len) { uint8_t ad[3]; uint8_t out; ad[0] = (addr & 0xFF0000) >> 16; ad[1] = (addr & 0x00FF00) >> 8; ad[2] = (addr & 0x0000FF) >> 0; digitalWrite(CS, LOW); vspi->beginTransaction(settings); vspi->transfer(0x03); // Read Data command vspi->transfer(ad[0]); vspi->transfer(ad[1]); vspi->transfer(ad[2]); for (uint32_t i = 0; i < len; i++) { *buff = vspi->transfer(0x00); buff++; } vspi->endTransaction(); digitalWrite(CS, HIGH); } void printHexPad32(uint32_t val) { for (int i = 7; i > 0; i--) { uint32_t v = (1 << (i * 4)); if (val < v) { Serial.print("0"); } else { break; } } Serial.print(val, HEX); } void printHexPad8(uint8_t val) { if (val < 0x10) { Serial.print("0"); } Serial.print(val, HEX); } void printASCII(uint8_t v) { if (v >= 0x20 && v <= 0x7E) { Serial.print((char)v); } else { Serial.print("."); } } void printBuff(uint8_t *buff, uint32_t len, uint32_t mainoffset) { Serial.println("-----------------------------"); for (uint32_t i = 0; i < len; i++) { if (i % 16 == 0) { printHexPad32(mainoffset + i); Serial.print(": "); } printHexPad8(buff[i]); Serial.print(" "); if (i % 16 == 15) { uint32_t off = (i / 16) * 16; for (uint32_t p = 0; p < 16; p++) { printASCII(buff[off+p]); } Serial.println(""); } } Serial.println("-----------------------------"); } #define CHUNK 256 uint8_t databuff[CHUNK]; uint32_t flashSize = 512 * 1024; uint8_t readStatus() { uint8_t status; digitalWrite(CS, LOW); vspi->beginTransaction(settings); vspi->transfer(0x05); status = vspi->transfer(0); vspi->endTransaction(); digitalWrite(CS, HIGH); return status; } void waitReady() { uint8_t status = 1; // Serial.println("Waiting device not BUSY"); while (status) { delay(1); status = readStatus(); status &= 1; // Only first bit } // Serial.println("Device is free!"); } void sectorErase(uint32_t addr) { uint8_t ad[3]; uint8_t out; ad[0] = (addr & 0xFF0000) >> 16; ad[1] = (addr & 0x00FF00) >> 8; ad[2] = (addr & 0x0000FF) >> 0; digitalWrite(CS, LOW); vspi->beginTransaction(settings); vspi->transfer(0x20); // Read Data command vspi->transfer(ad[0]); vspi->transfer(ad[1]); vspi->transfer(ad[2]); vspi->endTransaction(); digitalWrite(CS, HIGH); waitReady(); } #define SRP (1 << 7) #define TB (1 << 5) #define BP2 (1 << 4) #define BP1 (1 << 3) #define BP0 (1 << 2) #define WEL (1 << 1) void unprotect() { writeEnable(); uint8_t ok = 0; while(!ok) { uint8_t status = readStatus(); status &= ~(SRP | TB | BP2 | BP1 | BP0); // Reset protections status &= ~(WEL); // Avoid checking Write Enable that is reseted after operation digitalWrite(CS, HIGH); delay(1); digitalWrite(CS, LOW); vspi->beginTransaction(settings); vspi->transfer(0x01); vspi->transfer(status); vspi->endTransaction(); digitalWrite(CS, HIGH); delay(1); waitReady(); uint8_t status2 = readStatus(); if (status != status2) { Serial.print("Error writting status! Expected "); Serial.print(status, HEX); Serial.print(" got "); Serial.println(status2, HEX); } else { ok = 1; } } } void writeEnable() { // Serial.println("Write Enable"); digitalWrite(CS, LOW); vspi->beginTransaction(settings); vspi->transfer(0x06); vspi->endTransaction(); digitalWrite(CS, HIGH); delay(10); uint8_t status = readStatus(); status &= 2; if (status != 2) { Serial.println("ERROR setting Write Enable!"); } waitReady(); } void chipErase() { writeEnable(); Serial.println("Chip Erase"); digitalWrite(CS, LOW); vspi->beginTransaction(settings); vspi->transfer(0xC7); vspi->endTransaction(); digitalWrite(CS, HIGH); delay(10); waitReady(); } void programPage(uint32_t addr, uint8_t *data) { uint8_t ad[3]; ad[0] = (addr & 0xFF0000) >> 16; ad[1] = (addr & 0x00FF00) >> 8; ad[2] = (addr & 0x0000FF) >> 0; writeEnable(); digitalWrite(CS, LOW); vspi->beginTransaction(settings); vspi->transfer(0x02); vspi->transfer(ad[0]); vspi->transfer(ad[1]); vspi->transfer(ad[2]); for (int i = 0; i < 256; i++) { vspi->transfer(data[i]); } vspi->endTransaction(); digitalWrite(CS, HIGH); delay(1); waitReady(); } char *wololo = "ACNDEFHEJRHSUDIFKEMLOPEC"; void setup() { Serial.begin(115200); Serial.setDebugOutput(true); Serial.println("ON!!!"); pinMode(23, OUTPUT); pinMode(19, INPUT); pinMode(18,OUTPUT); pinMode(CS, OUTPUT); pinMode(13, OUTPUT); pinMode(22, OUTPUT); digitalWrite(CS, HIGH); digitalWrite(13, HIGH); digitalWrite(22, HIGH); if(FORMAT) { SPIFFS.format(); } if(!SPIFFS.begin(true)){ Serial.println("SPIFFS Mount Failed"); return; } // memcpy(databuff, wololo, 24); vspi = new SPIClass(VSPI); vspi->begin(); vspi->setDataMode(0); vspi->setBitOrder(MSBFIRST); delay(100); uint32_t offset = 0; waitReady(); // programPage(0, databuff); // DumpFlash(); // WriteFlash(); VerifyFlash(); } int compare(uint8_t *buff0, uint8_t *buff1, uint32_t len) { for (uint32_t i = 0; i < len; i++) { if (buff0[i] != buff1[i]) { return i; } } return -1; } void VerifyFlash() { File file = SPIFFS.open("/FLSHSAVE.BIN", FILE_READ); if (!file) { Serial.println("Error opening file!"); while(true) { delay(1000); } } uint32_t addr = 0; int diff = -1; Serial.println("VERIFING"); while(addr < flashSize) { // printHexPad32(addr); // Serial.println(""); file.read(databuff, 256); readBuffer(addr, databuff + 512, 256); diff = compare(databuff, databuff + 512, 256); if (diff != -1) { Serial.print("\nCorrupted at index "); Serial.print(addr + diff, HEX); Serial.println(""); break; } addr += 256; } file.close(); Serial.println("DONE"); } void WriteFlash() { unprotect(); chipErase(); File file = SPIFFS.open("/FLSHSAVE.BIN", FILE_READ); if (!file) { Serial.println("Error opening file!"); while(true) { delay(1000); } } uint32_t addr = 0; Serial.println("FLASHING"); while(addr < flashSize) { printHexPad32(addr); Serial.println(""); file.read(databuff, 256); programPage(addr, databuff); addr += 256; } file.close(); Serial.println("DONE"); } void PrintFlash() { uint32_t offset = 0; Serial.println("READING FLASH"); while (offset < flashSize) { readBuffer(offset, databuff, CHUNK); printBuff(databuff, CHUNK, offset); offset += CHUNK; } } void DumpFlash() { File file = SPIFFS.open("/SAVE.BIN", FILE_WRITE); if (!file) { Serial.println("Error opening file!"); while(true) { delay(1000); } } uint32_t offset = 0; Serial.println("READING FLASH"); while (offset < flashSize) { readBuffer(offset, databuff, CHUNK); file.write(databuff, CHUNK); printHexPad32(offset); Serial.println(""); offset += CHUNK; } file.close(); } void loop() { // digitalWrite(CS, HIGH); // delay(10); // digitalWrite(CS, LOW); //// delay(10); // vspi->beginTransaction(SPISettings(10000000, MSBFIRST, SPI_MODE0)); // vspi->transfer(0x90); // vspi->transfer(0); // vspi->transfer(0); // vspi->transfer(0); // jedec[0] = vspi->transfer(0); // manufacturer id // jedec[1] = vspi->transfer(0); // memory type //// jedec[2] = vspi->transfer(0); // capacity // // vspi->endTransaction(); // digitalWrite(CS, HIGH); // Serial.print("Response: "); // Serial.print(jedec[0], HEX); // Serial.print(","); // Serial.print(jedec[1], HEX); // Serial.print(","); // Serial.println(jedec[2], HEX); delay(1000); }