[TUT] [C] Using the EEPROM memory in AVR-GCC

Go To Last Post
356 posts / 0 new

Pages

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

Quote:

but the problem is that it won't to put in EEPROM,

I find your code close to impossible to read but how do you know it's not writing EEPROM? It does look like at least 5 elements of Array[] should hold some values by the time you do the eeprom_update_block().

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

1. How are you determining that the EEPROM does not get written.

2. When I said "minimal" I really meant it. For now, throw out all code that deals with the motors etc. Ideally we're talking about a test program of perhaps 10 lines. It is not unlikely that you will reveal the problem yourself during this process. This is how the seasoned folks deal with a problem they do not spot right away - it is much about reducing the problem space. Anyhow, it is likely that more people will read your code and try to help you. (By showing code that is full of irrelevant stuff (for solving the problem at hand) you are asking other people to take their time to do the isolation of the problem - that time should be spent by you, not (perhaps several) other persons.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

I tested Array[] and it repeated LED turn on/off pattern I had defined(with both "write/read" section out of comment) , but when I first did "Write" and comment that path, and than tried to read that, there was no pattern i had created before( so i came with that conclusion). I hope you understand what i tried to say.

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

Hello again,

I solved part of a problem. The problem was switch loop inside of for loop, I only put several "if" instead, but, now I have problem with "for" loop. It just read last element of Arrays. Do you know the reason? Maybe, I put smth else instead of "for", but what when I have to read Arrays?

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

Dear natalijana..

Imagine being in our place for just a few moments. Think about what you need to tell us in order for us to try to give good answers.
We can not guess what source code you have - you must show it. Or i) face the risk of getting answers like "the error is the missing semicolon in line 42", and ii) wearing out your welcome.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

Dear JohanEkdahl,

I know you are right (my code is 6. comment above this comment). But, if I'm no welcome anymore, I'll understand. I have only beautiful words to say about your work here in this forum.

Thank you for everything.

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

Quote:

(my code is 6. comment above this comment)

No that's how the code WAS a while back. Then you said:
Quote:

I solved part of a problem. The problem was switch loop inside of for loop, I only put several "if" instead, but, now I have problem with "for" loop. It just read last element of Arrays. Do you know the reason?

How can anyone here possibly guess what changes you actually made?

Can you consider following Johan's advice and stripping your problem down to just 10 lines or so? (as he says, when we do that to try and isolate a problem we often find the solution during the cut-down process).

BTW the purpose of this thread is only to give feedback to improve the tutorial in the first post - not to solve generic EEPROM programming problems. Can I suggest we take this to a new thread in AVR Forum or (because it may be specifically about GCC handling of EEPROM) the GCC Forum?

Moderator.

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

hi all. sorry to bother you but I need your help or I will go crazy...

I hope at least some of you still visit this thread ;)
Someone mentioned above to make problem as short as possible to get correct answer fast, so here it is.
Following the tut i just copied to new project part of code to see what happens. i program in eclipse with avrdude 5.11.
When i build this program:

#include 
#include 
#include 

//EEMEM uint8_t data;

void main ( void )
{
uint8_t ByteOfData ;
ByteOfData = 0x12 ;
eeprom_update_byte (( uint8_t *) 46, ByteOfData );
}

i get on my release new file called 'project.eep' and when i open it, i get this:

:00000001FF

btw its the same thing as at the end of hex file.

No matter if I put it in infinite loop or not, it does not show me the '0x12' value anywhere.
What is more, if i use sth like this:

#include 
#include 
#include 

EEMEM uint8_t data;

void main ( void )
{
uint8_t ByteOfData ;
ByteOfData = 0x12 ;
eeprom_update_byte (( uint8_t *) data, ByteOfData );
}

i get allocated space in eeprom:

:0100000000FF
:00000001FF

but still it is written with nothing. BUT, if i write

EEMEM uint8_t data=0x12;

i get correct value:

