PROGMEM woes

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

I can't get to work at all using the g++ WinAVR toolchain. I've read all the tutorials I could find.

Each of the following lines of code is followed by the compiler's complaint:

15: #include
...

583: const char PROGMEM newlineP[] = "\n" ;
LCD_Test.CPP: In function 'int main()':
LCD_Test.CPP:583: warning: '__progmem__' attribute ignored

{ ??? WHY is it being ignored ??? }

584 static const char PROGMEM newlineP5[] = "\n\n\n\n\n" ;
LCD_Test.CPP:584: warning: only initialized variables can be placed into program memory area

{ It looks perfectly initialized to me ! }

I'm using the following compile command :

avr-g++.exe -mmcu=atmega16 -lm -DF_CPU=16000000UL -Os -funsigned-char -funsigned -bitfields -fpack-struct -fshort-enums -Wall -Wundef -Wno-unused-variable -I. -ID:\AVR_INCLUDE_RDP LCD_Test.CPP --output LCD_Test.elf

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

For what it's worth, here's the #include file I use to provide macros that apply "put this in FLASH" attributes to data items. Pragmatically, it currently works for me (and I periodically inspect the final project.lss and .map files to make sure), but I have no clue as to why.

// forceFlash.h - Macro to add a "put this in the FLASH" attribute
//
// The stock WinAVR distribution provides a  include file
// that provides a "PROGMEM" macro allegedly for doing this, but
// the C++ compilation erroneously complains about the resulting
// memory layout.   A couple brilliant people on the "AVR Freaks"
// website found and posted this workaround, which takes advantage
// of the fact that the standard linker scripts add a wildcard '*'
// character at the end of the instructions for dealing with the
// '.progmem' section, which means (apparently) that all sections
// whose names start with '.progmem' are collected up.   Whatever
// bug the C++ compiler has seems to be mollified if it thinks that
// the named section one tries to force a definition into is a 'data'
// section, which it doesn't check too carefully for.   Any section
// name with 'data' (or maybe, ending in '.data') in it is OK, so
// if one names one's FLASH-resident section as '.progmem.data' ,
// the compiler is happy
//
#ifndef FORCEFLASH
#define FORCEFLASH __attribute__((section(".progmem.data")))


// Well, happy, that is, unless you try to apply the above attibute
// to more than one variable in the same module.  I despair of ever
// knowing what the rules are, so here are some more variations on
// the theme.  It seems that having N forced-to-FLASH allocations in
// a single file is OK so long as you make up N different section
// names for them..
//
#define FLASHSTRING __attribute__((section(".progmem.flashString")))
//
#define FLASHTABLES __attribute__((section(".progmem.tables")))

#endif

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

I suspect that the variable is a local variable, i.e. defined inside a function. AFAIK you can't combine that with PROGMEM. Make it a global variable.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

Yup. Just tested it. The conflict lies in the facts that

i) a local variable exists just for the duration of the execution of the function, and
ii) a PROGMEM variable exists for the duration of the execution of the program - they can't, per definition since they are in slash memory, cease to exist when a function exits.

I believe we've talked to you before about providing minimal programs that demonstrates the problem. In this case the minimal demo is actually as small as it can get:

#include 
#include 

int main(void)
{
  const char PROGMEM local[] = "\n" ;
  
  while(1) {}
}

This will produce the warning. The very slightly larger program that shows that it has to do with the variable being local looks like this:

#include 
#include 

const char PROGMEM global[] = "\n" ;

int main(void)
{
  const char PROGMEM local[] = "\n" ;
  
  while(1) {}
}

The variable 'global' does not result in any warning.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

JohanEkdahl wrote:
Make it a global variable.
Or static local.

Stefan Ernst

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

Darn! I was just out of 'freaks and in Studio to test that before I posted..

Yes, if you really want the scope of the variable to be just inside the function then

  const char static PROGMEM local[] = "\n" ;

will do that.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

JohanEkdahl: Yes, you provided a minimal program, but did you actually compile it yourself ?

My results:

TRY.CPP:5: warning: only initialized variables can be placed into program memory
area
TRY.CPP: In function 'int main()':
TRY.CPP:9: warning: '__progmem__' attribute ignored

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

Levenkay, Does your macro def take the place of including and using ?

I'd appreciate it if you would show a simple usage example.

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

Quote:
TRY.CPP:5: warning: only initialized variables can be placed into program memory
area
AFAIK that is a bug fixed in 4.6. You can use this as workaround:

#undef PROGMEM
#define PROGMEM __attribute__((section (".progmem.data")))

Edit:
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=34734

Stefan Ernst

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

