Storing to flash memory with PROGMEM

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

A newbie using Atmel Tiny 87, using Studio 7

"C:\Program Files\Atmel\Studio\7.0\Vs\Compiler.targets"

...Invoking: AVR/GNU Linker : 4.9.2

#include <avr/pgmspace.h>
const unsigned char array[] PROGMEM =
{
0x01, 0x02, 0x03
};

(actual data length is 256 bytes)

 

Execute 'Build solution' results = Error listed as "multiple definition of array, removing 'const' = error message that 'const' needed with PROGMEM.

 

My understanding is that AVR storing to Flash space is tricky and that read-back is by &Address pointer?

 

What's the trick? Thank you.

 

Albert

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

"Multiple definition of array" sounds like you have those lines in an H file and are included it into multiple C or CPP files. You can't do that.

 

Make the declaration once in a header file and define the data in a source file.

My digital portfolio: www.jamisonjerving.com

My game company: www.polygonbyte.com

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

Jamison,

 

I was doing this only in a header file (as with another processor).

 

Breaking the array description in the header file first as:

const unsigned char array[256];

...and then in the c file as:

const unsigned char array[] PROGMEM = {....DATA...}

...cured the compiler's confusion.

 

Thank you very much

AL

 

Albert

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

It is possible that this creates two arrays: one in the static RAM that is 256 bytes in size, and the other in flash that the compiler is reserving an address for the location of the first element.  It is possible that both arrays could have the same name because they are located in different memory spaces.  Just because code compiles doesn't mean that it will work correctly.

 

For "tricky" AVR memory constructions, I would do a Google search for how it is done in Arduino main code files ( which are extentioned .ino) and various Arduino C++ libraries.  Then convert its format into "real" C++.  It's all GCC AVR anyway, if you're lucky.

 

For example, here is code for using indexed strings of different lengths which are stored in flash:

const char month01[] PROGMEM = "January";     
const char month02[] PROGMEM = "February";
const char month03[] PROGMEM = "March";
const char month04[] PROGMEM = "April";
const char month05[] PROGMEM = "May";
const char month06[] PROGMEM = "June";
const char month07[] PROGMEM = "July";
const char month08[] PROGMEM = "August";
const char month09[] PROGMEM = "September";
const char month10[] PROGMEM = "October";
const char month11[] PROGMEM = "November";
const char month12[] PROGMEM = "December";

const char * const  monthStrs[ 12 ] PROGMEM = {              
   month01, month02, month03, month04, month05, month06,       
   month07, month08, month09, month10, month11, month12 };  
   
 char * ptr, showBuffer[11];
    ptr = (char *) pgm_read_word ( & monthStrs[month -1] );
    strcpy_P (showBuffer, ptr);
    tft.print (showBuffer);

 

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

AlbertIP wrote:
Breaking the array description in the header file first as:

const unsigned char array[256];

...and then in the c file as:

const unsigned char array[] PROGMEM = {....DATA...}

...cured the compiler's confusion.

There is no "confusion": the Linker (not compiler) was perfectly correct to say that you were making multiple definitions of the array.

 

A declaration with initialisation will always be a definition - so, if you do that in a header that's included in multiple .c files, you will get "multiple definition" Linker errors.

 

http://c-faq.com/decl/decldef.html

 

[sorry - the c-faq.com DNS seems to be broken at the moment]

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Simonetta wrote:
It is possible that this creates two arrays: one in the static RAM that is 256 bytes in size, and the other in flash

No - it's because the definition was in a header file that was included in multiple 'C' files.

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

awneil wrote:
it's because the definition was in a header file that was included in multiple 'C' files.
And still is. An "extern" is missing.

Stefan Ernst

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

Albert, awneil and Simonetta have provided some very valuable information. Make sure you understand it.

 

AlbertIP wrote:
...cured the compiler's confusion.

As sternst has eluded, it fixed the compiler's confusion but not the problem. Your header file needs an "extern" on the array declaration in order to say "the definition is somewhere else" so that source files that include the header can know this. I don't have access to AVR-GCC on this computer but I believe the PROGMEM macro also needs to carry over in both the source and header. Others may be able to verify this.

My digital portfolio: www.jamisonjerving.com

My game company: www.polygonbyte.com