Author Topic: XMEGA EEPROM Read and Write  (Read 23727 times)

0 Members and 1 Guest are viewing this topic.

Offline David_AVDTopic starter

  • Super Contributor
  • ***
  • Posts: 2806
  • Country: au
XMEGA EEPROM Read and Write
« on: September 15, 2013, 05:17:48 am »
I've read and Googled, but the answer still eludes me.  Using C (Atmel Studio) with an XMEGA, I'm wanting simply read and write the EEPROM using constant addresses.

The C function eeprom_write_byte takes two parameters; the address to write and the value to write at that address.

But the address parameter is of type uint8_t, so how can it work with more than 256 EE locations?  I'm obviously missing something here.   :-[
 

Online edavid

  • Super Contributor
  • ***
  • Posts: 3381
  • Country: us
Re: XMEGA EEPROM Read and Write
« Reply #1 on: September 15, 2013, 05:39:54 am »
The address parameter is a pointer to a uint8_t.
 

Offline David_AVDTopic starter

  • Super Contributor
  • ***
  • Posts: 2806
  • Country: au
Re: XMEGA EEPROM Read and Write
« Reply #2 on: September 15, 2013, 05:46:38 am »
OK, but what if I want to write to a specific EE address (such as 0x140), not at an address derived from another variable?
 

Offline David_AVDTopic starter

  • Super Contributor
  • ***
  • Posts: 2806
  • Country: au
Re: XMEGA EEPROM Read and Write
« Reply #3 on: September 15, 2013, 06:01:59 am »
Also, since the pointer is to an uint8_t type, doesn't that imply that the value pointed to can only be in the 0.255 value range?
 

Offline andete

  • Contributor
  • Posts: 19
  • Country: be
  • famous for its killer edible poets
Re: XMEGA EEPROM Read and Write
« Reply #4 on: September 15, 2013, 06:06:42 am »
you cast your address to a pointer:

something like this:

int address = 0x140;
uint8_t value = 32;

eeprom_write_byte((uint8_t *) address, value);
 

Offline David_AVDTopic starter

  • Super Contributor
  • ***
  • Posts: 2806
  • Country: au
Re: XMEGA EEPROM Read and Write
« Reply #5 on: September 15, 2013, 06:15:21 am »
Sounds like I will need to either;

1) Wrap the ee_read_byte and ee_write_byte functions so I can easily call them with with literal addresses

2) Ditch the ee library and write my own functions
 

Offline David_AVDTopic starter

  • Super Contributor
  • ***
  • Posts: 2806
  • Country: au
Re: XMEGA EEPROM Read and Write
« Reply #6 on: September 15, 2013, 06:33:17 am »
So you're saying that the data type that the pointer points to is not limited to an uint8_t type?

Also, is it the address of the pointer that's limited to the 0.255 range?
 

Offline David_AVDTopic starter

  • Super Contributor
  • ***
  • Posts: 2806
  • Country: au
Re: XMEGA EEPROM Read and Write
« Reply #7 on: September 15, 2013, 08:10:27 am »
OK, this is what I ended up with:

Code: [Select]
struct sSettings
{
uint8_t PresetNo;
        // More settings to go here
};

struct sSettings Settings;

Code: [Select]
void EE_Load_Settings(void)
{
_Bool UpdateRequired = 0;
uint16_t Address = 0x200;
// Read the whole structure into RAM
eeprom_read_block((void*)&Settings,(void*) Address,sizeof(Settings));
// Check validity of Preset No
if((Settings.PresetNo > 9))
{
Settings.PresetNo = 0;
UpdateRequired = 1;
}
// Check to see if we need to write any fixes back out
if(UpdateRequired==1)
EE_Save_Settings();
}

void EE_Save_Settings(void)
{
uint16_t Address = 0x200;
eeprom_update_block((const void*)&Settings,(void*) Address,sizeof(Settings));
}
 

Offline David_AVDTopic starter

  • Super Contributor
  • ***
  • Posts: 2806
  • Country: au
