From e24a2bcf28534c5e864842ecc20c1ce989b48eb7 Mon Sep 17 00:00:00 2001 From: Prajwal Bhattaram Date: Thu, 17 May 2018 20:14:05 +1000 Subject: [PATCH 01/12] Fixes #135 : The addition of the SFDP checking to _chipID resulted in a sudden (very large) increase in compiled code size. As of the current commit on the development branch, SFDP checking is an user controlled option. To get the library to work with SFDP compatible flash memory that is not officially supported, the user must uncomment '//#define USES_SFDP' in 'SPIMemory.h'. --- .../Diagnostics_functions.ino | 2 + examples/TestFlash/TestFlash.ino | 27 +- extras/Changes.log | 9 + src/SPIFlash.cpp | 350 +++++++++++++++++- src/SPIFlash.h | 6 +- src/SPIFlashIO.cpp | 126 ++++--- src/SPIMemory.h | 3 +- src/diagnostics.cpp | 2 +- 8 files changed, 431 insertions(+), 94 deletions(-) diff --git a/examples/FlashDiagnostics/Diagnostics_functions.ino b/examples/FlashDiagnostics/Diagnostics_functions.ino index 10f17f0..58494ac 100644 --- a/examples/FlashDiagnostics/Diagnostics_functions.ino +++ b/examples/FlashDiagnostics/Diagnostics_functions.ino @@ -430,6 +430,8 @@ void arrayTest() { for (uint16_t i = 0; i < 256; i++) { if (_data[i] != i) { pass(FALSE); + Serial.print(i); + Serial.print(", "); } } pass(TRUE); diff --git a/examples/TestFlash/TestFlash.ino b/examples/TestFlash/TestFlash.ino index 36edf1d..73713da 100644 --- a/examples/TestFlash/TestFlash.ino +++ b/examples/TestFlash/TestFlash.ino @@ -87,30 +87,37 @@ String inputString, outputString; #if defined (SIMBLEE) #define BAUD_RATE 250000 +#define RANDPIN 1 #else #define BAUD_RATE 115200 +#if defined(ARCH_STM32) +#define RANDPIN PA0 +#else +#define RANDPIN A0 +#endif #endif -SPIFlash flash(11); +SPIFlash flash; //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 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 +#if defined (ARDUINO_ARCH_SAMD) || (__AVR_ATmega32U4__) || defined(ARCH_STM32) || defined(NRF5) + while (!Serial) ; // Wait for Serial monitor to open +#endif delay(50); //Time to terminal get connected - Serial.print(F("Initialising Flash memory")); - for (int i = 0; i < 10; ++i) + Serial.print(F("Initialising")); + for (uint8_t 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 + randomSeed(analogRead(RANDPIN)); flash.begin(); -#endif + //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)); + Serial.println(); Serial.println(); commandList(); diff --git a/extras/Changes.log b/extras/Changes.log index 0892d8e..51b768a 100644 --- a/extras/Changes.log +++ b/extras/Changes.log @@ -1,6 +1,15 @@ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// // SPIMemory Library // // Changes log // +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// +// Version 3.2.1 // +// Author: Prajwal Bhattaram // +// 13.04.2018 // +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + +Bugs squashed +--> Fixes issue #135 : The addition of the SFDP checking to _chipID resulted in a sudden (very large) increase in compiled code size. As of the current version (v3.2.1), SFDP checking is an user controlled option. To get the library to work with SFDP compatible flash memory that is not officially supported, the user must uncomment '//#define USES_SFDP' in 'SPIMemory.h'. + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// // Version 3.2.0 // // Author: Prajwal Bhattaram // diff --git a/src/SPIFlash.cpp b/src/SPIFlash.cpp index cbede21..848dd97 100644 --- a/src/SPIFlash.cpp +++ b/src/SPIFlash.cpp @@ -360,7 +360,47 @@ bool SPIFlash::readStr(uint32_t _addr, String &data, bool fastRead) { // 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) { - return _write(_addr, data, sizeof(data), errorCheck, _BYTE_); + //return _write(_addr, data, sizeof(data), errorCheck, _BYTE_); + #ifdef RUNDIAGNOSTIC + _spifuncruntime = micros(); + #endif + if(!_prep(PAGEPROG, _addr, sizeof(data))) { + return false; + } + + _beginSPI(PAGEPROG); + _nextByte(WRITE, data); + CHIP_DESELECT + + if (!errorCheck) { + _endSPI(); + #ifdef RUNDIAGNOSTIC + _spifuncruntime = micros() - _spifuncruntime; + #endif + return true; + } + else { + if (!_notBusy()) { + return false; + } + _currentAddress = _addr; + uint8_t dataIn; + CHIP_SELECT + _nextByte(WRITE, READDATA); + _transferAddress(); + dataIn = _nextByte(READ); + _endSPI(); + if (dataIn != data) { + #ifdef RUNDIAGNOSTIC + _spifuncruntime = micros() - _spifuncruntime; + #endif + return false; + } + #ifdef RUNDIAGNOSTIC + _spifuncruntime = micros() - _spifuncruntime; + #endif + } + return true; } // Writes a char of data to a specific location in a page. @@ -371,7 +411,47 @@ bool SPIFlash::writeByte(uint32_t _addr, uint8_t data, bool errorCheck) { // 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) { - return _write(_addr, data, sizeof(data), errorCheck, _CHAR_); + //return _write(_addr, data, sizeof(data), errorCheck, _CHAR_); + #ifdef RUNDIAGNOSTIC + _spifuncruntime = micros(); + #endif + if(!_prep(PAGEPROG, _addr, sizeof(data))) { + return false; + } + + _beginSPI(PAGEPROG); + _nextByte(WRITE, data); + CHIP_DESELECT + + if (!errorCheck) { + _endSPI(); + #ifdef RUNDIAGNOSTIC + _spifuncruntime = micros() - _spifuncruntime; + #endif + return true; + } + else { + if (!_notBusy()) { + return false; + } + _currentAddress = _addr; + int8_t dataIn; + CHIP_SELECT + _nextByte(WRITE, READDATA); + _transferAddress(); + dataIn = _nextByte(READ); + _endSPI(); + if (dataIn != data) { + #ifdef RUNDIAGNOSTIC + _spifuncruntime = micros() - _spifuncruntime; + #endif + return false; + } + #ifdef RUNDIAGNOSTIC + _spifuncruntime = micros() - _spifuncruntime; + #endif + } + return true; } // Writes an array of bytes starting from a specific location in a page. @@ -389,7 +469,7 @@ bool SPIFlash::writeByteArray(uint32_t _addr, uint8_t *data_buffer, size_t buffe if (!_prep(PAGEPROG, _addr, bufferSize)) { return false; } - uint16_t maxBytes = _pageSize-(_addr % _pageSize); // Force the first set of bytes to stay within the first page + 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 @@ -422,7 +502,7 @@ bool SPIFlash::writeByteArray(uint32_t _addr, uint8_t *data_buffer, size_t buffe length -= writeBufSz; maxBytes = 256; // Now we can do up to 256 bytes per loop - if(!_notBusy(10000L) || !_writeEnable()){ + if(!_notBusy() || !_writeEnable()){ return false; } @@ -441,15 +521,10 @@ bool SPIFlash::writeByteArray(uint32_t _addr, uint8_t *data_buffer, size_t buffe return false; } _currentAddress = _addr; - //uint8_t _inByte; CHIP_SELECT _nextByte(WRITE, READDATA); _transferAddress(); for (uint16_t j = 0; j < bufferSize; j++) { - //_inByte = _nextByte(READ); - //if (_inByte != data_buffer[j]) { - //Serial.print("inByte = "); - //Serial.println(_inByte); if (_nextByte(READ) != data_buffer[j]) { return false; } @@ -477,13 +552,13 @@ bool SPIFlash::writeCharArray(uint32_t _addr, char *data_buffer, size_t bufferSi if (!_prep(PAGEPROG, _addr, bufferSize)) { return false; } - uint16_t maxBytes = _pageSize-(_addr % _pageSize); // Force the first set of bytes to stay within the first page + 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); + //_nextBuf(PAGEPROG, &data_buffer[0], bufferSize); for (uint16_t i = 0; i < bufferSize; ++i) { _nextByte(WRITE, data_buffer[i]); } @@ -533,7 +608,7 @@ bool SPIFlash::writeCharArray(uint32_t _addr, char *data_buffer, size_t bufferSi _nextByte(WRITE, READDATA); _transferAddress(); for (uint16_t j = 0; j < bufferSize; j++) { - if (_nextByte(READ) != data_buffer[j]) { + if ((char)_nextByte(READ) != data_buffer[j]) { return false; } } @@ -553,7 +628,54 @@ bool SPIFlash::writeCharArray(uint32_t _addr, char *data_buffer, size_t bufferSi // 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) { - return _write(_addr, data, sizeof(data), errorCheck, _WORD_); + //return _write(_addr, data, sizeof(data), errorCheck, _WORD_); + #ifdef RUNDIAGNOSTIC + _spifuncruntime = micros(); + #endif + if(!_prep(PAGEPROG, _addr, sizeof(data))) { + return false; + } + + _beginSPI(PAGEPROG); + for (uint8_t i = 0; i < sizeof(data); i++) { + _nextByte(WRITE, data >> (8*i)); + } + CHIP_DESELECT + + if (!errorCheck) { + _endSPI(); + #ifdef RUNDIAGNOSTIC + _spifuncruntime = micros() - _spifuncruntime; + #endif + return true; + } + else { + if (!_notBusy()) { + return false; + } + union { + uint8_t byte[2]; + uint16_t word; + } dataIn; + _currentAddress = _addr; + CHIP_SELECT + _nextByte(WRITE, READDATA); + _transferAddress(); + for (uint8_t i = 0; i < sizeof(data); i++) { + dataIn.byte[i] = _nextByte(READ); + } + _endSPI(); + if (dataIn.word != data) { + #ifdef RUNDIAGNOSTIC + _spifuncruntime = micros() - _spifuncruntime; + #endif + return false; + } + #ifdef RUNDIAGNOSTIC + _spifuncruntime = micros() - _spifuncruntime; + #endif + } + return true; } // Writes a signed int as two bytes starting from a specific location in a page @@ -564,7 +686,54 @@ bool SPIFlash::writeWord(uint32_t _addr, uint16_t data, bool errorCheck) { // 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) { - return _write(_addr, data, sizeof(data), errorCheck, _SHORT_); + //return _write(_addr, data, sizeof(data), errorCheck, _SHORT_); + #ifdef RUNDIAGNOSTIC + _spifuncruntime = micros(); + #endif + if(!_prep(PAGEPROG, _addr, sizeof(data))) { + return false; + } + + _beginSPI(PAGEPROG); + for (uint8_t i = 0; i < sizeof(data); i++) { + _nextByte(WRITE, data >> (8*i)); + } + CHIP_DESELECT + + if (!errorCheck) { + _endSPI(); + #ifdef RUNDIAGNOSTIC + _spifuncruntime = micros() - _spifuncruntime; + #endif + return true; + } + else { + if (!_notBusy()) { + return false; + } + union { + uint8_t byte[2]; + int16_t short_; + } dataIn; + _currentAddress = _addr; + CHIP_SELECT + _nextByte(WRITE, READDATA); + _transferAddress(); + for (uint8_t i = 0; i < sizeof(data); i++) { + dataIn.byte[i] = _nextByte(READ); + } + _endSPI(); + if (dataIn.short_ != data) { + #ifdef RUNDIAGNOSTIC + _spifuncruntime = micros() - _spifuncruntime; + #endif + return false; + } + #ifdef RUNDIAGNOSTIC + _spifuncruntime = micros() - _spifuncruntime; + #endif + } + return true; } // Writes an unsigned long as four bytes starting from a specific location in a page. @@ -575,7 +744,54 @@ bool SPIFlash::writeShort(uint32_t _addr, int16_t data, bool errorCheck) { // 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) { - return _write(_addr, data, sizeof(data), errorCheck, _ULONG_); + //return _write(_addr, data, sizeof(data), errorCheck, _ULONG_); + #ifdef RUNDIAGNOSTIC + _spifuncruntime = micros(); + #endif + if(!_prep(PAGEPROG, _addr, sizeof(data))) { + return false; + } + + _beginSPI(PAGEPROG); + for (uint8_t i = 0; i < sizeof(data); i++) { + _nextByte(WRITE, data >> (8*i)); + } + CHIP_DESELECT + + if (!errorCheck) { + _endSPI(); + #ifdef RUNDIAGNOSTIC + _spifuncruntime = micros() - _spifuncruntime; + #endif + return true; + } + else { + if (!_notBusy()) { + return false; + } + union { + uint8_t byte[4]; + uint32_t uLong; + } dataIn; + _currentAddress = _addr; + CHIP_SELECT + _nextByte(WRITE, READDATA); + _transferAddress(); + for (uint8_t i = 0; i < sizeof(data); i++) { + dataIn.byte[i] = _nextByte(READ); + } + _endSPI(); + if (dataIn.uLong != data) { + #ifdef RUNDIAGNOSTIC + _spifuncruntime = micros() - _spifuncruntime; + #endif + return false; + } + #ifdef RUNDIAGNOSTIC + _spifuncruntime = micros() - _spifuncruntime; + #endif + } + return true; } // Writes a signed long as four bytes starting from a specific location in a page @@ -586,7 +802,54 @@ bool SPIFlash::writeULong(uint32_t _addr, uint32_t data, bool errorCheck) { // 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) { - return _write(_addr, data, sizeof(data), errorCheck, _LONG_); + //return _write(_addr, data, sizeof(data), errorCheck, _LONG_); + #ifdef RUNDIAGNOSTIC + _spifuncruntime = micros(); + #endif + if(!_prep(PAGEPROG, _addr, sizeof(data))) { + return false; + } + + _beginSPI(PAGEPROG); + for (uint8_t i = 0; i < sizeof(data); i++) { + _nextByte(WRITE, data >> (8*i)); + } + CHIP_DESELECT + + if (!errorCheck) { + _endSPI(); + #ifdef RUNDIAGNOSTIC + _spifuncruntime = micros() - _spifuncruntime; + #endif + return true; + } + else { + if (!_notBusy()) { + return false; + } + union { + uint8_t byte[4]; + int32_t Long; + } dataIn; + _currentAddress = _addr; + CHIP_SELECT + _nextByte(WRITE, READDATA); + _transferAddress(); + for (uint8_t i = 0; i < sizeof(data); i++) { + dataIn.byte[i] = _nextByte(READ); + } + _endSPI(); + if (dataIn.Long != data) { + #ifdef RUNDIAGNOSTIC + _spifuncruntime = micros() - _spifuncruntime; + #endif + return false; + } + #ifdef RUNDIAGNOSTIC + _spifuncruntime = micros() - _spifuncruntime; + #endif + } + return true; } // Writes a float as four bytes starting from a specific location in a page @@ -597,7 +860,60 @@ bool SPIFlash::writeLong(uint32_t _addr, int32_t data, bool errorCheck) { // 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) { - return _write(_addr, data, sizeof(data), errorCheck, _FLOAT_); + //return _write(_addr, data, sizeof(data), errorCheck, _FLOAT_); + #ifdef RUNDIAGNOSTIC + _spifuncruntime = micros(); + #endif + if(!_prep(PAGEPROG, _addr, sizeof(data))) { + return false; + } + + union { + float Float; + uint8_t byte[sizeof(float)]; + } dataOut; + dataOut.Float = data; + + _beginSPI(PAGEPROG); + for (uint8_t i = 0; i < sizeof(data); i++) { + _nextByte(WRITE, dataOut.byte[i]); + } + CHIP_DESELECT + + if (!errorCheck) { + _endSPI(); + #ifdef RUNDIAGNOSTIC + _spifuncruntime = micros() - _spifuncruntime; + #endif + return true; + } + else { + if (!_notBusy()) { + return false; + } + union { + uint8_t byte[4]; + float Float; + } dataIn; + _currentAddress = _addr; + CHIP_SELECT + _nextByte(WRITE, READDATA); + _transferAddress(); + for (uint8_t i = 0; i < sizeof(data); i++) { + dataIn.byte[i] = _nextByte(READ); + } + _endSPI(); + if (dataIn.Float != data) { + #ifdef RUNDIAGNOSTIC + _spifuncruntime = micros() - _spifuncruntime; + #endif + return false; + } + #ifdef RUNDIAGNOSTIC + _spifuncruntime = micros() - _spifuncruntime; + #endif + } + return true; } // Writes a string to a specific location on a page diff --git a/src/SPIFlash.h b/src/SPIFlash.h index d7dca2b..0efc67b 100644 --- a/src/SPIFlash.h +++ b/src/SPIFlash.h @@ -172,7 +172,7 @@ class SPIFlash { float _spifuncruntime = 0; struct chipID { bool supported; - bool JEDECsupport; + bool supportedMan; bool sfdpAvailable; uint8_t manufacturerID; uint8_t memoryTypeID; @@ -198,6 +198,10 @@ class SPIFlash { const uint32_t _memSize[16] = {KB(64), KB(128), KB(256), KB(512), MB(1), MB(2), MB(4), MB(8), MB(16), MB(32), MB(8), MB(8), KB(256), KB(512), MB(4), KB(512)}; // To understand the _memSize definitions check defines.h + + const uint8_t _supportedManID[7] = {WINBOND_MANID, MICROCHIP_MANID, CYPRESS_MANID, ADESTO_MANID, MICRON_MANID, ON_MANID, AMIC_MANID}; + + const uint8_t _altChipEraseReq[3] = {A25L512, M25P40, SST26}; }; //--------------------------------- Public Templates ------------------------------------// diff --git a/src/SPIFlashIO.cpp b/src/SPIFlashIO.cpp index 4d64974..2d40ecb 100644 --- a/src/SPIFlashIO.cpp +++ b/src/SPIFlashIO.cpp @@ -462,22 +462,23 @@ //Checks the device ID to establish storage parameters bool SPIFlash::_getManId(uint8_t *b1, uint8_t *b2) { - if(!_notBusy()) - return false; - _beginSPI(MANID); + if(!_notBusy()) { + return false; + } + _beginSPI(MANID); _nextByte(READ); _nextByte(READ); _nextByte(READ); *b1 = _nextByte(READ); *b2 = _nextByte(READ); CHIP_DESELECT - return true; + return true; } //Checks for presence of chip by requesting JEDEC ID bool SPIFlash::_getJedecId(void) { if(!_notBusy()) { - return false; + return false; } _beginSPI(JEDECID); _chip.manufacturerID = _nextByte(READ); // manufacturer id @@ -519,85 +520,82 @@ //Identifies the chip bool SPIFlash::_chipID(uint32_t flashChipSize) { + //set some default values + kb4Erase.supported = kb32Erase.supported = kb64Erase.supported = chipErase.supported = true; + kb4Erase.opcode = SECTORERASE; + kb32Erase.opcode = BLOCK32ERASE; + kb64Erase.opcode = BLOCK64ERASE; + kb4Erase.time = BUSY_TIMEOUT; + kb32Erase.time = kb4Erase.time * 8; + kb64Erase.time = kb32Erase.time * 4; + kb256Erase.supported = false; + chipErase.opcode = CHIPERASE; + chipErase.time = kb64Erase.time * 100L; + _getJedecId(); - if (_chip.manufacturerID == MICROCHIP_MANID) { - _disableGlobalBlockProtect(); + for (uint8_t i = 0; i < sizeof(_supportedManID); i++) { + if (_chip.manufacturerID == _supportedManID[i]) { + _chip.supportedMan = true; + break; + } } - //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Begin SFDP ID section ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// - _checkForSFDP(); - if (_chip.sfdpAvailable) { - _getSFDPFlashParam(); - } - else { - kb4Erase.supported = kb32Erase.supported = kb64Erase.supported = chipErase.supported = true; - kb4Erase.opcode = SECTORERASE; - kb32Erase.opcode = BLOCK32ERASE; - kb64Erase.opcode = BLOCK64ERASE; - kb4Erase.time = BUSY_TIMEOUT; - kb32Erase.time = kb4Erase.time * 8; - kb64Erase.time = kb32Erase.time * 4; - kb256Erase.supported = false; - chipErase.opcode = CHIPERASE; - chipErase.time = kb64Erase.time * 100L; + for (uint8_t i = 0; i < sizeof(_altChipEraseReq); i++) { + if (_chip.memoryTypeID == _altChipEraseReq[i]) { + chipErase.opcode = ALT_CHIPERASE; + break; + } } - //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ End SFDP ID section ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// - if (!_chip.capacity) { - if (!flashChipSize) { - #ifdef RUNDIAGNOSTIC - Serial.println("No Chip size defined by user. Automated identification initiated."); - #endif + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Begin SFDP ID section ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + #ifdef USES_SFDP + if (_checkForSFDP()) { + _getSFDPFlashParam(); + } + #endif + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ End SFDP ID section ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// - if (_chip.manufacturerID == WINBOND_MANID || _chip.manufacturerID == MICROCHIP_MANID || _chip.manufacturerID == CYPRESS_MANID || _chip.manufacturerID == ADESTO_MANID || _chip.manufacturerID == MICRON_MANID || _chip.manufacturerID == ON_MANID || _chip.manufacturerID == AMIC_MANID) { - if (_chip.manufacturerID == AMIC_MANID) { - _chip.capacityID |= _chip.manufacturerID; - } - //Identify capacity - for (uint8_t i = 0; i < sizeof(_capID); i++) { - if (_chip.capacityID == _capID[i]) { - _chip.capacity = (_memSize[i]); - _chip.JEDECsupport = true; - _chip.supported = true; - #ifdef RUNDIAGNOSTIC - Serial.println("Chip identified. This chip is fully supported by the library."); - #endif - } - } - _getJedecId(); - if (!_chip.capacity) { - _troubleshoot(UNKNOWNCAP); - return false; - } - } - else { - _troubleshoot(UNKNOWNCHIP); //Error code for unidentified capacity - return false; + if (_chip.supportedMan) { + #ifdef RUNDIAGNOSTIC + Serial.println("No Chip size defined by user. Automated identification initiated."); + #endif + //Identify capacity + for (uint8_t j = 0; j < sizeof(_capID); j++) { + if (_chip.capacityID == _capID[j]) { + _chip.capacity = (_memSize[j]); + _chip.supported = true; + #ifdef RUNDIAGNOSTIC + Serial.println("Chip identified. This chip is fully supported by the library."); + #endif + return true; } } - else { + } + else { + _troubleshoot(UNKNOWNCHIP); //Error code for unidentified capacity + return false; + } + + if (!_chip.capacity) { + + if (flashChipSize) { // If a custom chip size is defined #ifdef RUNDIAGNOSTIC Serial.println("Custom Chipsize defined"); #endif _chip.capacity = flashChipSize; _chip.supported = false; + return true; } - } - if (_chip.manufacturerID == CYPRESS_MANID) { - setClock(SPI_CLK/4); // Cypress/Spansion chips appear to perform best at SPI_CLK/4 - } + else { + _troubleshoot(UNKNOWNCAP); + return false; + } - if ( ((_chip.manufacturerID == MICROCHIP_MANID) && (_chip.memoryTypeID == SST26))\ - || ((_chip.manufacturerID == MICRON_MANID) && (_chip.memoryTypeID == M25P40))\ - || ((_chip.manufacturerID == AMIC_MANID) && (_chip.memoryTypeID == A25L512)) ) { - chipErase.opcode = ALT_CHIPERASE; } - - return true; } //Troubleshooting function. Called when #ifdef RUNDIAGNOSTIC is uncommented at the top of this file. diff --git a/src/SPIMemory.h b/src/SPIMemory.h index 293c39d..2b3dd17 100644 --- a/src/SPIMemory.h +++ b/src/SPIMemory.h @@ -26,13 +26,14 @@ #ifndef SPIMEMORY_H #define SPIMEMORY_H +//#define USES_SFDP //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// // 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 // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// diff --git a/src/diagnostics.cpp b/src/diagnostics.cpp index 3ccbf3a..a6c57ba 100644 --- a/src/diagnostics.cpp +++ b/src/diagnostics.cpp @@ -48,7 +48,7 @@ void Diagnostics::troubleshoot(uint8_t _code, bool printoverride) { #elif defined (RUNDIAGNOSTIC) && defined (ARDUINO_ARCH_AVR) _printErrorCode(); #endif -#if !defined (RUNDIAGNOSTIC) +#if !defined (RUNDIAGNOSTIC) _printoverride = printoverride; #endif if (_printoverride) { From 44d7608cfff6a5850d0cec17d4e6ddd4430d3e42 Mon Sep 17 00:00:00 2001 From: Prajwal Bhattaram Date: Fri, 18 May 2018 17:25:51 +1000 Subject: [PATCH 02/12] Updated TestFlash.ino formatting --- examples/TestFlash/TestFlash.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/TestFlash/TestFlash.ino b/examples/TestFlash/TestFlash.ino index 73713da..1914216 100644 --- a/examples/TestFlash/TestFlash.ino +++ b/examples/TestFlash/TestFlash.ino @@ -510,7 +510,7 @@ void printPage(uint32_t _address, uint8_t outputType) { Serial.begin(115200); char buffer[24]; - sprintf(buffer, "Reading address (%04x)", _address); + sprintf(buffer, "Reading address 0x(%04x)", _address); Serial.println(buffer); uint8_t data_buffer[SPI_PAGESIZE]; From ea26a05e61a8e494f14e8b02077562f88f0fea9c Mon Sep 17 00:00:00 2001 From: Prajwal Bhattaram Date: Fri, 18 May 2018 17:26:07 +1000 Subject: [PATCH 03/12] Reduced code footprint further --- src/SPIFlash.cpp | 35 +++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/src/SPIFlash.cpp b/src/SPIFlash.cpp index 848dd97..359ce3f 100644 --- a/src/SPIFlash.cpp +++ b/src/SPIFlash.cpp @@ -384,21 +384,23 @@ bool SPIFlash::writeByte(uint32_t _addr, uint8_t data, bool errorCheck) { return false; } _currentAddress = _addr; - uint8_t dataIn; CHIP_SELECT _nextByte(WRITE, READDATA); _transferAddress(); - dataIn = _nextByte(READ); - _endSPI(); - if (dataIn != data) { + if (data != _nextByte(READ)) { + _endSPI(); #ifdef RUNDIAGNOSTIC _spifuncruntime = micros() - _spifuncruntime; #endif return false; } - #ifdef RUNDIAGNOSTIC - _spifuncruntime = micros() - _spifuncruntime; - #endif + else { + _endSPI(); + #ifdef RUNDIAGNOSTIC + _spifuncruntime = micros() - _spifuncruntime; + #endif + return true; + } } return true; } @@ -435,21 +437,23 @@ bool SPIFlash::writeChar(uint32_t _addr, int8_t data, bool errorCheck) { return false; } _currentAddress = _addr; - int8_t dataIn; CHIP_SELECT _nextByte(WRITE, READDATA); _transferAddress(); - dataIn = _nextByte(READ); - _endSPI(); - if (dataIn != data) { + if (data != (int8_t)_nextByte(READ)) { + _endSPI(); #ifdef RUNDIAGNOSTIC _spifuncruntime = micros() - _spifuncruntime; #endif return false; } - #ifdef RUNDIAGNOSTIC - _spifuncruntime = micros() - _spifuncruntime; - #endif + else { + _endSPI(); + #ifdef RUNDIAGNOSTIC + _spifuncruntime = micros() - _spifuncruntime; + #endif + return true; + } } return true; } @@ -492,6 +496,7 @@ bool SPIFlash::writeByteArray(uint32_t _addr, uint8_t *data_buffer, size_t buffe CHIP_SELECT _nextByte(WRITE, PAGEPROG); _transferAddress(); + //_nextBuf(PAGEPROG, &data_buffer[data_offset], writeBufSz); for (uint16_t i = 0; i < writeBufSz; ++i) { _nextByte(WRITE, data_buffer[data_offset + i]); } @@ -927,6 +932,8 @@ bool SPIFlash::writeStr(uint32_t _addr, String &data, bool errorCheck) { return _write(_addr, data, sizeof(data), errorCheck, _STRING_); } + + // Erases a number of sectors or blocks as needed by the data being input. // Takes an address and the size of the data being input as the arguments and erases the block/s of memory containing the address. bool SPIFlash::eraseSection(uint32_t _addr, uint32_t _sz) { From 2c876a54e03e843cc1fb396c18d3ef6e376a01b5 Mon Sep 17 00:00:00 2001 From: Consti Date: Sat, 19 May 2018 00:39:11 +0200 Subject: [PATCH 04/12] Timeout Bug fixed concerning #128 --- src/SPIFlashIO.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SPIFlashIO.cpp b/src/SPIFlashIO.cpp index 4d64974..c688963 100644 --- a/src/SPIFlashIO.cpp +++ b/src/SPIFlashIO.cpp @@ -427,7 +427,7 @@ { return true; } - _time++; + } while ((micros() - _time) < timeout); if (timeout <= (micros() - _time)) { _troubleshoot(CHIPBUSY); From ed1bf4b05a146e614f6bb0041fefb105a9d5fd18 Mon Sep 17 00:00:00 2001 From: Prajwal Bhattaram Date: Mon, 21 May 2018 11:57:29 +1000 Subject: [PATCH 05/12] Updated librar.properties to v3.2.1 --- library.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.properties b/library.properties index 5b3d75f..6e40c64 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=SPIMemory -version=3.2.0 +version=3.2.1 author=Prajwal Bhattaram maintainer=Prajwal Bhattaram sentence=SPI Memory library for Arduino. (Formerly SPIFlash) From 738df393a9dc3838e06d637faf14b920bb7e9a0d Mon Sep 17 00:00:00 2001 From: Prajwal Bhattaram Date: Mon, 21 May 2018 11:57:51 +1000 Subject: [PATCH 06/12] Updated change log --- extras/Changes.log | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/extras/Changes.log b/extras/Changes.log index 51b768a..e7aa42b 100644 --- a/extras/Changes.log +++ b/extras/Changes.log @@ -10,6 +10,15 @@ Bugs squashed --> Fixes issue #135 : The addition of the SFDP checking to _chipID resulted in a sudden (very large) increase in compiled code size. As of the current version (v3.2.1), SFDP checking is an user controlled option. To get the library to work with SFDP compatible flash memory that is not officially supported, the user must uncomment '//#define USES_SFDP' in 'SPIMemory.h'. +Enhancements +--> The way the basic functions execute has been modified to keep the function runtime the same (or improved) while reducing their memory footprint. + + Test sketch - FlashDiagnostics.ino from v3.2.0 with #RUNDIAGNOSTIC uncommented + Test platform - Arduino Pro Mini 8MHz 3.3V + Library version: v3.1.0 Compiled code size - 20500 bytes + Library version: v3.2.0 Compiled code size - 23010 bytes (12% larger than v3.1.0) + Library version: v3.2.1 Compiled code size - 18658 bytes (9% smaller than v3.1.0) + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// // Version 3.2.0 // // Author: Prajwal Bhattaram // From bf6859894ee1e9f3a5689b8b5f14f40b28f587ff Mon Sep 17 00:00:00 2001 From: Prajwal Bhattaram Date: Mon, 21 May 2018 12:03:40 +1000 Subject: [PATCH 07/12] Moved 'bool _loopedOver' from '_getAddress()' where it was doing nothing to being a global variable. Now it does what it was designed to do. --- src/SPIFlash.cpp | 1 - src/SPIFlash.h | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SPIFlash.cpp b/src/SPIFlash.cpp index 359ce3f..2796f77 100644 --- a/src/SPIFlash.cpp +++ b/src/SPIFlash.cpp @@ -184,7 +184,6 @@ uint64_t SPIFlash::getUniqueID(void) { // Takes the size of the data as an argument and returns a 32-bit address // All addresses in the in the sketch must be obtained via this function or not at all. uint32_t SPIFlash::getAddress(uint16_t size) { - bool _loopedOver = false; if (!_addressCheck(currentAddress, size)){ return false; } diff --git a/src/SPIFlash.h b/src/SPIFlash.h index 0efc67b..c6fc3d7 100644 --- a/src/SPIFlash.h +++ b/src/SPIFlash.h @@ -166,6 +166,7 @@ class SPIFlash { bool pageOverflow, SPIBusState; bool chipPoweredDown = false; bool address4ByteEnabled = false; + bool _loopedOver = false; uint8_t cs_mask, errorcode, stat1, stat2, stat3, _SPCR, _SPSR, _a0, _a1, _a2; char READ = 'R'; char WRITE = 'W'; From 70f6f575cf1969286afe7a67e99f9a0115050aaf Mon Sep 17 00:00:00 2001 From: Prajwal Bhattaram Date: Mon, 21 May 2018 12:12:18 +1000 Subject: [PATCH 08/12] Updated change log --- extras/Changes.log | 2 ++ 1 file changed, 2 insertions(+) diff --git a/extras/Changes.log b/extras/Changes.log index e7aa42b..58b7e18 100644 --- a/extras/Changes.log +++ b/extras/Changes.log @@ -10,6 +10,8 @@ Bugs squashed --> Fixes issue #135 : The addition of the SFDP checking to _chipID resulted in a sudden (very large) increase in compiled code size. As of the current version (v3.2.1), SFDP checking is an user controlled option. To get the library to work with SFDP compatible flash memory that is not officially supported, the user must uncomment '//#define USES_SFDP' in 'SPIMemory.h'. +--> Moved `bool _loopedOver` from being a local variable in `_getAddress()` to a global one. Now it actually does what it was meant to do - i.e. prevent looping over data a second time. + Enhancements --> The way the basic functions execute has been modified to keep the function runtime the same (or improved) while reducing their memory footprint. From 8520d2b0d55fe88ffe4eaaf272604bdb8492cb30 Mon Sep 17 00:00:00 2001 From: Prajwal Bhattaram Date: Mon, 21 May 2018 13:48:29 +1000 Subject: [PATCH 09/12] Added note about turning on SFDP discovery in SPIMemory.h --- .../Diagnostics_functions.ino | 38 +++++++++---------- extras/Changes.log | 4 +- src/SPIFlash.cpp | 2 +- src/SPIMemory.h | 13 +++++-- 4 files changed, 32 insertions(+), 25 deletions(-) diff --git a/examples/FlashDiagnostics/Diagnostics_functions.ino b/examples/FlashDiagnostics/Diagnostics_functions.ino index 58494ac..00b4b1d 100644 --- a/examples/FlashDiagnostics/Diagnostics_functions.ino +++ b/examples/FlashDiagnostics/Diagnostics_functions.ino @@ -29,7 +29,7 @@ void printTab(uint8_t _times) { } void printTime(uint32_t _wTime, uint32_t _rTime) { - printTab(2); + printTab(2); if (_rTime != 0) { printTimer(_wTime); printTab(3); @@ -118,7 +118,7 @@ bool getID() { Serial.print("Max Pages: "); Serial.println(flash.getMaxPage()); printUniqueID(); - + } return true; } @@ -150,7 +150,7 @@ void byteTest() { pass(FALSE); } printTime(wTime, rTime); - + } void charTest() { @@ -179,7 +179,7 @@ void charTest() { pass(FALSE); } printTime(wTime, rTime); - + } void wordTest() { @@ -208,7 +208,7 @@ void wordTest() { pass(FALSE); } printTime(wTime, rTime); - + } void shortTest() { @@ -237,7 +237,7 @@ void shortTest() { pass(FALSE); } printTime(wTime, rTime); - + } void uLongTest() { @@ -266,7 +266,7 @@ void uLongTest() { pass(FALSE); } printTime(wTime, rTime); - + } void longTest() { @@ -295,7 +295,7 @@ void longTest() { pass(FALSE); } printTime(wTime, rTime); - + } void floatTest() { @@ -324,7 +324,7 @@ void floatTest() { pass(FALSE); } printTime(wTime, rTime); - + } void stringTest() { @@ -353,7 +353,7 @@ void stringTest() { pass(FALSE); } printTime(wTime, rTime); - + } void structTest() { @@ -402,7 +402,7 @@ void structTest() { pass(FALSE); } printTime(wTime, rTime); - + } void arrayTest() { @@ -436,7 +436,7 @@ void arrayTest() { } pass(TRUE); printTime(wTime, rTime); - + } void powerDownTest() { @@ -454,7 +454,7 @@ void powerDownTest() { printTab(2); Serial.print("Not all chips support power down. Check your datasheet."); } - + } void powerUpTest() { @@ -470,7 +470,7 @@ void powerUpTest() { else { pass(FALSE); } - + } void eraseSectorTest() { @@ -487,7 +487,7 @@ void eraseSectorTest() { else { pass(FALSE); } - + } void eraseSectionTest() { @@ -504,7 +504,7 @@ void eraseSectionTest() { else { pass(FALSE); } - + } void eraseBlock32KTest() { @@ -521,7 +521,7 @@ void eraseBlock32KTest() { else { pass(FALSE); } - + } void eraseBlock64KTest() { @@ -538,7 +538,7 @@ void eraseBlock64KTest() { else { pass(FALSE); } - + } void eraseChipTest() { @@ -554,6 +554,6 @@ void eraseChipTest() { else { pass(FALSE); } - + } diff --git a/extras/Changes.log b/extras/Changes.log index 58b7e18..191022f 100644 --- a/extras/Changes.log +++ b/extras/Changes.log @@ -10,7 +10,7 @@ Bugs squashed --> Fixes issue #135 : The addition of the SFDP checking to _chipID resulted in a sudden (very large) increase in compiled code size. As of the current version (v3.2.1), SFDP checking is an user controlled option. To get the library to work with SFDP compatible flash memory that is not officially supported, the user must uncomment '//#define USES_SFDP' in 'SPIMemory.h'. ---> Moved `bool _loopedOver` from being a local variable in `_getAddress()` to a global one. Now it actually does what it was meant to do - i.e. prevent looping over data a second time. +--> Moved `bool _loopedOver` from being a local variable in `getAddress()` to a global one. Now it actually does what it was meant to do - i.e. prevent looping over data a second time. Enhancements --> The way the basic functions execute has been modified to keep the function runtime the same (or improved) while reducing their memory footprint. @@ -19,7 +19,7 @@ Enhancements Test platform - Arduino Pro Mini 8MHz 3.3V Library version: v3.1.0 Compiled code size - 20500 bytes Library version: v3.2.0 Compiled code size - 23010 bytes (12% larger than v3.1.0) - Library version: v3.2.1 Compiled code size - 18658 bytes (9% smaller than v3.1.0) + Library version: v3.2.1 Compiled code size - 18660 bytes (9% smaller than v3.1.0) //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// // Version 3.2.0 // diff --git a/src/SPIFlash.cpp b/src/SPIFlash.cpp index 2796f77..62e9aac 100644 --- a/src/SPIFlash.cpp +++ b/src/SPIFlash.cpp @@ -1009,7 +1009,7 @@ bool SPIFlash::eraseSection(uint32_t _addr, uint32_t _sz) { _timeFactor = kb4Erase.time; } if(!_notBusy(_timeFactor * 1000L)) { - return false; //Datasheet says erasing a sector takes 400ms max + return false; } if (j == noOfEraseRunsB4Boundary) { if (!_prep(ERASEFUNC, (_addr + (_sz - _addressOverflow)), _sz)) { diff --git a/src/SPIMemory.h b/src/SPIMemory.h index 2b3dd17..59738f2 100644 --- a/src/SPIMemory.h +++ b/src/SPIMemory.h @@ -26,14 +26,19 @@ #ifndef SPIMEMORY_H #define SPIMEMORY_H -//#define USES_SFDP +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// +// Uncomment the code below to enable SFDP discovery - especially // +// if using an unsupported chip // +// // +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// +#define USES_SFDP // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// // 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 // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// @@ -108,7 +113,7 @@ #define LIBVER 3 #define LIBSUBVER 2 -#define BUGFIXVER 0 +#define BUGFIXVER 1 class SPIMemory { public: @@ -116,6 +121,8 @@ class SPIMemory { SPIMemory(void) {}; ~SPIMemory(void) {}; //------------------------------- Public functions -----------------------------------// + //------------------------------- Public variables -----------------------------------// + }; From fa07241ef0e43a2d4b3caf638675bedc99d739ee Mon Sep 17 00:00:00 2001 From: Prajwal Bhattaram Date: Mon, 21 May 2018 13:52:27 +1000 Subject: [PATCH 10/12] Updated change log --- extras/Changes.log | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/extras/Changes.log b/extras/Changes.log index 191022f..c3e5ac9 100644 --- a/extras/Changes.log +++ b/extras/Changes.log @@ -15,11 +15,12 @@ Bugs squashed Enhancements --> The way the basic functions execute has been modified to keep the function runtime the same (or improved) while reducing their memory footprint. - Test sketch - FlashDiagnostics.ino from v3.2.0 with #RUNDIAGNOSTIC uncommented - Test platform - Arduino Pro Mini 8MHz 3.3V - Library version: v3.1.0 Compiled code size - 20500 bytes - Library version: v3.2.0 Compiled code size - 23010 bytes (12% larger than v3.1.0) - Library version: v3.2.1 Compiled code size - 18660 bytes (9% smaller than v3.1.0) + Test sketch - FlashDiagnostics.ino from v3.2.0 with #RUNDIAGNOSTIC uncommented + Test platform - Arduino Pro Mini 8MHz 3.3V + Library version: v3.1.0 Compiled code size - 20500 bytes (SFDP discovery not supported) + Library version: v3.2.0 Compiled code size - 23010 bytes (SFDP discovery supported & on by default) (12% larger than v3.1.0) + Library version: v3.2.1 Compiled code size - 18660 bytes (SFDP discovery turned off) (9% smaller than v3.1.0) + Library version: v3.2.1 Compiled code size - 21698 bytes (SFDP discovery turned on) (5% larger than v3.1.0) //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// // Version 3.2.0 // From c0acaddc478d68f6a4c207722ece488448df85f6 Mon Sep 17 00:00:00 2001 From: Prajwal Bhattaram Date: Mon, 21 May 2018 14:21:56 +1000 Subject: [PATCH 11/12] Final code fix for #135. ReadMe and change log updated. v3.2.1 is ready to go. Relative to v3.2.0 this version (v3.2.1) reduces compiled code memory footprint by 24% and 12%, with SFDP discovery turned off and turned on respectively. --- README.md | 3 ++ extras/Changes.log | 10 +++--- library.properties | 2 +- src/SPIFlash.cpp | 4 +-- src/SPIFlash.h | 80 +++++++++++++++++++++------------------------- src/SPIFlashIO.cpp | 4 +-- src/SPIMemory.h | 13 +++++--- src/defines.h | 6 ++-- 8 files changed, 61 insertions(+), 61 deletions(-) diff --git a/README.md b/README.md index e9c4035..bfe4211 100644 --- a/README.md +++ b/README.md @@ -97,6 +97,9 @@ SPIFlash flash(33); * Optional +##### Note on SFDP discovery +As of v3.2.1, SFDP parameter discovery is an user controlled option. To get the library to work with SFDP compatible flash memory chips that are not officially supported by the library, the user must uncomment '//#define USES_SFDP' in 'SPIMemory.h'. + ##### Notes on Address overflow and Error checking - The library has Address overflow enabled by default - i.e. if the last address read/written from/to, in any function, is 0xFFFFF then, the next address read/written from/to is 0x00000. This can be disabled by uncommenting ```#define DISABLEOVERFLOW``` in SPIMemory.h. (Address overflow only works for Read / Write functions. Erase functions erase only a set number of blocks/sectors irrespective of overflow.) - All write functions have Error checking turned on by default - i.e. every byte written to the flash memory will be checked against the data stored on the Arduino. Users who require greater write speeds can disable this function by setting an optional last 'errorCheck' argument in any write function to NOERRCHK - For eg. call the function ```writeByte(address, *data_buffer, NOERRCHK)``` instead of ```writeByte(address, *data_buffer)```. diff --git a/extras/Changes.log b/extras/Changes.log index c3e5ac9..cd9deec 100644 --- a/extras/Changes.log +++ b/extras/Changes.log @@ -15,12 +15,12 @@ Bugs squashed Enhancements --> The way the basic functions execute has been modified to keep the function runtime the same (or improved) while reducing their memory footprint. - Test sketch - FlashDiagnostics.ino from v3.2.0 with #RUNDIAGNOSTIC uncommented + Test sketch - FlashDiagnostics.ino from v3.2.0 with #RUNDIAGNOSTIC commented out Test platform - Arduino Pro Mini 8MHz 3.3V - Library version: v3.1.0 Compiled code size - 20500 bytes (SFDP discovery not supported) - Library version: v3.2.0 Compiled code size - 23010 bytes (SFDP discovery supported & on by default) (12% larger than v3.1.0) - Library version: v3.2.1 Compiled code size - 18660 bytes (SFDP discovery turned off) (9% smaller than v3.1.0) - Library version: v3.2.1 Compiled code size - 21698 bytes (SFDP discovery turned on) (5% larger than v3.1.0) + Library version: v3.1.0 Compiled code size - 17652 bytes (SFDP discovery not supported) + Library version: v3.2.0 Compiled code size - 20104 bytes (SFDP discovery supported & on by default) (13.9% larger than v3.1.0) + Library version: v3.2.1 Compiled code size - 15316 bytes (SFDP discovery turned off) (13.75% smaller than v3.1.0) + Library version: v3.2.1 Compiled code size - 17854 bytes (SFDP discovery turned on) (1.1% larger than v3.1.0) //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// // Version 3.2.0 // diff --git a/library.properties b/library.properties index 6e40c64..c2b4978 100644 --- a/library.properties +++ b/library.properties @@ -3,7 +3,7 @@ version=3.2.1 author=Prajwal Bhattaram maintainer=Prajwal Bhattaram sentence=SPI Memory library for Arduino. (Formerly SPIFlash) -paragraph=Starting v3.2.0, this library enables read, write, erase and power functions on all SFDP compatible Flash chips. Older versions are only compatible with specific chips as listed here - < v2.6.0 is compatible with W25X05**, W25X10**, W25X20**, W25X40**, W25Q80**, W25Q16**, W25Q32** & W25Q64**. All other Winbond flash chips can also be used with this library from v2.6.0 onwards. A number of Microchip, Cypress & Spansion chips - W25Q128**, W25Q256**, SST25VF064C, SST26VF064B & S25FL116K - can be used with with the library from v3.0.0 onwards. Refer to change log for further information about this release. +paragraph=This library enables read, write, erase and power functions on number of compatible flash memory chips. Refer to change log for further information about this release. To download any version of this library pre v3.2.0 (pre name-change from SPIFlash please visit https://github.com/Marzogh/SPIMemory/releases?after=v3.2.0 ) category=Data Storage url=https://github.com/Marzogh/SPIMemory architectures=avr,sam,samd,esp8266,esp32,Simblee,stm32 diff --git a/src/SPIFlash.cpp b/src/SPIFlash.cpp index 62e9aac..1dcfe4d 100644 --- a/src/SPIFlash.cpp +++ b/src/SPIFlash.cpp @@ -1,8 +1,8 @@ -/* Arduino SPIMemory Library v.3.1.0 +/* Arduino SPIMemory Library v.3.2.1 * Copyright (C) 2017 by Prajwal Bhattaram * Created by Prajwal Bhattaram - 19/05/2015 * Modified by @boseji - 02/03/2017 - * Modified by Prajwal Bhattaram - 24/02/2018 + * Modified by Prajwal Bhattaram - 21/05/2018 * * This file is part of the Arduino SPIMemory Library. This library is for * Winbond NOR flash memory modules. In its current form it enables reading diff --git a/src/SPIFlash.h b/src/SPIFlash.h index c6fc3d7..bff1393 100644 --- a/src/SPIFlash.h +++ b/src/SPIFlash.h @@ -1,8 +1,8 @@ -/* Arduino SPIMemory Library v.3.1.0 +/* Arduino SPIMemory Library v.3.2.1 * Copyright (C) 2017 by Prajwal Bhattaram * Created by Prajwal Bhattaram - 19/05/2015 * Modified by @boseji - 02/03/2017 - * Modified by Prajwal Bhattaram - 24/02/2018 + * Modified by Prajwal Bhattaram - 21/05/2018 * * This file is part of the Arduino SPIMemory Library. This library is for * Winbond NOR flash memory modules. In its current form it enables reading @@ -234,7 +234,7 @@ template bool SPIFlash::_writeErrorCheck(uint32_t _addr, const T& valu return false; } const uint8_t* p = (const uint8_t*)(const void*)&value; - if (_dataType == _STRUCT_) { + /*if (_dataType == _STRUCT_) { uint8_t _inByte[_sz]; _beginSPI(READDATA); _nextBuf(READDATA, &(*_inByte), _sz); @@ -249,7 +249,7 @@ template bool SPIFlash::_writeErrorCheck(uint32_t _addr, const T& valu } } } - else { + else {*/ CHIP_SELECT _nextByte(WRITE, READDATA); _transferAddress(); @@ -261,7 +261,7 @@ template bool SPIFlash::_writeErrorCheck(uint32_t _addr, const T& valu } } _endSPI(); - } + //} return true; } @@ -288,57 +288,51 @@ template bool SPIFlash::_write(uint32_t _addr, const T& value, uint32_ //Serial.print("_addrIn: "); //Serial.println(_addrIn, HEX); const uint8_t* p = ((const uint8_t*)(const void*)&value); -//Serial.print(F("Address being written to: ")); -//Serial.println(_addr); + //Serial.print(F("Address being written to: ")); + //Serial.println(_addr); + uint32_t length = _sz; + uint16_t maxBytes = SPI_PAGESIZE-(_addrIn % SPI_PAGESIZE); // Force the first set of bytes to stay within the first page + if (!SPIBusState) { _startSPIBus(); } CHIP_SELECT _nextByte(WRITE, PAGEPROG); _transferAddress(); - //If data is only one byte (8 bits) long - if (_sz == 0x01) { - _nextByte(WRITE, *p); + + if (maxBytes > length) { + for (uint16_t i = 0; i < length; ++i) { + _nextByte(WRITE, *p++); + } CHIP_DESELECT } - else { //If data is longer than one byte (8 bits) - uint32_t length = _sz; - uint16_t maxBytes = SPI_PAGESIZE-(_addrIn % SPI_PAGESIZE); // Force the first set of bytes to stay within the first page + else { + uint32_t writeBufSz; + uint16_t data_offset = 0; + + do { + writeBufSz = (length<=maxBytes) ? length : maxBytes; - if (maxBytes > length) { - for (uint16_t i = 0; i < length; ++i) { + for (uint16_t i = 0; i < writeBufSz; ++i) { _nextByte(WRITE, *p++); } 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 - if (!_addressOverflow) { - _currentAddress += writeBufSz; - } - else { - if (data_offset >= _addressOverflow) { - _currentAddress = 0x00; - _addressOverflow = false; - } - } - data_offset += writeBufSz; - length -= writeBufSz; - maxBytes = SPI_PAGESIZE; // Now we can do up to 256 bytes per loop - if(!_notBusy() || !_writeEnable()) { - return false; + if (!_addressOverflow) { + _currentAddress += writeBufSz; + } + else { + if (data_offset >= _addressOverflow) { + _currentAddress = 0x00; + _addressOverflow = false; } - } while (length > 0); - } + } + data_offset += writeBufSz; + length -= writeBufSz; + maxBytes = SPI_PAGESIZE; // Now we can do up to 256 bytes per loop + if(!_notBusy() || !_writeEnable()) { + return false; + } + } while (length > 0); } if (!errorCheck) { diff --git a/src/SPIFlashIO.cpp b/src/SPIFlashIO.cpp index 730aa2f..7611c20 100644 --- a/src/SPIFlashIO.cpp +++ b/src/SPIFlashIO.cpp @@ -1,8 +1,8 @@ -/* Arduino SPIMemory Library v.3.1.0 +/* Arduino SPIMemory Library v.3.2.1 * Copyright (C) 2017 by Prajwal Bhattaram * Created by Prajwal Bhattaram - 19/05/2015 * Modified by @boseji - 02/03/2017 - * Modified by Prajwal Bhattaram - 24/02/2018 + * Modified by Prajwal Bhattaram - 21/05/2018 * * This file is part of the Arduino SPIMemory Library. This library is for * Winbond NOR flash memory modules. In its current form it enables reading diff --git a/src/SPIMemory.h b/src/SPIMemory.h index 59738f2..67d7160 100644 --- a/src/SPIMemory.h +++ b/src/SPIMemory.h @@ -1,7 +1,7 @@ -/* Arduino SPIMemory Library v.3.2.0 +/* Arduino SPIMemory Library v.3.2.1 * Copyright (C) 2017 by Prajwal Bhattaram * Created by Prajwal Bhattaram - 18/04/2018 - * Modified by Prajwal Bhattaram - 20/04/2018 + * Modified by Prajwal Bhattaram - 21/05/2018 * * This file is part of the Arduino SPIMemory Library. This library is for * Winbond NOR flash memory modules. In its current form it enables reading @@ -31,14 +31,16 @@ // if using an unsupported chip // // // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// -#define USES_SFDP // +//#define USES_SFDP // +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// // 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 // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// @@ -49,6 +51,7 @@ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// //#define HIGHSPEED // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// // Uncomment the code below to disable overflow and force data // // to only be written to the last address of the flash memory // @@ -59,7 +62,7 @@ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// // Comment out the code below to disable DMA mode on SAMD based // -// platforms // +// platforms (In ALPHA) // // // // Change the ZERO_SPISERCOM define below to use other SPI ports // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// diff --git a/src/defines.h b/src/defines.h index b67f51e..0be893e 100644 --- a/src/defines.h +++ b/src/defines.h @@ -1,7 +1,7 @@ -/* Arduino SPIMemory Library v.3.1.0 +/* Arduino SPIMemory Library v.3.2.1 * Copyright (C) 2017 by Prajwal Bhattaram * Created by Prajwal Bhattaram - 19/05/2015 - * Modified by Prajwal Bhattaram - 24/02/2018 + * Modified by Prajwal Bhattaram - 21/05/2018 * * This file is part of the Arduino SPIMemory Library. This library is for * Winbond NOR flash memory modules. In its current form it enables reading @@ -191,7 +191,7 @@ #define VERBOSE true #define PRINTOVERRIDE true #define ERASEFUNC 0xEF -#define BUSY_TIMEOUT 10000000L +#define BUSY_TIMEOUT 1000000000L #define arrayLen(x) (sizeof(x) / sizeof(*x)) #define lengthOf(x) (sizeof(x))/sizeof(byte) #define BYTE 1L From 4a8a29066671176b5fc653895218e887a9ee8dcc Mon Sep 17 00:00:00 2001 From: Prajwal Bhattaram Date: Mon, 21 May 2018 14:24:51 +1000 Subject: [PATCH 12/12] Updated issue tempate --- .github/ISSUE_TEMPLATE.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 13f7e32..52d64e8 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -1,4 +1,6 @@ -![GitHub issue state](https://img.shields.io/github/issues/detail/s/Marzogh/SPIFlash/14.svg) ![GitHub issue title](https://img.shields.io/github/issues/detail/title/Marzogh/SPIFlash/14.svg) ![GitHub issue author](https://img.shields.io/github/issues/detail/u/Marzogh/SPIFlash/14.svg) ![GitHub issue label](https://img.shields.io/github/issues/detail/label/Marzogh/SPIFlash/14.svg) ![GitHub issue comments](https://img.shields.io/github/issues/detail/comments/Marzogh/SPIFlash/14.svg) ![GitHub issue age](https://img.shields.io/github/issues/detail/age/Marzogh/SPIFlash/14.svg) ![GitHub issue last update](https://img.shields.io/github/issues/detail/last-update/Marzogh/SPIFlash/14.svg) +![GitHub issue state](https://img.shields.io/github/issues/detail/s/Marzogh/SPIFlash/14.svg) ![GitHub issue title](https://img.shields.io/github/issues/detail/title/Marzogh/SPIFlash/14.svg) +![GitHub issue author](https://img.shields.io/github/issues/detail/u/Marzogh/SPIFlash/14.svg) ![GitHub issue label](https://img.shields.io/github/issues/detail/label/Marzogh/SPIFlash/14.svg) ![GitHub issue comments](https://img.shields.io/github/issues/detail/comments/Marzogh/SPIFlash/14.svg) +![GitHub issue age](https://img.shields.io/github/issues/detail/age/Marzogh/SPIFlash/14.svg) ![GitHub issue last update](https://img.shields.io/github/issues/detail/last-update/Marzogh/SPIFlash/14.svg) ###### ---------------------------- **DO NOT DELETE OR EDIT** anything above this line ---------------------------- ###### ---------------------------- **DO NOT DELETE OR EDIT** anything above this line ----------------------------