Go Down

Topic: Wire and 24LC256 Issue (Read 2045 times) previous topic - next topic

baum

I'm trying to erase an 24LC256, but it's taking a really long time... like more than 10 seconds per byte.
Here's my (abbreviated) code, which is inside a loop:
Code: [Select]
while(pointer < EXTERAL_E2_SIZE) {
    Wire.beginTransmission(ADDRESS);
    Wire.write(highByte(pointer));
    Wire.write(lowByte(pointer));
    Wire.write(0xFF);
    Wire.endTransmission();
    pointer++;
}


Using some serial debugging, I figured out that the the long delay comes from endTransmission(). My code seems fine, and my connection's alright... Where could this delay be coming from?


Thanks a lot!

baum

baum

Update: I have found that this code works in my main program, but when copied and pasted over here, I takes ~1 minute per loop (I put a serial.println() at the end of the loop). Why would copy&pasted code work as fast as it should in the main program, but not here?

Nick Gammon


Using some serial debugging, I figured out that the the long delay comes from endTransmission().


endTransmission is the only thing that does any transmitting. The other stuff just puts things into a buffer. So if there is a delay, that's where it would be. Perhaps paste more code? Like the whole thing.
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

baum

Well, I just figured it out... I forgot wire.begin()...   :smiley-sad-blue: So maybe wire should tell you when you don't begin it?

It's erasing as I type!

baum

Nick Gammon

Note from the datasheet:

Quote
When doing a write of less than 64 bytes the data in the rest of the page is refreshed along with the data bytes being written. This will force the entire page to endure a write cycle, for this reason endurance is specified per page.


You may want to redesign so that you erase 64 bytes at a time. You are effectively making the chip do 64 lots of writes when it need only do one. In other words, you are reducing the chip life by a factor of 64 unnecessarily.
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

Nick Gammon


Well, I just figured it out... I forgot wire.begin()...   :smiley-sad-blue: So maybe wire should tell you when you don't begin it?


The Blue Screen of Death? Well maybe someone could make a BSOD shield. ;)
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

baum

Yeah, I guess. I'll just have to put in some page-detect code... but too bad there isn't a chip erase function.

baum

baum

Would this be good? I can only do half of a page b/c of Wire buffer size.


Code: [Select]

/* Erases both the internal and
* external 24LC256 EEPROMs.
*/


#include <Wire.h>
#include <EEPROM.h>

#define EEPROM_ADDRESS        0x50
#define EXTERNAL_EEPROM_SIZE  32768 //size of 24LC

#define L_PIN  13

#define arrayLength(array) (sizeof(array)/sizeof(array[0]))

void setup() {
  unsigned int memPointer = 0;
 
  Serial.begin(19200);
  Wire.begin();

  pinMode(L_PIN, OUTPUT);

  /* First clear the internal. */
  for (int i = 0; i <= E2END; i++) {
    EEPROM.write(i, 0);
  }

  blink(L_PIN);

  /* And now the external EEPROM. */
  byte eraseArray[BUFFER_LENGTH]; //32 bytes for standard Wire library
  memset(eraseArray, byte(0xFF), sizeof(eraseArray));
  //Now eraseArray[] is filled with 0xFF.
 
  while(memPointer < EXTERAL_EEPROM_SIZE) {
    writeArray(eraseErray[], memPointer);
  }
 
  blink(L_PIN);

} //end setup

void loop() {
}


void blink(byte pin) {
  digitalWrite(pin, HIGH);
  delay(200);
  digitalWrite(pin, LOW);
  return;
}


/* writes and Array to the 24LC56.*/
void writeArray(byte data[], unsigned int& address) {

  if(arrayLength(data) > BUFFER_LENGTH) { //too big for Wire buffer!
    return;
  }

  unsigned int i;

  Wire.beginTransmission(EEPROM_ADDRESS);
  Wire.write(highByte(address));
  Wire.write(lowByte(address));

  /* Now do a page write */

  for(i = 0; i < arrayLength(data); i++) {
    Wire.write(data[i]);
  }

  address += arrayLength(data); //increase the address.

  Wire.endTransmission(); //send the data.

  return; 
}




