diff --git a/I2C_eeprom.cpp b/I2C_eeprom.cpp index 4064e17..2f45d06 100644 --- a/I2C_eeprom.cpp +++ b/I2C_eeprom.cpp @@ -147,6 +147,27 @@ uint16_t I2C_eeprom::readBlock(const uint16_t memoryAddress, uint8_t * buffer, c } +// returns true or false. +bool I2C_eeprom::verifyBlock(const uint16_t memoryAddress, const uint8_t * buffer, const uint16_t length) +{ + uint16_t addr = memoryAddress; + uint16_t len = length; + while (len > 0) + { + uint8_t cnt = I2C_BUFFERSIZE; + if (cnt > len) cnt = len; + if (_verifyBlock(addr, buffer, cnt) == false) + { + return false; + } + addr += cnt; + buffer += cnt; + len -= cnt; + } + return true; +} + + ///////////////////////////////////////////////////////////// // // UPDATE SECTION @@ -203,9 +224,7 @@ bool I2C_eeprom::writeByteVerify(const uint16_t memoryAddress, const uint8_t val bool I2C_eeprom::writeBlockVerify(const uint16_t memoryAddress, const uint8_t * buffer, const uint16_t length) { if (writeBlock(memoryAddress, buffer, length) != 0) return false; - uint8_t data[length]; - if (readBlock(memoryAddress, data, length) != length) return false; - return memcmp(data, buffer, length) == 0; + return verifyBlock(memoryAddress, buffer, length); } @@ -213,12 +232,18 @@ bool I2C_eeprom::writeBlockVerify(const uint16_t memoryAddress, const uint8_t * bool I2C_eeprom::setBlockVerify(const uint16_t memoryAddress, const uint8_t value, const uint16_t length) { if (setBlock(memoryAddress, value, length) != 0) return false; - uint8_t data[length]; + uint8_t * data = malloc(length); + if (data == NULL) return false; if (readBlock(memoryAddress, data, length) != length) return false; for (uint16_t i = 0; i < length; i++) { - if (data[i] != value) return false; + if (data[i] != value) + { + free(data); + return false; + } } + free(data); return true; } @@ -236,9 +261,7 @@ bool I2C_eeprom::updateByteVerify(const uint16_t memoryAddress, const uint8_t va bool I2C_eeprom::updateBlockVerify(const uint16_t memoryAddress, const uint8_t * buffer, const uint16_t length) { if (updateBlock(memoryAddress, buffer, length) != length) return false; - uint8_t data[length]; - if (readBlock(memoryAddress, data, length) != length) return false; - return memcmp(data, buffer, length) == 0; + return verifyBlock(memoryAddress, buffer, length); } @@ -640,6 +663,50 @@ uint8_t I2C_eeprom::_ReadBlock(const uint16_t memoryAddress, uint8_t * buffer, c } +// compares content of EEPROM with buffer. +// returns true if equal. +bool I2C_eeprom::_verifyBlock(const uint16_t memoryAddress, const uint8_t * buffer, const uint8_t length) +{ + _waitEEReady(); + + this->_beginTransmission(memoryAddress); + int rv = _wire->endTransmission(); + if (rv != 0) + { +// if (_debug) +// { +// SPRN("mem addr r: "); +// SPRNH(memoryAddress, HEX); +// SPRN("\t"); +// SPRNL(rv); +// } + return false; // error + } + + // readBytes will always be equal or smaller to length + uint8_t readBytes = 0; + if (this->_isAddressSizeTwoWords) + { + readBytes = _wire->requestFrom(_deviceAddress, length); + } + else + { + uint8_t addr = _deviceAddress | ((memoryAddress >> 8) & 0x07); + readBytes = _wire->requestFrom(addr, length); + } + yield(); // For OS scheduling + uint8_t cnt = 0; + while (cnt < readBytes) + { + if (buffer[cnt++] != _wire->read()) + { + return false; + } + } + return true; +} + + void I2C_eeprom::_waitEEReady() { // Wait until EEPROM gives ACK again. diff --git a/I2C_eeprom.h b/I2C_eeprom.h index 04b3493..69a6a46 100644 --- a/I2C_eeprom.h +++ b/I2C_eeprom.h @@ -2,7 +2,7 @@ // // FILE: I2C_eeprom.h // AUTHOR: Rob Tillaart -// VERSION: 1.8.2 +// VERSION: 1.8.3 // PURPOSE: Arduino Library for external I2C EEPROM 24LC256 et al. // URL: https://github.com/RobTillaart/I2C_EEPROM.git @@ -11,7 +11,7 @@ #include "Wire.h" -#define I2C_EEPROM_VERSION (F("1.8.2")) +#define I2C_EEPROM_VERSION (F("1.8.3")) #define I2C_DEVICESIZE_24LC512 65536 #define I2C_DEVICESIZE_24LC256 32768 @@ -92,7 +92,7 @@ class I2C_eeprom // reads length bytes into buffer // returns bytes read. uint16_t readBlock(const uint16_t memoryAddress, uint8_t * buffer, const uint16_t length); - + bool verifyBlock(const uint16_t memoryAddress, const uint8_t * buffer, const uint16_t length); // updates a byte at memoryAddress, writes only if there is a new value. // return 0 if data is same or written OK, error code otherwise. @@ -159,11 +159,14 @@ class I2C_eeprom void _beginTransmission(const uint16_t memoryAddress); // returns I2C status, 0 = OK + // TODO incrBuffer is an implementation name, not a functional name. int _pageBlock(const uint16_t memoryAddress, const uint8_t * buffer, const uint16_t length, const bool incrBuffer); // returns I2C status, 0 = OK int _WriteBlock(const uint16_t memoryAddress, const uint8_t * buffer, const uint8_t length); // returns bytes read. uint8_t _ReadBlock(const uint16_t memoryAddress, uint8_t * buffer, const uint8_t length); + // compare bytes in EEPROM. + bool _verifyBlock(const uint16_t memoryAddress, const uint8_t * buffer, const uint8_t length); // to optimize the write latency of the EEPROM void _waitEEReady(); diff --git a/README.md b/README.md index 77ce185..22e3ad4 100644 --- a/README.md +++ b/README.md @@ -263,6 +263,8 @@ See examples - investigate smarter strategy for **updateBlock()** => find first and last changed position could possibly result in less writes. - can **setBlock()** use strategies from **updateBlock()** +- **pageBlock()**: incrBuffer is an implementation name, not a functional name. + #### Wont diff --git a/examples/I2C_eeprom_test/I2C_eeprom_test.ino b/examples/I2C_eeprom_test/I2C_eeprom_test.ino index 5bed50a..83ff564 100644 --- a/examples/I2C_eeprom_test/I2C_eeprom_test.ino +++ b/examples/I2C_eeprom_test/I2C_eeprom_test.ino @@ -39,11 +39,6 @@ void setup() SERIAL_OUT.println("ERROR: Can't find eeprom\nstopped..."); while (1); } - - SERIAL_OUT.print("I2C eeprom library: "); - SERIAL_OUT.print(I2C_EEPROM_VERSION); - SERIAL_OUT.println("\n"); - SERIAL_OUT.print("isConnected:\t"); SERIAL_OUT.println(ee.isConnected()); diff --git a/examples/I2C_eeprom_verify/performance_1.8.2.txt b/examples/I2C_eeprom_verify/performance_1.8.2.txt new file mode 100644 index 0000000..6b25a31 --- /dev/null +++ b/examples/I2C_eeprom_verify/performance_1.8.2.txt @@ -0,0 +1,44 @@ +I2C_EEPROM_VERSION: 1.8.2 + +Testruns NN: 100 + + +TEST: NN x writeByte() +DUR1: 466516 + +TEST: NN x writeByteVerify() +DUR1: 542336 + +TEST: NN x updateByte() same data +DUR2: 58616 + +TEST: NN x updateByteVerify() same data +DUR2: 116896 + +TEST: NN x updateByteVerify() not same data +DUR2: 596672 + +TEST: NN x writeBlock() +DUR1: 1414432 + +TEST: NN x writeBlockVerify() +DUR1: 2010844 + +TEST: NN x updateBlock() same data +DUR2: 594796 + +TEST: NN x updateBlockVerify() same data +DUR2: 1186644 + +TEST: NN x updateBlockVerify() not same data +DUR2: 1204960 + +TEST: NN x setBlock() same data +DUR2: 1415932 + +TEST: NN x setBlockVerify() same data +DUR2: 2014048 + +TEST: NN x setBlockVerify() not same data +DUR2: 2009780 +done...