Re: XMEGA EEPROM Read and Write
« Reply #8 on: September 15, 2013, 09:05:02 am »
I understand how pointers work, but my earlier understanding was that the pointer was to a 8 bit variable.  This means that the value returned by the pointer could only be an 8 bit value.

Then it seemed that the pointer itself was 8 bits in size, which would limit its addressing range.

The fact that the function has byte in its name only means that the value read from / written to the selected EE location is an 8 bit value.  That makes perfect sense.  The confusion for me was how the function could address more than 256 bytes of EE via a pointer that seemed to be limited.

I did look at the ASF and to be honest didn't like the way it hid so much.  Coming from an assembler code background I like seeing the nuts and bolts of the code.
 

Online bingo600

  • Super Contributor
  • ***
  • Posts: 1987
  • Country: dk
Re: XMEGA EEPROM Read and Write
« Reply #9 on: September 15, 2013, 09:16:51 am »
But you said it your self ....
The "Object the pointer points at" is uint8_t or "8-bit" ...
The pointer (aka address/offset/index) is not , so the pointer could easily be a 16-bit value (index) , "pointing to/on a 8-bit value".


Code: [Select]
uint8_t *pointer;

pointer = 0x300;  //Pointer points at the value @ 0x300 (This one just loads the pointer address)
*pointer = 0x100 //Sets the (uint8_t) value @ pointer to 0x100; (This one changes the value that pointer points at)

/Bingo
 

Offline Psi

  • Super Contributor
  • ***
  • Posts: 9925
  • Country: nz
Re: XMEGA EEPROM Read and Write
« Reply #10 on: September 15, 2013, 09:28:53 am »
I think you're missing the key thing about declaring pointers and what is actually happening.

// here you're declaring a simple variable foo and the uint8_t means foo can store 8bits;
uint8_t Foo;

// here the * means this is a pointer called Foo.  (keep in mind that the uint8_t here means something quite different)
uint8_t *Foo

Foo can be refereed to in two ways. 
Foo = The memory address number
*Foo = The contents of that memory address (that's where the type comes in).

The pointer variable Foo is always whatever size is needed on your CPU to store an address in memory. I think they're 16bit on AVR but don't quote me. So it doesn't matter if you go "uint16_t *Foo;"  or "uint64_t *Foo;"  Foo is always the same length variable because it only ever needs to contain a memory address that points to the start of something.

(I'm probably going to explain this next bit a little wrong from a low level perspective but it may help explain the concept....)

You can think of the type part (uint8_t in this example) as a message to the C compiler to expect an 8bit number at the Foo memory address. 

This becomes important when you think about larger variables.
Say you want a pointer to a uint32_t which is of course 4 bytes long.
uint32_t *Bar

Bar is only a single 16bit memory address. It points to the memory for the first byte of this 4 byte number.
The type (uint32_t) helps the compiler out by letting it know what you're going to be doing with *Bar.

If you increment Bar by 1 the address is incremented by 4.
Bar++;    //jump forward 4 bytes because bar is uint32_t and that is a 4 byte type.
You'd be stupid to do that here since that's unknown memory but if you had an array of uint32_t you could correctly step through memory in increments of 4.

« Last Edit: September 16, 2013, 10:13:45 am by Psi »
Greek letter 'Psi' (not Pounds per Square Inch)
 

Online bingo600

  • Super Contributor
  • ***
  • Posts: 1987
  • Country: dk
Re: XMEGA EEPROM Read and Write
« Reply #11 on: September 15, 2013, 09:29:26 am »

Hmmm ... PSI beat me to it :-)



But you said it your self ....
The "Object the pointer points at" is uint8_t or "8-bit" ...
The pointer (aka address/offset/index) is not , so the pointer could easily be a 16-bit value (index) , "pointing to/on a 8-bit value".


Code: [Select]
uint8_t *pointer;

pointer = 0x300;  //Pointer points at the value @ 0x300 (This one just loads the pointer address)
*pointer = 0x100 //Sets the (uint8_t) value @ pointer to 0x100; (This one changes the value that pointer points at)

/Bingo
Code: [Select]
In pseudo asm ....
X= 16bit index reg
A= 8bit accum.

LD    X,#0x300   //Init pointer
LD    A,#0x100
ST    [X],A
The confusion comes from us old asm guyzz in why should the compiler know what the pointer points at .......

But that makes sense here .....


Code: [Select]
uint8_t *pointer;

pointer = 0x300;  //Pointer points at the value @ 0x300 (This one just loads the pointer address)
*pointer++ = 0x100 //Sets the (uint8_t) value @ pointer to 0x100; (This one changes the value that pointer points at , [b]and increments the pointer to point at the next element[/b])


Code: [Select]
LD    X,#0x300   //Init pointer
LD    A,#0x100   //
ST    [X],A          //Store A , where X points
INC   X               // Point @ next element.

But what of the element pointed at  was a 16bit ??

Then the compiler had to do
INC   X
INC   X

Or

ADD  X,#2


In "C" Notation ....

ADD   X,"sizeof element pointed at".

That's why you have to tell the C compiler what the pointer is pointing at

/Bingo
 

Online bingo600

  • Super Contributor
  • ***
  • Posts: 1987
  • Country: dk
Re: XMEGA EEPROM Read and Write
« Reply #12 on: September 15, 2013, 09:40:01 am »

If you use the * symbol when using bar in code it means you want to work on the actual memory address number instead of what it points to.
so
*Bar = *Bar + 1  would make Bar point to the next memory location (2nd byte of the 4 byte number.)

Naahhh ....

The above would actually increment the *Bar memory location by 1 , not change the pointer (Bar) it self  ;)