:0100000012ED
:00000001FF

where is the problem.. :( can anyone help me with this? PLEASE PLEASE PLEASE!![/code]

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

Quote:
where is the problem.

What problem? It's behaving exactly as you'd expect. You only get initial values for initialised globals. Your first code only write 0x12 to location 46 at run time. Why would you have expected anything in the .eep for that?

Your second bit of code simply reserves a location in EEPROM called "data" but does nothing to set an initial value at compile time. As the compiler/linker don't know what else to do they actually assign it an initial value of 0x00 (just like .bss variables in RAM) so that's why you see:

:0100000000FF 

which is setting that 0x00.

Only whe yiou explicitly make a compile time initialisation of the (global) variable:

EEMEM uint8_t data=0x12; 

do you finally get a .eep to set this initial value.

This is completely predictable C behaviour so I'm not sure why you would have expected to see anything else?

Think of .eep as just being like .data initialisers but for EEPROM (because that's what it is).

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

ummm. fine. thanks a lot! soo, what you are saying is that I have to write my program to uC, run, and than download it and than check if values are correct, right?
once again, thanks A LOT!

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

Quote:

what you are saying is that I have to write my program to uC, run, and than download it and than check if values are correct, right?

I didn't say that at all. There are two completely predictable ways to get initial values into EEPROM:

1)

#include 

uint8_t data EEMEM = 123;

int main(void) {
}

This is compile time initialisation - you build this file and as well as a .hex being produced you also get a .eep file. When you ISP the chip you program the .eep into EEPROM as well as putting some .hex (probably doing a little more than this one!) into the flash. You are then guaranteed that the location labelled 'data' contains 123 when you eeprom_read_byte() access it.

2) The alternative is run time initialisation:

#include 

uint8_t data EEMEM;

int main(void) {
  eeprom_update_byte(&data, 123);
}

This is the simplest form. When the .hex file for this is ISP'd into the chip then because of the chip eraser performed at that time the EEPROM will start with 0xFF in every location. Before the call to eeprom_update_byte() the 'data' location will therefore contain 0xFF but after that line it will hold 123.

