Some questions to the attribute 'EEMEM'

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

Hello,

Some questions to the attribute 'EEMEM'

1. Why is the definition of variables with 'EEMEM' in a function not allowed?
2. If I make a casting like

eeprom_write_block((void *)src, (const void EEMEM *)save_in_eeprom, 10);

I get 2 warnings:
warning: 'section' attribute does not apply to types.
warning: passing arg 1 of 'eeprom_write_word' from incompatible pointer type.
Why is it so?
3. With this call

eeprom_write_word(&data_in_eeprom, FLASH_CONSTANT);

I get such a warning:
passing arg 1 of 'eeprom_write_word' from incompatible pointer type
Definitions of this example:

#define FLASH_CONSTANT 0xFFFF
uint16_t EEMEM data_in_eeprom;

Thank you.

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

1. It is allowed; however, such a variable cannot have "automatic" storage class, because that implies that it must be dynamically created and bound to the stack. Obviously, such a variable cannot simultaneously be placed in a separate, statically bound memory space. The language standard specifies that the automatic storage class is assumed by default for any variable defined inside a function block if no other explicit storage class is specified.

If you apply the "static" storage class to such a local variable, the compiler will swallow the EEMEM section attribute just fine.
However, the tangible benefit of bending over backwards to limit such a variable's scope to one function instead of just taking the easy route and making it global is debatable.

2. I find it highly dubious that you're getting a warning about the incorrect use of eeprom_write_word() when you're invoking eeprom_write_block(). Could you please verify this error?

3. I get no such warning when I compile this code:

#include 
#include 
#include 

uint16_t EEMEM data_in_eeprom;
#define FLASH_CONSTANT 0xFFFF 

int main(void)
{
	eeprom_write_word(&data_in_eeprom, FLASH_CONSTANT);
	while(1);
	return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sorry, I mixed some warnings.
To 2:
warning: `section' attribute does not apply to types
warning: passing arg 2 of `eeprom_write_block' discards qualifiers from pointer target type

To3:
warning: passing arg 1 of `eeprom_write_word' from incompatible pointer type

Thank you for your advice.

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

2. Regarding the "passing arg 2..." warning:
You're attaching the "const" qualifier to the EEPROM pointer that's being typecast before being passed into eeprom_write_block(). The specific syntax you've supplied actually implies that the pointer is pointing to an object that you don't want to be modifiable.

GCC is warning you that the function you're calling makes no guarantees of respecting that "const" qualifier.
(In the real world, since you're calling an EEPROM writing function, it's guaranteed that the function *will* attempt to modify the memory being pointed to, so the "const" qualifier is inappropriate.)

Regarding the "'section' attribute..." warning:
Remember that the section attribute would apply to the pointer itself, and not to the object being pointed to by that pointer. (As far as GCC is concerned, the object being pointed to by the pointer is nothing more than an address.)

Applying a section attribute as part of a typecast is meaningless - when you typecast an object, you can only change the way in which the compiler interprets the type of the object. You cannot use typecasting to relocate the object out of one memory section and into another on the fly.

May I see how [b]save_in_eeprom[b] is declared? You might not need to use any typecasting at all.

3. Like I said, the sample code I posted previously compiles without any warnings at all. In which ways does your code differ from my sample?

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

Hello,

The definition is

void EEMEM *save_in_eeprom;

I call this function like this

eeprom_write_block((void *)src, (void *)save_in_eeprom, 10);

and the warnings are gone.

If I call

uint16_t data_temp;
data_temp = FLASH_CONSTANT;
eeprom_write_block(&data_temp, &datain_eeprom, 2);

for the same purpose, there are no more warnings.

By the way, my gcc version is 1.4.3.

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

Hum, I don't think there ever was a version 1.4.3 of GCC that was capable of targeting the AVR.

More likely, your avr-libc version is 1.4.3. That is somewhat out of date, but it should be fine for what we're talking about here.

Quote:
The definition is
void EEMEM *save_in_eeprom;

I call this function like this
eeprom_write_block((void *)src, (void *)save_in_eeprom, 10);

and the warnings are gone.


There may be no warnings, but that is definitely *not* going to accomplish what you are expecting.

For one thing, you're not actually reserving 10 bytes in EEPROM (which is the data size implied by the 3rd argument to eeprom_write_block) -- in fact, you're reserving exactly 2 bytes in EEPROM, and the compiler is set to interpret those 2 bytes as a pointer to a void.

For that invocation of eeprom_write_block, I'd expect a destination in EEPROM that was declared something like this:

char EEMEM save_in_eeprom[10];

In that case, the invocation to eeprom_write_block might look like this:

eeprom_write_block(source, &save_in_eeprom[0], 10);

Or equivalently:

eeprom_write_block(source, save_in_eeprom, 10);

Note that explicit typecasting to the void* type is virtually never necessary - the compiler is able to perform the conversion from any other pointer type to the void* type implicitly.

How much experience do you have with pointers in C in general? I get the feeling you may need to go back to first principles with pointers first, before you should think about diving into more advanced topics like avr-libc's treatment of the AVR's multiple address spaces.

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

Hello,

I would also like to use array if possible. But the number of bytes can only be available at run time, so I have to use dynamic structure. Regarding the memory reservation I do have an allocation before calling eeprom_write_block():

save_in_eeprom = (void *) malloc (ByteCount);

Thanks

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

The version of malloc provided with avr-libc works exclusively on variables in the AVR's SRAM heap. It doesn't work on variables inside EEPROM.