ATmega128 EEPROM wont remember second variable

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

Hello,

 

Im making application where user is being able to change some variables that will be saved to EEPROM to be restored after power down.

 

Im using default avr/eeprom.h

 

Following Dean Camera EEPROM tutorial this is what i do:

 

Before main function i save initial EEPROM variables using EEMEM argument.

Then inside main function i assign values from EEPROM into program variables reading them back from EEPROM.

And then somewhere in code under certain condition i let user to save changed variables back to EEPROM by using eeprom_update_byte.

After compiling code i write to AVR both EEP and HEX file.

 

Saving initial variables works OK.

Reading back those variables in between int main() and while() also works OK.

What is not working is the part where i want to save modified variables back to EEPROM while the program is running.

 

If in whole code im using only one EEPROM variable, lets say FAN1_bias_default and im writing back to it FAN1_bias then its ok.

If in whole code im using still only one EEPROM variable, this time FAN2_bias_default and im writing back to it FAN2_bias then it also ok.

 

The problem starts when im starting to use two or more EEPROM variables.

 

Using EEMEM argument should save those variables into EEPROM starting from address 0 so first is address 0, next is 1 etc. And when im updating bytes in EEPROM i use addresses 0 and 1.

 

But the result is :

attempting to save FAN1_bias variable to FAN1_bias_default EEMEM variable using address 0 will overwrite the FAN2_bias_default EEMEM

attempting to save FAN2_bias variable to FAN2_bias_default EEMEM variable using address 1 will overwrite the FAN1_bias_default EEMEM

 

 

For some reason they are being written into wrong places? Anyone have suggestion how to fix it?

#include <avr/io.h>
#include <util/delay.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <avr/eeprom.h>

//...//


int8_t   EEMEM FAN1_bias_default=10; //FAN1 minimum speed adjust
int8_t   EEMEM FAN2_bias_default=10; //FAN2 minimum speed adjust

//...//

int main(void)
{

    //...//

    int8_t FAN1_bias = eeprom_read_byte (&FAN1_bias_default);		//FAN1 minimum speed adjust
    int8_t FAN2_bias = eeprom_read_byte (&FAN2_bias_default);		//FAN2 minimum speed adjust

    //...//
    
    while(1)
	{
	    //...//
	    
	    if (menu_level == 1)
		{
			eeprom_update_byte((uint8_t*)0, FAN1_bias );
			menu_depth=2;
			}
		if (menu_level == 2)
		{
			eeprom_update_byte((uint8_t*)1, FAN2_bias );
			menu_depth=2;
		}
		
		//...//
	}
	
	//...//

}

 

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

Dean's tutorial really uses hard-coded addresses instead of variable names?!?

 

KonradIC13 wrote:
Using EEMEM argument should save those variables into EEPROM starting from address 0 so first is address 0, next is 1 etc.

Why do you say "should"?  Yes, compilers will follow a pattern, but an optimizing compiler is free to put them wherever it pleases.  [and there is a reason not to use location 0, especially on older AVR8 models]

 

Anyway, what does the map and similar documents (LSS) say abo9ut the location of your EEPROM variables?

 

 

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.

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

So lets try to x our broken code. We're trying to read out a single byte of memory. Let's try to use the eeprom_read_byte() routine.

# include <avr/eeprom.h>
uint8_t EEMEM NonVolatileChar;
uint16_t EEMEM NonVolatileInt;
uint8_t EEMEM NonVolatileString [10];
int main( void )
{
10
CHAPTER 6. USING THE EEMEM ATTRIBUTE 11
uint8_t SRAMchar;
SRAMchar = eeprom_read_byte(&NonVolatileChar);
}

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.

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

That was helpful, especially that highlighted part with &NonVolatileChar and & symbol

 

I misinterpreted what was written in tutorial, it said "And the compiler will automatically allocate addresses for each of the EEPROM variables within
the EEPROM address space, starting from location 0. " and i wrongly assumed it meant address 0.

 

In addition to that, in every write example in tutorial, the example would write values to arbitrary chosen address 46 and i didnt know where it came from.

 

So i tried and edited my code and now instead of

eeprom_update_byte((uint8_t*)0, FAN1_bias );

i use

eeprom_update_byte((uint8_t*)&FAN1_bias_default, FAN1_bias );

and its now working, writing 2,3, and more variables to eeprom on demand, right where its supposed to

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

KonradIC13 wrote:
In addition to that, in every write example in tutorial, the example would write values to arbitrary chosen address 46 and i didnt know where it came from.

Well, yes--in the early part of the totorial.

 

Once you get to EEMEM the magic numbers disappear.

 

And you still didn't post the build results so the actual addresses can be seen.

 

But I did...

 

#include <avr/io.h>
#include <avr/eeprom.h>

int8_t   EEMEM FAN1_bias_default=10; //FAN1 minimum speed adjust
int8_t   EEMEM FAN2_bias_default=10; //FAN2 minimum speed adjust

volatile	int8_t FAN1_bias;		//FAN1 minimum speed adjust
volatile	int8_t FAN2_bias;		//FAN2 minimum speed adjust

int main() {
	FAN1_bias = eeprom_read_byte (&FAN1_bias_default);		//FAN1 minimum speed adjust
	FAN2_bias = eeprom_read_byte (&FAN2_bias_default);		//FAN2 minimum speed adjust

while (1)
{
			eeprom_update_byte((uint8_t*)0, FAN1_bias );
			eeprom_update_byte((uint8_t*)1, FAN2_bias );

}
return (0);
}

 

.eeprom         0x00810000        0x2
 *(.eeprom*)
 .eeprom        0x00810000        0x2 GccApplication1.o
                0x00810000                FAN2_bias_default
                0x00810001                FAN1_bias_default
                0x00810002                __eeprom_end = .

And indeed, with this particular example, the EEPROM variables are in the order you did not expect.

 

Note that if you want hard-coded EEPROM locations (e.g. to communicate with bootloader), then you can use a struct and place it where desired.  In practice, putting the bank of values in a struct to preserve order is often used, but actually placing the struct is rarely used.

 

When EEMEM is introduced, the article says

px; "> <Chapter 6
Using the EEMEM attribute
You should now know how to read and write to the EEPROM using fixed addresses. But that’s not
very practical! In a large application, maintaining all the fixed addresses is an absolute nightmare
at best. But there’s a solution to push this work onto the compiler — the EEMEM attribute.

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: Mon. Jan 25, 2016 - 03:54 PM