xmega E5 LOAD_EEPROM_BUFFER command missing

Go To Last Post
13 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi All,

I'm trying to compile the xmega bootloader using an ATxmega32E5, but it's failing compilation because the NVM_CMD_LOAD_EEPROM_BUFFER_gc #define is not present in the iox32e5.h file.

Looking further into this it seems the NVM command LOAD_EEPROM_BUFFER (0x33) is missing from the E5 datasheet in the 'EEPROM self programming' section. However it is present in the 'NVM commands available for external programming' section.

Is this a silicon bug, or document error? How is it possible to use the NVM to load the EEPROM buffer in E5 devices? (The description of how to do this is different in the E5 and other xmega families, the E5 states "To load EEPROM page buffer, direct or indirect store instruction must be used and repeated until the arbitrary number of bytes are loaded into the page buffer" but I cant see how can this be done without the LOAD_EEPROM_BUFFER command).

Any help much appreciated.
Mark.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

For Xmega E5, memory mapping for EEPROM is always turned on. To fill the EEPROM page buffer you should write data to the appropriate location in the RAM address space instead of use the LOAD_EEPROM_BUFFER command. After that you call the WRITE_EEPROM_PAGE or the ERASE_WRITE_EEPROM_PAGE command as usual.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks for the reply. I'm a little confused though, are you saying the EEPROM buffer (not the actual EEPROM itself) is memory mapped from 0x1000 upwards?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Of course, EEPROM buffer is used to read and write EEPROM data.
When you read data from memory mapped EEPROM, you can treat it as whole EEPROM itself available, because NVM does everything for you. When you want to read 0x35th byte of the EEPROM, you read data from RAM location 0x1035.
When you write data to the EEPROM buffer using EEPROM memory mapping, only five least significant bits of address are used, as the buffer size is 32 bytes in XmegaE5. You can use only this five bits to address data in the buffer, but you can also use full address. For example, when you want to write one byte to the 0x35th byte of EEPROM, you can write to the RAM location 0x1035 (0x1000 + full offset in EEPROM) or 0x1015 (0x1000 + five least significant bytes of offset in EEPROM). In both cases you need to write correct values to the NVM.ADDR0, NVM.ADDR1 and NVM.ADDR2 registers before using write page command.

In my opinion use of the full address when writing to the EEPROM is more convenient, as you use full address when you read data from EEPROM.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

OK, I think I've got it!
Just so that I'm clear:

If I want to read the 320th byte in EEPROM I can read location 0x1140, the results from that location will be put in the buffer. Since only the lower 5 bits are relevant I can make NVM.ADDR0 == 0x40 (others don't care) then I can read the correct data from the buffer.

If I want to write to the 320th location I can write to 0x1140 which will write to the buffer with only the lower 5 bits used, but to write to the correct location in EEPROM I have to set all the NVM.ADDR[2-0] registers accordingly and use a write page command.

Presumably I also have to clear the buffer before writing to clear the tags so that only new tagged data is actually written.

Is that correct?
Thanks!
Mark.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

When you read EEPROM, you don't need set the NVM.ADDR registers. Just read data from location 0x1140. That's all. These five bits are important only when you want to write EEPROM.

When you write EEPROM - everything is as you have written. Of course, page buffer has to be cleared before new data can be written to it, but this is often done automatically - see ATXmega E manual, page 405.

Remember, that when you write EEPROM you can't do anything with NVM until the NVM.STATUS register indicates that write operation is finished. This applies also to read operation.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I thought you had to set NVM_CTRLB |= (1<<3) to read the eeprom at 0x1000.

I read the eeprom as an array of structs at 0x1000, then to write it use eeprom_update_byte and the like, remembering to remove the 0x1000 from the address.

The largest known prime number: 282589933-1

It's easy to stop breaking the 10th commandment! Break the 8th instead. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Torby,

That's not true in Xmega E5. There is nothing at bit 3 in NVM_CTRLB, this bit is 'reserved' according to the Xmega E manual. EEPROM memory mapping is always turned on.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks for your help Marek, I've successfully implemented this now (with some help too from the AVR1315 app note) and it works fine, with avrdude latest version. Unfortunately I can't post the actual fix due to IP restrictions that I can do nothing about :(

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

MarekJ71 wrote:
Torby,

That's not true in Xmega E5. There is nothing at bit 3 in NVM_CTRLB, this bit is 'reserved' according to the Xmega E manual. EEPROM memory mapping is always turned on.

Well, I'll be. It's easier than I expected.

The largest known prime number: 282589933-1

It's easy to stop breaking the 10th commandment! Break the 8th instead. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I've read this branch, and it is not clear for me about writing to eeprom.

in this function where i can put the value?

void EEPROM_WriteByte(uint32_t address, uint8_t value)
{
	/*  Flush buffer to make sure no unintentional data is written and load
	 *  the "Page Load" command into the command register.
	 */
//	EEPROM_DisableMapping();
	EEPROM_FlushBuffer();
//	NVM.CMD = NVM_CMD_LOAD_EEPROM_BUFFER_gc;

	/* Set address to write to. */
	NVM.ADDR0 = address & 0xFF;
	NVM.ADDR1 = (address >> 8) & 0x1F;
	NVM.ADDR2 = 0x00;

	/* Load data to write, which triggers the loading of EEPROM page buffer. */
	NVM.DATA0 = value;

	/*  Issue EEPROM Atomic Write (Erase&Write) command. Load command, write
	 *  the protection signature and execute command.
	 */
	NVM.CMD = NVM_CMD_ERASE_WRITE_EEPROM_PAGE_gc;
	NVM_EXEC();
//	EEPROM_EnableMapping();
}

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I've found that function .. thanks :D

void nvm_eeprom_write_byte(eeprom_addr_t address, uint8_t value)
{
	uint8_t old_cmd;

	Assert(address <= EEPROM_SIZE);
	/*  Flush buffer to make sure no unintentional data is written and load
	 *  the "Page Load" command into the command register.
	 */
	old_cmd = NVM.CMD;
	nvm_eeprom_flush_buffer();
	// Wait until NVM is ready
	nvm_wait_until_ready();
	nvm_eeprom_load_byte_to_buffer(address, value);

	// Set address to write to
	NVM.ADDR2 = 0x00;
	NVM.ADDR1 = (address >> 8) & 0xFF;
	NVM.ADDR0 = address & 0xFF;

	/*  Issue EEPROM Atomic Write (Erase&Write) command. Load command, write
	 *  the protection signature and execute command.
	 */
	NVM.CMD = NVM_CMD_ERASE_WRITE_EEPROM_PAGE_gc;
	nvm_exec();
	NVM.CMD = old_cmd;
}

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Glad to be of service

The largest known prime number: 282589933-1

It's easy to stop breaking the 10th commandment! Break the 8th instead.