/Bingo
 

Offline Psi

  • Super Contributor
  • ***
  • Posts: 9925
  • Country: nz
Re: XMEGA EEPROM Read and Write
« Reply #13 on: September 15, 2013, 09:44:44 am »
Isn't that what i said?

Maybe i should reword it from "next memory location"  to "next location in memory" ?

(You can see why people say pointers are confusing)
Greek letter 'Psi' (not Pounds per Square Inch)
 

Online bingo600

  • Super Contributor
  • ***
  • Posts: 1987
  • Country: dk
Re: XMEGA EEPROM Read and Write
« Reply #14 on: September 15, 2013, 10:01:17 am »
Isn't that what i said?

Maybe i should reword it from "next memory location"  to "next location in memory" ?

(You can see why people say pointers are confusing)

But it doesn't do anything "next" it just increments "location"

*Bar = *Bar + 1  "==>" (*Bar)++  not Bar++

Quote
(You can see why people say pointers are confusing)
Yuppp , especially for asm programmers that doesn't expect the C-Compiler to handle the pointer arithmatik automatically ... Witch is excactly why you need to tell the compiler what the objecttype is that the pointer is pointing at.

/Bingo
« Last Edit: September 15, 2013, 10:03:45 am by bingo600 »
 

Offline Psi

  • Super Contributor
  • ***
  • Posts: 9925
  • Country: nz
Re: XMEGA EEPROM Read and Write
« Reply #15 on: September 15, 2013, 10:02:41 am »
Yeah, "Next" was a bad word to use.

It could mean next <type> or next number
« Last Edit: September 15, 2013, 10:11:42 am by Psi »
Greek letter 'Psi' (not Pounds per Square Inch)
 

Offline baljemmett

  • Supporter
  • ****
  • Posts: 665
  • Country: gb
Re: XMEGA EEPROM Read and Write
« Reply #16 on: September 15, 2013, 11:42:18 am »
Sounds like I will need to either;

1) Wrap the ee_read_byte and ee_write_byte functions so I can easily call them with with literal addresses

2) Ditch the ee library and write my own functions

You might want to take a quick read of http://www.avrfreaks.net/?name=PNphpBB2&file=viewtopic&t=38417 which shows some examples, including how you can use literal addresses by casting the constant as appropriate.
 

Offline David_AVDTopic starter

  • Super Contributor
  • ***
  • Posts: 2806
  • Country: au
Re: XMEGA EEPROM Read and Write
« Reply #17 on: September 15, 2013, 11:49:25 am »
For EE access, there is an address (where the EE data is held) and the data (the data at that EE address).

