EEPROM pages

I learned from another thread that the EEPROM is organised in pages of 4 bytes each, therefore for the Atmega 328 there are 256 pages of 4 bytes each for a total of 1024 bytes.

However when I write to the EEPROM I can only write a byte - does this mean that writing all the 4 bytes to the page will require writing the whole page 4 times ?

For example if I do "EEPROM.write(1,10);"

Does this instruction write the page 0, all 4 bytes, simply to modify the one byte?

This instruction modify single byte only and to write the whole page will require to use it 4 times.

Since the EEPROM has a use limit of 100,000 writes, does this mean that I can write 1024 bytes, 100,000 times each byte ?

Yes, this is the minimal durability according the data sheet. For that reason is better to use update as write (to read and compare if byte needs to be changed).

Personally, I'm using this class definition or let say lib modification:

class _EEPROM
{
public:
	_EEPROM();

/* functions & methods */
	uint8_t  read_byte   (uint16_t __address)
							{ return(eeprom_read_byte((const uint8_t *)__address));   }
	uint16_t read_word   (uint16_t __address)
							{ return(eeprom_read_word((const uint16_t *)__address));  }
	uint32_t read_dword  (uint16_t __address)
							{ return(eeprom_read_dword((const uint32_t *)__address)); }
	uint64_t read_qword  (uint16_t __address);

	void     read_block  (void *__data, uint16_t __address, size_t n)
							{ eeprom_read_block(__data, (const void *)__address, n);  }

	void     write_byte  (uint16_t __address, uint8_t value)
							{ eeprom_write_byte((uint8_t *)__address, value);         }
	void     write_word  (uint16_t __address, uint16_t value)
							{ eeprom_write_word((uint16_t *)__address, value);        }
	void     write_dword (uint16_t __address, uint32_t value)
							{ eeprom_write_dword((uint32_t *)__address, value);       }
	void     write_qword (uint16_t __address, uint64_t value)
							{ this->write_block((const void *)&value, __address, 8);  }
	void     write_block (const void *__data, uint16_t __address, size_t n)
							{ eeprom_write_block(__data, (void *)__address, n);       }

	void     update_byte (uint16_t __address, uint8_t value);

	void     update_word (uint16_t __address, uint16_t value)
							{ this->update_block((const void *)&value, __address, 2); }
	void     update_dword(uint16_t __address, uint32_t value)
							{ this->update_block((const void *)&value, __address, 4); }
	void     update_qword(uint16_t __address, uint64_t value)
							{ this->update_block((const void *)&value, __address, 8); }
	void     update_block(const void *__data, uint16_t __address, size_t n);
};
// --------------------------------------------------------------------------------------
//
// ****************
// *  read_qword  *
// ****************
//
// Read 8-byte unsigned integer from EEPROM address

uint64_t _EEPROM::read_qword(uint16_t __address)
{
uint64_t data;

	this->read_block(&data,__address, 8);
	return(data);
}

// --------------------------------------------------------------------------------------
//
// *****************
// *  update_byte  *
// *****************
//
// Update one byte to EEPROM address (write only if it is different)

void _EEPROM::update_byte(uint16_t __address, uint8_t value)
	{ if(this->read_byte(__address) != value) this->write_byte(__address, value); }

// --------------------------------------------------------------------------------------
//
// ******************
// *  update_block  *
// ******************
//
// Update n-byte unsigned integer to EEPROM address (write only if it is different)

void _EEPROM::update_block(const void *__data, uint16_t __address, size_t n)
{
uint8_t *_p_data = (uint8_t *)__data;

	while(n--) {
		if(this->read_byte(__address) != *_p_data) this->write_byte(__address, *_p_data);
		__address++;
		_p_data++;
	}
}

Thanks for the code samples.

I am still not sure I understand though.

Let me rephrase my question:

If I write to the EEPROM at location 0, will I also be modifying locations 1, 2 and 3, since the EEPROM is oragnised in pages of 4 bytes each?

If I write to the EEPROM at location 0, will I also be modifying locations 1, 2 and 3, since the EEPROM is oragnised in pages of 4 bytes each?

No, just the byte at address 0 will be modified.

The EPPROM can withstand 100,000 write cycles.

So I can write to location 0 100,000 times.
Then write to location 1, another 100,000 times.
Then write to location 2, another 100,000 times.

Every time I call "EEPROM.write(0,10)" I am ONLY affecting location 0, and nothing else within the EEPROM?

Sorry about all this, but in another thread another member said that the EEPROM is organised in pages of 4 bytes each, which I took it to mean that you always write to a page, ie all 4 bytes (or the hardware does this for you anyway).

I can not find any reference to a "page size" in the data sheet:

The ATmega48PA/88PA/168PA/328P contains 256/512/512/1K bytes of data EEPROM mem- ory. It is organized as a separate data space, in which single bytes can be read and written. The EEPROM has an endurance of at least 100,000 write/erase cycles.

Where did you find it mentioned?

@olf2012
ATmega328P datasheet, chapter 28.5 Page Size, chapter 28.7.5 Programming the EEPROM etc. And also each ATmega is the same, I think.

@akis_t
As I wrote above, each EEPROM cell can be erased/written 100k times at least.
Same data sheet, chapter 8.4 EEPROM Data Memory and 8.4.1 EEPROM Read/Write Access. There are also an examples in further reading.

The EEPROM page size is only relevant for serial / parallel (ISP) programming.

Access to the EEPROM from the running program is always byte-wise.

Every time I call "EEPROM.write(0,10)" I am ONLY affecting location 0, and nothing else within the EEPROM?

Correct.

As I wrote above, each EEPROM cell can be erased/written 100k times at least.

Exactly.

Thank you for your comments.