1.8.3 I2C_EEPROM

This commit is contained in:
Rob Tillaart 2024-03-28 10:50:48 +01:00
parent 6f2cc904c9
commit 7c3a797cfb
14 changed files with 260 additions and 28 deletions

View File

@ -1,4 +1,5 @@
# These are supported funding model platforms
github: RobTillaart
custom: "https://www.paypal.me/robtillaart"

View File

@ -5,8 +5,9 @@ on: [push, pull_request]
jobs:
lint:
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- uses: arduino/arduino-lint-action@v1
with:
library-manager: update

View File

@ -6,12 +6,14 @@ on: [push, pull_request]
jobs:
runTest:
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- uses: ruby/setup-ruby@v1
with:
ruby-version: 2.6
- run: |
sudo sysctl vm.mmap_rnd_bits=28
gem install arduino_ci
arduino_ci.rb

View File

@ -9,10 +9,11 @@ on:
jobs:
test:
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: json-syntax-check
uses: limitusus/json-syntax-check@v1
uses: limitusus/json-syntax-check@v2
with:
pattern: "\\.json$"

View File

@ -5,7 +5,18 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).
## [1.8.2] - 2023-01-02
## [1.8.3] - 2024-03-28
- Fix #64, compiler warning.
- add **verifyBlock(memoryAddress, buffer, length)**
- add example **I2C_eeprom_verifyBlock.ino**
- update GitHub actions
- update keywords.txt
- update examples
- update readme.md
## [1.8.2] - 2024-01-02
- updated **uint32_t determineSizeNoWrite()**, kudos to roelandkluit
- minor edits
@ -14,7 +25,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- add example
- minor edits
## [1.8.0] - 2023-11-24 (breaking change)
- simplify **begin()**, remove setting Wire pins from library.
- add **getAddress()**

View File

@ -1,7 +1,7 @@
//
// FILE: I2C_eeprom.cpp
// 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
@ -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 = (uint8_t *) 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);
}
@ -380,7 +403,7 @@ uint32_t I2C_eeprom::determineSizeNoWrite()
//Read is perfomed just over size (size + BUFSIZE), this will only work for devices with mem > size; therefore return size * 2
_isAddressSizeTwoWords = addressSize;
return size * 2;
}
}
}
_isAddressSizeTwoWords = addressSize;
return 0;
@ -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.

View File

@ -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 @@ public:
// 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 @@ private:
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();

View File

@ -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());

View File

@ -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...

View File

@ -0,0 +1,99 @@
//
// FILE: I2C_eeprom_verifyBlock.ino
// AUTHOR: Rob Tillaart
// PURPOSE: demo I2C_EEPROM library
//
// uses a 24LC256 (32KB) EEPROM
#include "Wire.h"
#include "I2C_eeprom.h"
I2C_eeprom ee(0x50, I2C_DEVICESIZE_24LC256);
uint32_t start, dur1;
char buffer[] = "12345678901234567890123456789012345678901234567890"; // 50 bytes
void setup()
{
Serial.begin(115200);
while (!Serial); // wait for Serial port to connect. Needed for Leonardo only
Serial.println(__FILE__);
Serial.print("I2C_EEPROM_VERSION: ");
Serial.println(I2C_EEPROM_VERSION);
Wire.begin();
ee.begin();
if (! ee.isConnected())
{
Serial.println("ERROR: Can't find eeprom\nstopped...");
while (1);
}
delay(10);
//////////////////////////////////////////////////////////////////////
Serial.println("\nTEST: writeBlock()");
delay(10);
start = micros();
ee.writeBlock(0, (uint8_t *) buffer, 50);
dur1 = micros() - start;
Serial.print("DUR1: ");
Serial.println(dur1);
delay(10);
Serial.println("\nTEST: verifyBlock() no change");
delay(10);
start = micros();
if (ee.verifyBlock(0, (uint8_t *) buffer, 50) == false)
{
Serial.print("X");
}
dur1 = micros() - start;
Serial.print("DUR1: ");
Serial.println(dur1);
delay(10);
for (uint8_t loc = 0; loc < 50; loc += 5)
{
disrupt(loc);
}
Serial.println("done...");
}
void loop()
{
}
void disrupt(uint8_t location)
{
bool flag = true;
// disrupt memory
Serial.print("\nTEST: verifyBlock() after change @ ");
Serial.println(location);
delay(10);
ee.writeBlock(0, (uint8_t *) buffer, 50);
ee.writeByte(location, 255);
start = micros();
if (ee.verifyBlock(0, (uint8_t *) buffer, 50) == false)
{
flag = false;
}
dur1 = micros() - start;
Serial.print("DUR1: ");
Serial.println(dur1);
Serial.println(flag);
delay(10);
}
// -- END OF FILE --

View File

@ -19,6 +19,7 @@ setBlock KEYWORD2
readByte KEYWORD2
readBlock KEYWORD2
verifyBlock KEYWORD2
updateByte KEYWORD2
updateBlock KEYWORD2
@ -35,6 +36,8 @@ getDeviceSize KEYWORD2
getPageSize KEYWORD2
getLastWrite KEYWORD2
setDeviceSize KEYWORD2
setExtraWriteCycleTime KEYWORD2
getExtraWriteCycleTime KEYWORD2

View File

@ -15,7 +15,7 @@
"type": "git",
"url": "https://github.com/RobTillaart/I2C_EEPROM.git"
},
"version": "1.8.2",
"version": "1.8.3",
"license": "MIT",
"frameworks": "*",
"platforms": "*",

View File

@ -1,5 +1,5 @@
name=I2C_EEPROM
version=1.8.2
version=1.8.3
author=Rob Tillaart <rob.tillaart@gmail.com>
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
sentence=Library for I2C EEPROMS

View File

@ -52,13 +52,13 @@ before calling **I2C_eeprom.begin()**.
```cpp
+---U---+
A0 | 1 8 | VCC = +5V
A0 | 1 8 | VCC = 1.7V to 5.5V
A1 | 2 7 | WP = write protect pin
A2 | 3 6 | SCL = I2C clock
GND | 4 5 | SDA = I2C data
+-------+
default address = 0x50 .. 0x57 depending on three address lines
Default address = 0x50 .. 0x57 depending on three address lines (A0, A1, A2).
```
@ -131,6 +131,9 @@ Same as write and update functions above. Returns true if successful, false indi
- **bool setBlockVerify(uint16_t memoryAddress, uint8_t value, uint16_t length)**
- **bool updateByteVerify(uint16_t memoryAddress, uint8_t value)**
- **bool updateBlockVerify(uint16_t memoryAddress, uint8_t \* buffer, uint16_t length)**
- **bool verifyBlock(uint16_t memoryAddress, uint8_t \* buffer, uint16_t length)**
Returns true is buffer equals memoryAddres for length bytes.
### Other
@ -263,6 +266,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
@ -270,6 +275,7 @@ See examples
- circular buffer? (see FRAM library)
- dump function?
## Support
If you appreciate my libraries, you can support the development and maintenance.