sparkfun / SparkFun_External_EEPROM_Arduino_Library

An Arduino library for the easy control of external I2C EEPROMs.
Other
54 stars 14 forks source link

Bug in buffered reading? #2

Closed ullix closed 3 years ago

ullix commented 4 years ago

I am using your lib with an ESP32-Wroom-Dev and an EEPROM ATMEL188 24C256. Reading and Writing generally ok, but:

When I do reads like x256PRM.get(i, buf), with buf being a byte buffer from 16, 32, 64, 128, ..., 16k, I almost always (95% of the time) get a sequence of 0xFF somewhere in the bytes read from the buffer. This sequence length is varying, ranging from 3 to 15 - clearly not always powers of 2 - and they seem to appear an random places within the EEPROM memory.

When I read that very modul via single-byte-reads, no FFs are present. Do I then follow with a buffered read, FFs are there again, but perhaps at a different location, and different sequence length.

I tried adding delays, but that did not help. I use page_size 64, write_time 5. My reading speed turns out at ~0.1ms/byte.

Can you help?

ullix commented 4 years ago

Just an example: 2 consecutive reads from the same EEPROM; look for the 2 different fff sequences in what is supposed to be identical text (a 0xFF byte read from EEPROM was replaced with 'f'):

`<1st read>

DateTime from AMEpocheTime UTC: 2020-02-28 13:48:44 f80 ESP32-WROOM-Dev , Saves, Chip t[s], d[us], Sum, NTP-AM,(mi,ma), NTP-RTC,(mi,ma), dur[ms],( mi, ma), Ipts, Heapfree[kB] 1000 2020-02-28 13:49:44, 1, 71, -2, -2, 9,( 9, 9), 0,( 0, 0), 139,( 1, 139), 0(2), 148(107,278) 1080 2020-02-28 13:50:44, 2, 131, -1, -3, 9,( 9, 9), 0,( 0, 0), 138,( 1, 139), 0(2), 148(107,278) 1100 2020-02-28 13:51:44, 3, 191, 1, -2, 9,( 9, 9), 0,( 0, 0), 140,( 1, 140), 0(2), 148(107,278) 1180 2020-02-28 13:52:44, 4, 251, 0, -2, 9,( 9, 9), 0,( 0, 0), 142,( 1, 142), 0(2), 148(107ffffff1200 2020-02-28 13:53:44, 5, 311, 0, -2, 9,( 9, 9), 0,( 0, 0), 138,( 1, 142), 0(2), 148(107,278) 1280 2020-02-28 13:54:44, 6, 371, 0, -2, 9,( 9, 9), 0,( 0, 0), 138,( 1, 142), 0(2), 148(107,278)

<2nd read> DateTime from AMEpocheTime UTC: 2020-02-28 13:48:44 f80 ESP32-WROOM-Dev , Saves, Chip t[s], d[us], Sum, NTP-AM,(mi,ma), NTP-RTC,(mi,ma), dur[ms],( mi, ma), Ipts, Heapfree[kB] 1000 2020-02-28 13:49:44, 1, 71, -2, -2, 9,( 9, 9), 0,( 0, 0), 139,( 1, 139), 0(2), 148(107,278) 1080 2020-02-28 13:50:44, 2, 131, -1, -3, 9,( 9, 9), 0,( 0, 0), 138,( 1, 139), 0(2), 148(107,278) 1100 2020-02-28 13:51:44, 3, 191, 1, -2, 9,( 9, 9), 0,( 0, 0), 140,( 1, 140), 0(2), 148(107,278) 1180 2020-02-28 13:52:44, 4, 251, 0, -2, 9,( 9, 9), 0,( 0, 0), 142,( 1, 142), 0(2), 148(107,278) 1200 2020-02-28 13:53:44, 5, 311, 0, -2, 9,( 9, 9), 0,( 0, 0), 138,( 1, 142), 0(2), 148(107,278) 1280 2020-02-28 13:54:44, 6, 371, 0, -2, 9,( 9, 9), 0,( 0, 0), 138,( 1, 142), 0(2), 148(107,278) ... 2000 2020-02-28 13:49:44 appendBinFile: FFat: /logBin size:8880 + 148 T[ms]: O:1.9 W:0.2 F:99 C:0.2 T:102 (101,101) 2080 2020-02-28 13:50:44 appendBinFile: FFat: /logBin size:9028 + 148 T[ms]: O:2.0 W:0.1 F:99 C:0.1 T:102 (101,101) 2100 2020-02-28 13:51:44 appendBinFile: FFat: /logBin size:9176 + 148 T[ms]: O:2.0 W:0.1 F:101 C:0.1 T:104 (101,103) 2180 2020-02-28 13:52:44 appendBinFile: FF**ffffffffffffffffffffff**+ 148 T[ms]: O:2.0 W:0.1 F:103 C:0.1 T:106 (101,105) 2200 2020-02-28 13:53:44 appendBinFile: FFat: /logBin size:9472 + 148 T[ms]: O:2.0 W:0.1 F:99 C:0.1 T:102 (101,105) 2280 2020-02-28 13:54:44 appendBinFile: FFat: /logBin size:9620 + 148 T[ms]: O:2.0 W:0.1 F:99 C:0.1 T:102 (101,105) `
ullix commented 4 years ago