In the world of asm, you'd set the address high and low bytes, then do the read or write.

My confusion about the pointer is in relation the the function:

Code: [Select]
eeprom_write_byte((uint8_t *) address, value);
To me, the uint8_t could mean one of two things;
1) The address pointer is 8 bits in width, but that would mean you could only have 256 pointers (assuming they pointed to 8-bit data types)
2) The value returned by the address pointer is 8 bits in width, but that would mean the effective EE address could only access EE locations 0.255

Obviously neither of those is true.  The value ultimately used as the EE address is actually 16 bits.

I'm sure it's just a case of moving from asm (and Delphi on PC) to C being in some ways be worse than starting from scratch.  Some things in C seem so bat shit crazy compared to other languages.   :D
 

Offline David_AVDTopic starter

  • Super Contributor
  • ***
  • Posts: 2806
  • Country: au
Re: XMEGA EEPROM Read and Write
« Reply #18 on: September 15, 2013, 11:51:38 am »
You might want to take a quick read of http://www.avrfreaks.net/?name=PNphpBB2&file=viewtopic&t=38417 which shows some examples, including how you can use literal addresses by casting the constant as appropriate.

I saw those examples, but they have one glaring problem;  they only deal with literals that are within the 8-bit data size.  For someone new to C, examples showing larger address ranges would be better.
 

Offline baljemmett

  • Supporter
  • ****
  • Posts: 665
  • Country: gb
Re: XMEGA EEPROM Read and Write
« Reply #19 on: September 15, 2013, 12:26:00 pm »
To me, the uint8_t could mean one of two things;
1) The address pointer is 8 bits in width, but that would mean you could only have 256 pointers (assuming they pointed to 8-bit data types)
2) The value returned by the address pointer is 8 bits in width, but that would mean the effective EE address could only access EE locations 0.255

Obviously neither of those is true.  The value ultimately used as the EE address is actually 16 bits.
No, you're right with the second one -- the value the pointer points to is indeed 8 bits in width.  However, you're making the mistake (quite reasonably) of thinking that the value it points to is going to be used as the EE address -- it isn't.  The actual value of the pointer, i.e. the address it represents, is what's going to be used as the EE address -- so it's actually a pointer into the EEPROM address space (literally a pointer to the 8-bit value in the EEPROM), with 0 being the first byte of EEPROM, etc.

I'm sure it's just a case of moving from asm (and Delphi on PC) to C being in some ways be worse than starting from scratch.  Some things in C seem so bat shit crazy compared to other languages.   :D
To be honest, even as a seasoned C programmer I think your confusion is understandable -- I would usually expect the 'address' parameter of an EEPROM read/write routine to be an integral type, not a pointer to an object of the transaction size.  However, from a quick glance at some of the library documentation (not having used any AVR chips myself), I get the impression that the EEPROM is actually mapped into the processor's address space, so using pointers may make some sense.

I still think it's a trifle weird, though, as surely you can't actually use them as pointers (otherwise why do you need the library functions?)  It does let you do things like struct { uint8_t foo; unit16_t bar; } *p = 0x42; eeprom_write_word(&p->bar, 0x4242); though, I suppose.

I saw those examples, but they have one glaring problem;  they only deal with literals that are within the 8-bit data size.  For someone new to C, examples showing larger address ranges would be better.
Yes, there is that -- I don't know how large the EEPROM is on 'common' AVRs.  Some of the popular PICs that people choose to get started with have <= 256 bytes, for instance, so perhaps people writing tutorial material stick to smaller addresses to make sure it all fits -- or they just pick numbers off the top of their head ;)
 

Online madires

  • Super Contributor
  • ***
  • Posts: 7749
  • Country: de
  • A qualified hobbyist ;)
Re: XMEGA EEPROM Read and Write
« Reply #20 on: September 15, 2013, 12:33:05 pm »

My confusion about the pointer is in relation the the function:

Code: [Select]
eeprom_write_byte((uint8_t *) address, value);

If you like to write a 8 bit value to 0x0140:

