## avr-gcc 4.6.1 const string literal

10 posts / 0 new
Author
Message

Hi,

unfortunately I updated my avr-gcc today to 4.6.1. Now it is complaining about this line:

strcpy_P(menu[0], PSTR("Stat"));


With the following error message:
error: variable '__c' must be const in order to be put into read-only section by means of '__attribute__((progmem))'

Until now I thought string literals like above are const?! :shock:
How can I fix this or is the only way to go back to 4.5.3?

Thanks,
Markus

You'll need a similarly updated version of avr-libc. In the meantime, you can edit this in pgmspace.h of your library:

#if defined(__DOXYGEN__)
/*
* The #define below is just a dummy that serves documentation
* purposes only.
*/
/** \ingroup avr_pgmspace
\def PSTR(s)

Used to declare a static pointer to a string in program space. */
# define PSTR(s) ((const PROGMEM char *)(s))
#else  /* !DOXYGEN */
/* The real thing. */
# define PSTR(s) (__extension__({static char __c[] PROGMEM = (s); &__c[0];}))
#endif /* DOXYGEN */

To this:

#if defined(__DOXYGEN__)
/*
* The #define below is just a dummy that serves documentation
* purposes only.
*/
/** \ingroup avr_pgmspace
\def PSTR(s)

Used to declare a static pointer to a string in program space. */
# define PSTR(s) ((const PROGMEM char *)(s))
#else  /* !DOXYGEN */
/* The real thing. */
# define PSTR(s) (__extension__({static const char __c[] PROGMEM = (s); &__c[0];}))
#endif /* DOXYGEN */

Note the const qualifier added to the actual PSTR() definition, which is required for PROGMEM allocated variables in GCC 4.6 onwards.

- Dean :twisted:

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

Oh, I wish there were a way to "flag" postings, on a user-by-user basis. Here is one I need to pay attention to until it is no longer relevant.

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

You don't, Jim.

It will catch you hard when you get there - you will be told zillions of times by the compiler... :-)

Meantime, you might want to change your coding habits and start adding "const" to each PROGMEM variable you create.

You might also start to vote against SprinterSB's movement to remove the typedefs from pgmspace.h before replacing them with the forthcoming "true" named space support.

Jan

Quote:
You might also start to vote against SprinterSB's movement to remove the typedefs from pgmspace.h before replacing them with the forthcoming "true" named space support.

But the typedefs don't work. Aren't allowed to work. "Attributes do not apply to types", they say.
http://gcc.gnu.org/bugzilla/show...

Or is the vote against the "before" qualifier?

While the typedefs might have never been supported officially, during the last years nobody complained about they not working everywhere except C++ - which can be "solved" by documenting this.

And, once they have been provided, there's no reason to break existing code and force users to rewrite their sources, if there's a hope they will work in the foreseable future - even if on different grounds.

Thus, if anybody has an unsuppressable urge to change on that detail rather than solve real problems, I'd suggest to replace them by macros as an interim step.

JW

butterface wrote:
avr-gcc today to 4.6.1. Now it is complaining about this line:
strcpy_P(menu[0], PSTR("Stat"));

With the following error message:
error: variable '__c' must be const in order to be put into read-only section by means of '__attribute__((progmem))'

You ran into https://savannah.nongnu.org/bugs... (fixed in 1.8.0?) and/or into http://gcc.gnu.org/PR49764 (fixed for 4.6.2+).

wek wrote:
You might also start to vote against SprinterSB's movement to remove the typedefs from pgmspace.h before replacing them with the forthcoming "true" named space support.
I won't remove anything, it's just a recommendation to the avr-libc maintainers to do respective changes â€“ it's up them to weight robustness of code against zillions of users crying for a nonsensical feature.

Nonsensical that the compiler ever accepted it.

