Forum Menu




 


Log in Problems?
New User? Sign Up!
AVR Freaks Forum Index

Post new topic   Reply to topic
View previous topic Printable version Log in to check your private messages View next topic
Author Message
clawson
PostPosted: Feb 09, 2011 - 11:34 AM
10k+ Postman


Joined: Jul 18, 2005
Posts: 62354
Location: (using avr-gcc in) Finchingfield, Essex, England

This thread is not for diagnosing EEPROM usage problems. It is for discussing the article in the first post.

Moderator.

PS As for your warnings. Take for example:
Code:
/*60*/eeprom_write_word(&eeEtot, Etot);

where:
Code:
int EEMEM eeEtot;
int Etot, Es_month;

Now look at the prototype in eeprom.h:
Code:
void eeprom_write_word (uint16_t *__p, uint16_t __value);

uint16_t is "unsigned int". When you use just "int" then by default it is interpreted as "signed int".

THAT is why you get a signedness warning. Either cast or use the right type.

Also consider:
Code:
      /*62*/eeprom_write_block((void*)&eeEw_month,(const void*)&Ew_month, sizeof(double));

and the prototype in eeprom.h
Code:
void eeprom_write_block (const void *__src, void *__dst, size_t __n);

It's warning about param2 which is the "void * __dst" in the prototype and which you cast as "(const void*)". The warning is about the loss of the const qualifier.

_________________
 
 View user's profile Send private message  
Reply with quote Back to top
schamton
PostPosted: Feb 09, 2011 - 06:36 PM
Hangaround


Joined: Feb 17, 2010
Posts: 157


thanks clawson, i saw several other comments to this tutorial with eeprom issues so i thought it'd be ok.
the tutorial quotes:
Quote:
void eeprom_write_block (void *pointer_eeprom, const void *pointer_ram, size_t n)

while eeprom.h void function is:
Quote:
void eeprom_write_block (const void *__src, void *__dst, size_t __n);

warnings corrected, and the output improved:
Code:
<NUL>2<NUL><NUL><NUL>3456789<NUL>

but the first byte is corrupted. it should be
Code:
12<NUL><NUL><NUL>3456789<NUL>

any ideas? thank you!
 
 View user's profile Send private message  
Reply with quote Back to top
schamton
PostPosted: Feb 10, 2011 - 04:28 PM
Hangaround


Joined: Feb 17, 2010
Posts: 157


ahhh ok, after a few trials, basically when Es_month is 4 digits, the response has the 1st byte of Etot corrupted.

For ex:
Code:

Etot = 12657;
Es_month = 345;
Ew_month = 789;

Code:

12657345<NUL>789<NUL>

ok. If
Code:
Etot = 12657;
Es_month = 3456;
Ew_month = 789;

Code:

<NUL>26573456789<NUL>

WRONG. 1's byte corrupted. Should be 12657.

Code:
Etot = 12657;
Es_month = 345;
Ew_month = 7896;

Code:
12657345<NUL>7896

ok.
Code:

Etot = 1265;
Es_month = 3456;
Ew_month = 789;

Code:
<NUL>265<NUL>3456789<NUL>

wrong.

Code:
Etot = 1265;
Es_month = 34;
Ew_month = 789;

Code:
1265<NUL>34<NUL><NUL>789<NUL>

ok...

Dean mentioned:
Quote:
Remember that in C a zero byte is treated as a null-terminator -- if you have junk data in the first 10 bytes of the string, chances are one might be a terminator which will stop any display of the buffer contents before the contents of the EEPROM read string is reached.


and again a few comments later
Quote:
You need to read/write one more byte to EEPROM than there are characters in the string -- there's a hidden 0x00 byte at the end of each string which terminates it. Without the terminator, your string routines will become confused.


Maybe this could be the problem? I can't find why the 1st byte is getting corrupted when Es_month is a 4 digit number :/
 
 View user's profile Send private message  
Reply with quote Back to top
clawson
PostPosted: Feb 10, 2011 - 04:48 PM
10k+ Postman


Joined: Jul 18, 2005
Posts: 62354
Location: (using avr-gcc in) Finchingfield, Essex, England

Code:
char Etot_str[5];
char Es_m_str[4];
char Ew_m_str[4];

These are surely far too small? A string defined as [5] can hold 4 digits and the terminating 0x00. A string defined as [4] can hold just 3 digits and the 0x00. If you try to put a four digit string into [4] it will write over the start of the next string in mmeory.

