diff --git a/.travis.yml b/.travis.yml index 71b4eaf..261a945 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,6 +4,7 @@ before_install: - source <(curl -SLs https://raw.githubusercontent.com/Marzogh/Travis-CI/master/install.sh) script: - build_main_platforms + - build_platform trinket - build_platform rtl8195a #- build_platform uno #- build_platform due @@ -15,7 +16,6 @@ script: #- build_platform mega #- build_platform fio #- build_platform micro - #- build_platform trinket notifications: email: on_success: change diff --git a/README.md b/README.md index 312e006..944efb7 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,4 @@ -# SPIFlash [![Build Status](https://travis-ci.org/Marzogh/SPIFlash.svg?branch=dev)](https://travis-ci.org/Marzogh/SPIFlash) [![DOI](https://zenodo.org/badge/18908/Marzogh/SPIFlash.svg)](https://zenodo.org/badge/latestdoi/18908/Marzogh/SPIFlash) -[![GitHub release](https://img.shields.io/github/release/Marzogh/SPIFlash.svg)](https://github.com/Marzogh/SPIFlash) -[![GitHub commits](https://img.shields.io/github/commits-since/Marzogh/SPIFlash/v2.7.0.svg)](https://github.com/Marzogh/SPIFlash/compare/v2.7.0...development) -[![GitHub issues](https://img.shields.io/github/issues/Marzogh/SPIFlash.svg)](https://github.com/Marzogh/SPIFlash) -[![GitHub pull requests](https://img.shields.io/github/issues-pr/Marzogh/SPIFlash.svg)](https://github.com/Marzogh/SPIFlash) -[![license](https://img.shields.io/github/license/Marzogh/SPIFlash.svg)](https://github.com/Marzogh/SPIFlash) +# SPIFlash [![Build Status](https://travis-ci.org/Marzogh/SPIFlash.svg?branch=master)](https://travis-ci.org/Marzogh/SPIFlash) [![DOI](https://zenodo.org/badge/18908/Marzogh/SPIFlash.svg)](https://zenodo.org/badge/latestdoi/18908/Marzogh/SPIFlash) ### Arduino library for Winbond Flash Memory Chips Download the latest stable release (v2.6.0) from here. Please report any bugs in issues. @@ -18,7 +13,7 @@ This Arduino library is for use with Winbond serial flash memory chips. In its c - IDE v1.5.x - IDE v1.6.0-v1.6.5 - IDE v1.6.9-v1.6.12 -- IDE v1.8.1-v1.8.3 +- IDE v1.8.2 ##### Boards @@ -33,6 +28,7 @@ This Arduino library is for use with Winbond serial flash memory chips. In its c - Arduino Mega - Arduino Micro - Arduino Fio +- Attiny85 Boards ###### In BETA - ESP32 Boards (Tested on the Adafruit Esp32 Feather) The library is known to work with the ESP32 core as of the current commit 9618eec on 02.08.2017. ```ESP32 support will remain in beta till the ESP32 core can be installed via the Arduino boards manager.``` diff --git a/examples/FlashDiagnostics/.trinket.test.skip b/examples/FlashDiagnostics/.trinket.test.skip new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/examples/FlashDiagnostics/.trinket.test.skip @@ -0,0 +1 @@ + diff --git a/examples/FlashDiagnostics/Diagnostics_functions.ino b/examples/FlashDiagnostics/Diagnostics_functions.ino deleted file mode 100644 index b5d8e1a..0000000 --- a/examples/FlashDiagnostics/Diagnostics_functions.ino +++ /dev/null @@ -1,533 +0,0 @@ -/* - |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| - | FlashDiagnostic_functions.ino | - | SPIFlash library | - | v 3.0.0 | - |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| - | Marzogh | - | 04.11.2017 | - |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| - | | - | For a full diagnostics rundown - with error codes and details of the errors | - | uncomment #define RUNDIAGNOSTIC in SPIFlash.cpp in the library before compiling | - | and loading this application onto your Arduino. | - | | - |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| -*/ -void printLine() { - Serial.println(); - for (uint8_t i = 0; i < 230; i++) { - Serial.print(F("-")); - } - Serial.println(); -} - -void clearprintBuffer(char *bufPtr) { - for (uint8_t i = 0; i < 128; i++) { - //printBuffer[i] = 0; - *bufPtr++ = 0; - } -} - -void printTime(uint32_t _wTime, uint32_t _rTime) { - if (_rTime != 0) { - Serial.print(F("\t\tWrite Time: ")); - printTimer(_wTime); - Serial.print(F(",\tRead Time: ")); - printTimer(_rTime); - } - else { - Serial.print(F("\t\tTime: ")); - printTimer(_wTime); - } -} - -void printTimer(uint32_t _us) { - - if (_us > 1000000) { - float _s = _us / (float)1000000; - Serial.print(_s, 3); - Serial.print(" s"); - } - else if (_us > 1000) { - float _ms = _us / (float)1000; - Serial.print(_ms, 3); - Serial.print(" ms"); - } - else { - Serial.print(_us); - Serial.print(F(" us")); - } - delay(20); -} - -void pass(bool _status) { - Serial.print(F("\tData I/O test ")); - if (_status) { - Serial.print(F("PASS\t")); - } - else { - Serial.print(F("FAIL\t")); - } -} - -void printUniqueID(void) { - Serial.print("Unique ID: "); - long long _uniqueID = flash.getUniqueID(); - Serial.print(uint32_t(_uniqueID/1000000L)); - Serial.print(uint32_t(_uniqueID%1000000L)); - Serial.print(", "); - Serial.print(uint32_t(_uniqueID >> 32), HEX); - Serial.print(uint32_t(_uniqueID), HEX); -} - -void getID() { - char printBuffer[128]; - printLine(); - for (uint8_t i = 0; i < 68; i++) { - Serial.print(F(" ")); - } - Serial.print(F("SPIFlash Library version")); -#ifdef LIBVER - uint8_t _ver, _subver, _bugfix; - flash.libver(&_ver, &_subver, &_bugfix); - clearprintBuffer(&printBuffer[1]); - sprintf(printBuffer, ": %d.%d.%d", _ver, _subver, _bugfix); - Serial.print(printBuffer); -#else - Serial.print(F("< 2.5.0")); -#endif - printLine(); - - for (uint8_t i = 0; i < 80; i++) { - Serial.print(F(" ")); - } - Serial.print(F("Get ID")); - printLine(); - uint8_t b1, b2; - //uint16_t b3; - uint32_t JEDEC = flash.getJEDECID(); - uint32_t maxPage = flash.getMaxPage(); - uint32_t capacity = flash.getCapacity(); - b1 = (JEDEC >> 16); - b2 = (JEDEC >> 8); - //b3 = (JEDEC >> 0); - - - printLine(); - //---------------------------------------------------------------------------------------------// - - clearprintBuffer(&printBuffer[1]); - #if defined (ARDUINO_ARCH_ESP32) - sprintf(printBuffer, "\t\t\tJEDEC ID: %04xh", JEDEC); - #else - sprintf(printBuffer, "\t\t\tJEDEC ID: %04lxh", JEDEC); - #endif - Serial.println(printBuffer); - //Serial.print(F("\t\t\tJEDEC ID: ")); - //Serial.print(JEDEC, HEX); - //Serial.println(F("xh")); - clearprintBuffer(&printBuffer[1]); - #if defined (ARDUINO_ARCH_ESP32) - sprintf(printBuffer, "\t\t\tManufacturer ID: %02xh\n\t\t\tMemory Type: %02xh\n\t\t\tCapacity: %u bytes\n\t\t\tMaximum pages: %u", b1, b2, capacity, maxPage); - #else - sprintf(printBuffer, "\t\t\tManufacturer ID: %02xh\n\t\t\tMemory Type: %02xh\n\t\t\tCapacity: %lu bytes\n\t\t\tMaximum pages: %lu", b1, b2, capacity, maxPage); - #endif - Serial.print(printBuffer); - Serial.print("\n\t\t\t"); - printUniqueID(); - printLine(); -} - -void byteTest() { - Serial.println(); - uint32_t wTime = 0; - uint32_t rTime, addr; - uint8_t _data, _d; - _d = 35; - - addr = random(0, 0xFFFFF); - - if (flash.writeByte(addr, _d)) { - wTime = flash.functionRunTime(); - } - - - _data = flash.readByte(addr); - rTime = flash.functionRunTime(); - - Serial.print ("\t\t\tByte: \t\t"); - if (_data == _d) { - pass(TRUE); - } - else { - pass(FALSE); - } - printTime(wTime, rTime); -} - -void charTest() { - Serial.println(); - uint32_t wTime = 0; - uint32_t rTime, addr; - int8_t _data, _d; - _d = -110; - - addr = random(0, 0xFFFFF); - - if (flash.writeChar(addr, _d)) { - wTime = flash.functionRunTime(); - } - - - _data = flash.readChar(addr); - rTime = flash.functionRunTime(); - - - Serial.print ("\t\t\tChar: \t\t"); - if (_data == _d) { - pass(TRUE); - } - else { - pass(FALSE); - } - printTime(wTime, rTime); -} - -void wordTest() { - Serial.println(); - uint32_t wTime = 0; - uint32_t rTime, addr; - uint16_t _data, _d; - _d = 4520; - - addr = random(0, 0xFFFFF); - - if (flash.writeWord(addr, _d)) { - wTime = flash.functionRunTime(); - } - - - _data = flash.readWord(addr); - rTime = flash.functionRunTime(); - - - Serial.print ("\t\t\tWord: \t\t"); - if (_data == _d) { - pass(TRUE); - } - else { - pass(FALSE); - } - printTime(wTime, rTime); -} - -void shortTest() { - Serial.println(); - uint32_t wTime = 0; - uint32_t rTime, addr; - int16_t _data, _d; - _d = -1250; - - addr = random(0, 0xFFFFF); - - if (flash.writeShort(addr, _d)) { - wTime = flash.functionRunTime(); - } - - - _data = flash.readShort(addr); - rTime = flash.functionRunTime(); - - - Serial.print ("\t\t\tShort: \t\t"); - if (_data == _d) { - pass(TRUE); - } - else { - pass(FALSE); - } - printTime(wTime, rTime); -} - -void uLongTest() { - Serial.println(); - uint32_t wTime = 0; - uint32_t rTime, addr; - uint32_t _data, _d; - _d = 876532; - - addr = random(0, 0xFFFFF); - - if (flash.writeULong(addr, _d)) { - wTime = flash.functionRunTime(); - } - - - _data = flash.readULong(addr); - rTime = flash.functionRunTime(); - - - Serial.print ("\t\t\tULong: \t\t"); - if (_data == _d) { - pass(TRUE); - } - else { - pass(FALSE); - } - printTime(wTime, rTime); -} - -void longTest() { - Serial.println(); - uint32_t wTime = 0; - uint32_t rTime, addr; - int32_t _data, _d; - _d = -10959; - - addr = random(0, 0xFFFFF); - - if (flash.writeLong(addr, _d)) { - wTime = flash.functionRunTime(); - } - - - _data = flash.readLong(addr); - rTime = flash.functionRunTime(); - - - Serial.print ("\t\t\tLong: \t\t"); - if (_data == _d) { - pass(TRUE); - } - else { - pass(FALSE); - } - printTime(wTime, rTime); -} - -void floatTest() { - Serial.println(); - uint32_t wTime = 0; - uint32_t rTime, addr; - float _data, _d; - _d = 3.14; - - addr = random(0, 0xFFFFF); - - if (flash.writeFloat(addr, _d)) { - wTime = flash.functionRunTime(); - } - - - _data = flash.readFloat(addr); - rTime = flash.functionRunTime(); - - - Serial.print ("\t\t\tFloat: \t\t"); - if (_data == _d) { - pass(TRUE); - } - else { - pass(FALSE); - } - printTime(wTime, rTime); -} - -void stringTest() { - uint32_t wTime = 0; - uint32_t rTime, addr; - String _data, _d; - _d = "This is a test String 123!@#"; - - addr = random(0, 0xFFFFF); - - if (flash.writeStr(addr, _d)) { - wTime = flash.functionRunTime(); - } - - flash.readStr(addr, _data); - rTime = flash.functionRunTime(); - - - Serial.print ("\t\t\tString: \t"); - if (_data == _d) { - pass(TRUE); - } - else { - pass(FALSE); - } - printTime(wTime, rTime); - -#if defined (ARDUINO_ARCH_SAM) || defined (ARDUINO_ARCH_ESP8266) - Serial.println(); - printLine(); - if (!flash.functionRunTime()) { - Serial.println(F("Please uncomment RUNDIAGNOSTIC in SPIFlash.h to see the time taken by each function to run.")); - } -#endif -} - -void structTest() { - Serial.println(); - struct Test { - uint16_t s1; - float s2; - int32_t s3; - bool s4; - uint8_t s5; - }; - Test _d; - Test _data; - - _d.s1 = 31325; - _d.s2 = 4.84; - _d.s3 = 880932; - _d.s4 = true; - _d.s5 = 5; - - uint32_t wTime = 0; - uint32_t addr, rTime; - - addr = random(0, 0xFFFFF); - - if (flash.writeAnything(addr, _d)) { - wTime = flash.functionRunTime(); - } - - - flash.readAnything(addr, _data); - rTime = flash.functionRunTime(); - - - Serial.print ("\t\t\tStruct: \t"); - if ((_d.s1 == _data.s1) && (_d.s2 == _data.s2) && (_d.s3 == _data.s3) && (_d.s4 == _data.s4) && (_d.s5 == _data.s5)) { - pass(TRUE); - } - else { - pass(FALSE); - } - printTime(wTime, rTime); -} - -void arrayTest() { - Serial.println(); - uint32_t wTime = 0; - uint32_t rTime, addr; - uint8_t _d[256], _data[256]; - - for (uint16_t i = 0; i < 256; i++) { - _d[i] = i; - } - - addr = random(0, 0xFFFFF); - - if (flash.writeByteArray(addr, _d, 256)) { - wTime = flash.functionRunTime(); - } - - - flash.readByteArray(addr, _data, 256); - rTime = flash.functionRunTime(); - - - Serial.print ("\t\t\tByte Array: \t"); - for (uint16_t i = 0; i < 256; i++) { - if (_data[i] != i) { - pass(FALSE); - } - } - pass(TRUE); - printTime(wTime, rTime); - Serial.println(); -} - -void powerDownTest() { - Serial.println(); - uint32_t _time; - Serial.print(F("\t\t\tPower Down: \t")); - if (flash.powerDown()) { - _time = flash.functionRunTime(); - pass(TRUE); - printTime(_time, 0); - } - else { - pass(FALSE); - Serial.print(F("\t\tNot all chips support power down. Please check your datasheet.")); - } -} - -void powerUpTest() { - Serial.println(); - uint32_t _time; - Serial.print(F("\t\t\tPower Up: \t")); - if (flash.powerUp()) { - _time = flash.functionRunTime(); - pass(TRUE); - printTime(_time, 0); - } - else { - pass(FALSE); - } -} - -void eraseSectorTest() { - Serial.println(); - uint32_t _time, _addr; - _addr = random(0, 0xFFFFF); - Serial.print(F("\t\t\tErase 4KB Sector: ")); - if (flash.eraseSector(_addr)) { - _time = flash.functionRunTime(); - pass(TRUE); - printTime(_time, 0); - } - else { - pass(FALSE); - } - Serial.println(); -} - -void eraseBlock32KTest() { - Serial.println(); - uint32_t _time, _addr; - _addr = random(0, 0xFFFFF); - Serial.print(F("\t\t\tErase 32KB Block: ")); - if (flash.eraseBlock32K(_addr)) { - _time = flash.functionRunTime(); - pass(TRUE); - printTime(_time, 0); - } - else { - pass(FALSE); - } -} - -void eraseBlock64KTest() { - Serial.println(); - uint32_t _time, _addr; - _addr = random(0, 0xFFFFF); - Serial.print(F("\t\t\tErase 64KB Block: ")); - if (flash.eraseBlock64K(_addr)) { - _time = flash.functionRunTime(); - pass(TRUE); - printTime(_time, 0); - } - else { - pass(FALSE); - } -} - -void eraseChipTest() { - Serial.println(); - uint32_t _time; - Serial.print(F("\t\t\tErase Chip: \t")); - if (flash.eraseChip()) { - _time = flash.functionRunTime(); - pass(TRUE); - printTime(_time, 0); - } - else { - pass(FALSE); - } -} - diff --git a/examples/FlashDiagnostics/FlashDiagnostic_functions.ino b/examples/FlashDiagnostics/FlashDiagnostic_functions.ino new file mode 100644 index 0000000..399a231 --- /dev/null +++ b/examples/FlashDiagnostics/FlashDiagnostic_functions.ino @@ -0,0 +1,863 @@ +/* + |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| + | FlashDiagnostic_functions.ino | + | SPIFlash library | + | v 2.6.0 | + |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| + | Marzogh | + | 13.11.2016 | + |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| + | | + | For a full diagnostics rundown - with error codes and details of the errors | + | uncomment #define RUNDIAGNOSTIC in SPIFlash.cpp in the library before compiling | + | and loading this application onto your Arduino. | + | | + |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| +*/ + +void getID() { + char printBuffer[128]; + printLine(); + for (uint8_t i = 0; i < 68; i++) { + Serial.print(F(" ")); + } + Serial.print(F("SPIFlash Library version")); +#ifdef LIBVER + uint8_t _ver, _subver, _bugfix; + flash.libver(&_ver, &_subver, &_bugfix); + clearprintBuffer(&printBuffer[1]); + sprintf(printBuffer, ": %d.%d.%d", _ver, _subver, _bugfix); + Serial.println(printBuffer); +#else + Serial.println(F("< 2.5.0")); +#endif + printLine(); + + for (uint8_t i = 0; i < 80; i++) { + Serial.print(F(" ")); + } + Serial.println(F("Get ID")); + printLine(); + uint8_t b1, b2; + uint16_t b3; + uint32_t JEDEC = flash.getJEDECID(); + uint32_t maxPage = flash.getMaxPage(); + uint32_t capacity = flash.getCapacity(); + b1 = (JEDEC >> 16); + b2 = (JEDEC >> 8); + b3 = (JEDEC >> 0); + + + printLine(); + //---------------------------------------------------------------------------------------------// + + clearprintBuffer(&printBuffer[1]); + sprintf(printBuffer, "\t\t\tJEDEC ID: %04lxh", JEDEC); + Serial.println(printBuffer); + clearprintBuffer(&printBuffer[1]); + sprintf(printBuffer, "\t\t\tManufacturer ID: %02xh\n\t\t\tMemory Type: %02xh\n\t\t\tCapacity: %lu bytes\n\t\t\tMaximum pages: %lu", b1, b2, capacity, maxPage); + Serial.println(printBuffer); +} + +bool checkPage(uint8_t *data_buffer) { + for (int i = 0; i < 256; i++) { + if (data_buffer[i] != i) + return false; + } + return true; +} + +void diagnose() { + printLine(); + for (uint8_t i = 0; i < 79; i++) { + Serial.print(F(" ")); + } + Serial.println(F("Data Check")); + printLine(); + + Serial.println(F("\tData Written\t||\tData Read\t||\tResult\t\t||\tWrite Time\t||\tRead Time\t||\tWrite Time\t||\tFast Read Time")); + Serial.print(F("\t\t\t||\t\t\t||\t\t\t||\t\t\t||\t\t\t||")); + Serial.println(F("\t(No Error Chk)\t||")); + printLine(); + byteDiag(); + charDiag(); + wordDiag(); + shortDiag(); + uLongDiag(); + longDiag(); + floatDiag(); + stringDiag(); + structDiag(); + pageDiag(); + powerFuncDiag(); + +} + +void byteDiag(void) { + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Byte // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + uint8_t _byte = 35; + uint8_t _b; + float startTime; + uint32_t addr, wTime, rTime; + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Write // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + addr = random(0, 0xFFFFF); + startTime = micros(); + flash.writeByte(addr, _byte); + wTime = micros() - startTime; + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Read // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + startTime = micros(); + _b = flash.readByte(addr); + rTime = micros() - startTime; + //Print result + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Print Result // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + printTab(1, 0); + Serial.print(_byte); + printTab(2, 1); + Serial.print(_b); + printTab(2, 1); + if (_byte == _b) + printPass(); + else + printFail(); + printTime(wTime, rTime); + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Write (No Error) // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + addr = random(0, 0xFFFFF); + startTime = micros(); + flash.writeByte(addr, _byte, false); + wTime = micros() - startTime; + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Fast Read // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + startTime = micros(); + _b = flash.readByte(addr, true); + rTime = micros() - startTime; + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Print Result // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + printTime(wTime, rTime); + Serial.println(); + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + //-----------------------------------------------------------------------------------------------------------------------------------------------------// +} + +void charDiag(void) { + //-----------------------------------------------------------------------------------------------------------------------------------------------------// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Char // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + int8_t _char = -110; + int8_t _c; + float startTime; + uint32_t addr, wTime, rTime; + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Write // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + addr = random(0, 0xFFFFF); + startTime = micros(); + flash.writeChar(addr, _char); + wTime = micros() - startTime; + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Read // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + startTime = micros(); + _c = flash.readChar(addr); + rTime = micros() - startTime; + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Print Result // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + printTab(1, 0); + Serial.print(_char); + printTab(2, 1); + Serial.print(_c); + printTab(2, 1); + if (_char == _c) + printPass(); + else + printFail(); + printTime(wTime, rTime); + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Write (No Error) // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + addr = random(0, 0xFFFFF); + startTime = micros(); + flash.writeChar(addr, _char, false); + wTime = micros() - startTime; + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Fast Read // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + startTime = micros(); + _c = flash.readChar(addr, true); + rTime = micros() - startTime; + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Print Result // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + printTime(wTime, rTime); + Serial.println(); + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + //-----------------------------------------------------------------------------------------------------------------------------------------------------// +} + +void wordDiag(void) { + //-----------------------------------------------------------------------------------------------------------------------------------------------------// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Word // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + uint16_t _word = 4520; + uint16_t _w; + float startTime; + uint32_t addr, wTime, rTime; + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Write // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + addr = random(0, 0xFFFFF); + startTime = micros(); + flash.writeWord(addr, _word); + wTime = micros() - startTime; + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Read // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + startTime = micros(); + _w = flash.readWord(addr); + rTime = micros() - startTime; + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Print Result // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + printTab(1, 0); + Serial.print(_word); + printTab(2, 1); + Serial.print(_w); + printTab(2, 1); + if (_word == _w) + printPass(); + else + printFail(); + printTime(wTime, rTime); + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Write (No Error) // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + addr = random(0, 0xFFFFF); + startTime = micros(); + flash.writeWord(addr, _word, false); + wTime = micros() - startTime; + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Fast Read // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + startTime = micros(); + _w = flash.readWord(addr, true); + rTime = micros() - startTime; + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Print Result // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + printTime(wTime, rTime); + Serial.println(); + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + //-----------------------------------------------------------------------------------------------------------------------------------------------------// +} + +void shortDiag(void) { + //-----------------------------------------------------------------------------------------------------------------------------------------------------// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Short // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + int16_t _short = -1250; + int16_t _s; + float startTime; + uint32_t addr, wTime, rTime; + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Write // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + addr = random(0, 0xFFFFF); + startTime = micros(); + flash.writeShort(addr, _short); + wTime = micros() - startTime; + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Read // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + startTime = micros(); + _s = flash.readShort(addr); + rTime = micros() - startTime; + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Print Result // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + printTab(1, 0); + Serial.print(_short); + printTab(2, 1); + Serial.print(_s); + printTab(2, 1); + if (_short == _s) + printPass(); + else + printFail(); + printTime(wTime, rTime); + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Write (No Error) // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + addr = random(0, 0xFFFFF); + startTime = micros(); + flash.writeShort(addr, _short, false); + wTime = micros() - startTime; + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Fast Read // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + startTime = micros(); + _s = flash.readShort(addr, true); + rTime = micros() - startTime; + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Print Result // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + printTime(wTime, rTime); + Serial.println(); + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + //-----------------------------------------------------------------------------------------------------------------------------------------------------// +} + +void uLongDiag(void) { + //-----------------------------------------------------------------------------------------------------------------------------------------------------// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Ulong // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + uint32_t _uLong = 876532; + uint32_t _uL; + float startTime; + uint32_t addr, wTime, rTime; + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Write // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + addr = random(0, 0xFFFFF); + startTime = micros(); + flash.writeULong(addr, _uLong); + wTime = micros() - startTime; + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Read // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + startTime = micros(); + _uL = flash.readULong(addr); + rTime = micros() - startTime; + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Print Result // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + printTab(1, 0); + Serial.print(_uLong); + printTab(2, 1); + Serial.print(_uL); + printTab(2, 1); + if (_uLong == _uL) + printPass(); + else + printFail(); + printTime(wTime, rTime); + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Write (No Error) // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + addr = random(0, 0xFFFFF); + startTime = micros(); + flash.writeULong(addr, _uLong, false); + wTime = micros() - startTime; + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Fast Read // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + startTime = micros(); + _uL = flash.readULong(addr, true); + rTime = micros() - startTime; + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Print Result // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + printTime(wTime, rTime); + Serial.println(); + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + //-----------------------------------------------------------------------------------------------------------------------------------------------------// +} + +void longDiag(void) { + //-----------------------------------------------------------------------------------------------------------------------------------------------------// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Long // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + int32_t _long = -10959; + int32_t _l; + float startTime; + uint32_t addr, wTime, rTime; + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Write // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + addr = random(0, 0xFFFFF); + startTime = micros(); + flash.writeLong(addr, _long); + wTime = micros() - startTime; + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Read // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + startTime = micros(); + _l = flash.readLong(addr); + rTime = micros() - startTime; + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Print Result // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + printTab(1, 0); + Serial.print(_long); + printTab(2, 1); + Serial.print(_l); + printTab(2, 1); + if (_long == _l) + printPass(); + else + printFail(); + printTime(wTime, rTime); + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Write (No Error) // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + addr = random(0, 0xFFFFF); + startTime = micros(); + flash.writeLong(addr, _long, false); + wTime = micros() - startTime; + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Fast Read // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + startTime = micros(); + _l = flash.readLong(addr, true); + rTime = micros() - startTime; + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Print Result // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + printTime(wTime, rTime); + Serial.println(); + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + //-----------------------------------------------------------------------------------------------------------------------------------------------------// +} + +void floatDiag(void) { + //-----------------------------------------------------------------------------------------------------------------------------------------------------// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Float // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + float _float = 3.1415; + float _f; + float startTime; + uint32_t addr, wTime, rTime; + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Write // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + addr = random(0, 0xFFFFF); + startTime = micros(); + if (flash.writeFloat(addr, _float)) { + wTime = micros() - startTime; + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Read // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + startTime = micros(); + _f = flash.readFloat(addr); + rTime = micros() - startTime; + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Print Result // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + printTab(1, 0); + Serial.print(_float); + printTab(2, 1); + Serial.print(_f); + printTab(2, 1); + if (_float == _f) + printPass(); + else + printFail(); + printTime(wTime, rTime); + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Write (No Error) // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + addr = random(0, 0xFFFFF); + startTime = micros(); + if (flash.writeFloat(addr, _float, false)) { + wTime = micros() - startTime; + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Fast Read // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + startTime = micros(); + _f = flash.readFloat(addr, true); + rTime = micros() - startTime; + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Print Result // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + printTime(wTime, rTime); + Serial.println(); + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + //-----------------------------------------------------------------------------------------------------------------------------------------------------// +} + +void stringDiag(void) { + //-----------------------------------------------------------------------------------------------------------------------------------------------------// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // String // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + String _string = "123 Test !@#"; + String _str = ""; + float startTime; + uint32_t addr, wTime, rTime; + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Write // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + addr = random(0, 0xFFFFF); + startTime = micros(); + if (flash.writeStr(addr, _string)) { + wTime = micros() - startTime; + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Read // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + startTime = micros(); + if (flash.readStr(addr, _str)) { + rTime = micros() - startTime; + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Print Result // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + printTab(1, 0); + Serial.print(_string); + printTab(1, 1); + Serial.print(_str); + printTab(1, 1); + if (_string == _str) + printPass(); + else + printFail(); + printTime(wTime, rTime); + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Write (No Error) // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + addr = random(0, 0xFFFFF); + startTime = micros(); + if (flash.writeStr(addr, _string, false)) { + wTime = micros() - startTime; + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Fast Read // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + startTime = micros(); + if (flash.readStr(addr, _str, true)) { + rTime = micros() - startTime; + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Print Result // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + printTime(wTime, rTime); + Serial.println(); + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + //-----------------------------------------------------------------------------------------------------------------------------------------------------// +} + +void structDiag(void) { + //-----------------------------------------------------------------------------------------------------------------------------------------------------// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Struct // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + struct Test { + word s1; + float s2; + long s3; + bool s4; + byte s5; + }; + Test inputStruct; + Test outputStruct; + + inputStruct.s1 = 31325; + inputStruct.s2 = 4.84; + inputStruct.s3 = 880932; + inputStruct.s4 = true; + inputStruct.s5 = 5; + + float startTime; + uint32_t addr, wTime, rTime; + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Write // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + addr = random(0, 0xFFFFF); + startTime = micros(); + flash.writeAnything(addr, inputStruct); + wTime = micros() - startTime; + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Read // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + startTime = micros(); + flash.readAnything(addr, outputStruct); + rTime = micros() - startTime; + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Print Result // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + printTab(1, 0); + Serial.print(F("inputStruct")); + printTab(1, 1); + Serial.print(F("outputStruct")); + printTab(1, 1); + if (inputStruct.s1 == outputStruct.s1 && inputStruct.s2 == outputStruct.s2 && inputStruct.s3 == outputStruct.s3 && inputStruct.s4 == outputStruct.s4 && inputStruct.s5 == outputStruct.s5) + printPass(); + else + printFail(); + printTime(wTime, rTime); + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Write (No Error) // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + addr = random(0, 0xFFFFF); + startTime = micros(); + flash.writeAnything(addr, inputStruct, false); + wTime = micros() - startTime; + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Fast Read // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + startTime = micros(); + flash.readAnything(addr, outputStruct, true); + rTime = micros() - startTime; + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Print Result // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + printTime(wTime, rTime); + Serial.println(); + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + //-----------------------------------------------------------------------------------------------------------------------------------------------------// +} + +void pageDiag(void) { + //-----------------------------------------------------------------------------------------------------------------------------------------------------// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Page // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + float startTime; + uint32_t addr, wTime, rTime; + uint8_t pageBuffer[PAGESIZE]; + + for (int i = 0; i < PAGESIZE; ++i) { + pageBuffer[i] = i; + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Write // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + addr = random(0, flash.getMaxPage()); + startTime = micros(); + while (!flash.writeByteArray(addr, pageBuffer, PAGESIZE)); + wTime = micros() - startTime; + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Read & Print Result // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + for (int i = 0; i < PAGESIZE; ++i) { + pageBuffer[i] = 0; + } + startTime = micros(); + printTab(1, 0); + Serial.print(F("0 - ")); + Serial.print(PAGESIZE - 1); + printTab(2, 1); + startTime = micros(); + + flash.readByteArray(addr, pageBuffer, PAGESIZE); + rTime = micros() - startTime; + bool _pass; + for (uint16_t i = 0; i < 256; i++) { + if (pageBuffer [i] != i) { + _pass = false; + break; + } + else { + _pass = true; + } + } + + if (_pass) { + Serial.print(F("0 - ")); + Serial.print(PAGESIZE - 1); + printTab(2, 1); + printPass(); + } + else { + Serial.print(F("Unknown")); + printTab(2, 1); + printFail(); + } + printTime(wTime, rTime); + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Write (No Error) // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + for (int i = 0; i < 256; ++i) { + pageBuffer[i] = i; + } + addr = random(0, flash.getMaxPage()); + startTime = micros(); + flash.writeByteArray(addr, pageBuffer, PAGESIZE, false); + wTime = micros() - startTime; + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Fast Read & Print Result // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + for (int i = 0; i < 256; ++i) { + pageBuffer[i] = 0; + } + startTime = micros(); + flash.readByteArray(addr, pageBuffer, PAGESIZE, true); + rTime = micros() - startTime; + printTime(wTime, rTime); + Serial.println(); + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + //-----------------------------------------------------------------------------------------------------------------------------------------------------// +} + +void powerFuncDiag(void) { + String _string = "123 Test !@#"; + float wTime; + + printLine(); + for (uint8_t i = 0; i < 72; i++) { + Serial.print(" "); + } + Serial.println(F("Check Other Functions")); + printLine(); + Serial.println(F("\t\t\t\t\tFunction\t\t||\t\tResult\t\t\t||\t\tTime")); + printLine(); + Serial.flush(); + + uint32_t capacity = flash.getCapacity(); + if (!Serial) + Serial.begin(115200); + uint32_t stringAddress1 = random(0, capacity); + uint32_t stringAddress2 = random(0, capacity); + uint32_t stringAddress3 = random(0, capacity); + + printTab(5, 0); + Serial.print(F("powerDown")); + printTab(2, 2); + //if (flash.writeStr(stringAddress1, _string)) { + wTime = micros(); + if (flash.powerDown()) { + wTime = micros() - wTime; + printPass(); + } + else { + wTime = micros() - wTime; + printFail(); + } + //} + printTab(3, 2); + printTimer(wTime); + Serial.println(); + + printTab(5, 0); + Serial.print(F("powerUp")); + printTab(3, 2); + wTime = micros(); + if (flash.powerUp()) { + wTime = micros() - wTime; + //if (flash.writeStr(stringAddress3, _string)) { + printPass(); + } + else { + printFail(); + } + //} + printTab(3, 2); + printTimer(wTime); + Serial.println(); + + printTab(5, 0); + Serial.print(F("eraseSector")); + wTime = micros(); + printTab(2, 2); + if (flash.eraseSector(stringAddress1)) { + wTime = micros() - wTime; + printPass(); + } + else { + printFail(); + } + wTime = wTime / 3; + printTab(3, 2); + printTimer(wTime); + Serial.println(); + + printTab(5, 0); + Serial.print(F("eraseBlock32K")); + wTime = micros(); + printTab(2, 2); + if (flash.eraseBlock32K(stringAddress2)) { + wTime = micros() - wTime; + printPass(); + } + else { + printFail(); + } + wTime = wTime / 3; + printTab(3, 2); + printTimer(wTime); + Serial.println(); + + printTab(5, 0); + Serial.print(F("eraseBlock64K")); + wTime = micros(); + printTab(2, 2); + if (flash.eraseBlock64K(stringAddress3)) { + wTime = micros() - wTime; + printPass(); + } + else { + printFail(); + } + wTime = wTime / 3; + printTab(3, 2); + printTimer(wTime); + Serial.println(); + + printTab(5, 0); + Serial.print(F("eraseChip")); + printTab(2, 2); + wTime = micros(); + if (flash.eraseChip()) { + wTime = micros() - wTime; + printPass(); + } + else { + printFail(); + } + + + printTab(3, 2); + printTimer(wTime); + Serial.println(); + + printLine(); +} diff --git a/examples/FlashDiagnostics/FlashDiagnostics.ino b/examples/FlashDiagnostics/FlashDiagnostics.ino index f153eab..c58dfbb 100644 --- a/examples/FlashDiagnostics/FlashDiagnostics.ino +++ b/examples/FlashDiagnostics/FlashDiagnostics.ino @@ -2,10 +2,10 @@ |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| | FlashDiagnostics.ino | | SPIFlash library | - | v 3.0.0 | + | v 2.6.0 | |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| | Marzogh | - | 04.11.2017 | + | 16.04.2017 | |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| | | | For a full diagnostics rundown - with error codes and details of the errors | @@ -17,94 +17,110 @@ #include +//Define a flash memory size (if using non-Winbond memory) according to the list in defines.h +//#define CHIPSIZE MB64 + #if defined(ARDUINO_SAMD_ZERO) && defined(SERIAL_PORT_USBVIRTUAL) // Required for Serial on Zero based boards #define Serial SERIAL_PORT_USBVIRTUAL #endif #if defined (SIMBLEE) - #define BAUD_RATE 250000 - #define RANDPIN 1 +#define BAUD_RATE 250000 +#define RANDPIN 1 #else - #define BAUD_RATE 115200 - #if defined(ARCH_STM32) - #define RANDPIN PA0 - #else - #define RANDPIN A0 - #endif +#define BAUD_RATE 115200 +#define RANDPIN A0 #endif -#define TRUE 1 -#define FALSE 0 - -//SPIFlash flash(SS1, &SPI1); //Use this constructor if using an SPI bus other than the default SPI. Only works with chips with more than one hardware SPI bus SPIFlash flash; void setup() { Serial.begin(BAUD_RATE); - #if defined (ARDUINO_ARCH_SAMD) || (__AVR_ATmega32U4__) || defined(ARCH_STM32) - while (!Serial) ; // Wait for Serial monitor to open - #endif - delay(50); //Time to terminal get connected +#if defined (ARDUINO_ARCH_SAMD) || (__AVR_ATmega32U4__) + while (!Serial) ; // Wait for Serial monitor to open +#endif Serial.print(F("Initialising Flash memory")); - for (uint8_t i = 0; i < 10; ++i) + for (int i = 0; i < 10; ++i) { Serial.print(F(".")); } Serial.println(); - randomSeed(analogRead(RANDPIN)); +#if defined (CHIPSIZE) + flash.begin(CHIPSIZE); //use flash.begin(CHIPSIZE) if using non-Winbond flash (Refer to '#define CHIPSIZE' above) +#else flash.begin(); - //To use a custom flash memory size (if using memory from manufacturers not officially supported by the library) - declare a size variable according to the list in defines.h - //flash.begin(MB(1)); +#endif Serial.println(); Serial.println(); - + randomSeed(analogRead(RANDPIN)); getID(); - eraseChipTest(); - eraseBlock64KTest(); - eraseBlock32KTest(); - eraseSectorTest(); - -#if defined(ARDUINO_ARCH_SAM) || defined(ARDUINO_ARCH_ESP8266) - delay(10); - powerDownTest(); - powerUpTest(); - Serial.println(); -#endif + diagnose(); +} - byteTest(); - charTest(); - wordTest(); - shortTest(); - uLongTest(); -#if defined(ARDUINO_ARCH_SAM) || defined(ARDUINO_ARCH_ESP8266) - delay(10); -#endif - longTest(); - floatTest(); - structTest(); - arrayTest(); - stringTest(); - -#if !defined(ARDUINO_ARCH_SAM) || !defined(ARDUINO_ARCH_ESP8266) - powerDownTest(); - powerUpTest(); -#endif - printLine(); - if (!flash.functionRunTime()) { - Serial.println(F("Please uncomment RUNDIAGNOSTIC in SPIFlash.h to see the time taken by each function to run.")); +void loop() { + +} + + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~Serial Print Functions~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + +void clearprintBuffer(char *bufPtr) +{ + for (uint8_t i = 0; i < 128; i++) { + //printBuffer[i] = 0; + *bufPtr++ = 0; } } -void loop() { +void printLine() { + for (uint8_t i = 0; i < 230; i++) { + Serial.print(F("-")); + } + Serial.println(); +} +void printPass() { + Serial.print(F("Pass")); } -void longBlink() { - pinMode(LED_BUILTIN, OUTPUT); - digitalWrite(LED_BUILTIN, HIGH); - delay(3000); - digitalWrite(LED_BUILTIN, LOW); - delay(2000); +void printFail() { + Serial.print(F("Fail")); } +void printTab(uint8_t a, uint8_t b) { + for (uint8_t i = 0; i < a; i++) { + Serial.print(F("\t")); + } + if (b > 0) { + Serial.print("||"); + for (uint8_t i = 0; i < b; i++) { + Serial.print(F("\t")); + } + } +} + +void printTime(uint32_t _wTime, uint32_t _rTime) { + printTab(2, 1); + printTimer(_wTime); + printTab(2, 1); + printTimer(_rTime); +} + +void printTimer(uint32_t _us) { + + if (_us > 1000000) { + float _s = _us / (float)1000000; + Serial.print(_s, 4); + Serial.print(" s"); + } + else if (_us > 10000) { + float _ms = _us / (float)1000; + Serial.print(_ms, 4); + Serial.print(" ms"); + } + else { + Serial.print(_us); + Serial.print(F(" us")); + } +} diff --git a/examples/Struct_writer/.trinket.test.skip b/examples/Struct_writer/.trinket.test.skip new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/examples/Struct_writer/.trinket.test.skip @@ -0,0 +1 @@ + diff --git a/examples/Struct_writer/Struct_writer.ino b/examples/Struct_writer/Struct_writer.ino index 23fd488..26f1129 100644 --- a/examples/Struct_writer/Struct_writer.ino +++ b/examples/Struct_writer/Struct_writer.ino @@ -45,7 +45,6 @@ -//SPIFlash flash(SS1, &SPI1); //Use this constructor if using an SPI bus other than the default SPI. Only works with chips with more than one hardware SPI bus SPIFlash flash; @@ -55,7 +54,6 @@ struct Configuration { float RLDR; // Resistance calculation of potential divider with LDR bool light; uint8_t adc; - uint8_t arr[8]; }; Configuration configuration; @@ -83,17 +81,12 @@ void setup() { configuration.RLDR = 889.32; configuration.light = true; configuration.adc = 5; - for (uint8_t i = 0; i < 8; i++) { - configuration.arr[i] = i; - } #endif #ifdef SENSOR readLDR(); #endif - if (flash.eraseChip()) { - Serial.println("Chip has been erased"); - } + if (flash.writeAnything(_addr, configuration)) Serial.println ("Data write successful"); else @@ -104,20 +97,13 @@ void setup() { Serial.println(configuration.RLDR); Serial.println(configuration.light); Serial.println(configuration.adc); - for (uint8_t i = 0; i < 8; i++) { - Serial.print(configuration.arr[i]); - Serial.print(", "); - } - Serial.println(); + Serial.println("Saved!"); configuration.lux = 0; configuration.vOut = 0; configuration.RLDR = 0; configuration.light = 0; configuration.adc = 0; - for (uint8_t i = 0; i < 8; i++) { - configuration.arr[i] = 0; - } Serial.println(); Serial.println("Local values set to 0"); Serial.println(configuration.lux); @@ -125,14 +111,9 @@ void setup() { Serial.println(configuration.RLDR); Serial.println(configuration.light); Serial.println(configuration.adc); - for (uint8_t i = 0; i < 8; i++) { - Serial.print(configuration.arr[i]); - Serial.print(", "); - } - Serial.println(); Serial.println(); flash.readAnything(_addr, configuration); - flash.eraseSector(_addr); + flash.eraseSector(_addr, 0); Serial.println("After reading"); Serial.println(configuration.lux); @@ -140,11 +121,6 @@ void setup() { Serial.println(configuration.RLDR); Serial.println(configuration.light); Serial.println(configuration.adc); - for (uint8_t i = 0; i < 8; i++) { - Serial.print(configuration.arr[i]); - Serial.print(", "); - } - Serial.println(); } diff --git a/examples/TestFlash/.trinket.test.skip b/examples/TestFlash/.trinket.test.skip new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/examples/TestFlash/.trinket.test.skip @@ -0,0 +1 @@ + diff --git a/examples/TestFlash/TestFlash.ino b/examples/TestFlash/TestFlash.ino index 1cc0977..6af1df5 100644 --- a/examples/TestFlash/TestFlash.ino +++ b/examples/TestFlash/TestFlash.ino @@ -16,46 +16,46 @@ | 1. getID | | '1' gets the JEDEC ID of the chip | | | - | 2. writeByte [address] [byte] | - | '2' followed by '2435' and then by '224' writes the byte 224 to address 2435 | + | 2. writeByte [page] [offset] [byte] | + | '2' followed by '100' and then by '20' and then by '224' writes the byte 224 to page 100 position 20 | | | - | 3. readByte [address] | - | '3' followed by '2435' returns the byte from address '2435' | + | 3. readByte [page] [offset] | + | '3' followed by '100' and then by '20' returns the byte from page 100 position 20 | | | - | 4. writeWord [address] [word] | - | '4' followed by '5948' and then by '633' writes the int 633 to address 5948 | + | 4. writeWord [page] [offset] | + | '4' followed by '55' and then by '35' and then by '633' writes the int 633 to page 5 position 35 | | | - | 5. readWord [address] | - | '5' followed by '5948' returns the int from address 5948 | + | 5. readWord [page] [offset] | + | '5' followed by '200' and then by '30' returns the int from page 200 position 30 | | | - | 6. writeStr [address] [inputString] | - | '6' followed by '345736' and then by 'Test String 1!' writes the String 'Test String 1! to address 345736 | + | 6. writeStr [page] [offset] [inputString] | + | '6' followed by '345' and then by '65' and then by 'Test String 1!' writes the String 'Test String 1! to page 345 position 65 | | | - | 7. readStr [address] [outputString] | - | '7' followed by '345736' reads the String from address 345736 into the outputString | + | 7. readStr [page] [offset] [outputString] | + | '7' followed by '2050' and then by '73' reds the String from page 2050 position 73 into the outputString | | | | 8. writePage [page] | - | '8' followed by '33' writes bytes from 0 to 255 sequentially to fill a page (256 bytes) starting with address 33 | + | '8' followed by '33' writes bytes from 0 to 255 sequentially to fill page 33 | | | | 9. printPage [page] | - | '9' followed by 33 reads & prints a page (256 bytes) starting with address 33. To just read a page to a data buffer, refer | + | '9' followed by 33 reads & prints page 33. To just read a page to a data buffer, refer | | to 'ReadMe.md' in the library folder. | | | - | 10. printAllData | - | '10' reads the entire chip and outputs the data as a byte array to the serial console | + | 10. printAllPages | + | '10' reads all 4096 pages and outputs them to the serial console | | This function is to extract data from a flash chip onto a computer as a text file. | | Refer to 'Read me.md' in the library for details. | | | | 11. Erase 4KB sector | - | '11' followed by 2 erases a 4KB sector containing the address be erased | + | '11' followed by 2 erases a 4KB sector containing the page to be erased | | Page 0-15 --> Sector 0; Page 16-31 --> Sector 1;......Page 4080-4095 --> Sector 255 | | | | 12. Erase 32KB block | - | '12' followed by 2 erases a 32KB block containing the address to be erased | + | '12' followed by 2 erases a 32KB block containing the page to be erased | | Page 0-15 --> Sector 0; Page 16-31 --> Sector 1;......Page 4080-4095 --> Sector 255 | | | | 13. Erase 64KB block | - | '13' followed by 2 erases a 64KB block containing the address to be erased | + | '13' followed by 2 erases a 64KB block containing the page to be erased | | Page 0-15 --> Sector 0; Page 16-31 --> Sector 1;......Page 4080-4095 --> Sector 255 | | | | 14. Erase Chip | @@ -70,14 +70,11 @@ uint8_t pageBuffer[256]; String serialCommand; char printBuffer[128]; -uint32_t addr; -uint8_t dataByte; +uint16_t page; +uint8_t offset, dataByte; uint16_t dataInt; String inputString, outputString; -//Define a flash memory size (if using non-Winbond memory) according to the list in defines.h -//#define CHIPSIZE MB64 - #if defined(ARDUINO_SAMD_ZERO) && defined(SERIAL_PORT_USBVIRTUAL) // Required for Serial on Zero based boards #define Serial SERIAL_PORT_USBVIRTUAL @@ -89,7 +86,6 @@ String inputString, outputString; #define BAUD_RATE 115200 #endif -//SPIFlash flash(SS1, &SPI1); //Use this constructor if using an SPI bus other than the default SPI. Only works with chips with more than one hardware SPI bus SPIFlash flash; void setup() { @@ -101,11 +97,7 @@ void setup() { Serial.print(F(".")); } Serial.println(); -#if defined (CHIPSIZE) - flash.begin(CHIPSIZE); //use flash.begin(CHIPSIZE) if using non-Winbond flash (Refer to '#define CHIPSIZE' above) -#else flash.begin(); -#endif Serial.println(); Serial.println(); commandList(); @@ -142,15 +134,24 @@ void loop() { Serial.println(F(" Function 2 : Write Byte ")); printSplash(); printLine(); - inputAddress(); + Serial.print(F("Please enter the number of the page you wish to modify: ")); + while (!Serial.available()) { + } + page = Serial.parseInt(); + Serial.println(page); + Serial.print(F("Please enter the position on the page (0-255) you wish to modify: ")); + while (!Serial.available()) { + } + offset = Serial.parseInt(); + Serial.println(offset); Serial.print(F("Please enter the value of the byte (0-255) you wish to save: ")); while (!Serial.available()) { } dataByte = Serial.parseInt(); Serial.println(dataByte); - if (flash.writeByte(addr, dataByte)) { + if (flash.writeByte(page, offset, dataByte)) { clearprintBuffer(); - sprintf(printBuffer, "%d has been written to address %d", dataByte, addr); + sprintf(printBuffer, "%d has been written to position %d on page %d", dataByte, offset, page); Serial.println(printBuffer); } else { @@ -164,11 +165,20 @@ void loop() { Serial.println(F(" Function 3 : Read Byte ")); printSplash(); printLine(); - inputAddress(); + Serial.print(F("Please enter the number of the page the byte you wish to read is on: ")); + while (!Serial.available()) { + } + page = Serial.parseInt(); + Serial.println(page); + Serial.print(F("Please enter the position of the byte on the page (0-255) you wish to read: ")); + while (!Serial.available()) { + } + offset = Serial.parseInt(); + Serial.println(offset); clearprintBuffer(); - sprintf(printBuffer, "The byte at address %d is: ", addr); + sprintf(printBuffer, "The byte at position %d on page %d is: ", offset, page); Serial.print(printBuffer); - Serial.println(flash.readByte(addr)); + Serial.println(flash.readByte(page, offset)); printLine(); printNextCMD(); } @@ -177,15 +187,24 @@ void loop() { Serial.println(F(" Function 4 : Write Word ")); printSplash(); printLine(); - inputAddress(); + Serial.print(F("Please enter the number of the page you wish to modify: ")); + while (!Serial.available()) { + } + page = Serial.parseInt(); + Serial.println(page); + Serial.print(F("Please enter the position on the page (0-255) you wish to modify: ")); + while (!Serial.available()) { + } + offset = Serial.parseInt(); + Serial.println(offset); Serial.print(F("Please enter the value of the word (>255) you wish to save: ")); while (!Serial.available()) { } dataInt = Serial.parseInt(); Serial.println(dataInt); - if (flash.writeWord(addr, dataInt)) { + if (flash.writeWord(page, offset, dataInt)) { clearprintBuffer(); - sprintf(printBuffer, "%d has been written to address %d", dataInt, addr); + sprintf(printBuffer, "%d has been written to position %d on page %d", dataInt, offset, page); Serial.println(printBuffer); } else { @@ -199,11 +218,20 @@ void loop() { Serial.println(F(" Function 5 : Read Word ")); printSplash(); printLine(); - inputAddress(); + Serial.print(F("Please enter the number of the page the byte you wish to read is on: ")); + while (!Serial.available()) { + } + page = Serial.parseInt(); + Serial.println(page); + Serial.print(F("Please enter the position of the word on the page (0-255) you wish to read: ")); + while (!Serial.available()) { + } + offset = Serial.parseInt(); + Serial.println(offset); clearprintBuffer(); - sprintf(printBuffer, "The unsigned int at address %d is: ", addr); + sprintf(printBuffer, "The unsigned int at position %d on page %d is: ", offset, page); Serial.print(printBuffer); - Serial.println(flash.readWord(addr)); + Serial.println(flash.readWord(page, offset)); printLine(); printNextCMD(); } @@ -213,16 +241,25 @@ void loop() { printSplash(); printLine(); Serial.println(F("This function will write a String of your choice to the page selected.")); - inputAddress(); + Serial.print(F("Please enter the number of the page you wish to write to: ")); + while (!Serial.available()) { + } + page = Serial.parseInt(); + Serial.println(page); + Serial.print(F("Please enter the position on the page (0-255) you wish to write to: ")); + while (!Serial.available()) { + } + offset = Serial.parseInt(); + Serial.println(offset); Serial.println(F("Please enter the String you wish to save: ")); while (!Serial.available()) { } readSerialStr(inputString); - if (flash.writeStr(addr, inputString)) { + if (flash.writeStr(page, offset, inputString)) { clearprintBuffer(); Serial.print(F("String '")); Serial.print(inputString); - sprintf(printBuffer, "' has been written to address %d", addr); + sprintf(printBuffer, "' has been written to position %d on page %d", offset, page); Serial.println(printBuffer); } else { @@ -236,12 +273,20 @@ void loop() { Serial.println(F(" Function 7 : Read String ")); printSplash(); printLine(); - Serial.print(F("This function will read a string from your address of choice: ")); - inputAddress(); + Serial.print(F("Please enter the number of the page the String you wish to read is on: ")); + while (!Serial.available()) { + } + page = Serial.parseInt(); + Serial.println(page); + Serial.print(F("Please enter the position of the String on the page (0-255) you wish to read: ")); + while (!Serial.available()) { + } + offset = Serial.parseInt(); + Serial.println(offset); clearprintBuffer(); - sprintf(printBuffer, "The String at address %d is: ", addr); + sprintf(printBuffer, "The String at position %d on page %d is: ", offset, page); Serial.print(printBuffer); - flash.readStr(addr, outputString); + flash.readStr(page, offset, outputString); Serial.println(outputString); printLine(); printNextCMD(); @@ -251,18 +296,18 @@ void loop() { Serial.println(F(" Function 8 : Write Page ")); printSplash(); printLine(); - Serial.println(F("This function will write a sequence of bytes (0-255) starting from your address of choice")); - Serial.print(F("Please enter the address you wish to write to: ")); + Serial.println(F("This function will write a sequence of bytes (0-255) to the page selected.")); + Serial.print(F("Please enter the number of the page you wish to write to: ")); while (!Serial.available()) { } - addr = Serial.parseInt(); - Serial.println(addr); - for (uint16_t i = 0; i < SPI_PAGESIZE; ++i) { + page = Serial.parseInt(); + Serial.println(page); + for (uint16_t i = 0; i < PAGESIZE; ++i) { pageBuffer[i] = i; } - if (flash.writeByteArray(addr, &pageBuffer[0], SPI_PAGESIZE)) { + if (flash.writeByteArray(page, 0, &pageBuffer[0], PAGESIZE)) { clearprintBuffer(); - sprintf(printBuffer, "Values from 0 to 255 have been written starting from the address %d", addr); + sprintf(printBuffer, "Values from 0 to 255 have been written to the page %d", page); Serial.println(printBuffer); printReadChoice(); while (!Serial.available()) { @@ -275,7 +320,7 @@ void loop() { } uint8_t outputType = Serial.parseInt(); Serial.println(outputType); - printPage(addr, outputType); + printPage(page, outputType); } } else { @@ -289,18 +334,18 @@ void loop() { Serial.println(F(" Function 9 : Read Page ")); printSplash(); printLine(); - Serial.println(F("This function will read 256 bytes from the address selected.")); - Serial.print(F("Please enter the address you wish to read: ")); + Serial.println(F("This function will read the entire page selected.")); + Serial.print(F("Please enter the number of the page you wish to read: ")); while (!Serial.available()) { } - addr = Serial.parseInt(); - Serial.println(addr); + page = Serial.parseInt(); + Serial.println(page); printOutputChoice(); while (!Serial.available()) { } uint8_t outputType = Serial.parseInt(); Serial.println(outputType); - printPage(addr, outputType); + printPage(page, outputType); printLine(); printNextCMD(); } @@ -332,14 +377,14 @@ void loop() { printSplash(); printLine(); Serial.println(F("This function will erase a 4KB sector.")); - Serial.print(F("Please enter the address you wish to erase: ")); + Serial.print(F("Please enter the number of the page you wish to erase: ")); while (!Serial.available()) { } - addr = Serial.parseInt(); - Serial.println(addr); - flash.eraseSector(addr); + page = Serial.parseInt(); + Serial.println(page); + flash.eraseSector(page, 0); clearprintBuffer(); - sprintf(printBuffer, "A 4KB sector containing address %d has been erased", addr); + sprintf(printBuffer, "A 4KB sector containing page %d has been erased", page); Serial.println(printBuffer); printReadChoice(); while (!Serial.available()) { @@ -352,7 +397,7 @@ void loop() { } uint8_t outputType = Serial.parseInt(); Serial.println(outputType); - printPage(addr, outputType); + printPage(page, outputType); } printLine(); printNextCMD(); @@ -363,14 +408,14 @@ void loop() { printSplash(); printLine(); Serial.println(F("This function will erase a 32KB block.")); - Serial.print(F("Please enter the address you wish to erase: ")); + Serial.print(F("Please enter the number of the page you wish to erase: ")); while (!Serial.available()) { } - addr = Serial.parseInt(); - Serial.println(addr); - flash.eraseBlock32K(addr); + page = Serial.parseInt(); + Serial.println(page); + flash.eraseBlock32K(page, 0); clearprintBuffer(); - sprintf(printBuffer, "A 32KB block containing address %d has been erased", addr); + sprintf(printBuffer, "A 32KB block containing page %d has been erased", page); Serial.println(printBuffer); printReadChoice(); while (!Serial.available()) { @@ -383,7 +428,7 @@ void loop() { } uint8_t outputType = Serial.parseInt(); Serial.println(outputType); - printPage(addr, outputType); + printPage(page, outputType); } printLine(); printNextCMD(); @@ -394,14 +439,14 @@ void loop() { printSplash(); printLine(); Serial.println(F("This function will erase a 64KB block.")); - Serial.print(F("Please enter the address you wish to erase: ")); + Serial.print(F("Please enter the number of the page you wish to erase: ")); while (!Serial.available()) { } - addr = Serial.parseInt(); - Serial.println(addr); - flash.eraseBlock64K(addr); + page = Serial.parseInt(); + Serial.println(page); + flash.eraseBlock64K(page, 0); clearprintBuffer(); - sprintf(printBuffer, "A 64KB block containing address %d has been erased", addr); + sprintf(printBuffer, "A 64KB block containing page %d has been erased", page); Serial.println(printBuffer); printReadChoice(); while (!Serial.available()) { @@ -414,7 +459,7 @@ void loop() { } uint8_t outputType = Serial.parseInt(); Serial.println(outputType); - printPage(addr, outputType); + printPage(page, outputType); } printLine(); printNextCMD(); @@ -484,16 +529,16 @@ void _printPageBytes(uint8_t *data_buffer, uint8_t outputType) { } //Reads a page of data and prints it to Serial stream. Make sure the sizeOf(uint8_t data_buffer[]) == 256. -void printPage(uint32_t _address, uint8_t outputType) { +void printPage(uint16_t page_number, uint8_t outputType) { if (!Serial) Serial.begin(115200); char buffer[24]; - sprintf(buffer, "Reading address (%04x)", _address); + sprintf(buffer, "Reading page (%04x)", page_number); Serial.println(buffer); - uint8_t data_buffer[SPI_PAGESIZE]; - flash.readByteArray(_address, &data_buffer[0], SPI_PAGESIZE); + uint8_t data_buffer[PAGESIZE]; + flash.readByteArray(page_number, 0, &data_buffer[0], PAGESIZE); _printPageBytes(data_buffer, outputType); } @@ -506,11 +551,10 @@ void printAllPages(uint8_t outputType) { Serial.println("Reading all pages"); uint8_t data_buffer[256]; - uint32_t maxAddr = flash.getCapacity(); - for (int a = 0; a < maxAddr; a++) { - flash.readByteArray(a, &data_buffer[0], 256); + uint32_t maxPage = flash.getMaxPage(); + for (int a = 0; a < maxPage; a++) { + flash.readByteArray(a, 0, &data_buffer[0], 256); _printPageBytes(data_buffer, outputType); - delay(100); } } @@ -550,12 +594,3 @@ void writeFail() { Serial.println("Data write failed"); } - -void inputAddress(void) { - Serial.print(F("Please enter the address (0 - CAPACITY) you wish to access: ")); - while (!Serial.available()) { - } - addr = Serial.parseInt(); - Serial.println(addr); -} - diff --git a/examples/getAddressEx/.trinket.test.skip b/examples/getAddressEx/.trinket.test.skip new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/examples/getAddressEx/.trinket.test.skip @@ -0,0 +1 @@ + diff --git a/examples/getAddressEx/getAddressEx.ino b/examples/getAddressEx/getAddressEx.ino index 6a84572..d391801 100644 --- a/examples/getAddressEx/getAddressEx.ino +++ b/examples/getAddressEx/getAddressEx.ino @@ -41,7 +41,6 @@ byte testByte[] = { 3, 245, 84, 100 }; -//SPIFlash flash(SS1, &SPI1); //Use this constructor if using an SPI bus other than the default SPI. Only works with chips with more than one hardware SPI bus SPIFlash flash; void getAddresses(); diff --git a/examples/readWriteString/.trinket.test.skip b/examples/readWriteString/.trinket.test.skip new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/examples/readWriteString/.trinket.test.skip @@ -0,0 +1 @@ + diff --git a/examples/readWriteString/readWriteString.ino b/examples/readWriteString/readWriteString.ino index 64c6572..84ed6a2 100644 --- a/examples/readWriteString/readWriteString.ino +++ b/examples/readWriteString/readWriteString.ino @@ -2,10 +2,10 @@ |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| | readWriteString.ino | | SPIFlash library | - | v 3.0.0 | + | v 2.5.0 | |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| | Marzogh | - | 29.05.2017 | + | 16.11.2016 | |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| | | | This program shows the method of reading a string from the console and saving it to flash memory | @@ -14,7 +14,8 @@ */ #include -uint32_t strAddr; +int strPage, strSize; +byte strOffset; #if defined(ARDUINO_SAMD_ZERO) && defined(SERIAL_PORT_USBVIRTUAL) // Required for Serial on Zero based boards @@ -29,41 +30,56 @@ uint32_t strAddr; #define RANDPIN A0 #endif -//SPIFlash flash(SS1, &SPI1); //Use this constructor if using an SPI bus other than the default SPI. Only works with chips with more than one hardware SPI bus SPIFlash flash; bool readSerialStr(String &inputStr); void setup() { +#ifndef __AVR_ATtiny85__ Serial.begin(BAUD_RATE); +#endif #if defined (ARDUINO_SAMD_ZERO) || (__AVR_ATmega32U4__) while (!Serial) ; // Wait for Serial monitor to open #endif flash.begin(); +#if defined __AVR_ATtiny85__ + randomSeed(65535537); +#else randomSeed(analogRead(RANDPIN)); - strAddr = random(0, flash.getCapacity()); +#endif + strPage = random(0, 4095); + strOffset = random(0, 255); String inputString = "This is a test String"; - flash.writeStr(strAddr, inputString); + flash.writeStr(strPage, strOffset, inputString); +#ifndef __AVR_ATtiny85__ Serial.print(F("Written string: ")); - Serial.println(inputString); - Serial.print(F("To address: ")); - Serial.println(strAddr); + Serial.print(inputString); + Serial.print(F(" to page ")); + Serial.print(strPage); + Serial.print(F(", at offset ")); + Serial.println(strOffset); +#endif String outputString = ""; - if (flash.readStr(strAddr, outputString)) { + if (flash.readStr(strPage, strOffset, outputString)) { +#ifndef __AVR_ATtiny85__ Serial.print(F("Read string: ")); - Serial.println(outputString); - Serial.print(F("From address: ")); - Serial.println(strAddr); + Serial.print(outputString); + Serial.print(F(" from page ")); + Serial.print(strPage); + Serial.print(F(", at offset ")); + Serial.println(strOffset); +#endif } - while (!flash.eraseSector(strAddr)); + while (!flash.eraseSector(strPage, 0)); } void loop() { } +#ifndef __AVR_ATtiny85__ //Reads a string from Serial bool readSerialStr(String &inputStr) { if (!Serial) @@ -75,3 +91,4 @@ bool readSerialStr(String &inputStr) { } return false; } +#endif diff --git a/examples/tinyFlashDiagnostics/Attiny_functions.ino b/examples/tinyFlashDiagnostics/Attiny_functions.ino new file mode 100644 index 0000000..1091824 --- /dev/null +++ b/examples/tinyFlashDiagnostics/Attiny_functions.ino @@ -0,0 +1,279 @@ +/* + |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| + | Attiny_functions.ino | + | SPIFlash library | + | v 2.7.0 | + |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| + | Marzogh | + | 26.04.2017 | + |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| + | | + | For a full diagnostics rundown - with error codes and details of the errors | + | uncomment #define RUNDIAGNOSTIC in SPIFlash.cpp in the library before compiling | + | and loading this application onto your Arduino. | + | | + |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| +*/ + +#if defined (__AVR_ATtiny85__) + +void startup(void) { +#if defined (CHIPSIZE) + flash.begin(CHIPSIZE); //use flash.begin(CHIPSIZE) if using non-Winbond flash +#else + flash.begin(); +#endif +} + +void setWrittenStatus(void) { + dataPacket.writeStatus |= PASS; + dataPacket.writeStatus |= ATTINY85; +} + +void saveResults() { + flash.writeAnything(addr, dataPacket); +} + +void setTest(uint8_t _t) { + dataPacket.test |= _t; +} + +void intDiag(uint32_t _addr) { + //Set variables + word _data, _d; + _data = 4520; + setTest(INT); + + //Test & time Write function + if (flash.writeWord(_addr, _data)) { + dataPacket.Status |= iW; + } + else + { + dataPacket.Status &= !iW; + } + + + //Test & time Read function + _d = flash.readWord(_addr); + if (_d == _data) { + dataPacket.Status |= iR; + } + else + { + dataPacket.Status &= !iR; + } + + //Erase the sector previously written to + flash.eraseSector(_addr); +} + +void floatDiag(uint32_t _addr) { + //Set variables + float _data, _d; + _data = 3.1412; + setTest(FLOAT); + + //Test & time Write function + if (flash.writeFloat(_addr, _data)) { + dataPacket.Status |= fW; + } + else + { + dataPacket.Status &= !fW; + } + + + //Test & time Read function + _d = flash.readFloat(_addr); + if (_d == _data) { + dataPacket.Status |= fR; + } + else + { + dataPacket.Status &= !fR; + } + + //Erase the sector previously written to + flash.eraseSector(_addr); +} + +void structDiag(uint32_t _addr) { + //Set variables + struct Configuration { // Voltage ouput fR;om potential divider to Analog input + float RLDR; // Resistance calculation of potential divider with LDR + bool light; + uint8_t adc; + }; + Configuration _data, _d; + _data.RLDR = 89.32; + _data.light = true; + _data.adc = 5; + setTest(STRUCT); + + //Test & time Write function + if (flash.writeAnything(_addr, _data)) { + dataPacket.Status |= scW; + } + else + { + dataPacket.Status &= !scW; + } + + //Test & time Read function + if (flash.readAnything(_addr, _d)) { + if (_d.RLDR == _data.RLDR && _d.light == _data.light && _d.adc == _data.adc) { + dataPacket.Status |= scR; + } + else + { + dataPacket.Status &= !scR; + } + } + else { + dataPacket.Status &= !scR; + } + + //Erase the sector previously written to + flash.eraseSector(_addr); +} + +void stringDiag(uint32_t _addr) { + //Set variables + String _d = ""; + String _data = "1Ab# D"; + setTest(STRING); + + //Test & time Write function + if (flash.writeStr(_addr, _data)) { + dataPacket.Status |= sgW; + } + else + { + dataPacket.Status &= !sgW; + } + + + //Test & time Read function + if (flash.readStr(_addr, _d)) { + if (_d == _data) { + dataPacket.Status |= sgR; + } + else + { + dataPacket.Status &= !sgR; + } + //Erase the sector previously written to + flash.eraseSector(_addr); + } +} + +void arrayDiag(uint32_t _addr) { + //Set variables + uint8_t _data[20], _d[20]; + setTest(ARRAY); + + for (uint8_t i = 0; i < 21; i++) { + _data[i] = i; + } + + //Test & time Write function + if (flash.writeByteArray(_addr, _data, 20)) { + dataPacket.Status |= aW; + } + else + { + dataPacket.Status &= !aW; + } + + + //Test & time Read function + if (flash.readByteArray(_addr, _d, 20)) { + for (uint8_t i = 0; i < 21; i++) + if (_d[i] != _data[i]) { + dataPacket.Status &= aR; + break; + } + dataPacket.Status |= aR; + } + //Erase the sector previously written to + flash.eraseSector(_addr); +} + +void eraseDiag(uint32_t _addr) { + setTest(ERASE); + + //Test & time eraseBlock32K function + if (flash.eraseBlock32K(_addr)) { + dataPacket.Status |= eB; + } + else + { + dataPacket.Status &= !eB; + } + + //Test & time eraseChip function + if (flash.eraseChip()) { + dataPacket.Status |= eC; + } + else + { + dataPacket.Status &= !eC; + } +} + +void powerDiag(void) { + setTest(ERASE); + + //Test & time powerDown function + if (flash.powerDown()) { + dataPacket.Status |= pOFF; + } + else + { + dataPacket.Status &= !pOFF; + } + + //Test & time powerUp function + if (flash.powerUp()) { + dataPacket.Status |= pON; + } + else + { + dataPacket.Status &= !pON; + } +} + +void diagnose(void) { + do { + flash.eraseChip(); + } while (prevWritten()); + + setWrittenStatus(); + + uint32_t testaddr = random(STARTADDR, 0xFFFFF); +#if defined INTTEST + intDiag(testaddr); +#endif +#if defined FLOATTEST + floatDiag(testaddr); +#endif +#if defined STRUCTTEST + structDiag(testaddr); +#endif +#if defined STRINGTEST + stringDiag(testaddr); +#endif +#if defined ARRAYTEST + arrayDiag(testaddr); +#endif +#if defined ERASETEST + eraseDiag(testaddr); +#endif +#if defined POWERTEST + powerDiag(); +#endif + saveResults(); +} + +#endif diff --git a/examples/tinyFlashDiagnostics/NonAttiny_functions.ino b/examples/tinyFlashDiagnostics/NonAttiny_functions.ino new file mode 100644 index 0000000..7b364cc --- /dev/null +++ b/examples/tinyFlashDiagnostics/NonAttiny_functions.ino @@ -0,0 +1,463 @@ +/* + |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| + | NonAttiny_functions.ino | + | SPIFlash library | + | v 2.7.0 | + |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| + | Marzogh | + | 26.04.2017 | + |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| + | | + | For a full diagnostics rundown - with error codes and details of the errors | + | uncomment #define RUNDIAGNOSTIC in SPIFlash.cpp in the library before compiling | + | and loading this application onto your Arduino. | + | | + |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| +*/ + +#if !defined (__AVR_ATtiny85__) +void startup(void) { + Serial.begin(BAUD_RATE); +#if defined (ARDUINO_ARCH_SAMD) || (__AVR_ATmega32U4__) + while (!Serial) ; // Wait for Serial monitor to open +#endif + Serial.print(F("Initialising Flash memory")); + for (int i = 0; i < 10; ++i) + { + Serial.print(F(".")); + } + Serial.println(); +#if defined (CHIPSIZE) + flash.begin(CHIPSIZE); //use flash.begin(CHIPSIZE) if using non-Winbond flash (Refer to '#define CHIPSIZE' above) +#else + flash.begin(); +#endif + Serial.println(); + Serial.println(); + +#if defined (ARDUINO_ARCH_ESP32) + randomSeed(65535537); +#else + randomSeed(analogRead(RANDPIN)); +#endif +} + +void clearprintBuffer(char *bufPtr) +{ + for (uint8_t i = 0; i < 128; i++) { + //printBuffer[i] = 0; + *bufPtr++ = 0; + } +} + +void printLine() { + for (uint8_t i = 0; i < 230; i++) { + Serial.print(F("-")); + } + Serial.println(); +} + +void printPass() { + Serial.print(F("Pass")); +} + +void printFail() { + Serial.print(F("Fail")); +} + +void printTab(uint8_t a, uint8_t b) { + for (uint8_t i = 0; i < a; i++) { + Serial.print(F("\t")); + } + if (b > 0) { + Serial.print("||"); + for (uint8_t i = 0; i < b; i++) { + Serial.print(F("\t")); + } + } +} + +void printTime(uint32_t _wTime, uint32_t _rTime) { + printTab(2, 1); + printTimer(_wTime); + printTab(2, 1); + printTimer(_rTime); +} + +void printTimer(uint32_t _us) { + + if (_us > 1000000) { + float _s = _us / (float)1000000; + Serial.print(_s, 4); + Serial.print(" s"); + } + else if (_us > 10000) { + float _ms = _us / (float)1000; + Serial.print(_ms, 4); + Serial.print(" ms"); + } + else { + Serial.print(_us); + Serial.print(F(" us")); + } +} + +void getID() { + char printBuffer[128]; + printLine(); + for (uint8_t i = 0; i < 68; i++) { + Serial.print(F(" ")); + } + Serial.print(F("SPIFlash Library version")); +#ifdef LIBVER + uint8_t _ver, _subver, _bugfix; + flash.libver(&_ver, &_subver, &_bugfix); + clearprintBuffer(&printBuffer[1]); + sprintf(printBuffer, ": %d.%d.%d", _ver, _subver, _bugfix); + Serial.println(printBuffer); +#else + Serial.println(F("< 2.5.0")); +#endif + printLine(); + + for (uint8_t i = 0; i < 80; i++) { + Serial.print(F(" ")); + } + Serial.println(F("Get ID")); + printLine(); + uint8_t b1, b2; + uint16_t b3; + uint32_t JEDEC = flash.getJEDECID(); + uint32_t maxPage = flash.getMaxPage(); + uint32_t capacity = flash.getCapacity(); + b1 = (JEDEC >> 16); + b2 = (JEDEC >> 8); + b3 = (JEDEC >> 0); + + + printLine(); + //---------------------------------------------------------------------------------------------// + + clearprintBuffer(&printBuffer[1]); + sprintf(printBuffer, "\t\t\tJEDEC ID: %04lxh", JEDEC); + Serial.println(printBuffer); + clearprintBuffer(&printBuffer[1]); + sprintf(printBuffer, "\t\t\tManufacturer ID: %02xh\n\t\t\tMemory Type: %02xh\n\t\t\tCapacity: %lu bytes\n\t\t\tMaximum pages: %lu", b1, b2, capacity, maxPage); + Serial.println(printBuffer); +} + +bool checkPage(uint8_t *data_buffer) { + for (int i = 0; i < 256; i++) { + if (data_buffer[i] != i) + return false; + } + return true; +} + +void printHeader(uint8_t _t) { + if (_t == DATA_FUNCTION && data_header == false) { + printLine(); + + for (uint8_t i = 0; i < 79; i++) { + Serial.print(F(" ")); + } + Serial.println(F("Data Check")); + printLine(); + + Serial.println(F("\tData Type\t||\tWrite Check\t||\tRead Check\t")); + printLine(); + + data_header = true; + } + if (_t == OTHER_FUNCTION && power_header == false) { + printLine(); + + for (uint8_t i = 0; i < 74; i++) { + Serial.print(F(" ")); + } + Serial.println(F("Other Function Check")); + printLine(); + + Serial.println(F("\tTest Type\t||\tStatus")); + printLine(); + + power_header = true; + } +} +void diagnose() { + getID(); + + uint16_t _stat; + if (prevWritten) { + if (dataPacket.test & INT) { + printHeader(DATA_FUNCTION); + intDiag(); + } + if (dataPacket.test & FLOAT) { + printHeader(DATA_FUNCTION); + floatDiag(); + } + if (dataPacket.test & STRING) { + printHeader(DATA_FUNCTION); + stringDiag(); + } + if (dataPacket.test & STRUCT) { + printHeader(DATA_FUNCTION); + structDiag(); + } + if (dataPacket.test & ARRAY) { + printHeader(DATA_FUNCTION); + arrayDiag(); + } + if (dataPacket.test & ERASE) { + printHeader(OTHER_FUNCTION); + eraseDiag(); + } + if (dataPacket.test & POWER) { + printHeader(OTHER_FUNCTION); + powerDiag(); + } + } + else { + Serial.println(F("No data found on chip. Please run this sketch on a an ATTiny85 connected to this flash chip first")); + } +} + +void intDiag(void) { + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Integer // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + printTab(1, 0); + Serial.print(F("Integer")); + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Write // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + printTab(2, 1); + if (dataPacket.Status & iW) { + printPass(); + } + else { + printFail(); + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Read // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + printTab(2, 1); + if (dataPacket.Status & iR) { + printPass(); + } + else { + printFail(); + } + Serial.println(); + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + //-----------------------------------------------------------------------------------------------------------------------------------------------------// +} + +void floatDiag(void) { + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Float // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + printTab(1, 0); + Serial.print(F("Float")); + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Write // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + printTab(2, 1); + if (dataPacket.Status & fW) { + printPass(); + } + else { + printFail(); + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Read // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + printTab(2, 1); + if (dataPacket.Status & fR) { + printPass(); + } + else { + printFail(); + } + Serial.println(); + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + //-----------------------------------------------------------------------------------------------------------------------------------------------------// +} + +void stringDiag(void) { + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Integer // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + printTab(1, 0); + Serial.print(F("String")); + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Write // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + printTab(2, 1); + if (dataPacket.Status & sgW) { + printPass(); + } + else { + printFail(); + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Read // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + printTab(2, 1); + if (dataPacket.Status & sgR) { + printPass(); + } + else { + printFail(); + } + Serial.println(); + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + //-----------------------------------------------------------------------------------------------------------------------------------------------------// +} + +void structDiag(void) { + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Integer // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + printTab(1, 0); + Serial.print(F("Integer")); + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Write // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + printTab(2, 1); + if (dataPacket.Status & scW) { + printPass(); + } + else { + printFail(); + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Read // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + printTab(2, 1); + if (dataPacket.Status & scR) { + printPass(); + } + else { + printFail(); + } + Serial.println(); + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + //-----------------------------------------------------------------------------------------------------------------------------------------------------// +} + +void arrayDiag(void) { + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Integer // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + printTab(1, 0); + Serial.print(F("Array")); + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Write // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + printTab(2, 1); + if (dataPacket.Status & aW) { + printPass(); + } + else { + printFail(); + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Read // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + printTab(2, 1); + if (dataPacket.Status & aR) { + printPass(); + } + else { + printFail(); + } + Serial.println(); + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + //-----------------------------------------------------------------------------------------------------------------------------------------------------// +} + +void eraseDiag(void) { + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Erase Block // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + printTab(1, 0); + Serial.print(F("Erase Block")); + printTab(2, 1); + if (dataPacket.Status & eB) { + printPass(); + } + else { + printFail(); + } + Serial.println(); + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Erase Chip // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + printTab(1, 0); + Serial.print(F("Erase Chip")); + printTab(2, 1); + if (dataPacket.Status & eC) { + printPass(); + } + else { + printFail(); + } + Serial.println(); + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + //-----------------------------------------------------------------------------------------------------------------------------------------------------// +} + +void powerDiag(void) { + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Power on // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + printTab(1, 0); + Serial.print(F("Power off")); + printTab(2, 1); + if (dataPacket.Status & pOFF) { + printPass(); + } + else { + printFail(); + } + Serial.println(); + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Power off // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + printTab(1, 0); + Serial.print(F("Power on")); + printTab(2, 1); + if (dataPacket.Status & pON) { + printPass(); + } + else { + printFail(); + } + Serial.println(); + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + //-----------------------------------------------------------------------------------------------------------------------------------------------------// +} +#endif diff --git a/examples/tinyFlashDiagnostics/Notes.cpp b/examples/tinyFlashDiagnostics/Notes.cpp new file mode 100644 index 0000000..1abbda2 --- /dev/null +++ b/examples/tinyFlashDiagnostics/Notes.cpp @@ -0,0 +1,46 @@ +/* + |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| + | Notes.cpp | + | SPIFlash library | + | v 2.7.0 | + |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| + | Marzogh | + | 26.04.2017 | + |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| + | | + | For a full diagnostics rundown - with error codes and details of the errors | + | uncomment #define RUNDIAGNOSTIC in SPIFlash.cpp in the library before compiling | + | and loading this application onto your Arduino. | + | | + |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| +*/ + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// +// // +// Structure of the status integer // +// _____________________________________________________________________________________ // +// | Bit number | // +// |_____________________________________________________________________________________| // +// | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | // +// |-------------------------------------------------------------------------------------| // +// | RES | RES | pOFF | pON | eC | eB | aR | aW | // +// |_____________________________________________________________________________________| // +// | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | // +// |-------------------------------------------------------------------------------------| // +// | scR | scW | sgR | sgW | fR | fW | iR | iW | // +// |_____________________________________________________________________________________| // +// // +// // +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// +// // +// Structure of the test byte // +// _____________________________________________________________________________________ // +// | Bit number | // +// |_____________________________________________________________________________________| // +// | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | // +// |-------------------------------------------------------------------------------------| // +// | RES | POWER | ERASE | ARRAY | STRUCT | STRING | FLOAT | INT | // +// |_____________________________________________________________________________________| // +// // +// // +//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!// diff --git a/examples/tinyFlashDiagnostics/tinyFlashDiagnostics.ino b/examples/tinyFlashDiagnostics/tinyFlashDiagnostics.ino new file mode 100644 index 0000000..4eb58c7 --- /dev/null +++ b/examples/tinyFlashDiagnostics/tinyFlashDiagnostics.ino @@ -0,0 +1,80 @@ +/* + |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| + | tinyFlashDiagnostics.ino | + | SPIFlash library | + | v 2.6.0 | + |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| + | Marzogh | + | 16.04.2017 | + |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| + | | + | For a full diagnostics rundown - with error codes and details of the errors | + | uncomment #define RUNDIAGNOSTIC in SPIFlash.cpp in the library before compiling | + | and loading this application onto your Arduino. | + | | + |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| +*/ + +#include "vars.h" + +#include + +//Define a flash memory size (if using non-Winbond memory) according to the list in defines.h +//#define CHIPSIZE MB64 + + //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!// + // // + // ___ _____ _____ _ _____ _____ // + // / _ \_ _|_ _(_) | _ || ___| // + // / /_\ \| | | | _ _ __ _ _ \ V / |___ \ // + // | _ || | | | | | '_ \| | | |/ _ \ \ \ // + // | | | || | | | | | | | | |_| | |_| |/\__/ / // + // \_| |_/\_/ \_/ |_|_| |_|\__, \_____/\____/ // + // __/ | // + // |___/ // + // // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Uncomment any of the tests below as required. // + // Remember, the ATTiny has a limited amount of SRAM, so only a limited number // + // of tests can be run concurrently. // + // // + //|------------------------------------------//----------------------------------------------|// + //| List of tests // _status bits |// + //|------------------------------------------//----------------------------------------------|// + #define INTTEST // iW, iR |// + #define FLOATTEST // fW, fR |// + //#define STRINGTEST // sgW, sgR |// + #define STRUCTTEST // scW, scR |// + //#define ARRAYTEST // aW, aR |// + #define ERASETEST // eB, eC |// + #define POWERTEST // pON, pOFF |// + //|------------------------------------------//----------------------------------------------|// + +SPIFlash flash; + +void setup() { + startup(); + diagnose(); +} + +void loop() { + +} + +//************************************************************************************************// +// // +// Non-board specific code // +// // +//************************************************************************************************// + +bool prevWritten() { + addr = flash.getAddress(sizeof(dataPacket)); + flash.readAnything(addr, dataPacket); + if (dataPacket.writeStatus != 0xFF) { + return true; + } + else { + return false; + } +} +//************************************************************************************************// diff --git a/examples/tinyFlashDiagnostics/vars.h b/examples/tinyFlashDiagnostics/vars.h new file mode 100644 index 0000000..378a8ab --- /dev/null +++ b/examples/tinyFlashDiagnostics/vars.h @@ -0,0 +1,96 @@ +/* + |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| + | vars.h | + | SPIFlash library | + | v 2.7.0 | + |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| + | Marzogh | + | 26.04.2017 | + |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| + | | + | For a full diagnostics rundown - with error codes and details of the errors | + | uncomment #define RUNDIAGNOSTIC in SPIFlash.cpp in the library before compiling | + | and loading this application onto your Arduino. | + | | + |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| +*/ +//************************************************************************************************// +// // +// Non-board specific code // +// // +//************************************************************************************************// +#define PASS 0x01 +#define FAIL 0x00 +#define ATTINY85 0x02 + +#define INT 0x01 +#define FLOAT 0x02 +#define STRING 0x04 +#define STRUCT 0x08 +#define ARRAY 0x10 +#define ERASE 0x20 +#define POWER 0x40 + + +#define iW 0x0001 +#define iR 0x0002 +#define fW 0x0004 +#define fR 0x0008 +#define sgW 0x0010 +#define sgR 0x0020 +#define scW 0x0040 +#define scR 0x0080 +#define aW 0x0100 +#define aR 0x0200 +#define eB 0x0400 +#define eC 0x0800 +#define pON 0x1000 +#define pOFF 0x2000 + +struct _dataPacket { + uint8_t writeStatus; + uint8_t test; + uint16_t Status; +}; +_dataPacket dataPacket; +uint32_t addr; + +//************************************************************************************************// +// // +// If using an ATTiny85 board // +// // +//************************************************************************************************// + +#if defined (__AVR_ATtiny85__) + +#define STARTADDR ((sizeof(dataPacket))*2) + +#endif + +//************************************************************************************************// +// // +// If using a non ATTiny85 board // +// // +//************************************************************************************************// +#if !defined (__AVR_ATtiny85__) + +#if defined(ARDUINO_SAMD_ZERO) && defined(SERIAL_PORT_USBVIRTUAL) +// Required for Serial on Zero based boards +#define Serial SERIAL_PORT_USBVIRTUAL +#endif + +#if defined (SIMBLEE) +#define BAUD_RATE 250000 +#define RANDPIN 1 +#else +#define BAUD_RATE 115200 +#define RANDPIN A0 +#endif + +#define DATA_FUNCTION 0x03 +#define OTHER_FUNCTION 0x04 + +bool data_header, power_header = false; + +#endif + diff --git a/examples/tinyFlashTester/tinyFlashTester.ino b/examples/tinyFlashTester/tinyFlashTester.ino new file mode 100644 index 0000000..173c20e --- /dev/null +++ b/examples/tinyFlashTester/tinyFlashTester.ino @@ -0,0 +1,69 @@ +/* + |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| + | Struct_writer.ino | + | SPIFlash library | + | v 2.7.0 | + |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| + | Marzogh | + | 19.04.2017 | + |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| + | | + | This program writes a struct to a random location on your flash memory chip and reads it back. | + | This particular program is designed to test the library with an ATTiny85 chip. Follow the steps below to make sure the test runs as it should | + | 1. Compile and run this program on an ATTiny85 board to which an SPIFlash memory has been wired in. | + | 2. Swap Flash chip over to another supported board (with Serial IO) and compile and run this program again | + | 3. Check serial output to see if data has been written/read properly. | + | | + |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| +*/ + +#include + +SPIFlash flash; + +struct Configuration { + float lux; + float vOut; // Voltage ouput from potential divider to Analog input + float RLDR; // Resistance calculation of potential divider with LDR + bool light; + uint8_t adc; +}; +Configuration configuration; + +void setup() { + flash.begin(); + uint32_t _addr = 34235; + +#if defined (__AVR_ATtiny85__) + configuration.lux = 98.43; + configuration.vOut = 4.84; + configuration.RLDR = 889.32; + configuration.light = true; + configuration.adc = 5; + flash.writeAnything(_addr, configuration); +#else + Serial.println("Data Written to flash was: "); + Serial.println(configuration.lux); + Serial.println(configuration.vOut); + Serial.println(configuration.RLDR); + Serial.println(configuration.light); + Serial.println(configuration.adc); + configuration.lux = 0; + configuration.vOut = 0; + configuration.RLDR = 0; + configuration.light = 0; + configuration.adc = 0; + flash.readAnything(_addr, configuration); + flash.eraseSector(_addr, 0); + Serial.println("After reading"); + Serial.println(configuration.lux); + Serial.println(configuration.vOut); + Serial.println(configuration.RLDR); + Serial.println(configuration.light); + Serial.println(configuration.adc); +#endif + +} + +void loop() { +} diff --git a/extras/Changes.log b/extras/Changes.log old mode 100755 new mode 100644 index 8d070c1..a45333e --- a/extras/Changes.log +++ b/extras/Changes.log @@ -2,65 +2,6 @@ // SPIFlash Library // // Changes log // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// -// Version 3.0.0 // -// Author: Prajwal Bhattaram // -// 09.08.2017 // -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// -To check: -Bugs Squashed: ---> The writeByteArray() & writeCharArray() bug that occurred when writing arrays that spanned page boundaries (squashed in v2.5.0), stayed around to haunt the other functions. Writing any data larger than a single byte that spanned page boundaries would cause the data to wrap around to the beginning of the page. The likelihood of this occurring was slim - no one has reported it to date. However, just in case, this has now been squashed in this release. - -Deprecations: ---> Going forward the ATTiny85 is no longer officially supported. ---> The library no longer supports using the page number + offset combination instead of addresses. If your code requires you to use a page number + offset combination, use the following code to help - address = (pagenumber << 8) + offset. - _____________________________________ - (32 bit) | (16 bit) | (8 bit) ---> The constructor no longer takes the pageOverflow variable as an argument. Page overflow is globally enabled by default and can be disabled by including a "#define DISABLEOVERFLOW" at the beginning of the user code. - -New Boards supported: ---> Nucleo-F091RC ---> Adafruit Feather M0 - -New Flash manufacturers supported: ---> Microchip (SST25 & SST26 series) ---> Cypress ---> Spansion - -Enhancements: ---> Confirmed to work with SPANSION/CYPRESS & MICROCHIP (Both SST25 & SST26 series). ---> If not using an officially supported chip, use the following variation of flash.begin() : - flash.begin(flashChipSize); - - where flashChipSize is indicated in Bytes, Kilobytes or Megabytes. (Refer to the next two items in this change log) ---> Including 'flashChipSize' in flash.begin() compiles more efficiently than in prvious versions. ---> The way memory size is indicated by the users in flash.begin(flashChipSize) has changed - please refer to defines.h or the wiki for further information. The new method enables users to define any custom size unlike the previous version where only a limited number of predetermined sizes were available to use. ---> Library faster than before (Refer to Library speed comparison in the extras folder for timing details): - - Improvements in speed in v3.0.0 when compared to v2.7.0 (values in percentage of time v3.0.0 is faster than v2.7.0) - (+) writeByte -> +3% - (+) writeChar -> +6% - (+) writeWord -> +3% - (+) writeShort -> +5% - (+) writeULong -> +7% - (+) writeLong | readLong -> +7% | +7% - (+) writeFloat -> +7% - (+) writeStr | readStr -> +57% | +61% - (+) writeAnything | readAnything (struct) -> +25% | +20% - (+) writeByteArray | readByteArray (256 bytes) -> +18% | +45% - (+) eraseSector -> +99% - (+) eraseBlock32K -> +99.4% - (+) eraseBlock64K -> +99.5% - (+) eraseChip -> +12% - ---> Constructor changed to enable user to choose one of multiple SPI ports - if available. Look at wiki for further info ---> When RUNDIAGNOSTIC is uncommented in SPIFlash.h, users now have access to a new function called flash.functionRunTime() which can be called after any library I/O function is run. flash.functionRunTime() returns the time taken by the previous function to run, in microseconds (as a float). An example use case can be found when the FlashDiagnostics sketch is run with RUNDIAGNOSTIC uncommented. ---> _notBusy() is faster ---> Completely re-written FlashDiagnostics - uses fewer resources, compatible with more chips and boards ---> All functions except the Byte/Char Array Read/Write functions now call an internal _write/_read function for increased ease of compilation, execution and troubleshooting ---> Restructured the internal _troubleshoot() function to be better human readable and faster to compile. ---> Added a function `getUniqueID()` which returns the unique ID of the flash memory chip as a 64-bit integer. -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// // Version 2.7.0 // // Author: Prajwal Bhattaram // // 17.04.2017 // diff --git a/extras/DMASAMD.cpp b/extras/DMASAMD.cpp deleted file mode 100644 index 678627b..0000000 --- a/extras/DMASAMD.cpp +++ /dev/null @@ -1,158 +0,0 @@ -/* Arduino SPIFlash Library v.2.6.0 - * Copyright (C) 2017 by Prajwal Bhattaram - * Created by Prajwal Bhattaram - 30/09/2016 - * Modified by Prajwal Bhattaram - 14/04/2017 - * Original code from @manitou48 - * - * This file is part of the Arduino SPIFlash Library. This library is for - * Winbond NOR flash memory modules. In its current form it enables reading - * and writing individual data variables, structs and arrays from and to various locations; - * reading and writing pages; continuous read functions; sector, block and chip erase; - * suspending and resuming programming/erase and powering down for low power operation. - * - * This Library is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This Library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License v3.0 - * along with the Arduino SPIFlash Library. If not, see - * . - */ - -#include "SPIFlash.h" - -//--------------------------- Private Arduino Zero Variables ----------------------------// - Sercom *sercom = (Sercom *)ZERO_SPISERCOM; //Set SPI SERCOM - // DMA 12 channels - typedef struct { - uint16_t btctrl; - uint16_t btcnt; - uint32_t srcaddr; - uint32_t dstaddr; - uint32_t descaddr; - } dmacdescriptor ; - volatile dmacdescriptor wrb[12] __attribute__ ((aligned (16))); - dmacdescriptor descriptor_section[12] __attribute__ ((aligned (16))); - dmacdescriptor descriptor __attribute__ ((aligned (16))); - - static uint32_t chnltx = 0, chnlrx = 1; // DMA channels - enum XfrType { DoTX, DoRX, DoTXRX}; - static XfrType xtype; - static uint8_t rxsink[1], txsrc[1] = {0xff}; - volatile uint32_t dmadone; - -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// -// Private functions used by Arduino Zero DMA operations // -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// - -void SPIFlash::_zeroDMAC_Handler(void) { - // interrupts DMAC_CHINTENCLR_TERR DMAC_CHINTENCLR_TCMPL DMAC_CHINTENCLR_SUSP - uint8_t active_channel; - - // disable irqs ? - __disable_irq(); - active_channel = DMAC->INTPEND.reg & DMAC_INTPEND_ID_Msk; // get channel number - DMAC->CHID.reg = DMAC_CHID_ID(active_channel); - dmadone = DMAC->CHINTFLAG.reg; - DMAC->CHINTFLAG.reg = DMAC_CHINTENCLR_TCMPL; // clear - DMAC->CHINTFLAG.reg = DMAC_CHINTENCLR_TERR; - DMAC->CHINTFLAG.reg = DMAC_CHINTENCLR_SUSP; - __enable_irq(); -} - -void SPIFlash::_zeroDma_init() { - // probably on by default - PM->AHBMASK.reg |= PM_AHBMASK_DMAC ; - PM->APBBMASK.reg |= PM_APBBMASK_DMAC ; - NVIC_EnableIRQ( DMAC_IRQn ) ; - - DMAC->BASEADDR.reg = (uint32_t)descriptor_section; - DMAC->WRBADDR.reg = (uint32_t)wrb; - DMAC->CTRL.reg = DMAC_CTRL_DMAENABLE | DMAC_CTRL_LVLEN(0xf); -} - -void SPIFlash::_zeroSpi_xfr(void *txdata, void *rxdata, size_t n) { - uint32_t temp_CHCTRLB_reg; - - // set up transmit channel - DMAC->CHID.reg = DMAC_CHID_ID(chnltx); - DMAC->CHCTRLA.reg &= ~DMAC_CHCTRLA_ENABLE; - DMAC->CHCTRLA.reg = DMAC_CHCTRLA_SWRST; - DMAC->SWTRIGCTRL.reg &= (uint32_t)(~(1 << chnltx)); - temp_CHCTRLB_reg = DMAC_CHCTRLB_LVL(0) | - DMAC_CHCTRLB_TRIGSRC(SERCOM4_DMAC_ID_TX) | DMAC_CHCTRLB_TRIGACT_BEAT; - DMAC->CHCTRLB.reg = temp_CHCTRLB_reg; - DMAC->CHINTENSET.reg = DMAC_CHINTENSET_MASK ; // enable all 3 interrupts - descriptor.descaddr = 0; - descriptor.dstaddr = (uint32_t) &sercom->SPI.DATA.reg; - descriptor.btcnt = n; - descriptor.srcaddr = (uint32_t)txdata; - descriptor.btctrl = DMAC_BTCTRL_VALID; - if (xtype != DoRX) { - descriptor.srcaddr += n; - descriptor.btctrl |= DMAC_BTCTRL_SRCINC; - } - memcpy(&descriptor_section[chnltx],&descriptor, sizeof(dmacdescriptor)); - - // rx channel enable interrupts - DMAC->CHID.reg = DMAC_CHID_ID(chnlrx); - DMAC->CHCTRLA.reg &= ~DMAC_CHCTRLA_ENABLE; - DMAC->CHCTRLA.reg = DMAC_CHCTRLA_SWRST; - DMAC->SWTRIGCTRL.reg &= (uint32_t)(~(1 << chnlrx)); - temp_CHCTRLB_reg = DMAC_CHCTRLB_LVL(0) | - DMAC_CHCTRLB_TRIGSRC(SERCOM4_DMAC_ID_RX) | DMAC_CHCTRLB_TRIGACT_BEAT; - DMAC->CHCTRLB.reg = temp_CHCTRLB_reg; - DMAC->CHINTENSET.reg = DMAC_CHINTENSET_MASK ; // enable all 3 interrupts - dmadone = 0; - descriptor.descaddr = 0; - descriptor.srcaddr = (uint32_t) &sercom->SPI.DATA.reg; - descriptor.btcnt = n; - descriptor.dstaddr = (uint32_t)rxdata; - descriptor.btctrl = DMAC_BTCTRL_VALID; - if (xtype != DoTX) { - descriptor.dstaddr += n; - descriptor.btctrl |= DMAC_BTCTRL_DSTINC; - } - memcpy(&descriptor_section[chnlrx],&descriptor, sizeof(dmacdescriptor)); - - // start both channels ? order matter ? - DMAC->CHID.reg = DMAC_CHID_ID(chnltx); - Serial.println("A"); - DMAC->CHCTRLA.reg |= DMAC_CHCTRLA_ENABLE; - system_interrupt_leave_critical_section(); - Serial.println("B"); - DMAC->CHID.reg = DMAC_CHID_ID(chnlrx); - Serial.println("C"); - DMAC->CHCTRLA.reg |= DMAC_CHCTRLA_ENABLE; - Serial.println("D"); - - while(!dmadone); // await DMA done isr - - DMAC->CHID.reg = DMAC_CHID_ID(chnltx); //disable DMA to allow lib SPI - DMAC->CHCTRLA.reg &= ~DMAC_CHCTRLA_ENABLE; - DMAC->CHID.reg = DMAC_CHID_ID(chnlrx); - DMAC->CHCTRLA.reg &= ~DMAC_CHCTRLA_ENABLE; -} - -void SPIFlash::_zeroSpi_write(void *data, size_t n) { - xtype = DoTX; - Serial.println("SPI_write started"); - _zeroSpi_xfr(data,rxsink,n); - Serial.println("WRITE DONE"); -} -void SPIFlash::_zeroSpi_read(void *data, size_t n) { - xtype = DoRX; - _zeroSpi_xfr(txsrc,data,n); - Serial.println("READ DONE"); -} -void SPIFlash::_zeroSpi_transfer(void *txdata, void *rxdata, size_t n) { - xtype = DoTXRX; - _zeroSpi_xfr(txdata,rxdata,n); - Serial.println("transfer done"); -} diff --git a/extras/Library speed comparisons.xlsx b/extras/Library speed comparisons.xlsx old mode 100755 new mode 100644 index 4ac6b3d..1c4586c Binary files a/extras/Library speed comparisons.xlsx and b/extras/Library speed comparisons.xlsx differ diff --git a/extras/SPI pinouts.md b/extras/SPI pinouts.md old mode 100755 new mode 100644 diff --git a/extras/Winbond Flash Instructions - Comparison.xlsx b/extras/Winbond Flash Instructions - Comparison.xlsx old mode 100755 new mode 100644 diff --git a/keywords.txt b/keywords.txt old mode 100755 new mode 100644 index f10adaa..92b31c3 --- a/keywords.txt +++ b/keywords.txt @@ -1,9 +1,9 @@ ####################################### -# Syntax Coloring Map SPIFlash +# Syntax Coloring Map SPI ####################################### ####################################### -# Class (KEYWORD1) +# Datatypes (KEYWORD1) ####################################### SPIFlash KEYWORD1 @@ -13,16 +13,14 @@ SPIFlash KEYWORD1 ####################################### begin KEYWORD2 setClock KEYWORD2 -libver KEYWORD2 error KEYWORD2 -getManID KEYWORD2 +libver KEYWORD2 getJEDECID KEYWORD2 -getUniqueID KEYWORD2 +getManID KEYWORD2 getAddress KEYWORD2 -sizeofStr KEYWORD2 getCapacity KEYWORD2 getMaxPage KEYWORD2 -functionRunTime KEYWORD2 +sizeofStr KEYWORD2 readByte KEYWORD2 readByteArray KEYWORD2 readChar KEYWORD2 @@ -54,20 +52,7 @@ resumeProg KEYWORD2 powerUp KEYWORD2 powerDown KEYWORD2 -####################################### -# Constants (LITERAL1) -####################################### -WINBOND_MANID LITERAL1 -MICROCHIP_MANID LITERAL1 -CYPRESS_MANID LITERAL1 -ADESTO_MANID LITERAL1 -MICRON_MANID LITERAL1 -NULLBYTE LITERAL1 -NULLINT LITERAL1 -BYTE LITERAL1 -KiB LITERAL1 -MiB LITERAL1 ####################################### -# Built-in variables (LITERAL2) +# Constants (LITERAL1) ####################################### diff --git a/library.properties b/library.properties index d3ad686..08fc05b 100644 --- a/library.properties +++ b/library.properties @@ -1,10 +1,10 @@ name=SPIFlash -version=3.0.0 +version=2.7.0 author=Prajwal Bhattaram maintainer=Prajwal Bhattaram sentence=Winbond SPI flash library for Arduino. paragraph=This library enables read, write, erase and power functions on the following Winbond NOR Flash chips - W25X05CL, W25X10BV, W25X20BV, W25X40BV, W25Q80BV, W25Q16BV, W25Q32BV, W25Q64BV & W25Q128BV. All other Winbond flash chips can also be used with this library from v2.6.0 onwards. Refer to change log for further information about this release. category=Data Storage url=https://github.com/Marzogh/SPIFlash -architectures=avr,sam,samd,esp8266,esp32,Simblee,ameba +architectures=avr,sam,samd,esp8266,esp32,simblee,ameba includes=SPIFlash.h diff --git a/src/DMASAMD.h b/src/DMASAMD.h deleted file mode 100644 index a319555..0000000 --- a/src/DMASAMD.h +++ /dev/null @@ -1,140 +0,0 @@ -// DMA memory to memory ZERO -// ch 18 beat burst block -// xdk sam0/drivers/dma/dma.c -// packages/arduino/tools/CMSIS/4.0.0-atmel/Device/ATMEL/samd21/include/component/dmac.h -// http://asf.atmel.com/docs/3.16.0/samd21/html/asfdoc_sam0_sercom_spi_dma_use_case.html -// assume normal SPI setup, then we take over with DMA -#ifdef ARDUINO_ARCH_SAMD -#include - -#define PRREG(x) Serial.print(#x" 0x"); Serial.println(x,HEX) - - -#define BYTES 1024 -char txbuf[BYTES], rxbuf[BYTES]; - -/*void prmbs(char *lbl,unsigned long us,int bits) { - float mbs = (float)bits/us; - Serial.print(mbs,2); Serial.print(" mbs "); - Serial.print(us); Serial.print(" us "); - Serial.println(lbl); -}*/ - -// DMA 12 channels -typedef struct { - uint16_t btctrl; - uint16_t btcnt; - uint32_t srcaddr; - uint32_t dstaddr; - uint32_t descaddr; -} dmacdescriptor ; -volatile dmacdescriptor wrb[12] __attribute__ ((aligned (16))); -dmacdescriptor descriptor_section[12] __attribute__ ((aligned (16))); -dmacdescriptor descriptor __attribute__ ((aligned (16))); - -static uint32_t chnltx = 0, chnlrx = 1; // DMA channels -enum XfrType { DoTX, DoRX, DoTXRX}; -static XfrType xtype; -static uint8_t rxsink[1], txsrc[1] = {0xFF}; -volatile uint32_t dmadone; - -void DMAC_Handler() { - // interrupts DMAC_CHINTENCLR_TERR DMAC_CHINTENCLR_TCMPL DMAC_CHINTENCLR_SUSP - uint8_t active_channel; - - // disable irqs ? - __disable_irq(); - active_channel = DMAC->INTPEND.reg & DMAC_INTPEND_ID_Msk; // get channel number - DMAC->CHID.reg = DMAC_CHID_ID(active_channel); - dmadone = DMAC->CHINTFLAG.reg; - DMAC->CHINTFLAG.reg = DMAC_CHINTENCLR_TCMPL; // clear - DMAC->CHINTFLAG.reg = DMAC_CHINTENCLR_TERR; - DMAC->CHINTFLAG.reg = DMAC_CHINTENCLR_SUSP; - __enable_irq(); -} - -void dma_init() { - // probably on by default - PM->AHBMASK.reg |= PM_AHBMASK_DMAC ; - PM->APBBMASK.reg |= PM_APBBMASK_DMAC ; - NVIC_EnableIRQ( DMAC_IRQn ) ; - - DMAC->BASEADDR.reg = (uint32_t)descriptor_section; - DMAC->WRBADDR.reg = (uint32_t)wrb; - DMAC->CTRL.reg = DMAC_CTRL_DMAENABLE | DMAC_CTRL_LVLEN(0xf); -} - - -Sercom *sercom = (Sercom *)SERCOM4; // SPI SERCOM - -void spi_xfr(void *txdata, void *rxdata, size_t n) { - uint32_t temp_CHCTRLB_reg; - - // set up transmit channel - DMAC->CHID.reg = DMAC_CHID_ID(chnltx); - DMAC->CHCTRLA.reg &= ~DMAC_CHCTRLA_ENABLE; - DMAC->CHCTRLA.reg = DMAC_CHCTRLA_SWRST; - DMAC->SWTRIGCTRL.reg &= (uint32_t)(~(1 << chnltx)); - temp_CHCTRLB_reg = DMAC_CHCTRLB_LVL(0) | - DMAC_CHCTRLB_TRIGSRC(SERCOM4_DMAC_ID_TX) | DMAC_CHCTRLB_TRIGACT_BEAT; - DMAC->CHCTRLB.reg = temp_CHCTRLB_reg; - DMAC->CHINTENSET.reg = DMAC_CHINTENSET_MASK ; // enable all 3 interrupts - descriptor.descaddr = 0; - descriptor.dstaddr = (uint32_t) &sercom->SPI.DATA.reg; - descriptor.btcnt = n; - descriptor.srcaddr = (uint32_t)txdata; - descriptor.btctrl = DMAC_BTCTRL_VALID; - if (xtype != DoRX) { - descriptor.srcaddr += n; - descriptor.btctrl |= DMAC_BTCTRL_SRCINC; - } - memcpy(&descriptor_section[chnltx],&descriptor, sizeof(dmacdescriptor)); - - // rx channel enable interrupts - DMAC->CHID.reg = DMAC_CHID_ID(chnlrx); - DMAC->CHCTRLA.reg &= ~DMAC_CHCTRLA_ENABLE; - DMAC->CHCTRLA.reg = DMAC_CHCTRLA_SWRST; - DMAC->SWTRIGCTRL.reg &= (uint32_t)(~(1 << chnlrx)); - temp_CHCTRLB_reg = DMAC_CHCTRLB_LVL(0) | - DMAC_CHCTRLB_TRIGSRC(SERCOM4_DMAC_ID_RX) | DMAC_CHCTRLB_TRIGACT_BEAT; - DMAC->CHCTRLB.reg = temp_CHCTRLB_reg; - DMAC->CHINTENSET.reg = DMAC_CHINTENSET_MASK ; // enable all 3 interrupts - dmadone = 0; - descriptor.descaddr = 0; - descriptor.srcaddr = (uint32_t) &sercom->SPI.DATA.reg; - descriptor.btcnt = n; - descriptor.dstaddr = (uint32_t)rxdata; - descriptor.btctrl = DMAC_BTCTRL_VALID; - if (xtype != DoTX) { - descriptor.dstaddr += n; - descriptor.btctrl |= DMAC_BTCTRL_DSTINC; - } - memcpy(&descriptor_section[chnlrx],&descriptor, sizeof(dmacdescriptor)); - - // start both channels ? order matter ? - DMAC->CHID.reg = DMAC_CHID_ID(chnltx); - DMAC->CHCTRLA.reg |= DMAC_CHCTRLA_ENABLE; - DMAC->CHID.reg = DMAC_CHID_ID(chnlrx); - DMAC->CHCTRLA.reg |= DMAC_CHCTRLA_ENABLE; - - while(!dmadone); // await DMA done isr - - DMAC->CHID.reg = DMAC_CHID_ID(chnltx); //disable DMA to allow lib SPI - DMAC->CHCTRLA.reg &= ~DMAC_CHCTRLA_ENABLE; - DMAC->CHID.reg = DMAC_CHID_ID(chnlrx); - DMAC->CHCTRLA.reg &= ~DMAC_CHCTRLA_ENABLE; -} - -void spi_write(void *data, size_t n) { - xtype = DoTX; - spi_xfr(data,rxsink,n); -} -void spi_read(void *data, size_t n) { - xtype = DoRX; - spi_xfr(txsrc,data,n); -} -void spi_transfer(void *txdata, void *rxdata, size_t n) { - xtype = DoTXRX; - spi_xfr(txdata,rxdata,n); -} -#endif diff --git a/src/SAM_DMASPI.cpp b/src/DMASPI.cpp similarity index 100% rename from src/SAM_DMASPI.cpp rename to src/DMASPI.cpp diff --git a/src/FLASHIO.cpp b/src/FLASHIO.cpp deleted file mode 100644 index d3f97af..0000000 --- a/src/FLASHIO.cpp +++ /dev/null @@ -1,491 +0,0 @@ -/* Arduino SPIFlash Library v.3.0.0 - * Copyright (C) 2017 by Prajwal Bhattaram - * Created by Prajwal Bhattaram - 04/11/2017 - * - * This file is part of the Arduino SPIFlash Library. This library is for - * Winbond NOR flash memory modules. In its current form it enables reading - * and writing individual data variables, structs and arrays from and to various locations; - * reading and writing pages; continuous read functions; sector, block and chip erase; - * suspending and resuming programming/erase and powering down for low power operation. - * - * This Library is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This Library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License v3.0 - * along with the Arduino SPIFlash Library. If not, see - * . - */ - -#include "SPIFlash.h" - -#include "DMASAMD.h" -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// -// Private functions used by read, write and erase operations // -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// - -//Double checks all parameters before calling a read or write. Comes in two variants -//Takes address and returns the address if true, else returns false. Throws an error if there is a problem. -bool SPIFlash::_prep(uint8_t opcode, uint32_t _addr, uint32_t size) { - switch (opcode) { - case PAGEPROG: - //Serial.print(F("Address being prepped: ")); - //Serial.println(_addr); - #ifndef HIGHSPEED - if(!_addressCheck(_addr, size) || !_notPrevWritten(_addr, size) || !_notBusy() || !_writeEnable()) { - return false; - } - #else - if (!_addressCheck(_addr, size) || !_notBusy() || !_writeEnable()) { - return false; - } - #endif - return true; - break; - - case ERASEFUNC: - _currentAddress = _addr; - if(!_notBusy()||!_writeEnable()) { - return false; - } - return true; - break; - - default: - if (!_addressCheck(_addr, size) || !_notBusy()) { - return false; - } - #ifdef ENABLEZERODMA - _delay_us(3500L); - #endif - return true; - break; - } -} - -// Transfer Address. -bool SPIFlash::_transferAddress(void) { - _nextByte(WRITE, Higher(_currentAddress)); - _nextByte(WRITE, Hi(_currentAddress)); - _nextByte(WRITE, Lo(_currentAddress)); - /*_nextByte(_currentAddress >> 16); - _nextByte(_currentAddress >> 8); - _nextByte(_currentAddress);*/ - return true; -} - -bool SPIFlash::_startSPIBus(void) { - #ifndef SPI_HAS_TRANSACTION - noInterrupts(); - #endif - - #if defined (ARDUINO_ARCH_SAM) - _dueSPIInit(DUE_SPI_CLK); - #elif defined (ARDUINO_ARCH_SAMD) - #ifdef SPI_HAS_TRANSACTION - _spi->beginTransaction(_settings); - #else - _spi->setClockDivider(SPI_CLOCK_DIV_4); - _spi->setDataMode(SPI_MODE0); - _spi->setBitOrder(MSBFIRST); - #endif - #if defined ENABLEZERODMA - dma_init(); - #endif - #else - #if defined (ARDUINO_ARCH_AVR) - //save current SPI settings - _SPCR = SPCR; - _SPSR = SPSR; - #endif - #ifdef SPI_HAS_TRANSACTION - SPI.beginTransaction(_settings); - #else - SPI.setClockDivider(SPI_CLOCK_DIV4); - SPI.setDataMode(SPI_MODE0); - SPI.setBitOrder(MSBFIRST); - #endif - #endif - SPIBusState = true; - return true; -} - -//Initiates SPI operation - but data is not transferred yet. Always call _prep() before this function (especially when it involves writing or reading to/from an address) -bool SPIFlash::_beginSPI(uint8_t opcode) { - if (!SPIBusState) { - _startSPIBus(); - } - CHIP_SELECT - switch (opcode) { - case READDATA: - _nextByte(WRITE, opcode); - _transferAddress(); - break; - - case PAGEPROG: - _nextByte(WRITE, opcode); - _transferAddress(); - break; - - case FASTREAD: - _nextByte(WRITE, opcode); - _nextByte(WRITE, DUMMYBYTE); - _transferAddress(); - - case SECTORERASE: - _nextByte(WRITE, opcode); - _transferAddress(); - - case BLOCK32ERASE: - _nextByte(WRITE, opcode); - _transferAddress(); - - case BLOCK64ERASE: - _nextByte(WRITE, opcode); - _transferAddress(); - - default: - _nextByte(WRITE, opcode); - break; - } - return true; -} -//SPI data lines are left open until _endSPI() is called - -//Reads/Writes next byte. Call 'n' times to read/write 'n' number of bytes. Should be called after _beginSPI() -uint8_t SPIFlash::_nextByte(char IOType, uint8_t data) { -#if defined (ARDUINO_ARCH_SAMD) - #ifdef ENABLEZERODMA - union { - uint8_t dataBuf[1]; - uint8_t val; - } rxData, txData; - txData.val = data; - spi_transfer(txData.dataBuf, rxData.dataBuf, 1); - return rxData.val; - #else - return xfer(data); - #endif -#else - return xfer(data); -#endif -} - -//Reads/Writes next int. Call 'n' times to read/write 'n' number of bytes. Should be called after _beginSPI() -uint16_t SPIFlash::_nextInt(uint16_t data) { -#if defined (ARDUINO_ARCH_SAMD) - return _spi->transfer16(data); -#else - return SPI.transfer16(data); -#endif -} - -//Reads/Writes next data buffer. Call 'n' times to read/write 'n' number of bytes. Should be called after _beginSPI() -void SPIFlash::_nextBuf(uint8_t opcode, uint8_t *data_buffer, uint32_t size) { - uint8_t *_dataAddr = &(*data_buffer); - switch (opcode) { - case READDATA: - #if defined (ARDUINO_ARCH_SAM) - _dueSPIRecByte(&(*data_buffer), size); - #elif defined (ARDUINO_ARCH_SAMD) - #ifdef ENABLEZERODMA - spi_read(&(*data_buffer), size); - #else - _spi->transfer(&data_buffer[0], size); - #endif - #elif defined (ARDUINO_ARCH_AVR) - SPI.transfer(&(*data_buffer), size); - #else - for (uint16_t i = 0; i < size; i++) { - *_dataAddr = xfer(NULLBYTE); - _dataAddr++; - } - #endif - break; - - case PAGEPROG: - #if defined (ARDUINO_ARCH_SAM) - _dueSPISendByte(&(*data_buffer), size); - #elif defined (ARDUINO_ARCH_SAMD) - #ifdef ENABLEZERODMA - spi_write(&(*data_buffer), size); - #else - _spi->transfer(&(*data_buffer), size); - #endif - #elif defined (ARDUINO_ARCH_AVR) - SPI.transfer(&(*data_buffer), size); - #else - for (uint16_t i = 0; i < size; i++) { - xfer(*_dataAddr); - _dataAddr++; - } - #endif - break; - } -} - -//Stops all operations. Should be called after all the required data is read/written from repeated _nextByte() calls -void SPIFlash::_endSPI(void) { - CHIP_DESELECT -#ifdef SPI_HAS_TRANSACTION - #if defined (ARDUINO_ARCH_SAMD) - _spi->endTransaction(); - #else - SPI.endTransaction(); - #endif -#else - interrupts(); -#endif -#if defined (ARDUINO_ARCH_AVR) - SPCR = _SPCR; - SPSR = _SPSR; -#endif - SPIBusState = false; -} - -// Checks if status register 1 can be accessed - used to check chip status, during powerdown and power up and for debugging -uint8_t SPIFlash::_readStat1(void) { - _beginSPI(READSTAT1); - stat1 = _nextByte(READ); - CHIP_DESELECT - return stat1; -} - -// Checks if status register 2 can be accessed, if yes, reads and returns it -uint8_t SPIFlash::_readStat2(void) { - _beginSPI(READSTAT2); - uint8_t stat2 = _nextByte(READ); - stat2 = _nextByte(READ); - CHIP_DESELECT - return stat2; -} - -// Checks the erase/program suspend flag before enabling/disabling a program/erase suspend operation -bool SPIFlash::_noSuspend(void) { - switch (_chip.manufacturerID) { - case WINBOND_MANID: - if(_readStat2() & SUS) { - _troubleshoot(SYSSUSPEND); - return false; - } - return true; - break; - - case MICROCHIP_MANID: - _readStat1(); - if(stat1 & WSE || stat1 & WSP) { - _troubleshoot(SYSSUSPEND); - return false; - } - } - return true; -} - -// Polls the status register 1 until busy flag is cleared or timeout -bool SPIFlash::_notBusy(uint32_t timeout) { - _delay_us(WINBOND_WRITE_DELAY); - uint32_t _time = micros(); - - do { - _readStat1(); - if (!(stat1 & BUSY)) - { - return true; - } - _time++; - } while ((micros() - _time) < timeout); - if ((micros() - _time) == timeout) { - return false; - } - return true; -} - -//Enables writing to chip by setting the WRITEENABLE bit -bool SPIFlash::_writeEnable(bool _troubleshootEnable) { - _beginSPI(WRITEENABLE); - CHIP_DESELECT - if (!(_readStat1() & WRTEN)) { - if (_troubleshootEnable) { - _troubleshoot(CANTENWRITE); - } - return false; - } - return true; -} - -//Disables writing to chip by setting the Write Enable Latch (WEL) bit in the Status Register to 0 -//_writeDisable() is not required under the following conditions because the Write Enable Latch (WEL) flag is cleared to 0 -// i.e. to write disable state: -// Power-up, Write Disable, Page Program, Quad Page Program, Sector Erase, Block Erase, Chip Erase, Write Status Register, -// Erase Security Register and Program Security register -bool SPIFlash::_writeDisable(void) { - _beginSPI(WRITEDISABLE); - CHIP_DESELECT - return true; -} - -//Checks the device ID to establish storage parameters -bool SPIFlash::_getManId(uint8_t *b1, uint8_t *b2) { - if(!_notBusy()) - return false; - _beginSPI(MANID); - _nextByte(READ); - _nextByte(READ); - _nextByte(READ); - *b1 = _nextByte(READ); - *b2 = _nextByte(READ); - CHIP_DESELECT - return true; -} - -//Checks for presence of chip by requesting JEDEC ID -bool SPIFlash::_getJedecId(void) { - if(!_notBusy()) { - return false; - } - _beginSPI(JEDECID); - _chip.manufacturerID = _nextByte(READ); // manufacturer id - _chip.memoryTypeID = _nextByte(READ); // memory type - _chip.capacityID = _nextByte(READ); // capacity - CHIP_DESELECT - if (!_chip.manufacturerID) { - _troubleshoot(NORESPONSE); - return false; - } - else { - return true; - } -} - -bool SPIFlash::_getSFDP(void) { - if(!_notBusy()) { - return false; - } - _currentAddress = 0x00; - _beginSPI(READSFDP); - _transferAddress(); - _nextByte(WRITE, DUMMYBYTE); - /*for (uint8_t i = 0; i < 4; i++) { - _chip.sfdp += (_nextByte(READ) << (8*i)); - }*/ - // Modification suggested by @VitorBoss on 13.08.2017. - // Ref issue 76 on Github here --> - // https://github.com/Marzogh/SPIFlash/issues/76 - Lo(_chip.sfdp) = _nextByte(READ); - Hi(_chip.sfdp) = _nextByte(READ); - Higher(_chip.sfdp) = _nextByte(READ); - Highest(_chip.sfdp) = _nextByte(READ); - CHIP_DESELECT - if (_chip.sfdp == 0x50444653) { - //Serial.print("_chip.sfdp: "); - //Serial.println(_chip.sfdp, HEX); - return true; - } - else { - return false; - } -} - -bool SPIFlash::_disableGlobalBlockProtect(void) { - if (_chip.memoryTypeID == SST25) { - _readStat1(); - stat1 &= 0xC3; - _beginSPI(WRITESTATEN); - CHIP_DESELECT - _beginSPI(WRITESTAT); - _nextByte(WRITE, stat1); - CHIP_DESELECT - } - else if (_chip.memoryTypeID == SST26) { - if(!_notBusy()) { - return false; - } - _writeEnable(); - _delay_us(10); - _beginSPI(ULBPR); - CHIP_DESELECT - _delay_us(50); - _writeDisable(); - } - return true; -} - -//Identifies the chip -bool SPIFlash::_chipID(void) { - //Get Manfucturer/Device ID so the library can identify the chip - //_getSFDP(); - if (!_getJedecId()) { - return false; - } - - if (_chip.manufacturerID == MICROCHIP_MANID) { - _disableGlobalBlockProtect(); - } - - if (!_chip.capacity) { - if (_chip.manufacturerID == WINBOND_MANID || _chip.manufacturerID == MICROCHIP_MANID || _chip.manufacturerID == CYPRESS_MANID || _chip.manufacturerID == ADESTO_MANID || _chip.manufacturerID == MICRON_MANID) { - //Identify capacity - for (uint8_t i = 0; i < sizeof(_capID); i++) { - if (_chip.capacityID == _capID[i]) { - _chip.capacity = (_memSize[i]); - _chip.supported = true; - return true; - } - } - if (!_chip.capacity) { - _troubleshoot(UNKNOWNCAP); - return false; - } - } - else { - _troubleshoot(UNKNOWNCHIP); //Error code for unidentified capacity - return false; - } - } - return true; -} - - -//Checks to see if page overflow is permitted and assists with determining next address to read/write. -//Sets the global address variable -bool SPIFlash::_addressCheck(uint32_t _addr, uint32_t size) { - if (errorcode == UNKNOWNCAP || errorcode == NORESPONSE) { - return false; - } - if (!_chip.capacity) { - _troubleshoot(CALLBEGIN); - return false; - } - - //for (uint32_t i = 0; i < size; i++) { - if (_addr + size >= _chip.capacity) { - #ifdef DISABLEOVERFLOW - _troubleshoot(OUTOFBOUNDS); - return false; // At end of memory - (!pageOverflow) - #else - _currentAddress = 0x00; - return true; // At end of memory - (pageOverflow) - #endif - } - //} - _currentAddress = _addr; - return true; // Not at end of memory if (address < _chip.capacity) -} - -bool SPIFlash::_notPrevWritten(uint32_t _addr, uint32_t size) { - _beginSPI(READDATA); - for (uint32_t i = 0; i < size; i++) { - if (_nextByte(READ) != 0xFF) { - CHIP_DESELECT; - return false; - } - } - CHIP_DESELECT - return true; -} diff --git a/src/SPIFlash.cpp b/src/SPIFlash.cpp index df805c8..b9da54f 100644 --- a/src/SPIFlash.cpp +++ b/src/SPIFlash.cpp @@ -1,8 +1,8 @@ -/* Arduino SPIFlash Library v.3.0.0 +/* Arduino SPIFlash Library v.2.7.0 * Copyright (C) 2017 by Prajwal Bhattaram * Created by Prajwal Bhattaram - 19/05/2015 * Modified by @boseji - 02/03/2017 - * Modified by Prajwal Bhattaram - 04/11/2017 + * Modified by Prajwal Bhattaram - 02/08/2017 * * This file is part of the Arduino SPIFlash Library. This library is for * Winbond NOR flash memory modules. In its current form it enables reading @@ -28,85 +28,476 @@ #include "SPIFlash.h" // Constructor -//If board has multiple SPI interfaces, this constructor lets the user choose between them -// Adding Low level HAL API to initialize the Chip select pinMode on RTL8195A - @boseji 2nd March 2017 #if defined (ARDUINO_ARCH_AVR) -SPIFlash::SPIFlash(uint8_t cs) { +SPIFlash::SPIFlash(uint8_t cs, bool overflow) { csPin = cs; +#ifndef __AVR_ATtiny85__ + cs_port = portOutputRegister(digitalPinToPort(csPin)); +#endif cs_mask = digitalPinToBitMask(csPin); + pageOverflow = overflow; pinMode(csPin, OUTPUT); - CHIP_DESELECT -} -#elif defined (ARDUINO_ARCH_SAMD) || defined(ARCH_STM32) -SPIFlash::SPIFlash(uint8_t cs, SPIClass *spiinterface) { - _spi = spiinterface; //Sets SPI interface - if no user selection is made, this defaults to SPI - csPin = cs; - pinMode(csPin, OUTPUT); - CHIP_DESELECT } +// Adding Low level HAL API to initialize the Chip select pinMode on RTL8195A - @boseji 2nd March 2017 #elif defined (BOARD_RTL8195A) -SPIFlash::SPIFlash(PinName cs) { +SPIFlash::SPIFlash(PinName cs, bool overflow) { gpio_init(&csPin, cs); gpio_dir(&csPin, PIN_OUTPUT); gpio_mode(&csPin, PullNone); gpio_write(&csPin, 1); - CHIP_DESELECT + pageOverflow = overflow; } #else -SPIFlash::SPIFlash(uint8_t cs) { +SPIFlash::SPIFlash(uint8_t cs, bool overflow) { csPin = cs; + pageOverflow = overflow; pinMode(csPin, OUTPUT); - CHIP_DESELECT } #endif - - //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// -// Public functions used for read, write and erase operations // +// Private functions used by read, write and erase operations // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// -//Identifies chip and establishes parameters -bool SPIFlash::begin(size_t flashChipSize) { -#ifdef RUNDIAGNOSTIC - Serial.println("Chip Diagnostics initiated."); - Serial.println(); -#endif -#ifdef HIGHSPEED - Serial.println("Highspeed mode initiated."); - Serial.println(); +//Double checks all parameters before calling a read or write. Comes in two variants +//Variant A: Takes address and returns the address if true, else returns false. Throws an error if there is a problem. +bool SPIFlash::_prep(uint8_t opcode, uint32_t address, uint32_t size) { + switch (opcode) { + case PAGEPROG: + if (!_addressCheck(address, size)) { + return false; + } + if(!_notBusy() || !_writeEnable()){ + return false; + } + #ifndef HIGHSPEED + if(!_notPrevWritten(address, size)) { + return false; + } + #endif + return true; + break; + + default: + if (!_addressCheck(address, size)) { + return false; + } + if (!_notBusy()){ + return false; + } + return true; + break; + } +} + +//Variant B: Take the opcode, page number, offset and size of data block as arguments +bool SPIFlash::_prep(uint8_t opcode, uint32_t page_number, uint8_t offset, uint32_t size) { + uint32_t address = _getAddress(page_number, offset); + return _prep(opcode, address, size); +} + +bool SPIFlash::_transferAddress(void) { + _nextByte(_currentAddress >> 16); + _nextByte(_currentAddress >> 8); + _nextByte(_currentAddress); +} + +bool SPIFlash::_startSPIBus(void) { +#ifndef __AVR_ATtiny85__ + #ifndef SPI_HAS_TRANSACTION + noInterrupts(); + #endif + + #if defined (ARDUINO_ARCH_SAM) + _dueSPIInit(DUE_SPI_CLK); + #else + #if defined (ARDUINO_ARCH_AVR) + //save current SPI settings + _SPCR = SPCR; + _SPSR = SPSR; + #endif + #ifdef SPI_HAS_TRANSACTION + SPI.beginTransaction(_settings); + #else + SPI.setClockDivider(SPI_CLOCK_DIV_4) + SPI.setDataMode(SPI_MODE0); + SPI.setBitOrder(MSBFIRST); + #endif + #endif +#else + #endif - BEGIN_SPI -#ifdef SPI_HAS_TRANSACTION - //Define the settings to be used by the SPI bus - _settings = SPISettings(SPI_CLK, MSBFIRST, SPI_MODE0); + SPIBusState = true; + return true; +} + +//Initiates SPI operation - but data is not transferred yet. Always call _prep() before this function (especially when it involves writing or reading to/from an address) +bool SPIFlash::_beginSPI(uint8_t opcode) { + if (!SPIBusState) { + _startSPIBus(); + } + CHIP_SELECT + switch (opcode) { + case FASTREAD: + _nextByte(opcode); + _nextByte(DUMMYBYTE); + _transferAddress(); + break; + + case READDATA: + _nextByte(opcode); + _transferAddress(); + break; + + case PAGEPROG: + _nextByte(opcode); + _transferAddress(); + break; + + default: + _nextByte(opcode); + break; + } + return true; +} +//SPI data lines are left open until _endSPI() is called + +//Reads/Writes next byte. Call 'n' times to read/write 'n' number of bytes. Should be called after _beginSPI() +uint8_t SPIFlash::_nextByte(uint8_t data) { +#if defined (ARDUINO_ARCH_SAM) + return _dueSPITransfer(data); +#else + return xfer(data); #endif -// If no capacity is defined in user code - if (!flashChipSize) { +} + +//Reads/Writes next int. Call 'n' times to read/write 'n' number of bytes. Should be called after _beginSPI() +uint16_t SPIFlash::_nextInt(uint16_t data) { + #ifndef __AVR_ATtiny85__ + return SPI.transfer16(data); + #else + uint16_t _data; + _data = xfer(data >> 0); + data = (_data << 8); + _data += xfer(data >> 8); + return _data; + #endif +} + +//Reads/Writes next data buffer. Call 'n' times to read/write 'n' number of bytes. Should be called after _beginSPI() +void SPIFlash::_nextBuf(uint8_t opcode, uint8_t *data_buffer, uint32_t size) { + uint8_t *_dataAddr = &(*data_buffer); + switch (opcode) { + case READDATA: + #if defined (ARDUINO_ARCH_SAM) + _dueSPIRecByte(&(*data_buffer), size); + #elif defined (ARDUINO_ARCH_AVR) && !defined (__AVR_ATtiny85__) + SPI.transfer(&data_buffer[0], size); + #else + for (uint16_t i = 0; i < size; i++) { + *_dataAddr = xfer(NULLBYTE); + _dataAddr++; + } + #endif + break; + + case PAGEPROG: + #if defined (ARDUINO_ARCH_SAM) + _dueSPISendByte(&(*data_buffer), size); + #elif defined (ARDUINO_ARCH_AVR) && !defined (__AVR_ATtiny85__) + SPI.transfer(&(*data_buffer), size); + #else + for (uint16_t i = 0; i < size; i++) { + xfer(*_dataAddr); + _dataAddr++; + } + #endif + break; + } +} + +//Stops all operations. Should be called after all the required data is read/written from repeated _nextByte() calls +void SPIFlash::_endSPI(void) { + CHIP_DESELECT + #ifdef SPI_HAS_TRANSACTION + SPI.endTransaction(); + #else + interrupts(); + #endif + + #if defined (ARDUINO_ARCH_AVR) && !defined (__AVR_ATtiny85__) + SPCR = _SPCR; + SPSR = _SPSR; + #endif + SPIBusState = false; +} + +// Checks if status register 1 can be accessed - used during powerdown and power up and for debugging +uint8_t SPIFlash::_readStat1(void) { + _beginSPI(READSTAT1); + uint8_t stat1 = _nextByte(); + CHIP_DESELECT + return stat1; +} + +// Checks if status register 2 can be accessed, if yes, reads and returns it +uint8_t SPIFlash::_readStat2(void) { + _beginSPI(READSTAT2); + uint8_t stat2 = _nextByte(); + stat2 = _nextByte(); + CHIP_DESELECT + return stat2; +} + +// Checks the erase/program suspend flag before enabling/disabling a program/erase suspend operation +bool SPIFlash::_noSuspend(void) { + switch (_chip.manufacturerID) { + case WINBOND_MANID: + if(_readStat2() & SUS) { + errorcode = SYSSUSPEND; + return false; + } + return true; + break; + + case MICROCHIP_MANID: + if(_readStat1() & WSE || _readStat1() & WSP) { + errorcode = SYSSUSPEND; + return false; + } + return true; + } + +} + +// Polls the status register 1 until busy flag is cleared or timeout +bool SPIFlash::_notBusy(uint32_t timeout) { + uint32_t startTime = millis(); + + do { + state = _readStat1(); + if((millis()-startTime) > timeout){ + errorcode = CHIPBUSY; + #ifdef RUNDIAGNOSTIC + _troubleshoot(); + #endif + _endSPI(); + return false; + } + } while(state & BUSY); + return true; +} + +//Enables writing to chip by setting the WRITEENABLE bit +bool SPIFlash::_writeEnable(uint32_t timeout) { + uint32_t startTime = millis(); + if (!(state & WRTEN)) { + do { + _beginSPI(WRITEENABLE); + CHIP_DESELECT + state = _readStat1(); + if((millis()-startTime) > timeout) { + errorcode = CANTENWRITE; + #ifdef RUNDIAGNOSTIC + _troubleshoot(); + #endif + _endSPI(); + return false; + } + } while (!(state & WRTEN)); + } + return true; +} + +//Disables writing to chip by setting the Write Enable Latch (WEL) bit in the Status Register to 0 +//_writeDisable() is not required under the following conditions because the Write Enable Latch (WEL) flag is cleared to 0 +// i.e. to write disable state: +// Power-up, Write Disable, Page Program, Quad Page Program, Sector Erase, Block Erase, Chip Erase, Write Status Register, +// Erase Security Register and Program Security register +bool SPIFlash::_writeDisable(void) { + _beginSPI(WRITEDISABLE); + CHIP_DESELECT + return true; +} + +//Gets address from page number and offset. Takes two arguments: +// 1. page_number --> Any page number from 0 to maxPage +// 2. offset --> Any offset within the page - from 0 to 255 +uint32_t SPIFlash::_getAddress(uint16_t page_number, uint8_t offset) { + uint32_t address = page_number; + return ((address << 8) + offset); +} + +//Checks the device ID to establish storage parameters +bool SPIFlash::_getManId(uint8_t *b1, uint8_t *b2) { + if(!_notBusy()) + return false; + _beginSPI(MANID); + _nextByte(); + _nextByte(); + _nextByte(); + *b1 = _nextByte(); + *b2 = _nextByte(); + CHIP_DESELECT + return true; +} + +//Checks for presence of chip by requesting JEDEC ID +bool SPIFlash::_getJedecId(void) { + if(!_notBusy()) { + return false; + } + _beginSPI(JEDECID); + _chip.manufacturerID = _nextByte(NULLBYTE); // manufacturer id + _chip.memoryTypeID = _nextByte(NULLBYTE); // memory type + _chip.capacityID = _nextByte(NULLBYTE); // capacity + CHIP_DESELECT + if (!_chip.manufacturerID || !_chip.memoryTypeID || !_chip.capacityID) { + errorcode = NORESPONSE; #ifdef RUNDIAGNOSTIC - Serial.println("No Chip size defined by user"); + _troubleshoot(); #endif - bool retVal = _chipID(); - _endSPI(); - return retVal; + return false; + } + else { + return true; + } +} + +bool SPIFlash::_getSFDP(void) { + if(!_notBusy()) { + return false; + } + _beginSPI(READSFDP); + _currentAddress = 0x00; + _transferAddress(); + _nextByte(DUMMYBYTE); + for (uint8_t i = 0; i < 4; i++) { + _chip.sfdp += (_nextByte() << (8*i)); + } + CHIP_DESELECT + if (_chip.sfdp = 0x50444653) { + //Serial.print("_chip.sfdp: "); + //Serial.println(_chip.sfdp, HEX); + return true; + } + else { + return false; + } +} + +//Identifies the chip +bool SPIFlash::_chipID(void) { + //Get Manfucturer/Device ID so the library can identify the chip + _getSFDP(); + if (!_getJedecId()) { + return false; + } + + // If no capacity is defined in user code + if (!_chip.capacity) { + _chip.supported = _chip.manufacturerID; + if (_chip.supported == WINBOND_MANID || _chip.supported == MICROCHIP_MANID) { + //Identify capacity + for (uint8_t i = 0; i < sizeof(_capID); i++) + { + if (_chip.capacityID == _capID[i]) { + _chip.capacity = (_memSize[i]); + _chip.eraseTime = _eraseTime[i]; + } + } + return true; + } + else { + errorcode = UNKNOWNCAP; //Error code for unidentified capacity + #ifdef RUNDIAGNOSTIC + _troubleshoot(); + #endif + return false; + } } else { - _getJedecId(); // If a custom chip size is defined + _chip.eraseTime = _chip.capacity/KB8; + _chip.supported = false;// This chip is not officially supported + errorcode = UNKNOWNCHIP; //Error code for unidentified chip #ifdef RUNDIAGNOSTIC - Serial.println("Custom Chipsize defined"); + _troubleshoot(); #endif - _chip.capacity = flashChipSize; - _chip.supported = false; + //while(1); //Enable this if usercode is not meant to be run on unsupported chips } - _endSPI(); + return true; +} + +//Checks to see if pageOverflow is permitted and assists with determining next address to read/write. +//Sets the global address variable +bool SPIFlash::_addressCheck(uint32_t address, uint32_t size) { + if (errorcode == UNKNOWNCAP || errorcode == NORESPONSE) { + #ifdef RUNDIAGNOSTIC + _troubleshoot(); + #endif + return false; + } + if (!_chip.eraseTime) { + errorcode = CALLBEGIN; + #ifdef RUNDIAGNOSTIC + _troubleshoot(); + #endif + return false; + } - if (_chip.manufacturerID == CYPRESS_MANID) { - setClock(SPI_CLK/4); + for (uint32_t i = 0; i < size; i++) { + if (address + i >= _chip.capacity) { + if (!pageOverflow) { + errorcode = OUTOFBOUNDS; + #ifdef RUNDIAGNOSTIC + _troubleshoot(); + #endif + return false; // At end of memory - (!pageOverflow) + } + else { + _currentAddress = 0x00; + return true; // At end of memory - (pageOverflow) + } + } } + _currentAddress = address; + return true; // Not at end of memory if (address < _chip.capacity) +} +bool SPIFlash::_notPrevWritten(uint32_t address, uint32_t size) { + _beginSPI(READDATA); + for (uint16_t i = 0; i < size; i++) { + if (_nextByte() != 0xFF) { + CHIP_DESELECT; + return false; + } + } + CHIP_DESELECT return true; } +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// +// Public functions used for read, write and erase operations // +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + +//Identifies chip and establishes parameters +bool SPIFlash::begin(uint32_t _chipSize) { + if (_chipSize) { + _chip.capacity = _chipSize/8; + } + BEGIN_SPI +#ifdef SPI_HAS_TRANSACTION + //Define the settings to be used by the SPI bus + _settings = SPISettings(SPI_CLK, MSBFIRST, SPI_MODE0); +#endif + if(!_chipID()) { + #ifdef RUNDIAGNOSTIC + _troubleshoot(); + #endif + return false; + } +} + //Allows the setting of a custom clock speed for the SPI bus to communicate with the chip. //Only works if the SPI library in use supports SPI Transactions #ifdef SPI_HAS_TRANSACTION @@ -120,7 +511,7 @@ uint8_t SPIFlash::error(bool _verbosity) { return errorcode; } else { - _troubleshoot(errorcode, PRINTOVERRIDE); + _troubleshoot(); return errorcode; } } @@ -132,12 +523,7 @@ uint32_t SPIFlash::getCapacity(void) { //Returns maximum number of pages uint32_t SPIFlash::getMaxPage(void) { - return (_chip.capacity / SPI_PAGESIZE); -} - -//Returns the time taken to run a function. Must be called immediately after a function is run as the variable returned is overwritten eachtime a function from this library is called. Primarily used in the diagnostics sketch included in the library to track function time. -float SPIFlash::functionRunTime(void) { - return _spifuncruntime; + return (_chip.capacity / PAGESIZE); } //Returns the library version as a string @@ -165,45 +551,32 @@ uint32_t SPIFlash::getJEDECID(void) { return id; } -// Returns a 64-bit Unique ID that is unique to each flash memory chip -uint64_t SPIFlash::getUniqueID(void) { - if(!_notBusy()) { - return false; - } - _beginSPI(UNIQUEID); - for (uint8_t i = 0; i < 4; i++) { - _nextByte(DUMMYBYTE); - } - - for (uint8_t i = 0; i < 8; i++) { - _uniqueID[i] = _nextByte(READ); - } - CHIP_DESELECT - - long long _uid; - for (uint8_t i = 0; i < 8; i++) { - _uid += _uniqueID[i]; - _uid = _uid << 8; - } - return _uid; -} - //Gets the next available address for use. Has two variants: // A. Takes the size of the data as an argument and returns a 32-bit address // B. Takes a three variables, the size of the data and two other variables to return a page number value & an offset into. // All addresses in the in the sketch must be obtained via this function or not at all. // Variant A uint32_t SPIFlash::getAddress(uint16_t size) { - if (!_addressCheck(currentAddress, size)){ - _troubleshoot(OUTOFBOUNDS); + if (!_addressCheck(currentAddress, size)){ + errorcode = OUTOFBOUNDS; + #ifdef RUNDIAGNOSTIC + _troubleshoot(); + #endif return false; } else { - uint32_t _addr = currentAddress; + uint32_t address = currentAddress; currentAddress+=size; - return _addr; + return address; } } +// Variant B +bool SPIFlash::getAddress(uint16_t size, uint16_t &page_number, uint8_t &offset) { + uint32_t address = getAddress(size); + offset = (address >> 0); + page_number = (address >> 8); + return true; +} //Function for returning the size of the string (only to be used for the getAddress() function) uint16_t SPIFlash::sizeofStr(String &inputStr) { @@ -215,51 +588,97 @@ uint16_t SPIFlash::sizeofStr(String &inputStr) { } // Reads a byte of data from a specific location in a page. -// Takes two arguments - -// 1. _addr --> Any address from 0 to capacity -// 2. fastRead --> defaults to false - executes _beginFastRead() if set to true -uint8_t SPIFlash::readByte(uint32_t _addr, bool fastRead) { - #ifdef RUNDIAGNOSTIC - _spifuncruntime = micros(); - #endif +// Has two variants: +// A. Takes two arguments - +// 1. address --> Any address from 0 to capacity +// 2. fastRead --> defaults to false - executes _beginFastRead() if set to true +// B. Takes three arguments - +// 1. page --> Any page number from 0 to maxPage +// 2. offset --> Any offset within the page - from 0 to 255 +// 3. fastRead --> defaults to false - executes _beginFastRead() if set to true +// Variant A +uint8_t SPIFlash::readByte(uint32_t address, bool fastRead) { uint8_t data; - _read(_addr, data, sizeof(data), fastRead); - #ifdef RUNDIAGNOSTIC - _spifuncruntime = micros() - _spifuncruntime; - #endif + + if (!_prep(READDATA, address, sizeof(data))) { + return false; + } + switch (fastRead) { + case false: + _beginSPI(READDATA); + break; + + case true: + _beginSPI(FASTREAD); + break; + + default: + break; + } + data = _nextByte(); + _endSPI(); return data; } +// Variant B +uint8_t SPIFlash::readByte(uint16_t page_number, uint8_t offset, bool fastRead) { + uint32_t address = _getAddress(page_number, offset); + + return readByte(address, fastRead); +} // Reads a char of data from a specific location in a page. -// Takes two arguments - -// 1. _addr --> Any address from 0 to capacity -// 2. fastRead --> defaults to false - executes _beginFastRead() if set to true -int8_t SPIFlash::readChar(uint32_t _addr, bool fastRead) { - #ifdef RUNDIAGNOSTIC - _spifuncruntime = micros(); - #endif - int8_t data; - _read(_addr, data, sizeof(data), fastRead); - #ifdef RUNDIAGNOSTIC - _spifuncruntime = micros() - _spifuncruntime; - #endif +// Has two variants: +// A. Takes two arguments - +// 1. address --> Any address from 0 to capacity +// 2. fastRead --> defaults to false - executes _beginFastRead() if set to true +// B. Takes three arguments - +// 1. page --> Any page number from 0 to maxPage +// 2. offset --> Any offset within the page - from 0 to 255 +// 3. fastRead --> defaults to false - executes _beginFastRead() if set to true +// Variant A +int8_t SPIFlash::readChar(uint32_t address, bool fastRead) { + int8_t data; + if (!_prep(READDATA, address, sizeof(data))) { + return false; + } + switch (fastRead) { + case false: + _beginSPI(READDATA); + break; + + case true: + _beginSPI(FASTREAD); + break; + + default: + break; + } + data = _nextByte(); + _endSPI(); return data; } +// Variant B +int8_t SPIFlash::readChar(uint16_t page_number, uint8_t offset, bool fastRead) { + uint32_t address = _getAddress(page_number, offset); -// Reads an array of bytes starting from a specific location in a page. -// Takes four arguments -// 1. _addr --> Any address from 0 to capacity -// 2. data_buffer --> The array of bytes to be read from the flash memory - starting at the address indicated -// 3. bufferSize --> The size of the buffer - in number of bytes. -// 4. fastRead --> defaults to false - executes _beginFastRead() if set to true + return readChar(address, fastRead); +} -bool SPIFlash::readByteArray(uint32_t _addr, uint8_t *data_buffer, size_t bufferSize, bool fastRead) { - #ifdef RUNDIAGNOSTIC - _spifuncruntime = micros(); - #endif - if (!_prep(READDATA, _addr, bufferSize)) { +// Reads an array of bytes starting from a specific location in a page.// Has two variants: +// A. Takes three arguments +// 1. address --> Any address from 0 to capacity +// 2. data_buffer --> The array of bytes to be read from the flash memory - starting at the address indicated +// 3. fastRead --> defaults to false - executes _beginFastRead() if set to true +// B. Takes four arguments +// 1. page --> Any page number from 0 to maxPage +// 2. offset --> Any offset within the page - from 0 to 255 +// 3. data_buffer --> The array of bytes to be read from the flash memory - starting at the offset on the page indicated +// 4. fastRead --> defaults to false - executes _beginFastRead() if set to true +// Variant A +bool SPIFlash::readByteArray(uint32_t address, uint8_t *data_buffer, uint16_t bufferSize, bool fastRead) { + if (!_prep(READDATA, address, bufferSize)) { return false; - } + } if(fastRead) { _beginSPI(FASTREAD); } @@ -268,23 +687,28 @@ bool SPIFlash::readByteArray(uint32_t _addr, uint8_t *data_buffer, size_t buffe } _nextBuf(READDATA, &(*data_buffer), bufferSize); _endSPI(); - #ifdef RUNDIAGNOSTIC - _spifuncruntime = micros() - _spifuncruntime; - #endif return true; } +// Variant B +bool SPIFlash::readByteArray(uint16_t page_number, uint8_t offset, uint8_t *data_buffer, uint16_t bufferSize, bool fastRead) { + uint32_t address = _getAddress(page_number, offset); -// Reads an array of chars starting from a specific location in a page.. -// Takes four arguments -// 1. _addr --> Any address from 0 to capacity -// 2. data_buffer --> The array of bytes to be read from the flash memory - starting at the address indicated -// 3. bufferSize --> The size of the buffer - in number of bytes. -// 4. fastRead --> defaults to false - executes _beginFastRead() if set to true -bool SPIFlash::readCharArray(uint32_t _addr, char *data_buffer, size_t bufferSize, bool fastRead) { - #ifdef RUNDIAGNOSTIC - _spifuncruntime = micros(); - #endif - if (!_prep(READDATA, _addr, bufferSize)) { + return readByteArray(address, data_buffer, bufferSize, fastRead); +} + +// Reads an array of chars starting from a specific location in a page.// Has two variants: +// A. Takes three arguments +// 1. address --> Any address from 0 to capacity +// 2. data_buffer --> The array of bytes to be read from the flash memory - starting at the address indicated +// 3. fastRead --> defaults to false - executes _beginFastRead() if set to true +// B. Takes four arguments +// 1. page --> Any page number from 0 to maxPage +// 2. offset --> Any offset within the page - from 0 to 255 +// 3. data_buffer --> The array of bytes to be read from the flash memory - starting at the offset on the page indicated +// 4. fastRead --> defaults to false - executes _beginFastRead() if set to true +// Variant A +bool SPIFlash::readCharArray(uint32_t address, char *data_buffer, uint16_t bufferSize, bool fastRead) { + if (!_prep(READDATA, address, bufferSize)) { return false; } if(fastRead) { @@ -295,500 +719,1043 @@ bool SPIFlash::readCharArray(uint32_t _addr, char *data_buffer, size_t bufferSi } _nextBuf(READDATA, (uint8_t*) &(*data_buffer), bufferSize); _endSPI(); - #ifdef RUNDIAGNOSTIC - _spifuncruntime = micros() - _spifuncruntime; - #endif return true; } +// Variant B +bool SPIFlash::readCharArray(uint16_t page_number, uint8_t offset, char *data_buffer, uint16_t bufferSize, bool fastRead) { + uint32_t address = _getAddress(page_number, offset); + + return readCharArray(address, data_buffer, bufferSize, fastRead); +} // Reads an unsigned int of data from a specific location in a page. -// Takes two arguments - -// 1. _addr --> Any address from 0 to capacity -// 2. fastRead --> defaults to false - executes _beginFastRead() if set to true -uint16_t SPIFlash::readWord(uint32_t _addr, bool fastRead) { - #ifdef RUNDIAGNOSTIC - _spifuncruntime = micros(); - #endif - uint16_t data; - _read(_addr, data, sizeof(data), fastRead); - #ifdef RUNDIAGNOSTIC - _spifuncruntime = micros() - _spifuncruntime; - #endif - return data; +// Has two variants: +// A. Takes two arguments - +// 1. address --> Any address from 0 to capacity +// 2. fastRead --> defaults to false - executes _beginFastRead() if set to true +// B. Takes three arguments - +// 1. page --> Any page number from 0 to maxPage +// 2. offset --> Any offset within the page - from 0 to 255 +// 3. fastRead --> defaults to false - executes _beginFastRead() if set to true +// Variant A +uint16_t SPIFlash::readWord(uint32_t address, bool fastRead) { + const uint8_t size = sizeof(uint16_t); + union + { + uint8_t b[size]; + uint16_t I; + } data; + if (!_prep(READDATA, address, size)) { + return false; + } + switch (fastRead) { + case false: + _beginSPI(READDATA); + break; + + case true: + _beginSPI(FASTREAD); + break; + + default: + break; + } + _nextBuf(READDATA, &data.b[0], size); + _endSPI(); + return data.I; +} +// Variant B +uint16_t SPIFlash::readWord(uint16_t page_number, uint8_t offset, bool fastRead) { + uint32_t address = _getAddress(page_number, offset); + + return readWord(address, fastRead); } // Reads a signed int of data from a specific location in a page. -// Takes two arguments - -// 1. _addr --> Any address from 0 to capacity -// 2. fastRead --> defaults to false - executes _beginFastRead() if set to true -int16_t SPIFlash::readShort(uint32_t _addr, bool fastRead) { - #ifdef RUNDIAGNOSTIC - _spifuncruntime = micros(); - #endif - int16_t data; - _read(_addr, data, sizeof(data), fastRead); - #ifdef RUNDIAGNOSTIC - _spifuncruntime = micros() - _spifuncruntime; - #endif - return data; +// Has two variants: +// A. Takes two arguments - +// 1. address --> Any address from 0 to capacity +// 2. fastRead --> defaults to false - executes _beginFastRead() if set to true +// B. Takes three arguments - +// 1. page --> Any page number from 0 to maxPage +// 2. offset --> Any offset within the page - from 0 to 255 +// 3. fastRead --> defaults to false - executes _beginFastRead() if set to true +// Variant A +int16_t SPIFlash::readShort(uint32_t address, bool fastRead) { + const uint8_t size = sizeof(int16_t); + union + { + byte b[size]; + int16_t s; + } data; + + if (!_prep(READDATA, address, size)) { + return false; + } + switch (fastRead) { + case false: + _beginSPI(READDATA); + break; + + case true: + _beginSPI(FASTREAD); + break; + + default: + break; + } + _nextBuf(READDATA, &data.b[0], size); + _endSPI(); + return data.s; +} +// Variant B +int16_t SPIFlash::readShort(uint16_t page_number, uint8_t offset, bool fastRead) { + uint32_t address = _getAddress(page_number, offset); + + return readShort(address, fastRead); } // Reads an unsigned long of data from a specific location in a page. -// Takes two arguments - -// 1. _addr --> Any address from 0 to capacity -// 2. fastRead --> defaults to false - executes _beginFastRead() if set to true -uint32_t SPIFlash::readULong(uint32_t _addr, bool fastRead) { - #ifdef RUNDIAGNOSTIC - _spifuncruntime = micros(); - #endif - uint32_t data; - _read(_addr, data, sizeof(data), fastRead); - #ifdef RUNDIAGNOSTIC - _spifuncruntime = micros() - _spifuncruntime; - #endif - return data; +// Has two variants: +// A. Takes two arguments - +// 1. address --> Any address from 0 to capacity +// 2. fastRead --> defaults to false - executes _beginFastRead() if set to true +// B. Takes three arguments - +// 1. page --> Any page number from 0 to maxPage +// 2. offset --> Any offset within the page - from 0 to 255 +// 3. fastRead --> defaults to false - executes _beginFastRead() if set to true +// Variant A +uint32_t SPIFlash::readULong(uint32_t address, bool fastRead) { + const uint8_t size = (sizeof(uint32_t)); + union + { + uint8_t b[size]; + uint32_t l; + } data; + + if (!_prep(READDATA, address, size)) { + return false; + } + switch (fastRead) { + case false: + _beginSPI(READDATA); + break; + + case true: + _beginSPI(FASTREAD); + break; + + default: + break; + } + _nextBuf(READDATA, &data.b[0], size); + _endSPI(); + return data.l; +} +// Variant B +uint32_t SPIFlash::readULong(uint16_t page_number, uint8_t offset, bool fastRead) { + uint32_t address = _getAddress(page_number, offset); + + return readULong(address, fastRead); } // Reads a signed long of data from a specific location in a page. -// Takes two arguments - -// 1. _addr --> Any address from 0 to capacity -// 2. fastRead --> defaults to false - executes _beginFastRead() if set to true -int32_t SPIFlash::readLong(uint32_t _addr, bool fastRead) { - #ifdef RUNDIAGNOSTIC - _spifuncruntime = micros(); - #endif - int32_t data; - _read(_addr, data, sizeof(data), fastRead); - #ifdef RUNDIAGNOSTIC - _spifuncruntime = micros() - _spifuncruntime; - #endif - return data; +// Has two variants: +// A. Takes two arguments - +// 1. address --> Any address from 0 to capacity +// 2. fastRead --> defaults to false - executes _beginFastRead() if set to true +// B. Takes three arguments - +// 1. page --> Any page number from 0 to maxPage +// 2. offset --> Any offset within the page - from 0 to 255 +// 3. fastRead --> defaults to false - executes _beginFastRead() if set to true +// Variant A +int32_t SPIFlash::readLong(uint32_t address, bool fastRead) { + const uint8_t size = (sizeof(int32_t)); + union + { + byte b[size]; + int32_t l; + } data; + + if (!_prep(READDATA, address, size)) { + return false; + } + switch (fastRead) { + case false: + _beginSPI(READDATA); + break; + + case true: + _beginSPI(FASTREAD); + break; + + default: + break; + } + _nextBuf(READDATA, &data.b[0], size); + _endSPI(); + return data.l; } +// Variant B +int32_t SPIFlash::readLong(uint16_t page_number, uint8_t offset, bool fastRead) { + uint32_t address = _getAddress(page_number, offset); -// Reads a float of data from a specific location in a page. -// Takes two arguments - -// 1. _addr --> Any address from 0 to capacity -// 2. fastRead --> defaults to false - executes _beginFastRead() if set to true -float SPIFlash::readFloat(uint32_t _addr, bool fastRead) { - #ifdef RUNDIAGNOSTIC - _spifuncruntime = micros(); - #endif - float data; - _read(_addr, data, sizeof(data), fastRead); - #ifdef RUNDIAGNOSTIC - _spifuncruntime = micros() - _spifuncruntime; - #endif - return data; + return readLong(address, fastRead); +} + +// Reads a signed long of data from a specific location in a page. +// Has two variants: +// A. Takes two arguments - +// 1. address --> Any address from 0 to capacity +// 2. fastRead --> defaults to false - executes _beginFastRead() if set to true +// B. Takes three arguments - +// 1. page --> Any page number from 0 to maxPage +// 2. offset --> Any offset within the page - from 0 to 255 +// 3. fastRead --> defaults to false - executes _beginFastRead() if set to true +// Variant A +float SPIFlash::readFloat(uint32_t address, bool fastRead) { + const uint8_t size = (sizeof(float)); + union + { + byte b[size]; + float f; + } data; + + if (!_prep(READDATA, address, size)) { + return false; + } + + switch (fastRead) { + case false: + _beginSPI(READDATA); + break; + + case true: + _beginSPI(FASTREAD); + break; + + default: + break; + } + _nextBuf(READDATA, &data.b[0], size); + _endSPI(); + return data.f; +} +// Variant B +float SPIFlash::readFloat(uint16_t page_number, uint8_t offset, bool fastRead) { + uint32_t address = _getAddress(page_number, offset); + + return readFloat(address, fastRead); } // Reads a string from a specific location on a page. -// Takes three arguments -// 1. _addr --> Any address from 0 to capacity -// 2. outputString --> String variable to write the output to -// 3. fastRead --> defaults to false - executes _beginFastRead() if set to true -bool SPIFlash::readStr(uint32_t _addr, String &data, bool fastRead) { - #ifdef RUNDIAGNOSTIC - _spifuncruntime = micros(); - bool _retVal = _read(_addr, data, sizeof(data), fastRead); - _spifuncruntime = micros() - _spifuncruntime; - return _retVal; - #else - return _read(_addr, data, sizeof(data), fastRead); - #endif +// Has two variants: +// A. Takes three arguments +// 1. address --> Any address from 0 to capacity +// 2. outputString --> String variable to write the output to +// 3. fastRead --> defaults to false - executes _beginFastRead() if set to true +// B. Takes four arguments +// 1. page --> Any page number from 0 to maxPage +// 2. offset --> Any offset within the page - from 0 to 255 +// 3. outputString --> String variable to write the output to +// 4. fastRead --> defaults to false - executes _beginFastRead() if set to true +// This function first reads a short from the address to figure out the size of the String object stored and +// then reads the String object data +// Variant A +bool SPIFlash::readStr(uint32_t address, String &outStr, bool fastRead) { + uint16_t strLen; + //_delay_us(20); + strLen = readWord(address); + address+=(sizeof(strLen)); + char outputChar[strLen]; + + readCharArray(address, outputChar, strLen, fastRead); + + outStr = String(outputChar); + return true; +} +// Variant B +bool SPIFlash::readStr(uint16_t page_number, uint8_t offset, String &outStr, bool fastRead) { + uint32_t address = _getAddress(page_number, offset); + return readStr(address, outStr, fastRead); +} + +// Writes a byte of data to a specific location in a page. +// Has two variants: +// A. Takes three arguments - +// 1. address --> Any address - from 0 to capacity +// 2. data --> One byte of data to be written to a particular location on a page +// 3. errorCheck --> Turned on by default. Checks for writing errors +// B. Takes four arguments - +// 1. page --> Any page number from 0 to maxPage +// 2. offset --> Any offset within the page - from 0 to 255 +// 3. data --> One byte of data to be written to a particular location on a page +// 4. errorCheck --> Turned on by default. Checks for writing errors +// WARNING: You can only write to previously erased memory locations (see datasheet). +// Use the eraseSector()/eraseBlock32K/eraseBlock64K commands to first clear memory (write 0xFFs) +// Variant A +bool SPIFlash::writeByte(uint32_t address, uint8_t data, bool errorCheck) { + if(!_prep(PAGEPROG, address, sizeof(data))) { + return false; + } + + _beginSPI(PAGEPROG); + _nextByte(data); + CHIP_DESELECT + + if (!errorCheck) { + _endSPI(); + return true; + } + else { + return _writeErrorCheck(address, data); + } } +// Variant B +bool SPIFlash::writeByte(uint16_t page_number, uint8_t offset, uint8_t data, bool errorCheck) { + uint32_t address = _getAddress(page_number, offset); + + return writeByte(address, data, errorCheck); +} + +// Writes a char of data to a specific location in a page. +// Has two variants: +// A. Takes three arguments - +// 1. address --> Any address - from 0 to capacity +// 2. data --> One char of data to be written to a particular location on a page +// 3. errorCheck --> Turned on by default. Checks for writing errors +// B. Takes four arguments - +// 1. page --> Any page number from 0 to maxPage +// 2. offset --> Any offset within the page - from 0 to 255 +// 3. data --> One char of data to be written to a particular location on a page +// 4. errorCheck --> Turned on by default. Checks for writing errors +// WARNING: You can only write to previously erased memory locations (see datasheet). +// Use the eraseSector()/eraseBlock32K/eraseBlock64K commands to first clear memory (write 0xFFs) +// Variant A +bool SPIFlash::writeChar(uint32_t address, int8_t data, bool errorCheck) { + if(!_prep(PAGEPROG, address, sizeof(data))) { + return false; + } + + _beginSPI(PAGEPROG); + _nextByte(data); + CHIP_DESELECT + + if (!errorCheck) { + _endSPI(); + return true; + } + else { + return _writeErrorCheck(address, data); + } +} +// Variant B +bool SPIFlash::writeChar(uint16_t page_number, uint8_t offset, int8_t data, bool errorCheck) { + uint32_t address = _getAddress(page_number, offset); + + return writeChar(address, data, errorCheck); +} + +// Writes an array of bytes starting from a specific location in a page. +// Has two variants: +// A. Takes three arguments - +// 1. address --> Any address - from 0 to capacity +// 2. data --> An array of bytes to be written to a particular location on a page +// 3. errorCheck --> Turned on by default. Checks for writing errors +// B. Takes four arguments - +// 1. page --> Any page number from 0 to maxPage +// 2. offset --> Any offset within the page - from 0 to 255 +// 3. data --> An array of bytes to be written to a particular location on a page +// 4. errorCheck --> Turned on by default. Checks for writing errors +// WARNING: You can only write to previously erased memory locations (see datasheet). +// Use the eraseSector()/eraseBlock32K/eraseBlock64K commands to first clear memory (write 0xFFs) +// Variant A +bool SPIFlash::writeByteArray(uint32_t address, uint8_t *data_buffer, uint16_t bufferSize, bool errorCheck) { + if (!_prep(PAGEPROG, address, bufferSize)) { + return false; + } + uint16_t maxBytes = PAGESIZE-(address % PAGESIZE); // Force the first set of bytes to stay within the first page + uint16_t length = bufferSize; + uint16_t writeBufSz; + uint16_t data_offset = 0; + + while (length > 0) + { + writeBufSz = (length<=maxBytes) ? length : maxBytes; + + if(!_notBusy() || !_writeEnable()){ + return false; + } + + _beginSPI(PAGEPROG); + + for (uint16_t i = 0; i < writeBufSz; ++i) { + _nextByte(data_buffer[data_offset + i]); + } + _currentAddress += writeBufSz; + data_offset += writeBufSz; + length -= writeBufSz; + maxBytes = 256; // Now we can do up to 256 bytes per loop + CHIP_DESELECT + } + + if (!errorCheck) { + _endSPI(); + return true; + } + else { + if (!_notBusy()) { + return false; + } + _currentAddress = address; + CHIP_SELECT + _nextByte(READDATA); + _transferAddress(); + for (uint16_t j = 0; j < bufferSize; j++) { + if (_nextByte(NULLBYTE) != data_buffer[j]) { + return false; + } + } + _endSPI(); + return true; + } +} +// Variant B +bool SPIFlash::writeByteArray(uint16_t page_number, uint8_t offset, uint8_t *data_buffer, uint16_t bufferSize, bool errorCheck) { + uint32_t address = _getAddress(page_number, offset); + + return writeByteArray(address, data_buffer, bufferSize, errorCheck); +} + +// Writes an array of bytes starting from a specific location in a page. +// Has two variants: +// A. Takes three arguments - +// 1. address --> Any address - from 0 to capacity +// 2. data --> An array of chars to be written to a particular location on a page +// 3. errorCheck --> Turned on by default. Checks for writing errors +// B. Takes four arguments - +// 1. page --> Any page number from 0 to maxPage +// 2. offset --> Any offset within the page - from 0 to 255 +// 3. data --> An array of chars to be written to a particular location on a page +// 4. errorCheck --> Turned on by default. Checks for writing errors +// WARNING: You can only write to previously erased memory locations (see datasheet). +// Use the eraseSector()/eraseBlock32K/eraseBlock64K commands to first clear memory (write 0xFFs) +// Variant A +bool SPIFlash::writeCharArray(uint32_t address, char *data_buffer, uint16_t bufferSize, bool errorCheck) { + uint16_t writeBufSz; + uint16_t maxBytes = PAGESIZE-(address % PAGESIZE); // Force the first set of bytes to stay within the first page + uint16_t data_offset = 0; + uint16_t length = bufferSize; + if (!_prep(PAGEPROG, address, bufferSize)) { + return false; + } + + while (length > 0) + { + writeBufSz = (length<=maxBytes) ? length : maxBytes; + + if(!_notBusy() || !_writeEnable()){ + return false; + } + + _beginSPI(PAGEPROG); + + for (uint16_t i = 0; i < writeBufSz; ++i) { + _nextByte(data_buffer[data_offset + i]); + } + _currentAddress += writeBufSz; + data_offset += writeBufSz; + length -= writeBufSz; + maxBytes = 256; // Now we can do up to 256 bytes per loop + CHIP_DESELECT + } + + if (!errorCheck) { + _endSPI(); + return true; + } + else { + if (!_notBusy()) { + return false; + } + _currentAddress = address; + CHIP_SELECT + _nextByte(READDATA); + _transferAddress(); + for (uint16_t j = 0; j < bufferSize; j++) { + if (_nextByte(NULLBYTE) != data_buffer[j]) { + return false; + } + } + _endSPI(); + return true; + } +} +// Variant B +bool SPIFlash::writeCharArray(uint16_t page_number, uint8_t offset, char *data_buffer, uint16_t bufferSize, bool errorCheck) { + uint32_t address = _getAddress(page_number, offset); + + return writeCharArray(address, data_buffer, bufferSize, errorCheck); +} + +// Writes an unsigned int as two bytes starting from a specific location in a page. +// Has two variants: +// A. Takes three arguments - +// 1. address --> Any address - from 0 to capacity +// 2. data --> One unsigned int of data to be written to a particular location on a page +// 3. errorCheck --> Turned on by default. Checks for writing errors +// B. Takes four arguments - +// 1. page --> Any page number from 0 to maxPage +// 2. offset --> Any offset within the page - from 0 to 255 +// 3. data --> One unsigned int of data to be written to a particular location on a page +// 4. errorCheck --> Turned on by default. Checks for writing errors +// WARNING: You can only write to previously erased memory locations (see datasheet). +// Use the eraseSector()/eraseBlock32K/eraseBlock64K commands to first clear memory (write 0xFFs) +// Variant A +bool SPIFlash::writeWord(uint32_t address, uint16_t data, bool errorCheck) { + const uint8_t size = sizeof(uint16_t); + + if(!_prep(PAGEPROG, address, size)) { + return false; + } + + union + { + uint8_t b[size]; + uint16_t w; + } var; + var.w = data; + + uint16_t maxBytes = PAGESIZE-(address % PAGESIZE); // Force the first set of bytes to stay within the first page + if (maxBytes > size) { + _beginSPI(PAGEPROG); + _nextBuf(PAGEPROG, &var.b[0], size); + CHIP_DESELECT + } + else { + uint16_t writeBufSz; + uint16_t data_offset = 0; + uint16_t _sz = size; + + while (_sz > 0) + { + writeBufSz = (_sz<=maxBytes) ? _sz : maxBytes; + if(!_notBusy() || !_writeEnable()){ + return false; + } + + _beginSPI(PAGEPROG); + for (uint16_t i = 0; i < writeBufSz; ++i) { + _nextByte(var.b[data_offset + i]); + } + _currentAddress += writeBufSz; + data_offset += writeBufSz; + _sz -= writeBufSz; + maxBytes = 256; // Now we can do up to 256 bytes per loop + CHIP_DESELECT + } + } -// Writes a byte of data to a specific location in a page. -// Takes three arguments - -// 1. _addr --> Any address - from 0 to capacity -// 2. data --> One byte to be written to a particular location on a page -// 3. errorCheck --> Turned on by default. Checks for writing errors -// WARNING: You can only write to previously erased memory locations (see datasheet). -// Use the eraseSector()/eraseBlock32K/eraseBlock64K commands to first clear memory (write 0xFFs) -bool SPIFlash::writeByte(uint32_t _addr, uint8_t data, bool errorCheck) { - #ifdef RUNDIAGNOSTIC - _spifuncruntime = micros(); - bool _retVal = _write(_addr, data, sizeof(data), errorCheck); - _spifuncruntime = micros() - _spifuncruntime; - return _retVal; - #else - return _write(_addr, data, sizeof(data), errorCheck); - #endif + if (!errorCheck) { + _endSPI(); + return true; + } + else + return _writeErrorCheck(address, data); } +// Variant B +bool SPIFlash::writeWord(uint16_t page_number, uint8_t offset, uint16_t data, bool errorCheck) { + uint32_t address = _getAddress(page_number, offset); -// Writes a char of data to a specific location in a page. -// Takes three arguments - -// 1. _addr --> Any address - from 0 to capacity -// 2. data --> One char to be written to a particular location on a page -// 3. errorCheck --> Turned on by default. Checks for writing errors -// WARNING: You can only write to previously erased memory locations (see datasheet). -// Use the eraseSector()/eraseBlock32K/eraseBlock64K commands to first clear memory (write 0xFFs) -bool SPIFlash::writeChar(uint32_t _addr, int8_t data, bool errorCheck) { - #ifdef RUNDIAGNOSTIC - _spifuncruntime = micros(); - bool _retVal = _write(_addr, data, sizeof(data), errorCheck); - _spifuncruntime = micros() - _spifuncruntime; - return _retVal; - #else - return _write(_addr, data, sizeof(data), errorCheck); - #endif + return writeWord(address, data, errorCheck); } -// Writes an array of bytes starting from a specific location in a page. -// Takes four arguments - -// 1. _addr --> Any address - from 0 to capacity -// 2. data_buffer --> The pointer to the array of bytes be written to a particular location on a page -// 3. bufferSize --> Size of the array of bytes - in number of bytes -// 4. errorCheck --> Turned on by default. Checks for writing errors +// Writes a signed int as two bytes starting from a specific location in a page. +// Has two variants: +// A. Takes three arguments - +// 1. address --> Any address - from 0 to capacity +// 2. data --> One signed int of data to be written to a particular location on a page +// 3. errorCheck --> Turned on by default. Checks for writing errors +// B. Takes four arguments - +// 1. page --> Any page number from 0 to maxPage +// 2. offset --> Any offset within the page - from 0 to 255 +// 3. data --> One signed int of data to be written to a particular location on a page +// 4. errorCheck --> Turned on by default. Checks for writing errors // WARNING: You can only write to previously erased memory locations (see datasheet). -// Use the eraseSector()/eraseBlock32K/eraseBlock64K commands to first clear memory (write 0xFFs) -bool SPIFlash::writeByteArray(uint32_t _addr, uint8_t *data_buffer, size_t bufferSize, bool errorCheck) { - #ifdef RUNDIAGNOSTIC - _spifuncruntime = micros(); - #endif - if (!_prep(PAGEPROG, _addr, bufferSize)) { +// Use the eraseSector()/eraseBlock32K/eraseBlock64K commands to first clear memory (write 0xFFs) +// Variant A +bool SPIFlash::writeShort(uint32_t address, int16_t data, bool errorCheck) { + const uint8_t size = sizeof(data); + if(!_prep(PAGEPROG, address, size)) { return false; } - uint16_t maxBytes = SPI_PAGESIZE-(_addr % SPI_PAGESIZE); // Force the first set of bytes to stay within the first page - if (bufferSize <= maxBytes) { - CHIP_SELECT - _nextByte(WRITE, PAGEPROG); - _transferAddress(); - _nextBuf(PAGEPROG, &data_buffer[0], bufferSize); + union + { + uint8_t b[size]; + int16_t s; + } var; + var.s = data; + + uint16_t maxBytes = PAGESIZE-(address % PAGESIZE); // Force the first set of bytes to stay within the first page + if (maxBytes > size) { + _beginSPI(PAGEPROG); + _nextBuf(PAGEPROG, &var.b[0], size); CHIP_DESELECT } else { - uint16_t length = bufferSize; uint16_t writeBufSz; uint16_t data_offset = 0; + uint16_t _sz = size; - do { - writeBufSz = (length<=maxBytes) ? length : maxBytes; + while (_sz > 0) + { + writeBufSz = (_sz<=maxBytes) ? _sz : maxBytes; + if(!_notBusy() || !_writeEnable()){ + return false; + } - CHIP_SELECT - _nextByte(WRITE, PAGEPROG); - _transferAddress(); + _beginSPI(PAGEPROG); for (uint16_t i = 0; i < writeBufSz; ++i) { - _nextByte(WRITE, data_buffer[data_offset + i]); + _nextByte(var.b[data_offset + i]); } - CHIP_DESELECT - _currentAddress += writeBufSz; data_offset += writeBufSz; - length -= writeBufSz; + _sz -= writeBufSz; maxBytes = 256; // Now we can do up to 256 bytes per loop - - if(!_notBusy() || !_writeEnable()){ - return false; - } - - } while (length > 0); + CHIP_DESELECT + } } - if (!errorCheck) { + if (!errorCheck) { _endSPI(); - #ifdef RUNDIAGNOSTIC - _spifuncruntime = micros() - _spifuncruntime; - #endif return true; + } + else + return _writeErrorCheck(address, data); +} +// Variant B +bool SPIFlash::writeShort(uint16_t page_number, uint8_t offset, int16_t data, bool errorCheck) { + uint32_t address = _getAddress(page_number, offset); + + return writeShort(address, data, errorCheck); +} + +// Writes an unsigned long as four bytes starting from a specific location in a page. +// Has two variants: +// A. Takes three arguments - +// 1. address --> Any address - from 0 to capacity +// 2. data --> One unsigned long of data to be written to a particular location on a page +// 3. errorCheck --> Turned on by default. Checks for writing errors +// B. Takes four arguments - +// 1. page --> Any page number from 0 to maxPage +// 2. offset --> Any offset within the page - from 0 to 255 +// 3. data --> One unsigned long of data to be written to a particular location on a page +// 4. errorCheck --> Turned on by default. Checks for writing errors +// WARNING: You can only write to previously erased memory locations (see datasheet). +// Use the eraseSector()/eraseBlock32K/eraseBlock64K commands to first clear memory (write 0xFFs) +// Variant A +bool SPIFlash::writeULong(uint32_t address, uint32_t data, bool errorCheck) { + const uint8_t size = (sizeof(data)); + + if(!_prep(PAGEPROG, address, size)) { + return false; + } + + union + { + uint8_t b[size]; + uint32_t l; + } var; + var.l = data; + + uint16_t maxBytes = PAGESIZE-(address % PAGESIZE); // Force the first set of bytes to stay within the first page + if (maxBytes > size) { + _beginSPI(PAGEPROG); + _nextBuf(PAGEPROG, &var.b[0], size); + CHIP_DESELECT } else { - if (!_notBusy()) { - return false; - } - _currentAddress = _addr; - CHIP_SELECT - _nextByte(WRITE, READDATA); - _transferAddress(); - for (uint16_t j = 0; j < bufferSize; j++) { - if (_nextByte(READ) != data_buffer[j]) { + uint16_t writeBufSz; + uint16_t data_offset = 0; + uint16_t _sz = size; + + while (_sz > 0) + { + writeBufSz = (_sz<=maxBytes) ? _sz : maxBytes; + if(!_notBusy() || !_writeEnable()){ return false; } + + _beginSPI(PAGEPROG); + for (uint16_t i = 0; i < writeBufSz; ++i) { + _nextByte(var.b[data_offset + i]); + } + _currentAddress += writeBufSz; + data_offset += writeBufSz; + _sz -= writeBufSz; + maxBytes = 256; // Now we can do up to 256 bytes per loop + CHIP_DESELECT } + } + + if (!errorCheck){ _endSPI(); - #ifdef RUNDIAGNOSTIC - _spifuncruntime = micros() - _spifuncruntime; - #endif - return true; + return true; + } + else { + return _writeErrorCheck(address, data); } } +// Variant B +bool SPIFlash::writeULong(uint16_t page_number, uint8_t offset, uint32_t data, bool errorCheck) { + uint32_t address = _getAddress(page_number, offset); -// Writes an array of bytes starting from a specific location in a page. -// Takes four arguments - -// 1. _addr --> Any address - from 0 to capacity -// 2. data_buffer --> The pointer to the array of chars be written to a particular location on a page -// 3. bufferSize --> Size of the array of chars - in number of bytes -// 4. errorCheck --> Turned on by default. Checks for writing errors + return writeULong(address, data, errorCheck); +} + +// Writes a signed long as four bytes starting from a specific location in a page. +// Has two variants: +// A. Takes three arguments - +// 1. address --> Any address - from 0 to capacity +// 2. data --> One signed long of data to be written to a particular location on a page +// 3. errorCheck --> Turned on by default. Checks for writing errors +// B. Takes four arguments - +// 1. page --> Any page number from 0 to maxPage +// 2. offset --> Any offset within the page - from 0 to 255 +// 3. data --> One signed long of data to be written to a particular location on a page +// 4. errorCheck --> Turned on by default. Checks for writing errors // WARNING: You can only write to previously erased memory locations (see datasheet). -// Use the eraseSector()/eraseBlock32K/eraseBlock64K commands to first clear memory (write 0xFFs) -bool SPIFlash::writeCharArray(uint32_t _addr, char *data_buffer, size_t bufferSize, bool errorCheck) { - #ifdef RUNDIAGNOSTIC - _spifuncruntime = micros(); - #endif - if (!_prep(PAGEPROG, _addr, bufferSize)) { +// Use the eraseSector()/eraseBlock32K/eraseBlock64K commands to first clear memory (write 0xFFs) +// Variant A +bool SPIFlash::writeLong(uint32_t address, int32_t data, bool errorCheck) { +const uint8_t size = sizeof(data); + + if(!_prep(PAGEPROG, address, size)) { return false; } - uint16_t maxBytes = SPI_PAGESIZE-(_addr % SPI_PAGESIZE); // Force the first set of bytes to stay within the first page - if (bufferSize <= maxBytes) { - CHIP_SELECT - _nextByte(WRITE, PAGEPROG); - _transferAddress(); - _nextBuf(PAGEPROG, (uint8_t*) &data_buffer[0], bufferSize); + union + { + uint8_t b[size]; + int32_t l; + } var; + var.l = data; + + uint16_t maxBytes = PAGESIZE-(address % PAGESIZE); // Force the first set of bytes to stay within the first page + if (maxBytes > size) { + _beginSPI(PAGEPROG); + _nextBuf(PAGEPROG, &var.b[0], size); CHIP_DESELECT } else { - uint16_t length = bufferSize; uint16_t writeBufSz; uint16_t data_offset = 0; + uint16_t _sz = size; - do { - writeBufSz = (length<=maxBytes) ? length : maxBytes; + while (_sz > 0) + { + writeBufSz = (_sz<=maxBytes) ? _sz : maxBytes; + if(!_notBusy() || !_writeEnable()){ + return false; + } - CHIP_SELECT - _nextByte(WRITE, PAGEPROG); - _transferAddress(); + _beginSPI(PAGEPROG); for (uint16_t i = 0; i < writeBufSz; ++i) { - _nextByte(WRITE, data_buffer[data_offset + i]); + _nextByte(var.b[data_offset + i]); } - CHIP_DESELECT - _currentAddress += writeBufSz; data_offset += writeBufSz; - length -= writeBufSz; + _sz -= writeBufSz; maxBytes = 256; // Now we can do up to 256 bytes per loop + CHIP_DESELECT + } + } + + if (!errorCheck){ + _endSPI(); + return true; + } + else { + return _writeErrorCheck(address, data); + } +} +// Variant B +bool SPIFlash::writeLong(uint16_t page_number, uint8_t offset, int32_t data, bool errorCheck) { + uint32_t address = _getAddress(page_number, offset); + return writeLong(address, data, errorCheck); +} + +// Writes a float as four bytes starting from a specific location in a page. +// Has two variants: +// A. Takes three arguments - +// 1. address --> Any address - from 0 to capacity +// 2. data --> One float of data to be written to a particular location on a page +// 3. errorCheck --> Turned on by default. Checks for writing errors +// B. Takes four arguments - +// 1. page --> Any page number from 0 to maxPage +// 2. offset --> Any offset within the page - from 0 to 255 +// 3. data --> One float of data to be written to a particular location on a page +// 4. errorCheck --> Turned on by default. Checks for writing errors +// WARNING: You can only write to previously erased memory locations (see datasheet). +// Use the eraseSector()/eraseBlock32K/eraseBlock64K commands to first clear memory (write 0xFFs) +// Variant A +bool SPIFlash::writeFloat(uint32_t address, float data, bool errorCheck) { + const uint8_t size = (sizeof(data)); + + if(!_prep(PAGEPROG, address, size)) { + return false; + } + union + { + uint8_t b[size]; + float f; + } var; + var.f = data; + + uint16_t maxBytes = PAGESIZE-(address % PAGESIZE); // Force the first set of bytes to stay within the first page + if (maxBytes > size) { + _beginSPI(PAGEPROG); + _nextBuf(PAGEPROG, &var.b[0], size); + CHIP_DESELECT + } + else { + uint16_t writeBufSz; + uint16_t data_offset = 0; + uint16_t _sz = size; + + while (_sz > 0) + { + writeBufSz = (_sz<=maxBytes) ? _sz : maxBytes; if(!_notBusy() || !_writeEnable()){ return false; } - } while (length > 0); + _beginSPI(PAGEPROG); + for (uint16_t i = 0; i < writeBufSz; ++i) { + _nextByte(var.b[data_offset + i]); + } + _currentAddress += writeBufSz; + data_offset += writeBufSz; + _sz -= writeBufSz; + maxBytes = 256; // Now we can do up to 256 bytes per loop + CHIP_DESELECT + } } if (!errorCheck) { _endSPI(); - #ifdef RUNDIAGNOSTIC - _spifuncruntime = micros() - _spifuncruntime; - #endif return true; } else { - if (!_notBusy()) { - return false; - } - _currentAddress = _addr; - CHIP_SELECT - _nextByte(WRITE, READDATA); - _transferAddress(); - for (uint16_t j = 0; j < bufferSize; j++) { - if (_nextByte(READ) != data_buffer[j]) { - return false; - } - } - _endSPI(); - #ifdef RUNDIAGNOSTIC - _spifuncruntime = micros() - _spifuncruntime; - #endif - return true; + return _writeErrorCheck(address, data); } } +// Variant B +bool SPIFlash::writeFloat(uint16_t page_number, uint8_t offset, float data, bool errorCheck) { + uint32_t address = _getAddress(page_number, offset); -// Writes an unsigned int as two bytes starting from a specific location in a page. -// Takes three arguments - -// 1. _addr --> Any address - from 0 to capacity -// 2. data --> One word to be written to a particular location on a page -// 3. errorCheck --> Turned on by default. Checks for writing errors -// WARNING: You can only write to previously erased memory locations (see datasheet). -// Use the eraseSector()/eraseBlock32K/eraseBlock64K commands to first clear memory (write 0xFFs) -bool SPIFlash::writeWord(uint32_t _addr, uint16_t data, bool errorCheck) { - #ifdef RUNDIAGNOSTIC - _spifuncruntime = micros(); - bool _retVal = _write(_addr, data, sizeof(data), errorCheck); - _spifuncruntime = micros() - _spifuncruntime; - return _retVal; - #else - return _write(_addr, data, sizeof(data), errorCheck); - #endif + return writeFloat(address, data, errorCheck); } -// Writes a signed int as two bytes starting from a specific location in a page -// Takes three arguments - -// 1. _addr --> Any address - from 0 to capacity -// 2. data --> One short to be written to a particular location on a page -// 3. errorCheck --> Turned on by default. Checks for writing errors +// Reads a string from a specific location on a page. +// Has two variants: +// A. Takes two arguments - +// 1. address --> Any address from 0 to capacity +// 2. inputString --> String variable to write the data from +// 3. errorCheck --> Turned on by default. Checks for writing errors +// B. Takes four arguments - +// 1. page --> Any page number from 0 to maxPage +// 2. offset --> Any offset within the page - from 0 to 255 +// 3. inputString --> String variable to write the data from +// 4. errorCheck --> Turned on by default. Checks for writing errors // WARNING: You can only write to previously erased memory locations (see datasheet). -// Use the eraseSector()/eraseBlock32K/eraseBlock64K commands to first clear memory (write 0xFFs) -bool SPIFlash::writeShort(uint32_t _addr, int16_t data, bool errorCheck) { - #ifdef RUNDIAGNOSTIC - _spifuncruntime = micros(); - bool _retVal = _write(_addr, data, sizeof(data), errorCheck); - _spifuncruntime = micros() - _spifuncruntime; - return _retVal; - #else - return _write(_addr, data, sizeof(data), errorCheck); - #endif -} +// Use the eraseSector()/eraseBlock32K/eraseBlock64K commands to first clear memory (write 0xFFs) +// This function first writes the size of the string as an unsigned int to the address to figure out the size of the String object stored and +// then writes the String object data. Therefore it takes up two bytes more than the size of the String itself. +// Variant A +bool SPIFlash::writeStr(uint32_t address, String &inputStr, bool errorCheck) { + uint16_t inStrLen = inputStr.length() +1; + if(!_prep(PAGEPROG, address, inStrLen)) { + return false; + } -// Writes an unsigned long as four bytes starting from a specific location in a page. -// Takes three arguments - -// 1. _addr --> Any address - from 0 to capacity -// 2. data --> One unsigned long to be written to a particular location on a page -// 3. errorCheck --> Turned on by default. Checks for writing errors -// WARNING: You can only write to previously erased memory locations (see datasheet). -// Use the eraseSector()/eraseBlock32K/eraseBlock64K commands to first clear memory (write 0xFFs) -bool SPIFlash::writeULong(uint32_t _addr, uint32_t data, bool errorCheck) { - #ifdef RUNDIAGNOSTIC - _spifuncruntime = micros(); - bool _retVal = _write(_addr, data, sizeof(data), errorCheck); - _spifuncruntime = micros() - _spifuncruntime; - return _retVal; - #else - return _write(_addr, data, sizeof(data), errorCheck); - #endif -} + const uint16_t size = sizeof(inStrLen); + union + { + uint8_t b[size]; + uint16_t w; + } var; + + var.w = inStrLen; + char inputChar[inStrLen]; + inputStr.toCharArray(inputChar, inStrLen); + uint16_t maxBytes = PAGESIZE-(address % PAGESIZE); // Force the first set of bytes to stay within the first page + if (maxBytes > inStrLen) { + _beginSPI(PAGEPROG); + _nextBuf(PAGEPROG, &var.b[0], size); + _nextBuf(PAGEPROG, (uint8_t*)&inputChar, inStrLen); + CHIP_DESELECT + } + else { + uint16_t writeBufSz; + uint16_t data_offset = 0; + bool strLenWritten = false; -// Writes a signed long as four bytes starting from a specific location in a page -// Takes three arguments - -// 1. _addr --> Any address - from 0 to capacity -// 2. data --> One signed long to be written to a particular location on a page -// 3. errorCheck --> Turned on by default. Checks for writing errors -// WARNING: You can only write to previously erased memory locations (see datasheet). -// Use the eraseSector()/eraseBlock32K/eraseBlock64K commands to first clear memory (write 0xFFs) -bool SPIFlash::writeLong(uint32_t _addr, int32_t data, bool errorCheck) { - #ifdef RUNDIAGNOSTIC - _spifuncruntime = micros(); - bool _retVal = _write(_addr, data, sizeof(data), errorCheck); - _spifuncruntime = micros() - _spifuncruntime; - return _retVal; - #else - return _write(_addr, data, sizeof(data), errorCheck); - #endif -} + while (inStrLen > 0) + { + writeBufSz = (inStrLen<=maxBytes) ? inStrLen : maxBytes; + if(!_notBusy() || !_writeEnable()){ + return false; + } -// Writes a float as four bytes starting from a specific location in a page -// Takes three arguments - -// 1. _addr --> Any address - from 0 to capacity -// 2. data --> One float to be written to a particular location on a page -// 3. errorCheck --> Turned on by default. Checks for writing errors -// WARNING: You can only write to previously erased memory locations (see datasheet). -// Use the eraseSector()/eraseBlock32K/eraseBlock64K commands to first clear memory (write 0xFFs) -bool SPIFlash::writeFloat(uint32_t _addr, float data, bool errorCheck) { - #ifdef RUNDIAGNOSTIC - _spifuncruntime = micros(); - bool _retVal = _write(_addr, data, sizeof(data), errorCheck); - _spifuncruntime = micros() - _spifuncruntime; - return _retVal; - #else - return _write(_addr, data, sizeof(data), errorCheck); - #endif -} + _beginSPI(PAGEPROG); + for (uint16_t i = 0; i < writeBufSz; ++i) { + if(!strLenWritten) { + for (uint8_t j = 0; j < size; j++) { + _nextByte(var.b[j]); + } + strLenWritten = true; + } + _nextByte(inputChar[data_offset + i]); + } + _currentAddress += writeBufSz; + data_offset += writeBufSz; + inStrLen -= writeBufSz; + maxBytes = 256; // Now we can do up to 256 bytes per loop + CHIP_DESELECT + } + } -// Writes a string to a specific location on a page -// Takes three arguments - -// 1. _addr --> Any address - from 0 to capacity -// 2. data --> One String to be written to a particular location on a page -// 3. errorCheck --> Turned on by default. Checks for writing errors -// WARNING: You can only write to previously erased memory locations (see datasheet). -// Use the eraseSector()/eraseBlock32K/eraseBlock64K commands to first clear memory (write 0xFFs) -bool SPIFlash::writeStr(uint32_t _addr, String &data, bool errorCheck) { - #ifdef RUNDIAGNOSTIC - _spifuncruntime = micros(); - bool _retVal = _write(_addr, data, sizeof(data), errorCheck); - _spifuncruntime = micros() - _spifuncruntime; - return _retVal; - #else - return _write(_addr, data, sizeof(data), errorCheck); - #endif + if (!errorCheck) { + _endSPI(); + return true; + } + else { + String tempStr; + readStr(address, tempStr); + return inputStr.equals(tempStr); + } +} +// Variant B +bool SPIFlash::writeStr(uint16_t page_number, uint8_t offset, String &inputStr, bool errorCheck) { + uint32_t address = _getAddress(page_number, offset); + return writeStr(address, inputStr, errorCheck); } -// Erases one 4k sector. -// Takes an address as the argument and erases the block containing the address. -bool SPIFlash::eraseSector(uint32_t _addr) { - #ifdef RUNDIAGNOSTIC - _spifuncruntime = micros(); - #endif - if (!_prep(ERASEFUNC, _addr)) { - return false; - } - _beginSPI(SECTORERASE); //The address is transferred as a part of this function + +//Erases one 4k sector. Has two variants: +// A. Takes the address as the argument and erases the sector containing the address. +// B. Takes page to be erased as the argument and erases the sector containing the page. +// The sectors are numbered 0 - 255 containing 16 pages each. +// Page 0-15 --> Sector 0; Page 16-31 --> Sector 1;......Page 4080-4095 --> Sector 255 +// Variant A +bool SPIFlash::eraseSector(uint32_t address) { + if(!_notBusy()||!_writeEnable()) + return false; + + _beginSPI(SECTORERASE); + _nextByte(address >> 16); + _nextByte(address >> 8); + _nextByte(0); _endSPI(); - if(!_notBusy(500L)) { - return false; //Datasheet says erasing a sector takes 400ms max - } - //_writeDisable(); - #ifdef RUNDIAGNOSTIC - _spifuncruntime = micros() - _spifuncruntime; - #endif + if(!_notBusy(500L)) + return false; //Datasheet says erasing a sector takes 400ms max + + //_writeDisable(); //_writeDisable() is not required because the Write Enable Latch (WEL) flag is cleared to 0 + // i.e. to write disable state upon the following conditions: + // Power-up, Write Disable, Page Program, Quad Page Program, ``Sector Erase``, Block Erase, Chip Erase, Write Status Register, + // Erase Security Register and Program Security register return true; } +// Variant B +bool SPIFlash::eraseSector(uint16_t page_number, uint8_t offset) { + uint32_t address = _getAddress(page_number, offset); + return eraseSector(address); +} -// Erases one 32k block. -// Takes an address as the argument and erases the block containing the address. -bool SPIFlash::eraseBlock32K(uint32_t _addr) { - #ifdef RUNDIAGNOSTIC - _spifuncruntime = micros(); - #endif - if (!_prep(ERASEFUNC, _addr)) { - return false; +//Erases one 32k block. Has two variants: +// A. Takes the address as the argument and erases the block containing the address. +// B. Takes page to be erased as the argument and erases the block containing the page. +// The blocks are numbered 0 - 31 containing 128 pages each. +// Page 0-127 --> Block 0; Page 128-255 --> Block 1;......Page 3968-4095 --> Block 31 +// Variant A +bool SPIFlash::eraseBlock32K(uint32_t address) { + if(!_notBusy()||!_writeEnable()) { + return false; } _beginSPI(BLOCK32ERASE); + _nextByte(address >> 16); + _nextByte(address >> 8); + _nextByte(0); _endSPI(); - if(!_notBusy(1*S)) { - return false; //Datasheet says erasing a sector takes 400ms max - } - _writeDisable(); - #ifdef RUNDIAGNOSTIC - _spifuncruntime = micros() - _spifuncruntime; - #endif + if(!_notBusy(1*S)) + return false; //Datasheet says erasing a sector takes 400ms max + + //_writeDisable(); //_writeDisable() is not required because the Write Enable Latch (WEL) flag is cleared to 0 + // i.e. to write disable state upon the following conditions: + // Power-up, Write Disable, Page Program, Quad Page Program, Sector Erase, ``Block Erase``, Chip Erase, Write Status Register, + // Erase Security Register and Program Security register return true; } +// Variant B +bool SPIFlash::eraseBlock32K(uint16_t page_number, uint8_t offset) { + uint32_t address = _getAddress(page_number, offset); + return eraseBlock32K(address); +} -// Erases one 64k block. -// Takes an address as the argument and erases the block containing the address. -bool SPIFlash::eraseBlock64K(uint32_t _addr) { - #ifdef RUNDIAGNOSTIC - _spifuncruntime = micros(); - #endif - if (!_prep(ERASEFUNC, _addr)) { - return false; +//Erases one 64k block. Has two variants: +// A. Takes the address as the argument and erases the block containing the address. +// B. Takes page to be erased as the argument and erases the block containing the page. +// The blocks are numbered 0 - 15 containing 256 pages each. +// Page 0-255 --> Block 0; Page 256-511 --> Block 1;......Page 3840-4095 --> Block 15 +// Variant A +bool SPIFlash::eraseBlock64K(uint32_t address) { + if(!_notBusy()||!_writeEnable()) { + return false; } - _beginSPI(BLOCK64ERASE); + _nextByte(address >> 16); + _nextByte(address >> 8); + _nextByte(0); _endSPI(); - if(!_notBusy(1200L)) { - return false; //Datasheet says erasing a sector takes 400ms max - } - #ifdef RUNDIAGNOSTIC - _spifuncruntime = micros() - _spifuncruntime; - #endif + if(!_notBusy(1200L)) + return false; //Datasheet says erasing a sector takes 400ms max + + //_writeDisable(); //_writeDisable() is not required because the Write Enable Latch (WEL) flag is cleared to 0 + // i.e. to write disable state upon the following conditions: + // Power-up, Write Disable, Page Program, Quad Page Program, Sector Erase, ``Block Erase``, Chip Erase, Write Status Register, + // Erase Security Register and Program Security register + return true; } +// Variant B +bool SPIFlash::eraseBlock64K(uint16_t page_number, uint8_t offset) { + uint32_t address = _getAddress(page_number, offset); + return eraseBlock64K(address); +} //Erases whole chip. Think twice before using. bool SPIFlash::eraseChip(void) { - #ifdef RUNDIAGNOSTIC - _spifuncruntime = micros(); - #endif - if(!_notBusy() || !_writeEnable()) { - return false; - } + if(!_notBusy()||!_writeEnable()) + return false; _beginSPI(CHIPERASE); - _endSPI(); + _endSPI(); + if(!_notBusy(_chip.eraseTime)) + return false; //Datasheet says erasing chip takes 6s max - while(_readStat1() & BUSY) { - //_delay_us(30000L); - } - _endSPI(); + //_writeDisable(); //_writeDisable() is not required because the Write Enable Latch (WEL) flag is cleared to 0 + // i.e. to write disable state upon the following conditions: + // Power-up, Write Disable, Page Program, Quad Page Program, Sector Erase, Block Erase, ``Chip Erase``, Write Status Register, + // Erase Security Register and Program Security register - #ifdef RUNDIAGNOSTIC - _spifuncruntime = micros() - _spifuncruntime; - #endif return true; } @@ -798,37 +1765,27 @@ bool SPIFlash::eraseChip(void) { //Erase suspend is only allowed during Block/Sector erase. //Program suspend is only allowed during Page/Quad Page Program bool SPIFlash::suspendProg(void) { - #ifdef RUNDIAGNOSTIC - _spifuncruntime = micros(); - #endif if(_notBusy()) { return false; } if(!_noSuspend()) { - #ifdef RUNDIAGNOSTIC - _spifuncruntime = micros() - _spifuncruntime; - #endif return true; } - _beginSPI(SUSPEND); - _endSPI(); - _delay_us(20); - if(!_notBusy(50) || _noSuspend()) { - return false; + else { + _beginSPI(SUSPEND); + _endSPI(); + _delay_us(20); + if(!_notBusy(50) || _noSuspend()) { //Max suspend Enable time according to datasheet + return false; + } + return true; } - #ifdef RUNDIAGNOSTIC - _spifuncruntime = micros() - _spifuncruntime; - #endif - return true; } //Resumes previously suspended Block Erase/Sector Erase/Page Program. bool SPIFlash::resumeProg(void) { - #ifdef RUNDIAGNOSTIC - _spifuncruntime = micros(); - #endif if(!_notBusy() || _noSuspend()) { return false; } @@ -841,66 +1798,48 @@ bool SPIFlash::resumeProg(void) { if(_notBusy(10) || !_noSuspend()) { return false; } - #ifdef RUNDIAGNOSTIC - _spifuncruntime = micros() - _spifuncruntime; - #endif - return true; + return true; } //Puts device in low power state. Good for battery powered operations. +//Typical current consumption during power-down is 1mA with a maximum of 5mA. (Datasheet 7.4) //In powerDown() the chip will only respond to powerUp() bool SPIFlash::powerDown(void) { - if (_chip.manufacturerID != MICROCHIP_MANID) { - #ifdef RUNDIAGNOSTIC - _spifuncruntime = micros(); - #endif - if(!_notBusy(20)) - return false; + if(!_notBusy(20)) + return false; - _beginSPI(POWERDOWN); - _endSPI(); + _beginSPI(POWERDOWN); + _endSPI(); - _delay_us(5); + _delay_us(5); - #ifdef RUNDIAGNOSTIC - bool _retVal = !_writeEnable(false); - _spifuncruntime = micros() - _spifuncruntime; - return _retVal; - #else - return !_writeEnable(false); - #endif + _beginSPI(WRITEENABLE); + CHIP_DESELECT + if (_readStat1() & WRTEN) { + _endSPI(); + return false; } else { - _troubleshoot(UNSUPPORTEDFUNCTION); - return false; + + return true; } } //Wakes chip from low power state. bool SPIFlash::powerUp(void) { - #ifdef RUNDIAGNOSTIC - _spifuncruntime = micros(); - #endif _beginSPI(RELEASE); _endSPI(); _delay_us(3); //Max release enable time according to the Datasheet - #ifdef RUNDIAGNOSTIC - if (_writeEnable(false)) { - _writeDisable(); - _spifuncruntime = micros() - _spifuncruntime; - return true; - } - return false; - #else - if (_writeEnable(false)) { - _writeDisable(); + _beginSPI(WRITEENABLE); + CHIP_DESELECT + if (_readStat1() & WRTEN) { + _endSPI(); return true; } - return false; - #endif -} + else { -/* Note: _writeDisable() is not required at the end of any function that writes to the Flash memory because the Write Enable Latch (WEL) flag is cleared to 0 i.e. to write disable state upon the following conditions being completed: -Power-up, Write Disable, Page Program, Quad Page Program, Sector Erase, Block Erase, Chip Erase, Write Status Register, Erase Security Register and Program Security register */ + return false; + } +} diff --git a/src/SPIFlash.h b/src/SPIFlash.h index 49705e9..e40aa96 100644 --- a/src/SPIFlash.h +++ b/src/SPIFlash.h @@ -1,8 +1,8 @@ -/* Arduino SPIFlash Library v.3.0.0 +/* Arduino SPIFlash Library v.2.7.0 * Copyright (C) 2017 by Prajwal Bhattaram * Created by Prajwal Bhattaram - 19/05/2015 * Modified by @boseji - 02/03/2017 - * Modified by Prajwal Bhattaram - 04/11/2017 + * Modified by Prajwal Bhattaram - 02/08/2017 * * This file is part of the Arduino SPIFlash Library. This library is for * Winbond NOR flash memory modules. In its current form it enables reading @@ -27,14 +27,17 @@ #ifndef SPIFLASH_H #define SPIFLASH_H +//ATTiny85 does not have enough pins to support Serial. So, the basic troubleshooting functions of this library are not applicable. It is up to the end user to come up with a diagnostic routine for the ATTiny85. +#ifndef __AVR_ATtiny85__ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// // Uncomment the code below to run a diagnostic if your flash // // does not respond // // // // Error codes will be generated and returned on functions // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// -#define RUNDIAGNOSTIC // +//#define RUNDIAGNOSTIC // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// +#endif //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// // Uncomment the code below to increase the speed of the library // @@ -44,19 +47,8 @@ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// //#define HIGHSPEED // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// - -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// -// Comment out the code below to disable DMA mode on SAMD based // -// platforms // -// // -// Change the ZERO_SPISERCOM define below to use other SPI ports // -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// -//#define ENABLEZERODMA // -//#define ZERO_SPISERCOM SERCOM4 // -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// - #include - #include "defines.h" - #include +#include +#include "defines.h" #if defined (ARDUINO_ARCH_SAM) #include @@ -64,153 +56,173 @@ #include #endif -#if defined (BOARD_RTL8195A) - #ifdef __cplusplus - extern "C" { - #endif - - #include "gpio_api.h" - #include "PinNames.h" - - #ifdef __cplusplus - } - #endif +#ifndef __AVR_ATtiny85__ + #include #endif -#ifndef ARCH_STM32 - #if defined(ARDUINO_ARCH_STM32) || defined(__STM32F1__) || defined(STM32F1) || defined(STM32F3) || defined(STM32F4) || defined(STM32F0xx) - #define ARCH_STM32 - #endif -#endif -#if defined (ARDUINO_ARCH_SAM) || defined (ARDUINO_ARCH_SAMD) || defined (ARDUINO_ARCH_ESP8266) || defined (SIMBLEE) || defined (ARDUINO_ARCH_ESP32) || defined (BOARD_RTL8195A) || defined(ARCH_STM32) +#if defined (ARDUINO_ARCH_SAM) || defined (ARDUINO_ARCH_SAMD) || defined (ARDUINO_ARCH_ESP8266) || defined (SIMBLEE) || defined (ARDUINO_ARCH_ESP32) || defined (BOARD_RTL8195A) // RTL8195A included - @boseji 02.03.17 - #define _delay_us(us) delayMicroseconds(us) + #define _delay_us(us) delayMicroseconds(us) #else - #include + #include +#endif +// Includes specific to RTL8195A to access GPIO HAL - @boseji 02.03.17 +#if defined (BOARD_RTL8195A) +#ifdef __cplusplus +extern "C" { #endif -// Defines and variables specific to SAM architecture -#if defined (ARDUINO_ARCH_SAM) - #define CHIP_SELECT digitalWrite(csPin, LOW); - #define CHIP_DESELECT digitalWrite(csPin, HIGH); - #define xfer _dueSPITransfer - #define BEGIN_SPI _dueSPIBegin(); - extern char _end; - extern "C" char *sbrk(int i); - //char *ramstart=(char *)0x20070000; - //char *ramend=(char *)0x20088000; +#include "gpio_api.h" +#include "PinNames.h" -// Specific access configuration for Chip select pin. Includes specific to RTL8195A to access GPIO HAL - @boseji 02.03.17 -#elif defined (BOARD_RTL8195A) - #ifdef __cplusplus - extern "C" { - #endif +#ifdef __cplusplus +} +#endif - #include "gpio_api.h" - #include "PinNames.h" +#endif - #ifdef __cplusplus - } +#ifdef ARDUINO_ARCH_AVR + #ifdef __AVR_ATtiny85__ + #define CHIP_SELECT PORTB &= ~cs_mask; + #define CHIP_DESELECT PORTB |= cs_mask; + #define SPIBIT \ + USICR = ((1<transfer(n) - #define BEGIN_SPI _spi->begin(); -#else +#elif defined (ARDUINO_ARCH_SAM) + #define CHIP_SELECT digitalWrite(csPin, LOW); + #define CHIP_DESELECT digitalWrite(csPin, HIGH); + #define xfer _dueSPITransfer + #define BEGIN_SPI _dueSPIBegin(); +// Specific access configuration for Chip select pin - @boseji 02.03.17 +#elif defined (BOARD_RTL8195A) + #define CHIP_SELECT gpio_write(&csPin, 0); + #define CHIP_DESELECT gpio_write(&csPin, 1); + #define xfer(n) SPI.transfer(n) + #define BEGIN_SPI SPI.begin(); +#else //#elif defined (ARDUINO_ARCH_ESP8266) || defined (ARDUINO_ARCH_SAMD) #define CHIP_SELECT digitalWrite(csPin, LOW); #define CHIP_DESELECT digitalWrite(csPin, HIGH); #define xfer(n) SPI.transfer(n) #define BEGIN_SPI SPI.begin(); #endif -#define LIBVER 3 -#define LIBSUBVER 0 +#define LIBVER 2 +#define LIBSUBVER 7 #define BUGFIXVER 0 +#if defined (ARDUINO_ARCH_SAM) + extern char _end; + extern "C" char *sbrk(int i); + //char *ramstart=(char *)0x20070000; + //char *ramend=(char *)0x20088000; +#endif + class SPIFlash { public: - //------------------------------------ Constructor ------------------------------------// + //----------------------------------------------Constructor----------------------------------------------- //New Constructor to Accept the PinNames as a Chip select Parameter - @boseji 02.03.17 - #if defined (ARDUINO_ARCH_SAMD) || defined(ARCH_STM32) - SPIFlash(uint8_t cs = CS, SPIClass *spiinterface=&SPI); - #elif defined (BOARD_RTL8195A) - SPIFlash(PinName cs = CS); + #if !defined (BOARD_RTL8195A) + SPIFlash(uint8_t cs = CS, bool overflow = true); #else - SPIFlash(uint8_t cs = CS); + SPIFlash(PinName cs = CS, bool overflow = true); #endif - //----------------------------- Initial / Chip Functions ------------------------------// - bool begin(size_t flashChipSize = 0); + //----------------------------------------Initial / Chip Functions----------------------------------------// + bool begin(uint32_t _chipSize = 0); void setClock(uint32_t clockSpeed); bool libver(uint8_t *b1, uint8_t *b2, uint8_t *b3); uint8_t error(bool verbosity = false); uint16_t getManID(void); uint32_t getJEDECID(void); - uint64_t getUniqueID(void); + bool getAddress(uint16_t size, uint16_t &page_number, uint8_t &offset); uint32_t getAddress(uint16_t size); uint16_t sizeofStr(String &inputStr); uint32_t getCapacity(void); uint32_t getMaxPage(void); - float functionRunTime(void); - //-------------------------------- Write / Read Bytes ---------------------------------// - bool writeByte(uint32_t _addr, uint8_t data, bool errorCheck = true); - uint8_t readByte(uint32_t _addr, bool fastRead = false); - //----------------------------- Write / Read Byte Arrays ------------------------------// - bool writeByteArray(uint32_t _addr, uint8_t *data_buffer, size_t bufferSize, bool errorCheck = true); - bool readByteArray(uint32_t _addr, uint8_t *data_buffer, size_t bufferSize, bool fastRead = false); - //-------------------------------- Write / Read Chars ---------------------------------// - bool writeChar(uint32_t _addr, int8_t data, bool errorCheck = true); - int8_t readChar(uint32_t _addr, bool fastRead = false); - //------------------------------ Write / Read Char Arrays -----------------------------// - bool writeCharArray(uint32_t _addr, char *data_buffer, size_t bufferSize, bool errorCheck = true); - bool readCharArray(uint32_t _addr, char *data_buffer, size_t buffer_size, bool fastRead = false); - //-------------------------------- Write / Read Shorts --------------------------------// - bool writeShort(uint32_t _addr, int16_t data, bool errorCheck = true); - int16_t readShort(uint32_t _addr, bool fastRead = false); - //-------------------------------- Write / Read Words ---------------------------------// - bool writeWord(uint32_t _addr, uint16_t data, bool errorCheck = true); - uint16_t readWord(uint32_t _addr, bool fastRead = false); - //-------------------------------- Write / Read Longs ---------------------------------// - bool writeLong(uint32_t _addr, int32_t data, bool errorCheck = true); - int32_t readLong(uint32_t _addr, bool fastRead = false); - //--------------------------- Write / Read Unsigned Longs -----------------------------// - bool writeULong(uint32_t _addr, uint32_t data, bool errorCheck = true); - uint32_t readULong(uint32_t _addr, bool fastRead = false); - //-------------------------------- Write / Read Floats --------------------------------// - bool writeFloat(uint32_t _addr, float data, bool errorCheck = true); - float readFloat(uint32_t _addr, bool fastRead = false); - //-------------------------------- Write / Read Strings -------------------------------// - bool writeStr(uint32_t _addr, String &data, bool errorCheck = true); - bool readStr(uint32_t _addr, String &data, bool fastRead = false); - //------------------------------- Write / Read Anything -------------------------------// - - template bool writeAnything(uint32_t _addr, const T& data, bool errorCheck = true); - template bool readAnything(uint32_t _addr, T& data, bool fastRead = false); - //-------------------------------- Erase functions ------------------------------------// - bool eraseSector(uint32_t _addr); - bool eraseBlock32K(uint32_t _addr); - bool eraseBlock64K(uint32_t _addr); + //-------------------------------------------Write / Read Bytes-------------------------------------------// + bool writeByte(uint32_t address, uint8_t data, bool errorCheck = true); + bool writeByte(uint16_t page_number, uint8_t offset, uint8_t data, bool errorCheck = true); + uint8_t readByte(uint16_t page_number, uint8_t offset, bool fastRead = false); + uint8_t readByte(uint32_t address, bool fastRead = false); + //----------------------------------------Write / Read Byte Arrays----------------------------------------// + bool writeByteArray(uint32_t address, uint8_t *data_buffer, uint16_t bufferSize, bool errorCheck = true); + bool writeByteArray(uint16_t page_number, uint8_t offset, uint8_t *data_buffer, uint16_t bufferSize, bool errorCheck = true); + bool readByteArray(uint32_t address, uint8_t *data_buffer, uint16_t bufferSize, bool fastRead = false); + bool readByteArray(uint16_t page_number, uint8_t offset, uint8_t *data_buffer, uint16_t bufferSize, bool fastRead = false); + //-------------------------------------------Write / Read Chars-------------------------------------------// + bool writeChar(uint32_t address, int8_t data, bool errorCheck = true); + bool writeChar(uint16_t page_number, uint8_t offset, int8_t data, bool errorCheck = true); + int8_t readChar(uint32_t address, bool fastRead = false); + int8_t readChar(uint16_t page_number, uint8_t offset, bool fastRead = false); + //----------------------------------------Write / Read Char Arrays----------------------------------------// + bool writeCharArray(uint32_t address, char *data_buffer, uint16_t bufferSize, bool errorCheck = true); + bool writeCharArray(uint16_t page_number, uint8_t offset, char *data_buffer, uint16_t bufferSize, bool errorCheck = true); + bool readCharArray(uint32_t address, char *data_buffer, uint16_t buffer_size, bool fastRead = false); + bool readCharArray(uint16_t page_number, uint8_t offset, char *data_buffer, uint16_t buffer_size, bool fastRead = false); + //------------------------------------------Write / Read Shorts------------------------------------------// + bool writeShort(uint32_t address, int16_t data, bool errorCheck = true); + bool writeShort(uint16_t page_number, uint8_t offset, int16_t data, bool errorCheck = true); + int16_t readShort(uint32_t address, bool fastRead = false); + int16_t readShort(uint16_t page_number, uint8_t offset, bool fastRead = false); + //-------------------------------------------Write / Read Words-------------------------------------------// + bool writeWord(uint32_t address, uint16_t data, bool errorCheck = true); + bool writeWord(uint16_t page_number, uint8_t offset, uint16_t data, bool errorCheck = true); + uint16_t readWord(uint32_t address, bool fastRead = false); + uint16_t readWord(uint16_t page_number, uint8_t offset, bool fastRead = false); + //-------------------------------------------Write / Read Longs-------------------------------------------// + bool writeLong(uint32_t address, int32_t data, bool errorCheck = true); + bool writeLong(uint16_t page_number, uint8_t offset, int32_t data, bool errorCheck = true); + int32_t readLong(uint32_t address, bool fastRead = false); + int32_t readLong(uint16_t page_number, uint8_t offset, bool fastRead = false); + //--------------------------------------Write / Read Unsigned Longs---------------------------------------// + bool writeULong(uint32_t address, uint32_t data, bool errorCheck = true); + bool writeULong(uint16_t page_number, uint8_t offset, uint32_t data, bool errorCheck = true); + uint32_t readULong(uint32_t address, bool fastRead = false); + uint32_t readULong(uint16_t page_number, uint8_t offset, bool fastRead = false); + //-------------------------------------------Write / Read Floats------------------------------------------// + bool writeFloat(uint32_t address, float data, bool errorCheck = true); + bool writeFloat(uint16_t page_number, uint8_t offset, float data, bool errorCheck = true); + float readFloat(uint32_t address, bool fastRead = false); + float readFloat(uint16_t page_number, uint8_t offset, bool fastRead = false); + //------------------------------------------Write / Read Strings------------------------------------------// + bool writeStr(uint32_t address, String &inputStr, bool errorCheck = true); + bool writeStr(uint16_t page_number, uint8_t offset, String &inputStr, bool errorCheck = true); + bool readStr(uint32_t address, String &outStr, bool fastRead = false); + bool readStr(uint16_t page_number, uint8_t offset, String &outStr, bool fastRead = false); + //------------------------------------------Write / Read Anything-----------------------------------------// + template bool writeAnything(uint32_t address, const T& value, bool errorCheck = true); + template bool writeAnything(uint16_t page_number, uint8_t offset, const T& value, bool errorCheck = true); + template bool readAnything(uint32_t address, T& value, bool fastRead = false); + template bool readAnything(uint16_t page_number, uint8_t offset, T& value, bool fastRead = false); + //--------------------------------------------Erase functions---------------------------------------------// + bool eraseSector(uint32_t address); + bool eraseSector(uint16_t page_number, uint8_t offset); + bool eraseBlock32K(uint32_t address); + bool eraseBlock32K(uint16_t page_number, uint8_t offset); + bool eraseBlock64K(uint32_t address); + bool eraseBlock64K(uint16_t page_number, uint8_t offset); bool eraseChip(void); - //-------------------------------- Power functions ------------------------------------// + //---------------------------------------------Power functions--------------------------------------------// bool suspendProg(void); bool resumeProg(void); bool powerDown(void); bool powerUp(void); - //-------------------------- Public Arduino Due Functions -----------------------------// + //-------------------------------------Public Arduino Due Functions-------------------------------------// //#if defined (ARDUINO_ARCH_SAM) //uint32_t freeRAM(void); //#endif - //------------------------------- Public variables ------------------------------------// + //-------------------------------------------Public variables-------------------------------------// private: #if defined (ARDUINO_ARCH_SAM) - //-------------------------- Private Arduino Due Functions ----------------------------// + //-------------------------------------Private Arduino Due Functions--------------------------------------// void _dmac_disable(void); void _dmac_enable(void); void _dmac_channel_disable(uint32_t ul_num); @@ -232,41 +244,42 @@ class SPIFlash { void _dueSPISendChar(char b); void _dueSPISendChar(const char* buf, size_t len); #endif - //------------------------------- Private functions -----------------------------------// - void _troubleshoot(uint8_t _code, bool printoverride = false); +//-------------------------------------Private ATTiny85 Functions-------------------------------------// +#if defined (__AVR_ATtiny85__) + static uint8_t _tinySPItransfer(uint8_t _data); + void _tinySPIbegin(); +#endif + //----------------------------------------Private functions----------------------------------------// + void _troubleshoot(void); void _printErrorCode(void); void _printSupportLink(void); void _endSPI(void); - bool _disableGlobalBlockProtect(void); - bool _prep(uint8_t opcode, uint32_t _addr, uint32_t size = 0); + bool _prep(uint8_t opcode, uint32_t address, uint32_t size); + bool _prep(uint8_t opcode, uint32_t page_number, uint8_t offset, uint32_t size); bool _startSPIBus(void); bool _beginSPI(uint8_t opcode); bool _noSuspend(void); bool _notBusy(uint32_t timeout = BUSY_TIMEOUT); - bool _notPrevWritten(uint32_t _addr, uint32_t size = 1); - bool _writeEnable(bool _troubleshootEnable = true); + bool _notPrevWritten(uint32_t address, uint32_t size = 1); + bool _writeEnable(uint32_t timeout = 10L); bool _writeDisable(void); bool _getJedecId(void); bool _getManId(uint8_t *b1, uint8_t *b2); bool _getSFDP(void); bool _chipID(void); bool _transferAddress(void); - bool _addressCheck(uint32_t _addr, uint32_t size = 1); - uint8_t _nextByte(char IOType, uint8_t data = NULLBYTE); + bool _addressCheck(uint32_t address, uint32_t size = 1); + uint8_t _nextByte(uint8_t data = NULLBYTE); uint16_t _nextInt(uint16_t = NULLINT); void _nextBuf(uint8_t opcode, uint8_t *data_buffer, uint32_t size); uint8_t _readStat1(void); uint8_t _readStat2(void); - template bool _write(uint32_t _addr, const T& value, uint32_t _sz, bool errorCheck); - template bool _read(uint32_t _addr, T& value, uint32_t _sz, bool fastRead = false); - template bool _writeErrorCheck(uint32_t _addr, const T& value); - template bool _writeErrorCheck(uint32_t _addr, const T& value, uint32_t _sz); - //-------------------------------- Private variables ----------------------------------// + uint32_t _getAddress(uint16_t page_number, uint8_t offset = 0); + template bool _writeErrorCheck(uint32_t address, const T& value); + //-------------------------------------------Private variables------------------------------------------// #ifdef SPI_HAS_TRANSACTION SPISettings _settings; #endif - //If multiple SPI ports are available this variable is used to choose between them (SPI, SPI1, SPI2 etc.) - SPIClass *_spi; #if !defined (BOARD_RTL8195A) uint8_t csPin; #else @@ -275,175 +288,154 @@ class SPIFlash { #endif volatile uint8_t *cs_port; bool pageOverflow, SPIBusState; - uint8_t cs_mask, errorcode, stat1, _SPCR, _SPSR, _a0, _a1, _a2; - char READ = 'R'; - char WRITE = 'W'; - float _spifuncruntime = 0; + uint8_t cs_mask, errorcode, state, _SPCR, _SPSR; struct chipID { - bool supported; uint8_t manufacturerID; uint8_t memoryTypeID; uint8_t capacityID; + uint16_t supported; uint32_t sfdp; uint32_t capacity; uint32_t eraseTime; }; chipID _chip; uint32_t currentAddress, _currentAddress = 0; - uint8_t _uniqueID[8]; - const uint8_t _capID[14] = - {0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x43, 0x4B, 0x00, 0x01}; - - const uint32_t _memSize[14] = - {64L * KiB, 128L * KiB, 256L * KiB, 512L * KiB, 1L * MiB, 2L * MiB, 4L * MiB, 8L * MiB, 6L * MiB, 32L * MiB, 8L * MiB, 8L * MiB, 256L * KiB, 512L * KiB}; + const uint8_t _capID[11] = {0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x43}; + const uint32_t _memSize[11] = {64L * K, 128L * K, 256L * K, 512L * K, 1L * M, 2L * M, 4L * M, 8L * M, + 16L * M, 32L * M, 8L * M}; + const uint32_t _eraseTime[11] = {1L * S, 2L * S, 2L * S, 4L * S, 6L * S, 10L * S, 15L * S, 100L * S, 200L * S, 400L * S, 50L}; //Erase time in milliseconds }; -//--------------------------------- Public Templates ------------------------------------// +//--------------------------------------------Templates-------------------------------------------// // Writes any type of data to a specific location in the flash memory. -// Takes three arguments - -// 1. _addr --> Any address from 0 to maxAddress -// 2. T& value --> Variable to write -// 3. errorCheck --> Turned on by default. Checks for writing errors +// Has two variants: +// A. Takes two arguments - +// 1. address --> Any address from 0 to maxAddress +// 2. T& value --> Variable to write data from +// 4. errorCheck --> Turned on by default. Checks for writing errors +// B. Takes three arguments - +// 1. page --> Any page number from 0 to maxPage +// 2. offset --> Any offset within the page - from 0 to 255 +// 3. const T& value --> Variable with the data to be written +// 4. errorCheck --> Turned on by default. Checks for writing errors // WARNING: You can only write to previously erased memory locations (see datasheet). // Use the eraseSector()/eraseBlock32K/eraseBlock64K commands to first clear memory (write 0xFFs) -template bool SPIFlash::writeAnything(uint32_t _addr, const T& data, bool errorCheck) { - return _write(_addr, data, sizeof(data), errorCheck); -} - -// Reads any type of data from a specific location in the flash memory. -// Takes three arguments - -// 1. _addr --> Any address from 0 to maxAddress -// 2. T& value --> Variable to return data into -// 3. fastRead --> defaults to false - executes _beginFastRead() if set to true -template bool SPIFlash::readAnything(uint32_t _addr, T& data, bool fastRead) { - return _read(_addr, data, sizeof(data), fastRead); -} - -//---------------------------------- Private Templates ----------------------------------// - -// Private template to check for errors in writing to flash memory -// Takes three arguments - -// 1. _addr --> Any address from 0 to maxAddress -// 2. const T& value --> Variable with the data to be error checked -// 3. _sz --> Size of the data variable to be error checked, in bytes (1 byte = 8 bits) -template bool SPIFlash::_writeErrorCheck(uint32_t _addr, const T& value, uint32_t _sz) { - if (!_notBusy()) { +// Variant A +template bool SPIFlash::writeAnything(uint32_t address, const T& value, bool errorCheck) { + if (!_prep(PAGEPROG, address, sizeof(value))) { return false; } - //Serial.print(F("Address being error checked: ")); - //Serial.println(_addr); - _currentAddress = _addr; - const uint8_t* p = (const uint8_t*)(const void*)&value; - CHIP_SELECT - _nextByte(WRITE, READDATA); - _transferAddress(); - for (uint16_t i = 0; i < _sz; i++) { - if (*p++ != _nextByte(READ)) { - _troubleshoot(ERRORCHKFAIL); - _endSPI(); - return false; + uint16_t maxBytes = PAGESIZE-(address % PAGESIZE); // Force the first set of bytes to stay within the first page + uint16_t length = sizeof(value); + + //if (maxBytes > length) { + uint32_t writeBufSz; + uint16_t data_offset = 0; + const uint8_t* p = ((const uint8_t*)(const void*)&value); + + if (!SPIBusState) { + _startSPIBus(); } - } - _endSPI(); - return true; -} + while (length > 0) + { + writeBufSz = (length<=maxBytes) ? length : maxBytes; -// Writes any type of data to a specific location in the flash memory. -// Takes four arguments - -// 1. _addr --> Any address from 0 to maxAddress -// 2. T& value --> Variable to write -// 3. _sz --> Size of variable in bytes (1 byte = 8 bits) -// 4. errorCheck --> Turned on by default. Checks for writing errors -// WARNING: You can only write to previously erased memory locations (see datasheet). -// Use the eraseSector()/eraseBlock32K/eraseBlock64K commands to first clear memory (write 0xFFs) + if(!_notBusy() || !_writeEnable()){ + return false; + } -template bool SPIFlash::_write(uint32_t _addr, const T& value, uint32_t _sz, bool errorCheck) { - if (!_prep(PAGEPROG, _addr, _sz)) { - return false; - } - const uint8_t* p = ((const uint8_t*)(const void*)&value); -//Serial.print(F("Address being written to: ")); -//Serial.println(_addr); - if (!SPIBusState) { - _startSPIBus(); - } - CHIP_SELECT - _nextByte(WRITE, PAGEPROG); - _transferAddress(); - //If data is only one byte (8 bits) long - if (_sz == 0x01) { - _nextByte(WRITE, *p); - CHIP_DESELECT - } - else { //If data is longer than one byte (8 bits) - uint32_t length = _sz; - uint16_t maxBytes = SPI_PAGESIZE-(_addr % SPI_PAGESIZE); // Force the first set of bytes to stay within the first page + CHIP_SELECT + (void)xfer(PAGEPROG); + _transferAddress(); - if (maxBytes > length) { - for (uint16_t i = 0; i < length; ++i) { - _nextByte(WRITE, *p++); + for (uint16_t i = 0; i < writeBufSz; ++i) { + _nextByte(*p++); } + _currentAddress += writeBufSz; + data_offset += writeBufSz; + length -= writeBufSz; + maxBytes = 256; // Now we can do up to 256 bytes per loop CHIP_DESELECT } - else { - uint32_t writeBufSz; - uint16_t data_offset = 0; - - do { - writeBufSz = (length<=maxBytes) ? length : maxBytes; - for (uint16_t i = 0; i < writeBufSz; ++i) { - _nextByte(WRITE, *p++); - } - CHIP_DESELECT - _currentAddress += writeBufSz; - data_offset += writeBufSz; - length -= writeBufSz; - maxBytes = 256; // Now we can do up to 256 bytes per loop - if(!_notBusy() || !_writeEnable()) { - return false; - } - } while (length > 0); - } - } if (!errorCheck) { _endSPI(); return true; } else { - //Serial.print(F("Address sent to error check: ")); - //Serial.println(_addr); - return _writeErrorCheck(_addr, value, _sz); + return _writeErrorCheck(address, value); } } +// Variant B +template bool SPIFlash::writeAnything(uint16_t page_number, uint8_t offset, const T& value, bool errorCheck) { + uint32_t address = _getAddress(page_number, offset); + return writeAnything(address, value, errorCheck); +} // Reads any type of data from a specific location in the flash memory. -// Takes four arguments - -// 1. _addr --> Any address from 0 to maxAddress -// 2. T& value --> Variable to return data into -// 3. _sz --> Size of the variable in bytes (1 byte = 8 bits) -// 4. fastRead --> defaults to false - executes _beginFastRead() if set to true -template bool SPIFlash::_read(uint32_t _addr, T& value, uint32_t _sz, bool fastRead) { - if (_prep(READDATA, _addr, _sz)) { +// Has two variants: +// A. Takes two arguments - +// 1. address --> Any address from 0 to maxAddress +// 2. T& value --> Variable to return data into +// 2. fastRead --> defaults to false - executes _beginFastRead() if set to true +// B. Takes three arguments - +// 1. page --> Any page number from 0 to maxPage +// 2. offset --> Any offset within the page - from 0 to 255 +// 3. T& value --> Variable to return data into +// 3. fastRead --> defaults to false - executes _beginFastRead() if set to true +// Variant A +template bool SPIFlash::readAnything(uint32_t address, T& value, bool fastRead) { + if (!_prep(READDATA, address, sizeof(value))) + return false; + uint8_t* p = (uint8_t*)(void*)&value; - CHIP_SELECT - if (fastRead) { - _nextByte(WRITE, FASTREAD); - } - else { - _nextByte(WRITE, READDATA); + if(!fastRead) + _beginSPI(READDATA); + else + _beginSPI(FASTREAD); + for (uint16_t i = 0; i < sizeof(value); i++) { + *p++ =_nextByte(); + } + _endSPI(); + return true; +} +// Variant B +template bool SPIFlash::readAnything(uint16_t page_number, uint8_t offset, T& value, bool fastRead) +{ + uint32_t address = _getAddress(page_number, offset); + return readAnything(address, value, fastRead); +} + +// Private template to check for errors in writing to flash memory +template bool SPIFlash::_writeErrorCheck(uint32_t address, const T& value) { +if (!_prep(READDATA, address, sizeof(value)) && !_notBusy()) { + return false; +} + + const uint8_t* p = (const uint8_t*)(const void*)&value; + _beginSPI(READDATA); + uint8_t _v; + for(uint16_t i = 0; i < sizeof(value);i++) + { +#if defined (ARDUINO_ARCH_SAM) + if(*p++ != _dueSPIRecByte()) + { + return false; } - _transferAddress(); - for (uint16_t i = 0; i < _sz; i++) { - *p++ =_nextByte(READ); +#else + if(*p++ != _nextByte()) + { + errorcode = ERRORCHKFAIL; + #ifdef RUNDIAGNOSTIC + _troubleshoot(); + #endif + return false; } - _endSPI(); - return true; - } - else { - return false; +#endif } + _endSPI(); + return true; } #endif // _SPIFLASH_H_ diff --git a/src/defines.h b/src/defines.h index ff02333..df629e7 100644 --- a/src/defines.h +++ b/src/defines.h @@ -1,7 +1,7 @@ -/* Arduino SPIFlash Library v.3.0.0 +/* Arduino SPIFlash Library v.2.7.0 * Copyright (C) 2017 by Prajwal Bhattaram * Created by Prajwal Bhattaram - 19/05/2015 - * Modified by Prajwal Bhattaram - 04/11/2017 + * Modified by Prajwal Bhattaram - 02/08/2017 * * This file is part of the Arduino SPIFlash Library. This library is for * Winbond NOR flash memory modules. In its current form it enables reading @@ -35,62 +35,74 @@ #define WRITEDISABLE 0x04 #define READSTAT1 0x05 #define READSTAT2 0x35 -#define WRITESTATEN 0x50 #define WRITESTAT 0x01 #define WRITEENABLE 0x06 #define SECTORERASE 0x20 #define BLOCK32ERASE 0x52 -#define BLOCK64ERASE 0xD8 -#define CHIPERASE 0x60 +#define CHIPERASE 0xC7 #define SUSPEND 0x75 #define ID 0x90 #define RESUME 0x7A #define JEDECID 0x9F -#define POWERDOWN 0xB9 #define RELEASE 0xAB +#define POWERDOWN 0xB9 +#define BLOCK64ERASE 0xD8 #define READSFDP 0x5A -#define UNIQUEID 0x4B //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// // General size definitions // -// B = Bytes; KiB = Kilo Bytes; MiB = Mega Bytes // +// B = Bytes; KB = Kilo bits; MB = Mega bits // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// -#define B(x) size_t(x*BYTE) -#define KB(x) size_t(x*KiB) -#define MB(x) size_t(x*MiB) +#define B1 1L +#define B2 2L +#define B4 4L +#define B8 8L +#define B16 16L +#define B32 32L +#define B64 64L +#define B80 80L +#define B128 128L +#define B256 256L +#define B512 512L +#define KB1 B1 * K +#define KB2 B2 * K +#define KB4 B4 * K +#define KB8 B8 * K +#define KB16 B16 * K +#define KB32 B32 * K +#define KB64 B64 * K +#define KB128 B128 * K +#define KB256 B256 * K +#define KB512 B512 * K +#define MB1 B1 * M +#define MB2 B2 * M +#define MB4 B4 * M +#define MB8 B8 * M +#define MB16 B16 * M +#define MB32 B32 * M +#define MB64 B64 * M +#define MB128 B128 * M +#define MB256 B256 * M +#define MB512 B512 * M //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// // Chip specific instructions // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// -//~~~~~~~~~~~~~~~~~~~~~~~~~ Winbond ~~~~~~~~~~~~~~~~~~~~~~~~~// - #define WINBOND_MANID 0xEF - #define SPI_PAGESIZE 0x100 - #define WINBOND_WRITE_DELAY 0x02 - #define WINBOND_WREN_TIMEOUT 10L - -//~~~~~~~~~~~~~~~~~~~~~~~~ Microchip ~~~~~~~~~~~~~~~~~~~~~~~~// - #define MICROCHIP_MANID 0xBF - #define SST25 0x25 - #define SST26 0x26 - #define ULBPR 0x98 //Global Block Protection Unlock (Ref sections 4.1.1 & 5.37 of datasheet) - -//~~~~~~~~~~~~~~~~~~~~~~~~ Cypress ~~~~~~~~~~~~~~~~~~~~~~~~// - #define CYPRESS_MANID 0x01 + //~~~~~~~~~~~~~~~~~~~~~~~~~ Winbond ~~~~~~~~~~~~~~~~~~~~~~~~~// + #define WINBOND_MANID 0xEF + #define PAGESIZE 0x100 -//~~~~~~~~~~~~~~~~~~~~~~~~ Adesto ~~~~~~~~~~~~~~~~~~~~~~~~// - #define ADESTO_MANID 0x1F - -//~~~~~~~~~~~~~~~~~~~~~~~~ Micron ~~~~~~~~~~~~~~~~~~~~~~~~// - #define MICRON_MANID 0x20 + //~~~~~~~~~~~~~~~~~~~~~~~~ Microchip ~~~~~~~~~~~~~~~~~~~~~~~~// + #define MICROCHIP_MANID 0xBF //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// // Definitions // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// #define BUSY 0x01 #if defined (ARDUINO_ARCH_ESP32) -#define SPI_CLK 20000000 //Hz equivalent of 20MHz +#define SPI_CLK 20000000 #else -#define SPI_CLK 104000000 //Hz equivalent of 104MHz +#define SPI_CLK 104000000 //Hex equivalent of 104MHz #endif #define WRTEN 0x02 #define SUS 0x80 @@ -105,26 +117,23 @@ #define NOOVERFLOW false #define NOERRCHK false #define VERBOSE true -#define PRINTOVERRIDE true -#define ERASEFUNC 0xEF #if defined (SIMBLEE) #define BUSY_TIMEOUT 100L -#elif defined ENABLEZERODMA -#define BUSY_TIMEOUT 3500L #else -#define BUSY_TIMEOUT 1000L +#define BUSY_TIMEOUT 10L #endif #define arrayLen(x) (sizeof(x) / sizeof(*x)) #define lengthOf(x) (sizeof(x))/sizeof(byte) -#define BYTE 1L -#define KiB 1024L -#define MiB KiB * KiB +#define K 1024L +#define M K * K #define S 1000L #if defined (ARDUINO_ARCH_ESP8266) #define CS 15 #elif defined (ARDUINO_ARCH_SAMD) #define CS 10 +#elif defined __AVR_ATtiny85__ +#define CS 5 /********************************************************************************************* // Declaration of the Default Chip select pin name for RTL8195A // Note: This has been shifted due to a bug identified in the HAL layer SPI driver @@ -164,35 +173,19 @@ // List of Error codes // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// - #define SUCCESS 0x00 - #define CALLBEGIN 0x01 - #define UNKNOWNCHIP 0x02 - #define UNKNOWNCAP 0x03 - #define CHIPBUSY 0x04 - #define OUTOFBOUNDS 0x05 - #define CANTENWRITE 0x06 - #define PREVWRITTEN 0x07 - #define LOWRAM 0x08 - #define SYSSUSPEND 0x09 - #define UNSUPPORTED 0x0A - #define ERRORCHKFAIL 0x0B - #define NORESPONSE 0x0C - #define UNSUPPORTEDFUNCTION 0x0D - #define UNKNOWNERROR 0xFE - -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// -// Bit shift macros // -// Thanks to @VitorBoss // -// https://github.com/Marzogh/SPIFlash/issues/76 // -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// -#define Lo(param) ((char *)¶m)[0] //0x000y -#define Hi(param) ((char *)¶m)[1] //0x00y0 -#define Higher(param) ((char *)¶m)[2] //0x0y00 -#define Highest(param) ((char *)¶m)[3] //0xy000 -#define Low(param) ((int *)¶m)[0] //0x00yy -#define Top(param) ((int *)¶m)[1] //0xyy00 -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + #define SUCCESS 0x00 + #define CALLBEGIN 0x01 + #define UNKNOWNCHIP 0x02 + #define UNKNOWNCAP 0x03 + #define CHIPBUSY 0x04 + #define OUTOFBOUNDS 0x05 + #define CANTENWRITE 0x06 + #define PREVWRITTEN 0x07 + #define LOWRAM 0x08 + #define SYSSUSPEND 0x09 + #define UNSUPPORTED 0x0A + #define ERRORCHKFAIL 0x0B + #define NORESPONSE 0x0C + #define UNKNOWNERROR 0xFE -#ifndef LED_BUILTIN //fix for boards without that definition - #define LED_BUILTIN 13 -#endif + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// diff --git a/src/tinySPI.cpp b/src/tinySPI.cpp new file mode 100644 index 0000000..78e1303 --- /dev/null +++ b/src/tinySPI.cpp @@ -0,0 +1,53 @@ +/* Arduino SPIFlash Library v.2.7.0 + * Copyright (C) 2017 by Prajwal Bhattaram + * Created by Prajwal Bhattaram - 19/04/2017 + * Modified by Prajwal Bhattaram - 19/04/2017 + * Original code from @manitou48 + * + * This file is part of the Arduino SPIFlash Library. This library is for + * Winbond NOR flash memory modules. In its current form it enables reading + * and writing individual data variables, structs and arrays from and to various locations; + * reading and writing pages; continuous read functions; sector, block and chip erase; + * suspending and resuming programming/erase and powering down for low power operation. + * + * This Library is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This Library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License v3.0 + * along with the Arduino SPIFlash Library. If not, see + * . + */ + #include "SPIFlash.h" + +#if defined (__AVR_ATtiny85__) +void SPIFlash::_tinySPIbegin() { + PORTB &= ~(_BV(PORTB0) | _BV(PORTB1) | _BV(PORTB2) | cs_mask); + DDRB &= ~_BV(PORTB0); // DI (NOT MISO) + DDRB |= _BV(PORTB1) // DO (NOT MOSI) + | _BV(PORTB2) // SCK + | cs_mask; // CS +} + +static uint8_t SPIFlash::_tinySPItransfer(uint8_t _data) { + USIDR = _data; + for (uint8_t i = 0; i < 8; i++) { + SPIBIT + } + /*SPIBIT + SPIBIT + SPIBIT + SPIBIT + SPIBIT + SPIBIT + SPIBIT + SPIBIT*/ + return USIDR; +} +#endif diff --git a/src/troubleshoot.cpp b/src/troubleshoot.cpp index ce71a9f..41e4edc 100644 --- a/src/troubleshoot.cpp +++ b/src/troubleshoot.cpp @@ -1,4 +1,4 @@ -/* Arduino SPIFlash Library v.3.0.0 +/* Arduino SPIFlash Library v.2.7.0 * Copyright (C) 2017 by Prajwal Bhattaram * Created by Prajwal Bhattaram - 14/11/2016 * Modified by @boseji - 02/03/2017 @@ -25,110 +25,162 @@ * . */ -#include "SPIFlash.h" - -//Subfunctions for troubleshooting function -void SPIFlash::_printErrorCode(void) { - Serial.print("Error code: 0x"); - if (errorcode < 0x10) { - Serial.print("0"); - } - Serial.println(errorcode, HEX); -} - -void SPIFlash::_printSupportLink(void) { - Serial.print("If this does not help resolve/clarify this issue, "); - Serial.println("please raise an issue at http://www.github.com/Marzogh/SPIFlash/issues with the details of what your were doing when this error occurred"); -} -//Troubleshooting function. Called when #ifdef RUNDIAGNOSTIC is uncommented at the top of this file. -void SPIFlash::_troubleshoot(uint8_t _code, bool printoverride) { - bool _printoverride; - errorcode = _code; -#ifdef RUNDIAGNOSTIC - _printoverride = true; + #include "SPIFlash.h" + + #if !defined (__AVR_ATtiny85__) + //Subfunctions for troubleshooting function + void SPIFlash::_printErrorCode(void) { + Serial.print("Error code: 0x"); + if (errorcode < 0x10) { + Serial.print("0"); + } + Serial.println(errorcode, HEX); + } + + void SPIFlash::_printSupportLink(void) { + Serial.print("If this does not help resolve/clarify this issue, "); + Serial.println("please raise an issue at http://www.github.com/Marzogh/SPIFlash/issues with the details of what your were doing when this error occurred"); + } + //Troubleshooting function. Called when #ifdef RUNDIAGNOSTIC is uncommented at the top of this file. + void SPIFlash::_troubleshoot(void) { + + switch (errorcode) { + case SUCCESS: + #if defined (ARDUINO_ARCH_AVR) || defined (__AVR_ATtiny85__) + _printErrorCode(); + #else + Serial.println("Action completed successfully"); + #endif + break; + + case NORESPONSE: + #if defined (ARDUINO_ARCH_AVR) || defined (__AVR_ATtiny85__) + _printErrorCode(); + #else + Serial.println("Check your wiring. Flash chip is non-responsive."); + _printSupportLink(); + #endif + break; + + case CALLBEGIN: + #if defined (ARDUINO_ARCH_AVR) || defined (__AVR_ATtiny85__) + _printErrorCode(); + #else + Serial.println("*constructor_of_choice*.begin() was not called in void setup()"); + _printSupportLink(); + #endif + break; + + case UNKNOWNCHIP: + #if defined (ARDUINO_ARCH_AVR) || defined (__AVR_ATtiny85__) + Serial.print("Error code: 0x0"); + Serial.println(UNKNOWNCHIP, HEX); + #else + Serial.println("Unable to identify chip. Are you sure this chip is supported?"); + _printSupportLink(); + #endif + Serial.println("Chip details:"); + Serial.print("manufacturer ID: 0x"); Serial.println(_chip.manufacturerID, HEX); + Serial.print("capacity ID: 0x");Serial.println(_chip.memoryTypeID, HEX); + Serial.print("device ID: 0x");Serial.println(_chip.capacityID, HEX); + break; + + case UNKNOWNCAP: + #if defined (ARDUINO_ARCH_AVR) || defined (__AVR_ATtiny85__) + _printErrorCode(); + #else + Serial.println("Unable to identify capacity. Is this chip officially supported? If not, please define a `CAPACITY` constant and include it in flash.begin(CAPACITY)."); + _printSupportLink(); + #endif + break; + + case CHIPBUSY: + #if defined (ARDUINO_ARCH_AVR) || defined (__AVR_ATtiny85__) + _printErrorCode(); + #else + Serial.println("Chip is busy."); + Serial.println("Make sure all pins have been connected properly"); + _printSupportLink(); + #endif + break; + + case OUTOFBOUNDS: + #if defined (ARDUINO_ARCH_AVR) || defined (__AVR_ATtiny85__) + _printErrorCode(); + #else + Serial.println("Page overflow has been disabled and the address called exceeds the memory"); + _printSupportLink(); + #endif + break; + + case CANTENWRITE: + #if defined (ARDUINO_ARCH_AVR) || defined (__AVR_ATtiny85__) + _printErrorCode(); + #else + Serial.println("Unable to Enable Writing to chip."); + Serial.println("Please make sure the HOLD & WRITEPROTECT pins are pulled up to VCC"); + _printSupportLink(); + #endif + break; + + case PREVWRITTEN: + #if defined (ARDUINO_ARCH_AVR) || defined (__AVR_ATtiny85__) + _printErrorCode(); + #else + Serial.println("This sector already contains data."); + Serial.println("Please make sure the sectors being written to are erased."); + _printSupportLink(); + #endif + break; + + case LOWRAM: + #if defined (ARDUINO_ARCH_AVR) || defined (__AVR_ATtiny85__) + _printErrorCode(); + #else + Serial.println("You are running low on SRAM. Please optimise your program for better RAM usage"); + /*#if defined (ARDUINO_ARCH_SAM) + Serial.print("Current Free SRAM: "); + Serial.println(freeRAM()); + #endif*/ + _printSupportLink(); + #endif + break; + + case SYSSUSPEND: + #if defined (ARDUINO_ARCH_AVR) || defined (__AVR_ATtiny85__) + _printErrorCode(); + #else + Serial.println("Unable to suspend/resume operation."); + _printSupportLink(); + #endif + break; + + case UNSUPPORTED: + #if defined (ARDUINO_ARCH_AVR) || defined (__AVR_ATtiny85__) + _printErrorCode(); + #else + Serial.println("This function is not supported by the current flash IC."); + _printSupportLink(); + #endif + break; + + case ERRORCHKFAIL: +#if defined (ARDUINO_ARCH_AVR) || defined (__AVR_ATtiny85__) + _printErrorCode(); #else - _printoverride = printoverride; + Serial.println("Write Function has failed errorcheck."); + _printSupportLink(); #endif - if (_printoverride) { - #if defined (ARDUINO_ARCH_AVR) + break; + + default: + #if defined (ARDUINO_ARCH_AVR) || defined (__AVR_ATtiny85__) _printErrorCode(); #else - Serial.println(); - switch (_code) { - case SUCCESS: - Serial.println("Function executed successfully"); - break; - - case NORESPONSE: - Serial.println("Check your wiring. Flash chip is non-responsive."); - break; - - case CALLBEGIN: - Serial.println("*constructor_of_choice*.begin() was not called in void setup()"); - break; - - case UNKNOWNCHIP: - Serial.println("Unable to identify chip. Are you sure this chip is supported?"); - Serial.println("Chip details:"); - Serial.print("manufacturer ID: 0x"); Serial.println(_chip.manufacturerID, HEX); - Serial.print("capacity ID: 0x"); Serial.println(_chip.memoryTypeID, HEX); - Serial.print("device ID: 0x"); Serial.println(_chip.capacityID, HEX); - break; - - case UNKNOWNCAP: - Serial.println("Unable to identify capacity. Is this chip officially supported? If not, please define a `CAPACITY` constant and include it in flash.begin(CAPACITY)."); - break; - - case CHIPBUSY: - Serial.println("Chip is busy."); - Serial.println("Make sure all pins have been connected properly"); - break; - - case OUTOFBOUNDS: - Serial.println("Page overflow has been disabled and the address called exceeds the memory"); - break; - - case CANTENWRITE: - Serial.println("Unable to Enable Writing to chip."); - Serial.println("Please make sure the HOLD & WRITEPROTECT pins are pulled up to VCC"); - break; - - case PREVWRITTEN: - Serial.println("This sector already contains data."); - Serial.println("Please make sure the sectors being written to are erased."); - break; - - case LOWRAM: - Serial.println("You are running low on SRAM. Please optimise your program for better RAM usage"); - /*#if defined (ARDUINO_ARCH_SAM) - Serial.print("Current Free SRAM: "); - Serial.println(freeRAM()); - #endif*/ - break; - - case UNSUPPORTEDFUNCTION: - Serial.println("This function is not supported by the flash memory hardware."); - break; - - case SYSSUSPEND: - Serial.println("Unable to suspend/resume operation."); - break; - - case UNSUPPORTED: - Serial.println("This function is not supported by the current flash IC."); - break; - - case ERRORCHKFAIL: - Serial.println("Write Function has failed errorcheck."); - break; - - default: - Serial.println("Unknown error"); - break; - } - if (_code != SUCCESS) { - _printSupportLink(); - } + Serial.println("Unknown error"); + _printSupportLink(); #endif - } -} + break; + } + } + #endif