You see that it's nonsense (despite other type attributes like packed or deprecated etc.) as soon as you try to compose an aggregate out of aggregates/types in progmem and other, standard types living in RAM. Even more nonsensical would be to go through all of this and emit proper diagnostics in each and every place for such stuff and put effort and resources into that corner. I do not see any improvement in it.

Named address spaces won't be a drop-in replacement for avr/pgmspace.h, anyway. They are independent of each other and if there will ever be named addresses you will have to rewrite your code if you like to use/try it.

wek wrote:
While the typedefs might have never been supported officially, during the last years nobody complained about they not working everywhere except C++ - which can be "solved" by documenting this.
No.

In C, it works per accident and not per design. Similar for C++, the other way round. I'd never document something that's unspecified and works/does not work accidentally. My strong preference is to error if progmem is seen in a type decl.

avrfreaks does not support Opera. Profile inactive.

Last Edited: Mon. Sep 26, 2011 - 07:08 PM

SprinterSB wrote:
You see that it's nonsense (despte other type attributes like packed or deprecated etc.) as soon as you try to compose an aggregate out of aggregates/types in progmem and other, standard types living in RAM. Even more nonsensical would be to go through all of this and emit proper doagnostics in each and every place for such stuff and put effort and resources into that corner. I do not see any improvement in it.
With due respect to your work, I don't know how much you *use* avr-gcc and other compilers for various 8-bit microcontrollers, but thorough support for memory classes - or named spaces, whatever you call it - was always an important point for usability of those compilers. Then those compilers pay the required attention to all those details you mentioned.

Now we all know that gcc is simply not a microcontroller-oriented compiler and the progmem support is a kludge; still that kludge was designed acording to those already established principles. I might be wrong, but I suspect the typedefs and macros were put into pgmspace.h exactly because they mirror similar features, I believe according to IAR's, weren't they.

So if you stand back for a while and try to look at pgmspace.h without the developer hat, with the eyes of the everyday user of avr-gcc, you'll see that there's a need for shorthands for "create me a byte in FLASH" and "create me a pointer sitting in RAM and pointing to a byte in FLASH" - and that's exactly what those typedefs do.

SprinterSB wrote:
Named address spaces won't be no drop-in replacement for avr/pgmspace.h, anyway. They are independent of each other and if there will ever be named addresses you will have to rewrite your code if you like to use/try it.
You've got it the other way round. pgmspace.h is a continuity plan - we use it in today's programs in the hope that in future every bit of it will continue to work, even if in a potentially suboptimal way.

If you say that after implementation of progmem through named spaces the old programs using progmem.h couldn't be compiled and run (with a new progmem.h and avr-libc), then it's about time (or even late) to make a new plan.

SprinterSB wrote:
In C, it works per accident and not per design.
I explained above that it's a feature needed by users. Ergo it should've be been fixed to work per design. I don't plead for that only in the hope of it getting obsolete soon. (And I don't care about C++ which IMO is mostly inadequate for the 8-bitters).

Jan

I got to this page from searching google for the error message.

I just hit this wall now that I've taken avr-libc 1.8

This is because I was definting my program space strings in some lazy way that making use of a, now depreciated, defination in the pgmspace.h file.

http://www.nongnu.org/avr-libc/c...

In the end i just has to add 'const' to my all my definations of the string.

Thanks Dean for clarifing it in his documents.
http://www.fourwalledcubicle.com...

I actaually do it like this.

in my .h file:

#include
#include
#define TERM_MESSAGE(MESSAGE) const char MESSAGE[] PROGMEM
#define TERM_DEF(DEF) extern const char DEF[] PROGMEM

TERM_DEF(version);
TERM_DEF ....

in my .c file:

TERM_MESSAGE(version)  			= "My software Version 6.0.0 \n\n\r";
TERM_MESSAGE...

Then i just add lines using the defines TERM_DEF and TERM_MESSAGE.

its handy when you have 100+ strings and need to slightly modify the way that you are storing them all. Like making it const, or wanting to externalize them all, etc.