Personally I always work out the worst case> For example largest itoa() is going to be 5 digits, possibly with sign so 6 characters, then you need room for the 0x00. So 7 characters. To be safe I'd blow the memory budget and just make it [8] or if I was feeling particularly flaithiúl I'd actually make it [10] to be aboslutely positive. Start cutting the [10]s back to [8]s when you thing RAM is getting low. (and test the worst case strings)

_________________
 
 View user's profile Send private message  
Reply with quote Back to top
schamton
PostPosted: Feb 10, 2011 - 05:02 PM
Hangaround


Joined: Feb 17, 2010
Posts: 157


Quote:
A string defined as [5] can hold 4 digits and the terminating 0x00. A string defined as [4] can hold just 3 digits and the 0x00.


didn't know that! Thank you very much! : )

- Eric
 
 View user's profile Send private message  
Reply with quote Back to top
A-RapESTONIA
PostPosted: Feb 20, 2011 - 07:07 PM
Newbie


Joined: Jun 25, 2010
Posts: 5
Location: Estonia

Do somebody know if i could somehow monitor (make readable) my internal EEPROM to the device outside. For example: I have TI PGA309 signal conditioner which requires external EEPROM to read config data. It uses I2C aka TWI for reading. Can i somehow make my Atmega 324 memory readable by PGA309 via TWI?
Thanks!

_________________
Estonia, Otepää is the place where you can find me...
 
 View user's profile Send private message  
Reply with quote Back to top
clawson
PostPosted: Feb 20, 2011 - 07:16 PM
10k+ Postman


Joined: Jul 18, 2005
Posts: 62354
Location: (using avr-gcc in) Finchingfield, Essex, England

You can simulate whatever kind of interface the PGA309 expects to use with a microcontroller such as an AVR so the answer is yes.

_________________
 
 View user's profile Send private message  
Reply with quote Back to top
A-RapESTONIA
PostPosted: Feb 20, 2011 - 09:53 PM
Newbie


Joined: Jun 25, 2010
Posts: 5
Location: Estonia

So practically it means mechanically write all the functions: 1)set avr in slave read mode
2)make functions which emulate the prodecure when PGA asks memory location this n that answer with a memory location from AVR eeprom?
Okay then.
It would be simpler to program PGA through UART then...
I just thought maybe there is some shortcut how to do this.

_________________
Estonia, Otepää is the place where you can find me...
 
 View user's profile Send private message  
Reply with quote Back to top
hobbss
PostPosted: Mar 03, 2011 - 01:27 PM
Hangaround


Joined: Oct 06, 2010
Posts: 475
Location: Chicago

Question regarding the EESAVE fuse:

I am somewhat new to programming micro controllers, so please excuse me if this is a dumb question...

