__flash and arguments

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

I have a simple program with some string in __flash (using gcc 4.7.2)

#define _FLASH 	  const __flash
char _FLASH unit_strings[3][7] = { "Metric", "Imp US", "Imp UK" };

Now I can use command like

lcd_printP(unit_strings[1]);

which works fine, lcd_print_P accept a const __flash char* argument.

But now I want to pass unit_strings in argument to another function like

config_item(&param, unit_strings);

I tried this proto but it does not work

void config_item(uint8_t *p, const __flash **char);

GCC says:

note: expected 'const __flash char **' but argument is of type '__flash const __flash char (*)[7]'

trying const __flash *char[] in the proto does not work either.

trying to declare unit_string with char* _FLASH unit_strings[3] = { "Metric", "Imp US", "Imp UK" }; does not work either.

Can I pass unit_strings in argument to a function?

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

The diagnostic tells you how to write the correct param declaration:

extern char f (const __flash char (*var)[7]);

The "7" is needed to find the right place to read a char.

Notice that a 2-dimensional array is not a one-dimensional array with pointers.

There are several ways to model arrays of strings, cf. http://www.mikrocontroller.net/a...

avrfreaks does not support Opera. Profile inactive.

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

oh right, compiler needs to know the size of the strings...

so I changed this as:

char _FLASH strMetric[] = "Metric";
char _FLASH strImpUS[]  = "Imp US";
char _FLASH strImpUK[]  = "Imp UK";
_FLASH char* _FLASH unit_strings[] = { strMetric, strImpUS, strImpUK };

void config_item(uint8_t *v, _FLASH char* _FLASH *item_str);

and it compiles fine, now I need to test if inside config_item I can use item_str[1] for instance. Using __flash I do not need pgm_read_* function to access item inside the array, right?

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

Right. __flash is only needed in the declarations / definitions. The C code to access is vanilla C.

avrfreaks does not support Opera. Profile inactive.

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

I can confirm it works fine using call like

lcd_print_P(item_str[i]);

in my config_item() function, no need of any progmem stuff, just the right declaration. And all my strings and array are in flash, nice!

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

I'm using avr-gcc (AVR_8_bit_GNU_Toolchain_3.5.4_1709) 4.9.2, but it doesn't seem to like the __flash keyword - is there anything special I need to do to use it?

 

for instance

void dbg_print_msgnum(const __flash char * message, unsigned number);

results in

error: '__flash' does not name a type

 

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

That's a little curious as I thought __flash was added around 4.6 so one would expect it in 4.9.2

 

EDIT: confirmed. I went back through the history of GCC releases and the 4.6 manual did not mention __flash/__memx but by 4.7.4 there was this:

 

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

 

So this REALLY is odd!!

Last Edited: Thu. May 3, 2018 - 09:20 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
So this REALLY is odd!!
C++ perhaps?

Stefan Ernst

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

sternst wrote:

C++ perhaps?

 

Yes! I just figured this myself after seeing this thread. My first thought was I would just fix it my putting the implementation in a .c file and use extern "C" in the header in case of c++, but that doesn't work, of course, since an extern "C" block is still compiled by g++, not gcc (and I won't drop using c++) when included in a .cpp file. So back to old PROGMEM, I suppose, which is a pity since I was hoping to use __flash for function overloading, having one function for constant strings in flash, and another for strings in ram.

Last Edited: Thu. May 3, 2018 - 12:13 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If avr-gcc is invoked with .c files they are passed to the C compiler and if it is invoked with .cpp files they are passed to the C++ (avr-g++) compiler.

 

Atmel in their wisdom, when asked to create a "C++ project" in AS7 pass all files to avr-g++. Only God knows why they did it like this. But a couple of possibilities:

 

1) create an "external makefile" and use that - use something like Mfile to create it - it will pass everything to avr-gcc as intended.

 

2) build the __flash stuff as a separate project (a static lib - I knew there had to be a reason for it!!). Create that as a "C Static library". Then link the C++ to it and remember to use extern "C" in the shared .h file to remind C++ to use C linkage.

 

But I suppose it doesn't matter - the real power of __flash (over PROGMEM) is the implied LPM in the dereference so the access stuff in the C++ is still going to end up using pgm_read_XXX() so I guess it doesn't matter much if the data itself is "const PROGMEM" rather than "const __flash".

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

clawson wrote:
Atmel in their wisdom, when asked to create a "C++ project" in AS7 pass all files to avr-g++. Only God knows why they did it like this.

So if you tell AS7 that it's a 'C' project, but call all your files *.cpp - what happens ... ?

 

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...