closing was not intended

nseidle commented 4 years ago

Thanks for reporting! Sounds like you've stumbled onto something bad.

Do you have a full part# so I can pull the datasheet?

Do you have a minimal example sketch that I can use that demos the problem? I'll try to replicate.

nseidle commented 4 years ago

Here's the datasheet I'm looking at but the part looks obsolete so I'd like your full part #.

ullix commented 4 years ago

This is the complete imprint on the chip: ATMEL188 24C256 PU27 D.

Code to follow shortly.

nseidle commented 4 years ago

PU is DIP 27 is 2.7V so the max I2C clock is 400kHz

ATMEL188 I'm trying to make into the mfg year and week but that doesn't seem to fit their spec:

image

If the chip is from 2011 I might be a bit suspicious. If it's from 2018 I doubt the hardware is the problem.

ullix commented 4 years ago

It is this product (though I doubt it helps any further): https://www.amazon.de/gp/product/B07XTBXGXW/ref=ppx_yo_dt_b_asin_title_o06_s00?ie=UTF8&psc=1

ullix commented 4 years ago

I believe this is all the relevant code. Same effect no matter what the buffer size. I went from very big buffer to smaller because of timing issues, but that is a different matter.

`#include "SparkFun_External_EEPROM.h"

define XCFG256_START 0 // Start position in EEPROM to store setting structure

//#define XCFG256_SIZE 32768 // Size of EEPROM; 24C256 has 256k bit= 32768 byte //TESTING

define XCFG256_SIZE 16384 // Size of EEPROM; 24C256 has 256k bit= 32768 byte

define XCFG256_PAGE_SIZE 64 // Page Size of EEPROM; 24C256 has 64 byte

define XCFG256_PAGE_WRITE_TIME 5 // Page Write Time of EEPROM; 24C256 has 5 ms

define XCFG256_ADRESS 0x50 // I2C address of EEPROM 24C256 at 0x50

ExternalEEPROM x256PRM; // external EEPROM

//--------------------------

const uint16_t ddfull = 0x4000; // = 16384 = 128 * 128 -- only half size used for testing const uint16_t sbufsize = 64; // try 16, 32, 64, 128, 256, ... all the same problem byte smallbuf[sbufsize]; byte myBuffer[ddfull]; // use buffer to read full EEPROM into

for (int i = 0; i < ddfull; i += sbufsize){ x256PRM.get(i, smallbuf); for (int j = 0; j < sbufsize; j++){ // read chunks myBuffer[i + j] = smallbuf[j]; } yield(); }
`

The problems show when I print chars from myBuffer, but not when I read single bytes from EEPROM.

ullix commented 4 years ago

I became curious and lifted one DIP out of its socket. On its underside I see the text 18 18 33. Helpful?

ullix commented 4 years ago

I just converted my code to support another EEPROM, ATHYT532 24C32N SU27 D (part of an RTC), and the same problem shows, note the prominent ffff:

DateTime from NTP-Epoche180 ESP32-WROOM-Dev , Saves, Chip t[s], d[us], Sum, NTP-AM,(mi,ma), NTP-RTC,(mi,ma), dur[ms],( mi, ma), Ipts, Heapfree[kB] 200 2020-02-28 17:11:01, 1, 68, 0, 0, 5,( 5, 5), 0,( 0, 0), 135,(135, 135), 0(2), 160(122,290) 280 2020-02-28 17:12:01, 2, 128, 0, 0, 5,( 5, 5), 0,( 0, 0), 203,( 1, 203), 0(2), 160(116,290) 300 2020-02-28 17:13:01, 3, 187, 1, 1, 5,( 5, 5), 0,( 0, 0), 131,( 1, 203), 0(2), 159(116,290) ffffffffffffffffffffffffffffffff 400 2020-02-28 17:11:01 appendBinFile: FFat: /logBin size:36704 + 148 T[ms]: O:1.9 W:0.1 F:98 C:0.1 T:101 (100,100) 480 2020-02-28 17:12:01 appendBinFile: FFat: /logBin size:36852 + 148 T[ms]: O:2.0 W:51.1 F:116 C:0.1 T:170 (100,169) 500 2020-02-28 17:13:01 appendBinFile: FFat: /logBin size:37000 + 148 T[ms]: O:2.0 W:0.2 F:95 C:0.1 T:98 (97,169)

