Reading/Writing USERROW in ATMega4809.

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

Data sheet claims USERROW is 64 bytes of special EEPROM that is not cleared by chip-erase.  My question is how do I get access to this section? 

 

I see USERROW is a pre-defined structure.  Do I assign this structure an EEMEM attribute, if so, how does it know to go to the USERROW section of the memory?  

 

Also, I would like to assign Contant/Variable names to elements in structure USREROW for use in my code, any thoughts on best way to accomplish this?

 

I presume I could create a USROW attribute linking the USERROW section in the linker settings for this purpose.  I hope that I am just missing an include file that might be doing this.

 

 

 

 

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

I don't have a real answer for this, but maybe you could investigate how it's done in xmega, since it has a similar "user signature row". It should work similar to the atmega4809, but better documented, since people have more experience with xmega.

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

bill@rnrtech.com wrote:
Data sheet claims USERROW is 64 bytes of special EEPROM that is not cleared by chip-erase. My question is how do I get access to this section?

The "family" guide says

5.6  User Row (USERROW)
In addition to the EEPROM, the ATmega3208/3209/4808/4809 has one extra page of EEPROM memory
that can be used for firmware settings, the User Row (USERROW). This memory supports single byte read and write as the normal EEPROM. The CPU can write and read this memory as normal EEPROM
and the UPDI can write and read it as a normal EEPROM memory if the part is unlocked. The User Row
can also be written by the UPDI when the part is locked. USERROW is not affected by a chip erase. The
USERROW can be used for final configuration without having programming or debugging capabilities
enabled.

 That would seem to answer most of your query.  At a glance, I'd then need to know the address. The first datasheet hit is in I/O space?

0x1300 USERROW User Row X X X

So indeed I'd need further direction, as you are requesting.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

Last Edited: Sun. Jul 1, 2018 - 02:04 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I could not find a library that smart access to USERROW.
However, if it is an extended EEPROM page, I thought that normal EEPROM access would be possible.

Since I do not have mega 4809, I tried it with tiny1616 which has a similar function.

The result was successfully read and written as follows.

 

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

Hi All,

 

Thank you for your feedback.  I am coding some ideas now, but my boards won't be here for another week or so, then I can test them, and see how things work.

 

Regards,

 

Bill

 

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

Hi All,

 

Well I got my boards.  I can read and write to the EEPROM just fine using the standard "eeprom_-----" calls.  I did find the "eeprom_busy_wait" throwing errors, so I did the direct tests as "kabasan" showed in his example.  

 

However, my attempts to read and write the USERROW section with the same calls does not seem to work.  I may just break down and do direct coding to see if that works, but I would prefer to be able to use the standard calls if possible.

 

Any thoughts?

 

Bill

 

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

You don't really need a function to read the eeprom or user row, like on the classic AVRs. In the new xtinies, the eeprom is memory mapped so you can just read it.

Regarding why the write is nor working, the low level write commands are the same for eeprom, user row or flash. So maybe the eeprom_write_byte function is doing some kind of check to make sure it can only write to the eeprom? You need to look at the source.

It makes sense to have a check, you could write to the flash by accident and that could be bad.

 

edit: wait, why would you not be able to write the user row using the exact same method as Kabasan? You just need to subtract 0x1400 (eeprom base address) to wherever you want to write, like Kabasan did. Probably you can even write the flash like this.

Last Edited: Wed. Jul 11, 2018 - 10:05 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi El Tangas,

 

I wondered about the direct read and write, which MicroChip says the chip is set up to do.  I can see where you can remap variables to EEPROM space with the EEMEM attribute, however, there does not seem to be a USERROW equivalent attribute, and it does map to 0x1300 vs the 0x1400 that EEPROM maps to.

 

I tried Kabasan's idea of the 0x1400 offset subtraction, which works quite well for EEPROM, however it does not seem to work for the USERROW like his did.  I will try a few more ideas tomorrow, including exploring the direct assignments.

 

Thanks for responding.

 

Regards,

 

Bill

 

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

 

eeprom_write_byte(adr, val)
eeprom_read_byte(adr)

In the eeprom function, "adr" is the address in the eeprom section, which usually starts at 0x00. The function adds 0x1400 to it and accesses the device.

