Using XMEGA128A1U EEPROM with Assembler

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

Preface: I have already searched the forums and the web, and haven't found anything that seems to directly apply . . . I have reviewed the device datasheet, user manual, and the AVR1315 application note several times, and still haven't gotten anything truly useful out of any of it.

 

I am writing assembler routines that will copy 32 bytes of data from a RAM image buffer to a selected page in EEPROM.  The last two bytes are the CRC-16 value for data verification.

 

Q: What is the exact procedure for loading the EEPROM page buffer with 32 bytes of data?  Do I need to use the CCP register for every write?  Some suggestions would be very welcome.  Thank you!

 

Altazi

 

 

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

The following is the eeprom write byte function for the avr-gcc C compiler. But you could use the same technique in stand-alone assembler (syntax may need to change a bit for AVRASM2). Note that there are effectively two versions in this file. One for Xmega and one for tiny/mega - you want the Xmega version obviously:

 

http://svn.savannah.gnu.org/viewvc/avr-libc/trunk/avr-libc/libc/misc/eewr_byte.S?revision=2486&view=markup

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

Thanks for the response.  Mostly helpful, but I am still unclear on if I need to do this entire sequence to write every byte into the page buffer.  Ideally, I would like to enable 'EEPROM buffer load' and then just go into a simple data transfer loop - without having to go through all of the CCP and the rest.  Once all of the bytes have been transferred, THEN I would issue the erase & write command.

 

Am I completely off base here?  I haven't seen any discussions, flowcharts, or examples similar to what I wish to do.  Do I need to do all of that which is shown for every byte I need to transfer?

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

There is this, from application note AVR1315 - Accessing the XMEGA EEPROM:

 

" 3.2 Memory-mapped Access

Memory-mapped access means that EEPROM read and page buffer load operations are mapped into data space. This means that EEPROM data can be read simply by reading from a location in data memory. For the XMEGA A1 family, memory-mapped EEPROM starts at address 0x1000. Page buffer loading is also simply a matter of writing to data memory. However, flushing the buffer and erasing and writing pages must still be done through the NVM controller as for I/O-mapped access. Also, the NVM controller must not be busy when accessing EEPROM."

 

I have mapped the EEPROM into the data memory space by setting NVM_CTRLB = $08, and can read the values stored in EEPROM ($FF, all locations erased).  When I attempt to write data to a memory-mapped EEPROM location ($1000) and read the data back, the location still reads as $FF.

 

What should be reasonably simple appears to be miserably difficult.  What am I missing?

 

Thanks in advance.

 

Altazi

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

