PSTR compilation error.

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

Hi, all!
I have compilation error:

variable "˜__c' must be const in order to be put into read-only section by means of "˜__attribute__((progmem))'

The error points me to string

SendString2 (PSTR("123"));

I'm surprised string "123" is not const enough.

I've googled it and the only thing I have found at the moment is that this error is fixed in AVRLibC 1.7.1.
But upgrading from my 1.6.8 to 1.7.1 changed nothing.
How could it be fixed?

I'm using GCC-4.6.1.

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

Compile with --save-temps then take a look at the .i file to see how PSTR() has expanded out.

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

Expanded function call:

SendString2 ((__extension__({static char __c[] __attribute__((__progmem__)) = ("1123"); &__c[0];})));
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Did you say whether this was C or C++. I'm guessing the latter if it's more finicky about types. As a short term fix maybe try editing pgmspace.h and changing:

# define PSTR(s) (__extension__({static const char __c[] PROGMEM = (s); &__c[0];}))

Maybe see this thread too:

http://lists.gnu.org/archive/htm...

of perhaps more usefully this:

https://www.avrfreaks.net/index.p...

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

SlackAVR wrote:
I'm using GCC-4.6.1.

In newer versions of avr-gcc such as this, all variables with __attribute__((__progmem__)) must be tagged const.

The easiest way is to go and modify the #define PSTR in .

Be aware that there are more problems ahead in newer versions of avr-gcc. I'd stick to a proven version such as 4.3.x - I see nothing substantial to be gained by going for the bleeding edge here.

JW

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

I'm using Plain C.
Thanks, your advise to add "const" to definition of PSTR worked.
But it's not clear for me why it wasn't there.

I also had to install AVRLibC 1.6.8 back.
I had some undefined references to "fabs" and "__builtin_avr_delay_cycles" from delay.h while linking with 1.7.1.

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

Quote:

But it's not clear for me why it wasn't there.

Because AVR_LibC has not caught up to 4.6.1 yet.
Quote:

I had some undefined references to "fabs" and "__builtin_avr_delay_cycles" from delay.h while linking with 1.7.1.

Then you aren't using the functions correctly.

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

wek, thank for advise - I'm back to 4.3.4.
And it works even without "const" in PSTR definition.

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

Note that there are rumours of a new WinAVR in a few months and there's a strong possibility it could be 4.6.1 based in whch case it's almost certainly the case that there'll be an AVR-LibC update to match it.

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

Okay, thank you for rumours, I noted that.

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

I try to understand AVR memory management. And have another one question.

Quote:
Because the LCD_puts routine (or other string routines) are designed to work with strings in RAM, the compiler is forced to read out the entire string constant from program memory into RAM, and then pass the string's RAM pointer to the routine (in this case LCD_puts). It certainly works but the RAM wastage adds up to significant amounts with each string. Why?

In my case it does not work. Why?

void SendString (char *_String)
{
  while (*_String) SendChar(*_String++);
}
...
SendString ("Long-long-long String!\n");
...

I get string of some 0xFF.
Maybe I understand something wrong in "Progmem Basics"?

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

But the code you just posted has nothing to do with PROGMEM/PSTR at all? Everything is in RAM - it should just work.