Since the address of USERROW.USERROW0 is 0x1300, I reduced 0x1400 so that "adr" is 0xFF00.

 

 

 

Since the address of the EEMEM attribute variable is 0x00, you subtract 0x100 to access USERROW using it.

 

 

 

 

At the moment AVRLibC does not have a USERROW section and there is no dedicated header or function.
It will be prepared in the future, but until then you have to use the library you made.

Last Edited: Thu. Jul 12, 2018 - 08:55 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If you want to read the user row in a more simple way, you can use #define to create a pointer and use it as an array (this is a rather useless program, just an example):

 

#include <avr/io.h>

#define USER_ARRAY (&USERROW.USERROW0)

int main(void) {
	PORTA.DIRSET = 0xFF;
	for (int i = 0; i < sizeof(USERROW); i++) {
		PORTA.OUT = USER_ARRAY[i];
		
	}
}

 

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

Hi Guys,

 

Well I finally have it working to my satisfaction.   Thanks for all the hints, it did help resolve the issue.  What I ended up doing because it makes my code more readable is I declared all my EEPROM in a structure defined with a pointer type pointing to 0x0000, and I declared by USERROW as a structure defined with a pointer type pointing to 0xFF00.  Works great with the standard eeprom calls.

 

#define  EE     (*(Eeprom_t *) 0x0000)       // Eeprom_t is my EEPROM structure (map)

#define  UR     (*(Userrow_t *) 0xFF00)       // Userrow_t is my USERROW structure (map)

 

in my program, I can now just call the standard eeprom routines:

 

eeprom_update_byte((Uchar *)&UR.SN[0],nxt_byte);

 

eeprom_read_byte((Uchar *)&EE.INIT);

 

In actual fact, my application has many running interrupts which have to be paused while accessing the EEPROM, so I do not call the standard eeprom calls directly anyway, I have the standard calls wrapped in an interrupt disable/re-enable scheme.

 

Thanks again for all your help.

 

Regards,

Bil

 

 

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

Hi again,

 

One other thing, I did try writing to EEPROM with a direct assignment, but it did not work.  Of course, I am using the AVR-GCC compiler, which probably is not supporting that as yet.

 

Regards,

Bill

 

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

You can only read directly, not write (direct writes have no effect). To write you still need to use the proper functions.

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

Hi El Tangas,

 

Good to know, I did not try the reads, I was mostly concerned about writing to the USERROW.  Will try those soon.

 

Regards,

Bill

 

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

I don't get it. If a chip has 2K of EEPROM and 1K of "user row" and the user row is written, read and behaves just like the EEPROM why is this not simply described as 3K of EEPROM ??

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

The user row has the special property of not being erased with a "erase chip" command, so it's different from the rest of the eeprom. I suppose it's meant to store more permanent data.

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

But EESAVE achieves the same? Or maybe these new ones don't have EESAVE? Or is this so you can have some bits that are saved and some that are wiped?

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

Hi Clawson,

 

In my case, the USERROW data not being erased is a good thing.  Once the firmware is loaded into the application, the only access to the CPU is through our bootloader and application commands, the EESAVE is meaningless.  I can store critical info such as serial numbers, manufactured date, etc. in the USERROW section and not worry about it being cleared.  Other less critical stuff like current date, operational pointers , etc. can be quickly erased if a machine needs to be restored to "factory default" settings.  Prior to this, I had to have specific routines to do this byte by byte.

 

Bill

 

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

bill@rnrtech.com wrote:
I can store critical info such as serial numbers, manufactured date, etc. in the USERROW section and not worry about it being cleared.
But that's equally true of the "normal" EEPROM isn't it? Once the bootloader is in place you'll never be doing a "Chip Erase" anyway (with or without EESAVE)

Last Edited: Fri. Jul 13, 2018 - 04:08 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi, true, I would not be doing a "Chip Erase", however, the chips with USERROW have a separate EEPROM erase capability which erases the complete EEPROM less the USERROW, which can be activated from firmware.   It is just a convenience, my old way of doing this byte by byte works good enough for our products.  I am just considering taking advantage of this for new designs, and I "needed" the extra EEPROM anyway.