Thanks,

baum

Nick Gammon

Well, no, because you are sending 34 bytes, and the buffer size is 32 (you have to count the address).
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

baum

Thanks... so is there anyway of sending a full 64 byte page? And why does Wire only send the data @ endTransmission?

baum

Nick Gammon

You could increase the buffer size, bearing in mind there are 5 of them. So already you are using 5 x 32 bytes.

Why? Well sending is fairly time-critical, so I think they designed it so you can do calculations and stuff, and that just gets buffered.
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

baum

Quote
You could increase the buffer size, bearing in mind there are 5 of them. So already you are using 5 x 32 bytes.



So there are 5 buffers, each 32 bytes. I am using all 5 of them (160 bytes) yet only have a 32 byte buffer...? Which one's which?


Thanks for clarifying about endTransmission().

baum

Nick Gammon

Inside Wire.h:

Code: [Select]

...
#define BUFFER_LENGTH 32
...


Inside Wire.cpp:

Code: [Select]
...
uint8_t TwoWire::rxBuffer[BUFFER_LENGTH];
...
uint8_t TwoWire::txBuffer[BUFFER_LENGTH];
...


Inside twi.h:

Code: [Select]
...
  #define TWI_BUFFER_LENGTH 32
...


Inside twi.c:

Code: [Select]
...
static uint8_t twi_masterBuffer[TWI_BUFFER_LENGTH];
...
static uint8_t twi_txBuffer[TWI_BUFFER_LENGTH];
...
static uint8_t twi_rxBuffer[TWI_BUFFER_LENGTH];
...


So you don't have one buffer of 160 bytes, you have 5 x 32 byte buffers, used for different things.
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

baum

But I could change that 32 to something else, and get a larger buffer? Or is this hardcoded?

baum

baum

So I (tried) to incorporate in a page write, and now it won't erase. Odd thing is that the writeArray function is copied from another program, where it works.

Code: [Select]
/* Science Research Timer Erase
* Erases both the internal and
* external 24LC256 EEPROMs.
*/


#include <Wire.h>
#include <EEPROM.h>

#define EEPROM_ADDRESS        0x50
#define EXTERNAL_EEPROM_SIZE  32768L //size of 24LC

#define L_PIN  3

void setup() {
  unsigned long memPointer = 0;
 
  Serial.begin(19200);
  Wire.begin();

  pinMode(L_PIN, OUTPUT);

  /* First clear the internal. */
  for (int i = 0; i <= E2END; i++) {
    EEPROM.write(i, 0);
  }

  blink(L_PIN);

  /* And now the external EEPROM. */
  char eraseArray[BUFFER_LENGTH]; //32 bytes for standard Wire library
 
  for(int i = 0; i < BUFFER_LENGTH; i++) {
    eraseArray[i] = 0xFF;
  }
  //Now eraseArray[] is filled with 0xFF.
 
  while(memPointer < EXTERNAL_EEPROM_SIZE) {
    writeArray(eraseArray, BUFFER_LENGTH, memPointer);
    memPointer += BUFFER_LENGTH; //increase the address.
    Serial.println(memPointer);
  }
 
   digitalWrite(L_PIN, HIGH);
   
} //end setup

void loop() {
}


void blink(byte pin) {
  digitalWrite(pin, HIGH);
  delay(200);
  digitalWrite(pin, LOW);
  return;
}


/* writes an Array to the 24LC56.*/
void writeArray(char data[], int length, unsigned int address) {

  if((length + 2) > BUFFER_LENGTH) { //too big for Wire buffer!
    return;
  }

  unsigned int i;

  Wire.beginTransmission(EEPROM_ADDRESS);
  Wire.write(highByte(address));
  Wire.write(lowByte(address));

  /* Now do a page write */

  for(i = 0; i < length; i++) {
    Wire.write(data[i]);
  }

  Wire.endTransmission(); //send the data.

  return; 
}


Go Up