There might be C vs. C++ issues here as well.

Iluvatar is the better part of Valar.

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

The version of gcc/g++ supplied with WinAVR is 4.3.3, which explains the bug. I don't remember reading about PROGMEM being broken in the "known bugs". Version 4.6 hasn't been released yet.

PROGMEM is working for me using the following patch:

#include
#include

#ifdef PROGMEM
#undef PROGMEM
#endif
#define PROGMEM __attribute__((section (".progmem.data")))

static const char PROGMEM global[] = "ABC" ;

int main(void)
{
static const char PROGMEM local[] = "abc" ;

while(1) {}
}

Compiling/linking and then running:

> avr-size.exe -A TRY.elf | D:\DATA\UTIL\Find.exe /I ".text"
.text 114 0

> avr-size.exe -A TRY.elf | D:\DATA\UTIL\Find.exe /I ".data"
{{ NO OUTPUT }}

This proves that the PROGMEM redef works properly.

Thanks, skeeve !

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

Quote:

Yes, you provided a minimal program, but did you actually compile it yourself ?

Yes, but I missed to switch to the WinAVR-20100110 tool chain in studio. Sorry about that.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

The warning "only initialized variables...." has been emitted by the C++ compiler for several years. It happens to me whenever PROGMEM is used. Ignore it. The bug is in the compiler, not your code. Your code should work fine.

I think I've seen rumors that this extraneous warning bug has been fixed in the Atmel tool chain.

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

Quote:
I think I've seen rumors that this extraneous warning bug has been fixed in the Atmel tool chain.

It has. As my posts above hints at: Compiling with AVR Toolchain (as in Atmel Studio 6) does not emit that warning. Compiling with WinAVR-20100110 does.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

pascor wrote:
Version 4.6 hasn't been released yet.
It has been released. And 4.7 too.

WinAVR is a package containing avr-gcc (and related stuff) and some other tools. Eric Weddington has stopped making that package. But that does not mean that you can't get a newer avr-gcc (besides the one released by Atmel). If you don't want to compile it by yourself, you can find pre-build binaries here in the forum.

Stefan Ernst

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

steve17 wrote:
The warning "only initialized variables...." has been emitted by the C++ compiler for several years. [...] I think I've seen rumors that this extraneous warning bug has been fixed in the Atmel tool chain.
That's nothis specific to the Atmel tool chain.

It has been fixed in 4.6.2, thus any release that bases on 4.6.2 or newer will come with the fix.

avrfreaks does not support Opera. Profile inactive.

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

4.7.2 bug is still here.

In file included from :114:0:
./dac.c:83:31: warning: uninitialized variable 'dac_out_range' put into program memory area [-Wuninitialized]

If I add next lines warning is gone.

#ifdef PROGMEM 
#	undef PROGMEM 
#endif 
#define PROGMEM __attribute__((section (".progmem.data")))

Unfortunately, I still find it difficult to make a minimal test case.

dac.i

void dac_update(uint8_t ch, float x)
{
# 76 "./../../../arclib/common/metrology/dac.c"
 typedef struct
 {
   uint16_t lo;
   uint16_t hi;
 } range_t;

 static const range_t __attribute__((__progmem__)) dac_out_range[] =
 {
   {0UL, 0UL },
   {(0UL + ((uint32_t)(((16055UL - 0UL)/5.0f)+0.5f))), 16055UL},
   {0UL, (0UL + ((uint32_t)(((16055UL - 0UL)/4.0f)+0.5f))) },
   {0UL, 16055UL},
   {(0UL), (0UL + ((uint32_t)(((16055UL - 0UL))+0.5f))) },
   {(0UL), (0UL + ((uint32_t)(((16055UL - 0UL)/10.0f)+0.5f))) }
 };

dac.s

.LVL35:
.LBE35:
	.cfi_endproc
.LFE43:
	.size	dacs_off, .-dacs_off
	.section	.progmem.data.dac_out_range.2902,"a",@progbits
	.type	dac_out_range.2902, @object
	.size	dac_out_range.2902, 24
dac_out_range.2902:
	.word	0
	.word	0
	.word	3211
	.word	16055
	.word	0
	.word	4014
	.word	0
	.word	16055
	.word	0
	.word	16055
	.word	0
	.word	1606
	.text

and with redefined PROGMEM as __attribute__((section (".progmem.data")))

 static const range_t __attribute__((section (".progmem.data"))) dac_out_range[] =
...
	.section	.progmem.data,"a",@progbits
	.type	dac_out_range.2902, @object
	.size	dac_out_range.2902, 24
dac_out_range.2902:
	.word	0
...