In my program, I declare several "variables" with the EEMEM attribute. At the beginning of the program, I read the values in (garbage if the EEP file was not downloaded). The user of the program has the capability of changing the values stored in the EEPROM. Scenario: a user sets all of the EEPROM variables to valid values. The board is then turned off. When it is turned on again, the program re-initializes its SRAM equivalent variables from EEPROM. I understand all this (isn't that the point of EEPROM?). However, if I set the ESAVE fuse, make some changes to the program and recompile it, and re-download it to the chip, what does it matter if the EEPROM is overwritten or not? Won't the compiler have given different addresses to my EEMEM variables? How will the program know where the previously saved EEMEM variables are stored?
 
 View user's profile Send private message  
Reply with quote Back to top
abcminiuser
PostPosted: Mar 03, 2011 - 03:37 PM
Moderator


Joined: Jan 23, 2004
Posts: 9832
Location: Trondheim, Norway

That's true, however if you place *all* your EEPROM variables into a single struct, as long as the compiler's packing and ordering rules are not changes between versions those variables should always map to the same place.

It's also useful for assembly programmers or manual EEPROM location management, sine in that case you always certain where everything is stored.

- Dean Twisted Evil

_________________
Atmel Studio 6.1 is now released, grab it here.
Report AS6/ASF bugs here.
 
 View user's profile Send private message Send e-mail Visit poster's website 
Reply with quote Back to top
hobbss
PostPosted: Mar 03, 2011 - 03:51 PM
Hangaround


Joined: Oct 06, 2010
Posts: 475
Location: Chicago

That makes sense. If I create a struct with a bunch of settings, I think I would always need to read/write the EEMEM variable to/from EEPROM in its entirety (i.e., couldn't do just one of the subvariables). Is this true?

From Clawson's post on page 7:

clawson wrote:

Code:
#include <string.h>
#include <avr/eeprom.h>

typedef struct {
  int16_t n;
  char c;
  uint8_t array[10];
  uint32_t l;
} data_type;

data_type copy_in_EEPROM EEMEM;
data_type copy_in_RAM;

int main(void) {
  copy_in_RAM.n = -23456;
  copy_in_RAM.c = 'A';
  copy_in_RAM.l = 0xDEADBEEF;
  memset(copy_in_RAM.array, 0x5A, sizeof(copy_in_RAM.array));
  eeprom_write_block(&copy_in_RAM, &copy_in_EEPROM, sizeof(copy_in_RAM));
  while(1);
}

After that has run the EEPROM will contain those data values I set in the struct{}


If I wanted to read the data from memory into a RAM structure, would the code be:

Code:

myStruct EEMEM eepromCopy;
myStruct RAMcopy;

eeprom_read_block((void*)&RAMcopy, (const void*)eepromCopy, sizeof(RAMcopy));


P.S. Since I boorishly forgot to say it in my first post -- thanks for taking the time to put together such a good tutorial.
 
 View user's profile Send private message  
Reply with quote Back to top
clawson
PostPosted: Mar 03, 2011 - 04:38 PM
10k+ Postman


Joined: Jul 18, 2005
Posts: 62354
Location: (using avr-gcc in) Finchingfield, Essex, England

Quote:

would the code be:

Yes.

_________________
 
 View user's profile Send private message  
Reply with quote Back to top
rivanor
PostPosted: Mar 18, 2011 - 03:21 PM
Newbie


Joined: Mar 02, 2011
Posts: 11
Location: Salt Lake City

rosvall wrote:
abcminiuser wrote:

(...)

At the moment, we now have access to the eeprom memory, via the routines now provided by eeprom.h. There are three main types of EEPROM access: byte, word and block. Each type has both a write and a read variant, for obvious reasons. The names of the routines exposed by our new headers are:

Quote:

(...)
� void eeprom_read_block (void *pointer_ram, const void *pointer_eeprom, size_t n)
� void eeprom_write_block (const void *pointer_ram, void *pointer_eeprom, size_t n)

(...)


I think you've got the two first arguments to eeprom_write_block in the wrong order.

From eeprom.h:
Quote:

static __inline__ void
eeprom_write_block (void *__dst, const void *__src, size_t __n)


Well... I just tried writing some code using eeprom_write_block and my compiler gave me a warning so I checked and it looks like the order of my eeprom_write_block is back to the original "wrong" order. So which one is correct? Smile
Looks like someone is changing things on us hehe.
 
 View user's profile Send private message Visit poster's website 
Reply with quote Back to top
kax2007
PostPosted: May 15, 2011 - 12:34 PM
Newbie


Joined: Nov 25, 2007
Posts: 3


I currently use the EEPROM to store some program configuration data (i.e. thresholds, durations, ...).
Now I want to adapt the program behaviour by patching some single EEPROM bytes. As far as I know AVR-Studio can only writw down complete EEPROM-files. Which tool can be used to do that? Wouldt be great if someone knows a simple command line tool.
 
 View user's profile Send private message  
Reply with quote Back to top
clawson
PostPosted: May 15, 2011 - 02:09 PM
10k+ Postman


Joined: Jul 18, 2005
Posts: 62354
Location: (using avr-gcc in) Finchingfield, Essex, England

Quote:

As far as I know AVR-Studio can only writw down complete EEPROM-files. Which tool can be used to do that? Wouldt be great if someone knows a simple command line tool.

Read the entire eeprom to a .hex - change one byte then write the whole thing back.

_________________
 
 View user's profile Send private message  
Reply with quote Back to top
DigiAcid
PostPosted: May 21, 2011 - 09:38 PM
Newbie


Joined: May 10, 2011
Posts: 2


Thanks so much for all your helpful tutorials mate.
They are much appreciated especially when you've left your Final Year project this late lol Smile
 
 View user's profile Send private message  
Reply with quote Back to top
darshanys
PostPosted: Aug 15, 2011 - 03:19 PM
Newbie


Joined: Aug 15, 2011
Posts: 1


sir i am trying to do a line follower and i am not able to program it so pls help me with it
abcminiuser wrote:
Davef,

Damnit, yet another typo. That should indeed be read_word - I'll go fix that now. Amazing that anyone still bothers to read my tutorials with all these silly mistakes!

Quote:
In <avr/eeprom.h>, eeprom_read_byte and eeprom_write_byte use a u08 pointer for the address. Doesn't this mean you can only access 256 bytes in the EEPROM? What about the remaining 1024-256 = 968 EEPROM bytes in a ATmega32?


That tripped me up too at the start. In AVR-GCC, all pointers are an int in size, two bytes. The pointer typecast only specifies what type of data the pointer is pointing to, not the pointer's size. A (uint8_t*), (uint16_t*) and (uint32_t*) are all identical in size, they just point to increasingly larger datatypes.

For example, (uint8_t*)0x1234 is a pointer two bytes in size, pointing to a byte at the location 0x1234.

This is a problem when dealing with pointers to the AVR's flash memory, since in some AVRs this overflows an int. Because of this, pointers to flash addresses are still two bytes in size but the pointer is word rather than byte aligned, so an increase of one in the pointer's address corresponds to a jump of two bytes.

If I can think of enough material for this I might make it into a short tutorial since it seems to be such a prevalent issue.

- Dean Twisted Evil
 
 View user's profile Send private message  
Reply with quote Back to top
clawson
PostPosted: Aug 15, 2011 - 03:25 PM
10k+ Postman


Joined: Jul 18, 2005
Posts: 62354
Location: (using avr-gcc in) Finchingfield, Essex, England

Quote:

trying to do a line follower

Then kindly explain what on earth the post you quoted or this entire thread has to do with your question?!? This thread is about using EEPROM with the avr-gcc compiler.

_________________
 
 View user's profile Send private message  
Reply with quote Back to top
guyh22
PostPosted: Aug 28, 2011 - 11:56 AM
Newbie


Joined: Aug 28, 2011
Posts: 2


I've read this thread and now know how to use EEMEM to have the compiler generate a .eep file to 'initialise' basic eeprom variable, and arrays.

I am using an 'overall structure' to hold all my eeprom variables.

I need to initialise an array of structures within the outer structure
Code:

typedef struct INNER_STRUCT1 {
  uint8_t var1; 
  uint8_t var2;
  int8_t  var3;
} innerStruct1_t;

typedef struct INNER_STRUCT2 {
  uint8_t var1; 
  uint8_t var2;
  int8_t  var3;
} innerStruct2_t;

typedef struct OUTER_STRUCT {
  uint8_t        outerVar1;
  uint8_t        outerVar1;
  uint8_t        outerVar1; 
  innerStruct1   innerVars1[5];
  innerStruct2   innerVars2[5];
} outerVars_t;


So when I use
Code:
outerVars_t   EEMEM   EE_Vars = {22,100,12,?help;


is it possible initialise the inner array of structures?
or is there a better way of doing this?

Thanks
 
 View user's profile Send private message  
Reply with quote Back to top
clawson
PostPosted: Aug 28, 2011 - 12:38 PM
10k+ Postman


Joined: Jul 18, 2005
Posts: 62354
Location: (using avr-gcc in) Finchingfield, Essex, England

Code:
outerVars_t   EEMEM   EE_Vars = {
 22,
 100,
 12,
 {
   { is1_var1_val, is1_var2_val, is1_var3_val }, // iV1[0]
   { is1_var1_val, is1_var2_val, is1_var3_val }, // iV1[1]
   { is1_var1_val, is1_var2_val, is1_var3_val }, // iV1[2]
   { is1_var1_val, is1_var2_val, is1_var3_val }, // iV1[3]
   { is1_var1_val, is1_var2_val, is1_var3_val }  // iV1[4]
 },
 {
   { is2_var1_val, is2_var2_val, is2_var3_val }, // iV2[0]
   { is2_var1_val, is2_var2_val, is2_var3_val }, // iV2[1]
   { is2_var1_val, is2_var2_val, is2_var3_val }, // iV2[2]
   { is2_var1_val, is2_var2_val, is2_var3_val }, // iV2[3]
   { is2_var1_val, is2_var2_val, is2_var3_val }  // iV2[4]
 }
};

If your C compiler supports C99 you can also use named initializers:
Code:
outerVars_t   EEMEM   EE_Vars = {
 .outerVar1 = 22,
 .innerVars1[3].var2 = 0xF3,
 .innerVars2[1].var3 = -17
};

Cliff

_________________
 
 View user's profile Send private message  
Reply with quote Back to top
Display posts from previous:     
Jump to:  
All times are GMT + 1 Hour
Post new topic   Reply to topic
View previous topic Printable version Log in to check your private messages View next topic
Powered by PNphpBB2 © 2003-2006 The PNphpBB Group
Credits