Follow my previous link then go "back up a level" and you will get to the list of source files for EEPROM in avr-gcc. The one I linked to is the ultimate eeprom_write_byte (all other writing is based around this being called one or more times - so, for example when eeprom_write_dword is used it is called 4 times etc etc.

 

In the same code is eerd_byte.S (or some similar name) - that is the code the C compiler uses for reading one byte.

 

EDIT: so this is the read:  http://svn.savannah.gnu.org/viewvc/avr-libc/trunk/avr-libc/libc/misc/eerd_byte.S?revision=2486&view=markup

Last Edited: Tue. Feb 25, 2020 - 09:27 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Memory-mapped mode, read-only convenient.
You write in this mode not in eeprom, but in page buffer.
To write a page buffer to eeprom, you need to perform the same actions as the usual page record.

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

agentXMEGA wrote:

Memory-mapped mode, read-only convenient.
You write in this mode not in eeprom, but in page buffer.
To write a page buffer to eeprom, you need to perform the same actions as the usual page record.

Thanks.  I understand that to write the data in the page buffer to EEPROM I must use the NVM commands.  I can successfully read from the EEPROM when it is mapped into the memory space, but I seem to be unable to write the data to the page buffer by writing to the memory-mapped EEPROM space.  I write the data to location $1000, but when I read it back, I get $FF (erased EEPROM value).  That is what I do not understand.

 

[EDIT: Is there a way to read the data back from the page buffer?]

Last Edited: Tue. Feb 25, 2020 - 05:27 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

OK, I got the page write to work.  How painful.  However, I cannot seem to get the seemingly simple 'erase EEPROM' command to work - even though it is a single command with no parameters, and I am doing the change-protected thing.  Any suggestions would be welcome.

 

Thanks to any hardy souls who dare tread on this subject.

 

Altazi

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

Why would one ever need "erase EEPROM"? How would it ever be any different than write(0xFF)?

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

Hello clawson (looked like 'dawson' to my tired eyes . . .)

 

I am writing a series of test routines to support my intent of having a 32-byte RAM block that gets loaded & stored to successive EEPROM pages.  The code uses the RAM data, but then stores it as a block in an EEPROM page.  When something in the RAM block changes, the existing EEPROM block is 'decommisioned' and the data is stored in the next EEPROM page.  A CRC-16 is calculated and stored in the last two bytes of the page.

 

Routines that work fine:

- Calculate CRC-16 on first 30 bytes in 32-byte RAM image block

- Calculate CRC-16 on first 30 bytes in selected EEPROM page

- Load default image from flash ROM into RAM

- Load RAM from selected EEPROM page & check CRC

 

Routine that doesn't work:

- Erase all EEPROM

 

This is a command in the NVM controller, so I do not understand why it isn't working.

; Make sure NVM controller is ready

HC_EA_10:
    LDS     R16,NVM_STATUS   ; get NVM controller status
    ANDI    R16,$80          ; check for busy condition
    BRNE    HC_EA_10         ; loop until ready

; Erase EEPROM

    LDI     R16,$30          ; NVM command 'Erase EEPROM'
    STS     NVM_CMD,R16      ; set NVM command = erase page buffer

; NVM command execution is change-protected

    LDI     R16,$01          ; set CMDEX = 1
    LDI     R17,$D8          ; signature value to unlock I/O register access
    STS     CPU_CCP,R17      ; enable protected register access
    STS     NVM_CTRLA,R16    ; execute NVM command

HC_EA_15:
    LDS     R16,NVM_STATUS   ; get NVM controller status
    ANDI    R16,$80          ; check for busy condition
    BRNE    HC_EA_15         ; loop until ready

; completed

Sigh . . .

 

Thanks.

 

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

In a similar vein, the 'Erase Page' command doesn't seem to work, either . . .  WTH???  I'm getting a bit irked.  This  EEPROM stuff seems to troublesome.

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

Altazi wrote:

Routine that doesn't work:

- Erase all EEPROM

Assuming you do have a working "write byte to EEPROM" then how is an "erase" actually any different from?:

for (int i = 0; i < EEEND; i++) {
    eeprom_write(i, 0xFF);
}

But anyway you don't actually need a whole "erase" do you anyway? You say you have 32 byte pages. Each just needs one bit to say "alive" or "dead". When writing a new one you just scan along your blocks until you find the first one where the alive/dead bit is aset to "dead" then you dump 32 bytes (and a new "alive" flag) on top of that (maybe also now going back to the previously "alive" and switching it to "dead" too).

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

MYSTERY SOLVED.  clawson, you hit on it when you asked what was different between the successful routine that did the erase & write and the failed routine that was supposed to only do the erase?  It appears that the page buffer must be written prior to executing the erase command, even though the data is ignored.  Go figure . . .

 

I am not certain of the impact on the EEPROM cells if you write an $FF instead of just erasing to $FF.  Is the longevity degraded, even though you are writing ones to the bits?

 

The documentation is TERRIBLE.  What I was trying to do shouldn't have been so difficult.  And I was an FAE . . .God help you if you don't want to use some library . . .

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

The nature of flash is that you can easily make 1 to 0 bit transitions but the tricky bit is getting bits back to 1 as this involves a high voltage pump that causes oxidation of the gate isolation. So the memory "wears out" whenever there is even 1 bit in a byte that needs to get back to 1 from 0 because the entire byte has to be "erased" to get all the bits back to 1 (so 0xFF) then the easy 1 to 0 transitions can be made from there.

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

clawson wrote:

The nature of flash is that you can easily make 1 to 0 bit transitions but the tricky bit is getting bits back to 1 as this involves a high voltage pump that causes oxidation of the gate isolation. So the memory "wears out" whenever there is even 1 bit in a byte that needs to get back to 1 from 0 because the entire byte has to be "erased" to get all the bits back to 1 (so 0xFF) then the easy 1 to 0 transitions can be made from there.

 

 Nothing explains why the page buffer needs to be written in order to erase the page.  The data values don't even matter - just that the buffer was written.  Any thoughts on this?

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

Letting the smoke out since 1978

 

 

 

 

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

Thanks, Dan.  This explains what I saw . . . but I still think it's a stupid way to do things.  A 'PAGE ERASE" command should do just that, without any further qualifications.  Ditto for 'EEPROM ERASE'.  <sigh>

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

I confirmed that the 'ERASE_EEPROM' does indeed erase the entire EEPROM array.  But, of course, you have to write to all locations in the EEPROM page buffer to 'tag' them so the NVM controller will actually do the erase.  The page buffer is 32 bytes in size, but that apparently is enough to convince the NVM controller to erase all of the EEPROM when the ERASE_EEPROM command ($30) is executed.