__flash in place of PROGMEM

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

Hello,

 

I place the following in program memory:

 

char __const __flash cflOPTIONS_text[6][5]={"NO","YES", "OFF","ON", "sec","secs"};

 

this works by looking in app memory when debugging.

 

Now when passing cflOPTIONS_text[3] to a function, it passes the correct program memory address, but the function it is passed to sees it as the data memory address, not the program memory address.

I see this explained with PROGMEM (http://www.atmel.com/webdoc/AVRL...), but how do I solve this with __flash?

 

Thank you

 

This topic has a solution.
Last Edited: Wed. Feb 24, 2016 - 10:57 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

WOC wrote:
Now when passing cflOPTIONS_text[3] to a function, it passes the correct program memory address, but the function it is passed to sees it as the data memory address, not the program memory address.

Whatever you pass is just a number! In the case of AVR memory pointers those numbers are usually 16 bit long and allow you to most easily address 0 .. 64K. How you then use that 0..65535 value that comes into the function is then just a matter of interpretation. For example:

void access_data(unsigned int some_addr) {
    const __flash char * flash_ptr;
    flash_ptr = (const __flash char *)some_addr;
    PORTB = *flash_ptr;
}

in this code I just pass in an unsigned int (I suppose it could just as easily have been "void *" ;-) but then I assign it to a pointer to char in const flash. So the:

    PORTB = *flash_ptr;

will make a flash read from whatever value came in in the some_addr variable. If I had used:

void access_data(unsigned int some_addr) {
    * ram_ptr;
    ram_ptr = (char *)some_addr;
    PORTB = *ram_ptr;
}

then the read will be from the RAM address held in some_addr as I have interpreted the value as plain "char *" which is a pointer to RAM.

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

I still cannot seem to get it to read from program address.

 

char __const __flash cflOPTIONS_text[6][5]={"NO","YES", "OFF","ON", "sec","secs"};

 

Calling the function:

 

LCD_DISPLAYvString(cflOPTIONS_text[ucBEEP],10,20)

ucBEEP is either 2 for OFF or 3 for ON (Buzzer status).

10 & 20 are x,y positions respectively for displaying on LCD.

 

The function:

char cString[30];
void LCD_DISPLAYvString(char __const __flash *cflString_ptr, unsigned char ucString_LCDx,unsigned char ucString_LCDy)
{
char __const __flash *ptr;

ptr = (char __const __flash *)cflString_ptr;

 // display string
sprintf_P(cString,PSTR("%s"),*ptr);
//sprintf_P(cString,PSTR("%s"),(char __const __flash *)cflString_ptr);
LCDvPutStr(cString, ucString_LCDx,ucString_LCDy);
}

cString holds the value at cflString_ptr address of data, not of program memory?

LCDvPutStr is the function for displaying contents of cString; but the problem is already in what cString is holding from sprintf_P.

 

What am I doing incorrectly?

 

Last Edited: Tue. Feb 23, 2016 - 01:03 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I don't think you can do it like that. Try something like:

const __flash char msg0[] = "NO";
const __flash char msg1[] = "YES";
const __flash char msg2[] = "OFF";
const __flash char msg3[] = "ON";
const __flash char msg4[] = "sec";
const __flash char msg5[] = "secs";

const __flash * const __flash options[] = { msg0, msg1, msg2, msg3, msg4, msg5 };

I probably got the syntax of that wrong but the point is that you want both the strings themselves in flash and also the table of pointers to the flash strings to be in flash too.

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

That also did not work.

 

From:

ptr = (char __const __flash *)cflString_ptr;

using watch window while debugging,

ptr = 0x0b52

*(ptr) = 0

 

At address 0x0b52 in prog APP_SECTION holds 0x4F for "O" (beginning of "ON"); but *(ptr) is 0?

 

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

Word versus byte addressing? ;-)

 

Have a look at 0x5A9 (0xB52 / 2)

 

Also look at the code generated for the *ptr access  - is it an LPM? (IOW did you get the __flash pointer syntax correct?).

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

I see what you mean with having the __flash pointer as an int not char, because program memory address could be greater than byte.

 

I got it working.

Thank you.

 

What exactly is the difference between sprintf_P and strcpy_P? Because both transfer the data from the __flash variable "cflString" to the temporary RAM variable "cString" including the '\0'.

