mirror of
https://github.com/RobTillaart/Arduino.git
synced 2024-10-03 18:09:02 -04:00
1.8.3 I2C_EEPROM
This commit is contained in:
parent
6f2cc904c9
commit
7c3a797cfb
1
libraries/I2C_EEPROM/.github/FUNDING.yml
vendored
1
libraries/I2C_EEPROM/.github/FUNDING.yml
vendored
@ -1,4 +1,5 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
github: RobTillaart
|
||||
custom: "https://www.paypal.me/robtillaart"
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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$"
|
||||
|
||||
|
@ -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()**
|
||||
|
@ -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.
|
||||
|
@ -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();
|
||||
|
@ -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());
|
||||
|
||||
|
@ -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...
|
@ -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 --
|
@ -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
|
||||
|
||||
|
@ -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": "*",
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user