After reading through the forum and docs I made some test to access EEPROM and made up my mind how to structure data to be stored. One post stated that EEPROM access works on pages and a page is 32 bytes (I think it was an external EEPROM). I read in the ATmega328 specs that there are 256 pages each 4 bytes large. So I came up with a test for read speed using avr/eeprom.h and eeprom_read_byte/word/dword/block on a 32 byte struct (that's how I will organize my data, 28 bytes data, 4 bytes magic# and link to next block etc., including wear leveling). Somehow all the gathered information does not match the measured access times.
Here is the code used (Arduino 1.0):
void readTest(int nRepeat)
{
uint8_t nBuf[32];
uint8_t *pBuf;
uint32_t nStartTime1, nStartTime2;
eeprom_busy_wait();
nStartTime1= micros();
for(int nLoop= 0; nLoop < nRepeat; nLoop++)
{
eeprom_read_block(nBuf, (const void*)(0), 32);
eeprom_busy_wait();
}
nStartTime1= micros() - nStartTime1;
eeprom_busy_wait();
nStartTime2= micros();
for(int nLoop= 0; nLoop < nRepeat; nLoop++)
{
pBuf= nBuf;
for(int nPos= 0; nPos < 32; nPos++)
_EEGET(*pBuf++, nPos);
eeprom_busy_wait();
}
nStartTime2= micros() - nStartTime2;
Serial.println(nStartTime1);
Serial.println(nStartTime2);
}
The eeprom_busy_wait() has no effect and was for testing purposes in the code. The results for 32 rounds are 2320 for eeprom_read_block() and 1436 for eeprom_read_byte(). Reading DWORDs was a bit slower than block read and WORDs got even slower access. Using the EEPROM class brings a bit of overhead (about 400µs). So in the end byte reads are the only way to go, aren't they? Anyone doing something different?
void writeTest()
{
uint8_t nBuf[32];
uint8_t *pBuf;
uint32_t nStartTime1, nStartTime2;
uint32_t nEndTime1, nEndTime2;
memset(nBuf, 0, 32);
eeprom_busy_wait();
nStartTime1= micros();
eeprom_write_block(nBuf, (void*)32, 32);
nEndTime1= micros() - nStartTime1;
eeprom_busy_wait();
nStartTime1= micros() - nStartTime1;
eeprom_busy_wait();
nStartTime2= micros();
pBuf= nBuf;
for(int nPos= 0; nPos < 32; nPos++)
_EEPUT(nPos, *pBuf++);
nEndTime2= micros() - nStartTime2;
eeprom_busy_wait();
nStartTime2= micros() - nStartTime2;
Serial.println(nEndTime1);
Serial.println(nStartTime1);
Serial.println(nEndTime2);
Serial.println(nStartTime2);
}
Write results are 103464, 106796, 103516 and 106852. A single byte takes approx. 3.5ms - somebody posted 3.5 to 8ms as normal. This brings me to the point where I should only write data that changed instead of my 32 byte blocks and one byte after another using eeprom_is_ready() and preventing blocking calls to let other tasks work while writing. Is there something I missed? Anyone using eeprom_update_byte() instead of the write? Because I just started using the Arduino I'm looking for any experiences concerning EEPROM usage. Thank you for any input.
Edit: no eeprom_update_byte() in Arduino 1.0 (see avr-libc: <avr/eeprom.h>: EEPROM handling). Seems we are using an older version.