nseidle commented 4 years ago

I've got a 24LC256 and can't replicate the issue on Uno or Artemis.

Have you tried the Examples->Ex5_InterfaceTest? If that's failing for you I suspect it is platform dependent and it's time to break out the logic analyzer.

Here's my test sketch for reference.

include

include "SparkFun_External_EEPROM.h" // Click here to get the library: http://librarymanager/All#SparkFun_External_EEPROM

ExternalEEPROM myMem;

void setup() { Serial.begin(115200); Serial.println("I2C EEPROM example test 123");

//Pick any unconnected analog pin randomSeed(analogRead(A29)); //randomSeed(analogRead(A15));

unsigned int randomLocation;

Wire.begin(); Wire.setClock(400000); //Wire.setClock(1000000);

if (myMem.begin() == false) { Serial.println("No memory detected. Freezing."); while (1); } Serial.println("Memory detected!");

Serial.println(""); Serial.println("Buffer Write Test");

long startTime; long endTime; bool allTestsPassed = true;

//Buffer write test //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- //char myChars[242] = "Lorem ipsum dolor sit amet, has in verterem accusamus. Nulla viderer inciderint eum at. Quo elit nullam malorum te, agam fuisset detracto an sea, eam ut liber aperiri. Id qui velit facilisi. Mel probatus definitionem id, eu amet vidisse eum."; char myChars[88] = "Lorem ipsum dolor sit amet, has in verterem accusamus. Nulla viderer inciderint eum at."; randomLocation = random(0, myMem.length());

Serial.print("Calculated time to record array of " + (String)sizeof(myChars) + " characters: ~"); Serial.print((uint32_t)sizeof(myChars) / myMem.getPageSize() * myMem.getPageWriteTime()); Serial.println("ms");

startTime = micros(); //myMem.put(randomLocation, myChars); myMem.put(0, myChars); endTime = micros(); Serial.println("Time to record array: " + (String)(endTime - startTime) + " us");

char readMy[sizeof(myChars)];

startTime = micros(); //myMem.get(randomLocation, readMy); myMem.get(0, readMy); endTime = micros(); Serial.println("Time to read array: " + (String)(endTime - startTime) + " us");

Serial.println("Location " + (String)randomLocation + " string should read:"); Serial.println(myChars); Serial.println(readMy); if (strcmp(myChars, readMy) != 0) { Serial.println("String compare failed"); allTestsPassed = false; } //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

const uint16_t ddfull = 1024;//128128; // = 16384 = 128 128 -- only half size used for testing const uint16_t sbufsize = 64; // try 16, 32, 64, 128, 256, ... all the same problem byte smallbuf[sbufsize]; byte myBuffer[ddfull]; // use buffer to read full EEPROM into

for (int i = 0; i < ddfull; i += sbufsize) { myMem.get(i, smallbuf); for (int j = 0; j < sbufsize; j++) { // read chunks myBuffer[i + j] = smallbuf[j]; } }

for (int j = 0; j < ddfull; j++) { Serial.write(myBuffer[j]); } Serial.println();

Serial.println(); Serial.print("Memory Contents:"); for (uint16_t x = 0; x < 32 * 4; x ++) { if (x % 16 == 0) Serial.println(); Serial.print(" 0x"); if (myMem.read(x) < 0x10) Serial.print("0"); Serial.print(myMem.read(x), HEX); } Serial.println();

if (allTestsPassed == true) Serial.println("All tests PASSED!"); else Serial.println("Something went wrong. See output."); }

void loop() {

}

and output

image

ullix commented 4 years ago

Tested your code and it worked fine. Shrunk down my own code to the bare minimum - and it also worked fine. Yet, my big code still has the problem! Hmmm.

Eventually I got it. I tried to get some timing advantage by putting the EEPROM-reading code in a separate task (on Core 1, just as setup and loop). And this - what is it: Multitasking? Multithreading? - does interfere with reading the EEPROM. Code is below.

My wild guess: it is the Wire lib. Is that possible? Or could you put some remedy into the EEPROM lib?

The reason why I tried this tasking is that the time it takes to read the EEPROM gives me some difficulties. How can this be sped up? Does your lib work also for FRAM or only the good- ol' EEPROMs? FRAM can be written faster, but as long as it is I2C based, I am afraid they may not be faster to read? (Writing time is not an issue for me).

Any better ideas?

The code follows: A full 32k Bytes of '.' (dot) is written to EEPROM in setup and then read and printed in the loop. All ok. Next is to read the EEPROM via a task started in the loop. The problem is easily seen in the printing.

Comment out the very last code line to see it working just fine.

` /*

`

nseidle commented 3 years ago

Works for me. Closing stale issue.