Code: [Select]
eeprom_write_byte((uint8_t *) 0x0140, value);
The "(uint8_t *)" is necessary to keep the compiler happy. And it's a good coding style because it reminds the reader what the function expects for input.
 

Offline Psi

  • Super Contributor
  • ***
  • Posts: 9925
  • Country: nz
Re: XMEGA EEPROM Read and Write
« Reply #21 on: September 15, 2013, 01:09:17 pm »
At it's core a pointer is just a number.

Usually the number is used to interact with ram but in this case the function uses it to point to an eeprom location.
I think the function does it that way because eeprom is kinda like ram.

Basically the function just want a number that means the eeprom location from 0 to 2048 or however much eeprom you have.
But it wants this number in the form of a pointer because that is how the person who wrote the function decide to do it.

The fact that the pointer is of type uint8_t is only because he had to tell the compiler something about this pointer as it's a function parameter (or he could have used a void pointer (pointer to unknown type)).
It makes more sense to call it uint8_t because the function is about writing a byte.
It doesn't play a roll in whats going on other than that.
« Last Edit: March 10, 2014, 10:30:35 pm by Psi »
Greek letter 'Psi' (not Pounds per Square Inch)
 

Offline dannyf

  • Super Contributor
  • ***
  • Posts: 8221
  • Country: 00
Re: XMEGA EEPROM Read and Write
« Reply #22 on: September 15, 2013, 01:10:19 pm »
The key to understand this all is to recognize that the address pointer, (uint8_t *), is a multi-byte type, :)

After that, everything is clear.
================================
https://dannyelectronics.wordpress.com/
 

Offline David_AVDTopic starter

  • Super Contributor
  • ***
  • Posts: 2806
  • Country: au
Re: XMEGA EEPROM Read and Write
« Reply #23 on: September 15, 2013, 09:38:31 pm »
To me, the uint8_t could mean one of two things;
1) The address pointer is 8 bits in width, but that would mean you could only have 256 pointers (assuming they pointed to 8-bit data types)
2) The value returned by the address pointer is 8 bits in width, but that would mean the effective EE address could only access EE locations 0.255

Obviously neither of those is true.  The value ultimately used as the EE address is actually 16 bits.
No, you're right with the second one -- the value the pointer points to is indeed 8 bits in width.  However, you're making the mistake (quite reasonably) of thinking that the value it points to is going to be used as the EE address -- it isn't.  The actual value of the pointer, i.e. the address it represents, is what's going to be used as the EE address -- so it's actually a pointer into the EEPROM address space (literally a pointer to the 8-bit value in the EEPROM), with 0 being the first byte of EEPROM, etc.

According to the help docs, the EE address value (0x00..0x7FF) is shifted up into the 0x2000..0x27FF address space by the EE library.  I understand that.  The pointer itself and the value pointed to must both be 16-bit values though as otherwise you could never have enough range to access all of the EE space.

Anyway, I *think* I have a handle on it now.  I'll have to read up and see how to read back the EE data into Atmel Studio so I can confirm that the data is being stored where I want.

Some of you are probably wondering why I care exactly where the data is stored in the EE.  I need to allocate the areas used for the settings in such a way that they will persist during a firmware upgrade.  There will also be other generic read/write EE routines that are used for configuration via a PC application, so I need to know that existing data addresses won't change if more are added with later firmware revisions.

There are 10 preset modes of operation and I am leaving space so the structure for each mode (currently 22 bytes) can grow in the future to a max of 32 bytes.  There is 2K of EE space on the chip I'm using so I may space them out even more (64 bytes for example) to be sure.

As usual, I'd like to thank you guys for being patient with me and taking the time to answer my questions.   :-+
 

Offline Psi

  • Super Contributor
  • ***
  • Posts: 9925
  • Country: nz
Re: XMEGA EEPROM Read and Write
« Reply #24 on: September 16, 2013, 03:22:55 am »
The number located at a memory address stored in a pointer is always

8bits if the memory is organised in bytes
16bits if the memory is organised in words
etc.


Greek letter 'Psi' (not Pounds per Square Inch)
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf