String in flash question.

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

Hi all

 

I want to setup a sting in flash to store the time my program was compiled currently I am doing :

 

#define NOW "compiled at " __TIME__ " on " __DATE__ "\n"

#define log0(format,...) fprintf_P(&ser0stream,PSTR(format),##__VA_ARGS__) 

int main(void)
{
   	log0(NOW);
}

 

This works fine, but I want to be able to access the compile time from other modules in my program so I tried :

char			CompileTime[] PROGMEM = NOW;

But I get the error :  error: variable 'CompileTime' must be const in order to be put into read-only section by means of '__attribute__((progmem))'

 

How should I go about defining this, I have tried searching but all the examples I can find seem to be for generating just plain constant strings.

 

Cheers.

 

Phill.

 

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

prime wrote:
How should I go about defining this
You have never used any const variables before?

const char  CompileTime[] PROGMEM = NOW;

 

Stefan Ernst

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

sternst wrote:

prime wrote:

How should I go about defining this

 

You have never used any const variables before?

I have but really only as paremeters to functions, didn't think of using it here :)

 

Quote:

const char  CompileTime[] PROGMEM = NOW;

 

Yep that seems to have done the trick thanks.

 

Phill.

 

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

If you are writing new code then why are you still using PROGMEM? Surely __flash (4.7 onwards) is now the better solution? (no need for pgm_read_*() functions).

 

(BTW __flash still needs things to be "const" - in fact it was during the addition of __flash that the insistence that flash based data be "const" was added).

Last Edited: Thu. Mar 9, 2017 - 10:20 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:

If you are writing new code then why are you still using PROGMEM? Surely __flash (4.7 onwards) is now the better solution? (no need for pgm_read_*() functions).

Atmels docs still seem to suggest using it....I'd found these via a google search :)

 

http://www.atmel.com/webdoc/avrlibcreferencemanual/pgmspace_1pgmspace_data.html

 

Quote:

(BTW __flash still needs things to be "const" - in fact it was during the addition of __flash that the insistence that flash based data be "const" was added).

 

The bit documenting this is in a section on porting from IAR, which is probably why I didn't find it, I'll have a read now :)

 

Cheers.

 

Phill.

 

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

prime wrote:
Atmels docs still seem to suggest using it....
Out of date manual!

 

The key page for documenting the newly added "__flash" is actually:

 

https://gcc.gnu.org/onlinedocs/g...

 

That is part of the COMPILER manual not the AVR-LibC manual because this function is now built into the core of the compiler instead of requiring support from pgmspace.h (which is part of AVR-LibC).

 

There is also (brief) mention of __flash in this part of the GCC documentation too:

 

https://gcc.gnu.org/wiki/avr-gcc

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

Right,

 

Thanks for the pointers, variable now defined as :

const __flash char CompileTime[]  = NOW;

 

So if I wanted to copy this into a RAM buffer, would I still need to use strcpy_P ?

 

Cheers.

 

Phill.

 

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

yes, __flash still requires the _P() functions if you want to use those kind of library calls.

 

Where __flash comes into it's own will be when you might have written:

PORTB = pgm_read_byte(&CompileTime[7]);

and can now write:

PORTB = CompileTime[7];

Because CompileTime was defined as "__flash" the compiler knows where the 8th byte is located (flash) and that to read it the LPM instruction must be used.

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

Right that all works as I want for my main application, but if I wanted to do a similar thing for my bootloader which could be read by my main application what would be the best way of doing this?

 

I guess I'd still need something like :

 

const __flash char BLCompileTime[]  = NOW;

In my bootloader code, and some sort of pointer to it in my main application code but not sure exactly how?

 

Using Mega644 at the moment, but possibly 1284 depending on how big code grows, and if I need more RAM....

 

Cheers.

 

Phill.

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

Well the data is an array of "const _flash char" so the pointer to it would be:

const __flash char * pMsg;

Now when you access *pMsg it will do an LPM to get the byte at the address held in pMsg.

 

The old mechanism is still available so you could pgm_read_byte(&BLCOmpileTime[n]); too if you prefer to think of it that way. (with an include of avr/pgmspace.h of course).

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

clawson wrote:

Well the data is an array of "const _flash char" so the pointer to it would be:

const __flash char * pMsg;

Now when you access *pMsg it will do an LPM to get the byte at the address held in pMsg.

 

The old mechanism is still available so you could pgm_read_byte(&BLCOmpileTime[n]); too if you prefer to think of it that way. (with an include of avr/pgmspace.h of course).

Indeed, but how do I make it point to the string that is stored in the bootloader section?

I'm wanting to do this from the main app not the bootloader itself?

 

Cheers.

 

Phill.

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

Put it at a fixed place in the bootloader like 0x1234. Then:

const __flash char * pMsg = (const __flash char *)0x1234;

in the app code. If 0x1234 really does contain "Hello" then pMsg[1] == 'e' etc.

 

For the bootloader I would use (dropping __flash as it will be obvious it's in flash when it is given an address to position it):

const char BLCompileTime[] __attribute__((section(".bootstr"))) = NOW;

and later:

-Wl,-section-start=.bootstr=0x1234

as a command to the linker.

 

Use something other than 0x1234 to arrange to have it placed somewhere up near the end of the bootloader section - well out of the way of the code that lives there.

 

The 0x1234 value (or whatever it is) is then the only "shared secret" between the bootloader and the app.

 

Still use a __flash pointer in the app section to access it as it will need to use LPM to get the characters from the flash location.