While you can just use eeprom_update_byte() as shown here so it considers writing the location every time (but won't on 2nd and subsequent execution because it first checks and will find 123 there already) what a lot of people might do is use some kind of "cookie" value to mark whether the EEPROM has been initialised yet or not. Perhaps something like:

#include 

struct { 
  uint8_t data;
  uint8_t cookie;
} vars EEMEM;

int main(void) {
  if (eeprom_read_byte(&vars.cookie != 0xA5) {
    eeprom_update_byte(&vars.data, 123);
    eeprom_update_byte(&vars.cookie, 0xA5);
  }
}

The advantage of this is that if the code later went on to re-write the 'data' value the first version would just set it back to 123 every time the program started. This ensure it only gets set to initial value once (until the 'cookie' is cleared by setting it to other than 0xA5).

On the whole I would have thought (1) were easier than (2) but it does have the downside that the .eep and .hex must be distributed as a pair and if someone ever forgets to program the .eep into the chip you will get possibly mysterious behaviour.

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

Hi.

I have a problem with Atmel Studio 6 when I work with EEMEM.
First I found that when I use EEMEM to declare an eeprom variable, it takes same space in SRAM too.
for example:

EEMEM uint8_t x;

this will get 2 byte from EEPROM and 2 bytes from SRAM.
I checked it if we can store data from eeprom in order to use this assigned memeory:

EEMEM uint8_t x=10;
eeprom_write_word(&x,x); //Store 10 to eeprom

x=0;// Changing x to an arbitrary value
x=eeprom_read_word(&x);  // Retrieve 10 to x

But, that makes some problems. Value of x will be changed unexpectedly while program is running, especially when we declare multiple eeprom variables in this way.

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

Quote:

First I found that when I use EEMEM to declare an eeprom variable, it takes same space in SRAM too.

No that's just a bug in the "size" utility written by Atmel in AS6. Ignore it. If you want the real answer use avr-size from binutils as a post-build step. In fact in the As6 forum someone from Atmel even gave the steps to turn off their own size utility step so the misleading information is no longer seen.

EEMEM uint8_t x=10;
eeprom_write_word(&x,x); //Store 10 to eeprom 

Why would you even do it this way? Either you set an initial value in the definition and this leads to the generation of a .eep file that you put into the EEPROM when you program the chip so the &x location already contains 10 when the program starts or you would do:

EEMEM uint8_t x;
eeprom_write_word(&x, 10); //Store 10 to eeprom 

to initialise it at run time. But attempting both just seems plain odd.

Quote:

Value of x will be changed unexpectedly while program is running, especially when we declare multiple eeprom variables in this way.

You need to show more of a test case - clearly the code you quoted - even with the odd initialisation - will not corrupt EEPROM. In fact the only things ever likely to corrupt EEPROM (apart from a direct write to the location) are the issues to do with BOD explained in the EEPROM chapter of every AVR datasheet.

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

clawson wrote:
Quote:

First I found that when I use EEMEM to declare an eeprom variable, it takes same space in SRAM too.

No that's just a bug in the "size" utility written by Atmel in AS6. Ignore it. If you want the real answer use avr-size from binutils as a post-build step. In fact in the As6 forum someone from Atmel even gave the steps to turn off their own size utility step so the misleading information is no longer seen.

EEMEM uint8_t x=10;
eeprom_write_word(&x,x); //Store 10 to eeprom 

Why would you even do it this way? Either you set an initial value in the definition and this leads to the generation of a .eep file that you put into the EEPROM when you program the chip so the &x location already contains 10 when the program starts or you would do:

EEMEM uint8_t x;
eeprom_write_word(&x, 10); //Store 10 to eeprom 

to initialise it at run time. But attempting both just seems plain odd.

Quote:

Value of x will be changed unexpectedly while program is running, especially when we declare multiple eeprom variables in this way.

You need to show more of a test case - clearly the code you quoted - even with the odd initialisation - will not corrupt EEPROM. In fact the only things ever likely to corrupt EEPROM (apart from a direct write to the location) are the issues to do with BOD explained in the EEPROM chapter of every AVR datasheet.

Dear Clawson
Thanks for your information.
Here I write all the codes related to my problem:

struct Record
{
	uint16_t		Code;
	uint32_t		Date;
	double			Viscosity;
};

//EEPROM VARIABLES
EEMEM	uint8_t		e_sensor_sensivity;
EEMEM	uint16_t	e_pipe_dirty;
EEMEM	float		e_Temp_SetPoint;
EEMEM	uint8_t		e_pointer;
EEMEM	struct Record  Machines[100];

Now in a subroutine, i update values from eeprom:

void eeprom_init()
{
	while(!eeprom_is_ready());
	eeprom_write_word(&e_pipe_dirty,100);
	e_sensor_sensivity=eeprom_read_byte(&e_sensor_sensivity);
	e_pipe_dirty=eeprom_read_word(&e_pipe_dirty);	
	e_Temp_SetPoint=eeprom_read_float(&e_Temp_SetPoint);
	e_pointer=eeprom_read_byte(&e_pointer);
	
	//Default values checking...
	if (e_pointer==0xff)
	{
		e_pointer=0x00;
		eeprom_write_byte(&e_pointer,e_pointer);
	}
	
	if ((e_Temp_SetPoint>125)||(e_Temp_SetPoint<0))
	{
		e_Temp_SetPoint=100;
		eeprom_write_float(&e_Temp_SetPoint,e_Temp_SetPoint);
	}
	
	if (e_sensor_sensivity>100)
	{
		e_sensor_sensivity=40;
		eeprom_write_byte(&e_sensor_sensivity,40);
	}
	
	for (uint8_t i=0;i

When I ran the program step-by step while Optimization is set to any level, I found that the values of the most of the variables are changing. It seems I can not store the values into EEMEM variables and they only can keep their address in EEPROM.

Anyway, I have attached whole project to this post.
Any thank you very much for your useful comments. I did not affect your comments on these codes to have everything unchanged in order to reveal the probable fault.

Thanks again for your helps

Wishes
Hassan

Attachment(s): 

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

Quote:

It seems I can not store the values into EEMEM variables and they only can keep their address in EEPROM.

Are you talking about the simulator here - it has a fault with showing EEPROM updates.

By the way do NOT use the _write_ functions, use the _update_ functions instead. They won't write if they don't need to (which wears out the EEPROM needlessly).

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
EEMEM   uint8_t      e_pointer; 
...
e_pointer=0x00;
eeprom_write_byte(&e_pointer,e_pointer); 
...
e_pointer=eeprom_read_byte(&e_pointer);

Sorry, but all your EEPROM access is nonsense.
Read the tutorial again.

Edit:
To be a little more concrete: not the EEPROM access itself is nonsense, but where you load/store the data from/to RAM.

Stefan Ernst

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

To add to what Stefan says it may help you to do something like this:

//EEPROM VARIABLES
EEMEM   uint8_t      e_sensor_sensivity;
EEMEM   uint16_t   e_pipe_dirty;
EEMEM   float      e_Temp_SetPoint;
EEMEM   uint8_t      e_pointer;
EEMEM   struct Record  Machines[100];

// RAM copies of the same
uint8_t      ram_sensor_sensivity;
int16_t   ram_pipe_dirty;
float      ram_Temp_SetPoint;
uint8_t      ram_pointer;
struct Record  ram_Machines[100];

You read the eeprom values (using the e_ names) to ram_ variables using the various ram_name = eeprom_read_*(&e_location) functions. Then you write the values back after modification with eeprom_update_*(&e_location, ram_name).

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

clawson wrote:
Quote:

It seems I can not store the values into EEMEM variables and they only can keep their address in EEPROM.

Are you talking about the simulator here - it has a fault with showing EEPROM updates.

By the way do NOT use the _write_ functions, use the _update_ functions instead. They won't write if they don't need to (which wears out the EEPROM needlessly).

Thank you. I need to re-read the tutorial and do some changes.

Last Edited: Tue. Nov 13, 2012 - 11:02 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
To add to what Stefan says it may help you to do something like this:

//EEPROM VARIABLES
EEMEM   uint8_t      e_sensor_sensivity;
EEMEM   uint16_t   e_pipe_dirty;
EEMEM   float      e_Temp_SetPoint;
EEMEM   uint8_t      e_pointer;
EEMEM   struct Record  Machines[100];

// RAM copies of the same
uint8_t      ram_sensor_sensivity;
int16_t   ram_pipe_dirty;
float      ram_Temp_SetPoint;
uint8_t      ram_pointer;
struct Record  ram_Machines[100];

You read the eeprom values (using the e_ names) to ram_ variables using the various ram_name = eeprom_read_*(&e_location) functions. Then you write the values back after modification with eeprom_update_*(&e_location, ram_name).

Thanks a lot for your all helps. I got it completely.
Wishes, Hassan

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

is it possible with P89v51rd2. the micro-controller P89V51RD2 has 1 kB of RAM. We want to Store a incremental Variable in the flash and keep updating the value as a counter (long variable). Kindly advice me the embedded Sample C code for write/read a byte from flash memory.

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

Quote:

P89v51rd2

Did you lose your way on the Information SuperHighway? The CPu you are asking about on an Atmel site dedicated to AVR microcontrollers is an 8051 model made by NXP. Surely you can find an NXP or even just a generic 8051 support site?

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

Dean,
in your block write example in your tutorial ( http://deans-avr-tutorials.googl... ) you use & in front of the arrays, what is the purpose of it since the using the array name already points to the address?

# include 
uint8_t EEMEM NonVolatileChar ;
uint16_t EEMEM NonVolatileInt ;
uint8_t EEMEM NonVolatileString [10];
int main ( void )
{
uint8_t SRAMchar ;
uint16_t SRAMint ;
uint8_t SRAMstring [10];
SRAMchar = eeprom_read_byte (& NonVolatileChar );
SRAMint = eeprom_read_word (& NonVolatileInt );
eeprom_read_block (( void *)& SRAMstring , ( const void *)& NonVolatileString , 10) ;

why not

eeprom_read_block (( void *)SRAMstring , (const void *) NonVolatileString , 10) ;

I have tested both cases and they both seem to work, with or without & (winavr2010)

Alex

=========================================================================================

"For every effect there is a root cause. Find and address the root cause rather than try to fix the effect, as there is no end to the latter."
Author Unknown

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

Typo - will fix when I'm home. Adding & to a non-indexed portion of the array will work, but it's unnecessary as the array name will decay into a pointer.

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

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

I’ve got a question for you all.
I need to get user information into the EEPROM by way of the JTAGICE3. This information needs to be accessed by my program as it will contain configuration information generated externally from my program. In my profile definition file I set up an array like this:

unsigned char EEMEM manu_profile[4] = {
20, // manu_meas_interval [0]
1U, // manu_startup_delay_lo [1]
0xA0, // manu_alrmlevel_startdelayhi [2]
0xFA, // manu_alarm_type_en [3]
};
unsigned char EEMEM cust_profile[4] = {
23, // manu_meas_interval [0]
4U, // manu_startup_delay_lo [1]
0xAF, // manu_alrmlevel_startdelayhi [2]
0xF0, // manu_alarm_type_en [3]
};

This creates a default .eep file which I will replace with an externally generated file.
What I would like to do is to be able to define the location of these arrays in the EEPROM. Then when the externally generated .eep is ready it can be programmed into the unit and accessed by my program. In other words I’d like to be able to set the location of my EEPROM values.
Thanks for your help

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
__attribute__((section(".myee"))) unsigned char EEMEM manu_profile[4]...

Then pass:

-Wl,-section-start=.myee=0x810123

to the linker to place at 0x123 in the EEPROM. Don't forget to -j .myee on the avr-objcopy that creates the .eep

Alternatively group everything into a single struct{} and rely on the linker placing it at 0

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

Clawson, thanks for the quick reply.
I tried to compile your suggestion and come up with:
- section of 'manu_profile' conflicts with previous declaration -
I do not not have another declaration so this is troubling.

Your second suggest is what I had previously done and the location is at zero as you say. The issue we have is that we have two of these arrays, manu_profile and cust_profile that are defined in our file in that order.

This is a little confusing because cust_profile is located first in EEPROM (starts at zero) when we really want it to start after manu_profile. We can just swap the order of the arrays in our header file and get the EEPROM to line up to what we want but if someone else was to make an addition to the file there might be some confusion on how to setup the data. This doesn't give us much flexibility later on either.
I am using Studio 6.0 to program an ATmega169PA
Thanks for your help.
Tony

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

Quote:

The issue we have is that we have two of these arrays, manu_profile and cust_profile that are defined in our file in that order.

Yeah so:

typedef struct {
  char manu_profile[4];
  char cust_profile[4];
} all_eeprom_type;

all_eeprom_type all_eeprom EEMEM = {
 {20, 1U, 0xA0, 0xFA},
 {23, 4U, 0xAF, 0xF0}
}

as I suggested in the previous message stuct{} imposes any desired ordering you like on the data. It might not even just be a couple of char arrays but the elements in that struct could also be complex struct definitions themselves.

In this example it's true all_eeprom is at 0x0 but it guarantees the 4 bytes of cust_profile follow manu_profile. Even if you want to set a location for this stuff with an __atribute__section() and a -section-start it still pays to group everything in a composite struct{} to guarantee ordering and to save having to give each array its own section name and section start.

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

Awesome! Great idea!
Thank you this will work just fine.

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

My program us running low on PROGRAM MEMORY (and its not yet finished). It uses a lot of static text on LCD which is sent to LCD with commands like LCDtext("LCD STRING 123");

If ill save those static texts as EEMEM non volatile strings and save them to eeprom memory and then while displaying on LCD ill read those strings, will my program take up less PROGRAM MEMORY?

Will displaying like 40 diffrent strings with this method

#include 
...
#include  

uint8_t  EEMEM NonVolatileString[16]={"L","C","D"," ","S","T","R","T","I","N","G"," ","1","2","3","4"} 

int main(void)
{
	uint8_t  SRAMstring[16];   
	...
	eeprom_read_block((void*)&SRAMstring, (const void*)&NonVolatileString, 10);
	...
	LCDtext(SRAMstring);
}

Take less PROGRAM MEMORY than displaying strings with this method:

#include  
...

int main(void)
{
	...
	LCDtext("LCD STRING 1234");
	...
}

??

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

Quote:

will my program take up less PROGRAM MEMORY?

Yes.

(but don't forget that you now have to program both .hex and .eep files into the AVR when you program it or the EEPROM data will not be there or will be out of date). Once you finalise what's in EEPROM you can set the EESAVE fuse so you don't have to program .eep every time. Just reprogram when you change some of the EEPROM based text.

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

Excellent tutorial Dean, but there is one thing I am not clear on.

When using the EEMEM attribute do you still need to write values to to the EEPROM or does the EEMEM do that automatically?

For example,is this correct,

#include < avr / eeprom .h >

uint16_t EEMEM myInt;
unit16_t myOtherInt;

int main (void)
{
 myInt = 72;
 myOtherInt = eeprom_read_word (& myInt );
}

Or is there another step I have missed? I think that it is correct.

Thanks

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

You still need to use the eeprom_write_*() macros - or better yet, the eeprom_update_*() macros. Trying to write to a EEMEM variable directly will just corrupt your SRAM.

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

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

Or you can do:

#include < avr / eeprom .h > 

uint16_t EEMEM myInt = 72; 
unit16_t myOtherInt; 

int main (void) 
{ 
 myOtherInt = eeprom_read_word (& myInt ); 
} 

when you build this you will get two Intel hex files. Program the .hex into the flash and the .eep into the EEPROM. When the read is performed it will find 72 in the &myInt location in the EEPROM.

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

Thank you, that makes it clearer now. I did try it the way I posted before and was getting weird results, this is obviously why.

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

abcminiuser wrote:
For an updated version of this tutorial in PDF format, please see this page of my website.

My second tutorial. This tutorial will centre around GCC's handling of data stored into EEPROM memory.
...
- Dean :twisted:

Will it work with IAR EWAVR workbench?

Regards,
shreyas.

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

No, just AVR-GCC. IAR has its own syntax and implementation details.

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

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

abcminiuser wrote:
No, just AVR-GCC. IAR has its own syntax and implementation details.

- Dean :twisted:

what should be the changes if I want to use it for IAR?
In IAR tool chain for avr I did not find any eeprom.h file.
Does it mean there is no library for eeprom in IAR?

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

It's built in, see the user manual included with your installation. You just mark a variable with "__eeprom" and all reads and writes will be done to EEPROM rather than SRAM (but be careful not to write to it too often or you'll wear it out).

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

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

Great explanation!

Hari

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

I thought this might be a good question to ask here rather than starting a new thread.

I want to be able to update the firmware without losing previously saved EEPROM data. When I write a new version of the firmware, what should I do to ensure that the addresses assigned by using the EEMEM attribute on variables stay the same between versions?

Would I be right in assuming that adding new EEMEM variables should be possible, but removing any may change the addressing?

Thanks for the great tutorials!

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

Basically, you can't guarantee it without hard-coding addreses - but a near perfect analog would be to wrap all EEPROM definitions inside a struct. Structure entities are placed in the same order they are declared in, so by placing all EEPROM variables inside a single struct you enforce the ordering.

Without the wrapper struct adding or removing anything (or changing compiler versions) can result in a very different layout.

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

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

Quote:

Structure entities are placed in the same order they are declared in, so by placing all EEPROM variables inside a single struct you enforce the ordering.

What's more this allows you to add new variables in the later firmware without disturbing the existing ones. Just make sure you always add to the end of the struct{}.

If you want to ensure it is at a fixed address then do something like:

typedef struct {
  int n;
  char text[10];
  long l;
etc.
} myvars_t;

__attribute__((section(".eevars"))) myvars_t myvars_ee = {
  12345,
  "hello",
  0xBABEFACE
}

then pass

-Wl,-section-start=.eevars=0x8100C0

to the linker. The value 0x810000 is a special offset which means "in the EEPROM" so this will place this collection of vars at EEPROM address 0x00C0.

As Dean says this hard-codes the 0x00C0 so you run the risk of bumping into other EEPROM vars if you also use EEMEM as well ("EEMEM" is basically just __attribute__((section(".eeprom")))... and -Wl,-section-start=.eeprom=0x810000)

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

Thanks. I want to store various profiles (organized as structs) in EEPROM, along with a variety of other things, including two buffers for often saved values so as to not wear out EEPROM cells. I can just declare all my EEPROM variables like so, correct?

typedef struct {
	char		Profile_Name[17];
	uint16_t	Setting1;
	uint16_t	Setting2;
	} Profile;
	
//EEPROM Variables
typedef struct {
	//1024 bytes available
	uint8_t		EE_Var1;				
	uint16_t	EE_Var2;				
	
	Profile		Run_Profile[16];		
	uint16_t	RunTimeBuffer[16];		
	uint8_t		StatusBuffer[16];		
	
} Saved_Vars;

Saved_Vars EE_Vars EEMEM;

Is it going to cause a problem that some of these will be defined in code (and loaded via the .eep file), and others set by the user?

I don't show it here, but I plan to have ~half of the profiles preset and the other half available for the user to customize.

Would it be better to initialize everything in an .eep file, or does it really not matter provided there is no way to accidentally use an uninitialized value?

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

Quote:

correct?

Correct.
Quote:

Is it going to cause a problem that some of these will be defined in code (and loaded via the .eep file), and others set by the user?

Nope. When you do program the EEP the "runtime set" ones will obviously inherit some default value but you'll then over-write those so it doesn't really matter (probably best to make them 0xFF to save wear and tear).

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

What does the C standard guarantee w.r.t. alignment/padding? Can that suddenly change between two versions of a compiler?

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

Thank you dear cemox.

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

Hi,

 

Thanks for this tuto.

Very clear

French AVR user

 

 

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

I'm using an Atmega8a to display a countdown timer , what I would like to do is save the seconds and minutes local Variables that where entered into eeprom memory . Once unit is powered back on it will pull the last clock info back into clock so user doesn't have to re enter it.

 

Is there a way of doing this using eeprom, and if so can you provide some c code. Using Atmel studio 6.

 

Clock info is entered and changed by user on demand and eeprom would need to be updated on the go.

 

 

The purpose is that last input would auto load on power up.

 

Thanks

 

 

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

Is there a way of doing this using eeprom, and if so can you provide some c code.

Isn't that EXACTLY what this tutorial is about? Did the first post in this thread not provide what you were looking for (that was certainly the plan!)?

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

I thought this forum was a place to ask questions and to learn . I read and did all the examples here and none of them worked for what I trying to do.

Please read my question as it defines what my plan is . If you're able to help I would appreciate it .

 

 

Still learning and will look again to see if I missed something . Please provide code that shows how to read in write inside Main .

Last Edited: Tue. Mar 10, 2015 - 07:26 PM

Pages