(However you are doing the avr-obcopy properly so that .data is in flash aren't you?)

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

Quote:
(However you are doing the avr-obcopy properly so that .data is in flash aren't you?)

Exactly! I forgot to include data section into flash.
Great thanks! Now I can work with (and in) RAM and study "Progmem Basics".

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

Quote:

Exactly! I forgot to include data section into flash.

Use Mfile and avoid this and 50 other problems you haven't yet encountered.

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

Maybe this could help you a little

//------------------------------------------------

//send string located in RAM
void SendString (char *_String)
{
  while (*_String) SendChar(*_String++);
}

//------------------------------------------------

//send string located in FLASH
void SendString_P (const char* _String) 
{
unsigned char temp;

   while((temp = pgm_read_byte(_String++)))
   {
   SendChar(temp);
   }
}

//------------------------------------------------

//declare string located in RAM
char ram_str[]= "inram";

//declare string located in FLASH
char flash_str[] PROGMEM = "inflash";

//------------------------------------------------

int main (void)
{

   //send string located in RAM
   SendString(ram_str); 

   //send string located in FLASH
   SendString_P(flash_str); 


   SendString_P(PSTR("Anonymous string"));
   //compiler places anonymous string in FLASH
   //ergo you have to use  SendString_P()

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

Quote:
Use Mfile

Downloaded, had a short view on it. Not sure I'll use it as it's too complicated, but maybe I'll look at makefile_template sometimes.

And other one note:

Quote:
Although it is not an absolute requirement, we can remind ourselves - and possibly prevent bugs further down the track - that the string cannot be changed at all during execution by declaring it as a constant:

const char FlashString[] PROGMEM = "This is a string held completely in flash memory.";

Quote:
Now that the PROGMEM string has a "const" modifier, we cannot try to modify it in our code.

In my case it is not necessary to use "const" modifier. I couldn't modify PROGMEM variable in my program even without "const". And no errors occurs during compilation and no runtime bugs.
If this is not only my case (compiler version, MCU or something else) maybe we should note that "const" is not necessary - it's just to avoid warnings?

I've seen much searches and questions on the web about bugs produced by using PROGMEM on local variables without "static" modifier. Without it we'll get:

warning: '__progmem__' attribute ignored

Maybe we should mention at this place in "Progmem Basics" about that local program space variables should be marked as "static"?
Dean didn't mention he uses global variable at that moment at all. But being local or global variable is significant difference while using PROGMEM attribute.

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

Surely it's obvious that something with dynamic rather than static allocation could not be placed in flash?

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

SlackAVR wrote:
I've seen much searches and questions on the web about bugs produced by using PROGMEM on local variables without "static" modifier. Without it we'll get:
warning: '__progmem__' attribute ignored

Maybe we should mention at this place in "Progmem Basics" about that local program space variables should be marked as "static"? Dean didn't mention he uses global variable at that moment at all. But being local or global variable is significant difference while using PROGMEM attribute.

It's not important if they are global or local. What counts is if they are in static storage or not. Just think a minute and you'll find that it makes no sense to have an auto variable or parameter in Flash. How should the code look like?

avrfreaks does not support Opera. Profile inactive.

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

Quote:
Not sure I'll use it as it's too complicated,
Surely it is far less complicated than writing your own makefile.

Regards,
Steve A.

The Board helps those that help themselves.

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

SlackAVR wrote:
Quote:
Although it is not an absolute requirement, we can remind ourselves - and possibly prevent bugs further down the track - that the string cannot be changed at all during execution by declaring it as a constant:
const char FlashString[] PROGMEM = "This is a string held completely in flash memory.";

Now that the PROGMEM string has a "const" modifier, we cannot try to modify it in our code.

In my case it is not necessary to use "const" modifier. I couldn't modify PROGMEM variable in my program even without "const".
Of course you can:
void * foo (void)
{
    static char test[] PROGMEM = "test";
    *test = 'A';
    return test;
}

will pass without complains and modify a place in RAM. I don't think that's what you want, is it?

SlackAVR wrote:
And no errors occurs during compilation and no runtime bugs.
Told 1000 times before: No errors at runtime or compile time does not prove that your program is correct! You have just the converse: If you get an error then you know your program is not correct. Think about the difference.
SlackAVR wrote:
If this is not only my case (compiler version, MCU or something else) maybe we should note that "const" is not necessary - it's just to avoid warnings?
From avr-gcc 4.6 upward const qualifier is no more sugar: you will need the const in each and every place you put data in flash by means of PROGMEM aka. __attribute__((progmem)). You may think it's annoying but as you saw above, it helps to make your code more robust — so get used to that qualifier, it's not a loss.

And if your bootloader or magic software or external wizard like OCDS/JTAG or LASER or X-Ray or electron gun or whatever can change data in flash it is still constant! The appropriate definition/declaration in such a case is:

const volatile int PROGMEM = 42;

Notice that this applies to any constant data that can be changed like calibration data or serial number etc. that resides in a read-only section like, e.g. .rodata. "volatile const" prevents the compiler from inserting the constant's value into the code like LDI 42 in case of

static const volatile int the_answer = 42;

int get_answer (void)
{
    return the_answer;
}

avrfreaks does not support Opera. Profile inactive.