sprintf_P(cString,cflString_ptr);
strcpy_P(cString,cflString_ptr);

Which is best/correct to use?

 

Is there a way other than declaring a variable array to put string in flash?

So if I use:

LCD_DISPLAYvString("Buzzer");

or does this automatically use RAM for "Buzzer"?

 

Or does it have to be done this way?:

__const __flash __char cflText1[]="Buzzer";

LCD_DISPLAYvString(cflText1[]);

i.e. can something like the following be done:

LCD_DISPLAYvString((__flash)"Buzzer");

??

 

Last Edited: Wed. Feb 24, 2016 - 09:06 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Why would you even think of using sprintf() to copy strings? The C library contains one function intended for copying strings and that is strcpy()  (also it's about 50 bytes while sprintf may be the best part of 2000 bytes). 

 

To put a literal string in flash you still use PSTR() just as it's always been the case. 

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Excellent ... thank you very much

 

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

https://www.avrfreaks.net/comment/1455596#comment-1455596

https://www.avrfreaks.net/comment/1455601#comment-1455601

 

const __flash char * const __flash cflOPTIONS_text[] = 
{
  (const __flash char[]) { "NO"   },
  (const __flash char[]) { "YES"  },
  (const __flash char[]) { "OFF"  },
  (const __flash char[]) { "ON"   },
  (const __flash char[]) { "sec"  },
  (const __flash char[]) { "secs" }
};

 

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

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

Oh sweet! I guess I must have let that solution wash over me without actually taking it in last time. surprise

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

AVR programmers might be interested in how the imagecraft puts strings in flash... just check a box in the ide project options that says 'strings in flash'. No need to use PSTR. These extra decorations were one of the main confusions I had when trying to use winavr when coming to avr programming from 'regular' programming using processors with instructions and data in ram.

 

Imagecraft compiler user

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

Old thread but I'm trying to use __flash however it wont compile.

 

I've included <avr/pgmspace.h> , but on examionation there's no __flash code to be seen    Copyright (c) 2009-2010, Jan Waclawek.

Using Native in the compiler options. Microchips website still mentions using PROGMEM.

Can somebody spill the beans what I need to be doing to get a proper compilation using __flash because I've used all the examples I've seen here.

 

TIA

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

rowifi wrote:
Microchips website still mentions using PROGMEM.

AVR Libc - Porting From IAR to AVR GCC

...

IAR uses a non-standard keyword to declare a variable in Program Memory:

 __flash int mydata[] = ....

AVR GCC uses Variable Attributes to achieve the same effect:

 int mydata[] __attribute__((progmem)) 

...

__flash eventually arrived to FSF AVR GCC :

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

 

edit : Atmel AVR GCC 3.4.2 is from FSF AVR GCC 4.7.2 :

http://web.archive.org/web/20170830051938/http://distribute.atmel.no/tools/opensource/Atmel-AVR-GNU-Toolchain/3.4.2/

 

edit2 : 

AVR and SAM Downloads Archive | Microchip Technology

 

"Dare to be naïve." - Buckminster Fuller

Last Edited: Mon. Jun 10, 2019 - 04:29 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

rowifi wrote:
I've included <avr/pgmspace.h> , but on examionation there's no __flash code to be seen 
The whole point is that it's no longer some "kludge" in header files in AVR-LibC - it's now a core function of the compiler.  If you want to see where __flash is handled you need to look at the source of avr-gcc not AVR-LibC.

 

The one gotcha with __flash is that it is C ONLY. The C++ compiler folks would not allow it to be added to avr-g++ so if you are finding that "__flash" is not recognised either your C compiler is out of date or you are actually using C++

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

Thanks.

 It compiles ok now I removed an error, but how can I remove those annoying red underscores an all the __flash statements.. ??

The code snippet from one of the other post examples here. ( but the  red underscores don't copy ).

 


const __flash char * const __flash cflOPTIONS_text[] =
{
	(const __flash char[]) { "NO"   },
	(const __flash char[]) { "YES"  },
	(const __flash char[]) { "OFF"  },
	(const __flash char[]) { "ON"   },
	(const __flash char[]) { "sec"  },
	(const __flash char[]) { "secs" }
};

 

 

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

rowifi wrote:
how can I remove those annoying red underscores
I think that's done by VassistX - so turn it off (option for that in its menu)