What does the F() do exactly?

[quote author=Coding Badly link=topic=91314.msg685894#msg685894 date=1328909536]

ninja2:
Could this F() syntax be used in place of rather cumbersome:
strcpy_P(buffer, (char*)pgm_read_word(&(str_table[index])));

This may help...
http://arduiniana.org/libraries/flash/[/quote]

can you clarify the origin of the F() syntax, is it from Mikal Hart's Flash library, or is it part of C or the standard IDE ?

ninja2:
can you clarify the origin of the F() syntax, is it from Mikal Hart's Flash library

That's how I was introduced to it.

so:
(and this may seem a very dumb question)

if (I don't include the flash library in my sketch)
{ F() will not work? ;}
endif

1 Like

This sketch compiles and runs, so the answer seems to be no, one doesn't have to (explicitly) include Flash library to use F().

// F test

void setup() {
    Serial.begin(9600);
    
    Serial.println(F("STRINGA 1"));
    Serial.println(F("STRINGA 2"));
}

void loop() {
}

doh! I could've done that ... excellent way to resolve my query, thanks mromani

:slight_smile:

Could someone please help me out with this, I am unable to get the F() macro compiled on FreeBSD.
I am using avr-gcc and the arduino 1.0 codebase.
The following line
Serial << F("This is a test string");
throws up an error by the compiler which says

flash_streaming.cpp:210:13: error: reinterpret_cast from type 'const char*' to type '__FlashStringHelper*' casts away qualifiers

I apologize for cross posting, but I already asked the same question in an earlier post - but didn't make any headway

The command I am issuing is -
avr-gcc tst.cpp -mmcu=atmega328p -DF_CPU=16000000UL -Os -w -Wl,--gc-sections -ffunction-sections -fdata-sections -DARDUINO=100 -I /home/rr/code/arduino//include/arduino/ -I . -c -o tst.o

kb3dow:
Serial << F("This is a test string");

Try

Serial.print( F("This is a test string") );

or

Serial.println( F("This is a test string") );

It has nothing to do with the << operator, even Serial.print(F("Hello World")) has the same problem.
Serial.print(F("Hello World"));
gives
tst.cpp:19:18: error: reinterpret_cast from type 'const char*' to type '__FlashStringHelper*' casts away qualifiers

I have a medium sized multi-file sketch compiling and functioning using avr-gcc, so there is no problem in general with compiling/linking etc. But this particular issue has me puzzled.

What version of avr-gcc are you using?

avr-gcc-4.5.1

It seems you found a bug in the Arduino code. Here's the fix. Make the following change to WString.h.

class __FlashStringHelper;
//#define F(string_literal) (reinterpret_cast<__FlashStringHelper *>(PSTR(string_literal)))
#define F(string_literal) (reinterpret_cast<const __FlashStringHelper *>(PSTR(string_literal)))

Yes, that appears to fix it. It compiles and I'll test it at home later tonight.

Thank you very much.

I have posted a bug report to the Arduino team.

http://code.google.com/p/arduino/issues/detail?id=866

Another question with the F() macro, now that I have it working. The following code fails to compile

struct some_table{
char *name;
int val;
} arrary[] = {
{ F("a"), 0},
{ "b", 1}
};

The compiler says
tst.cpp:31:7: error: statement-expressions are not allowed outside functions nor in template-argument lists
Maybe I should try using the flash library and use a variable to hold that string in PROGMEM

Do you really need to store data in FLASH? Doing so isn't "free." You will pay a performance penalty in terms of the time it takes to read from FLASH as well as the complexity in terms of the code necessary to access FLASH.

mkwired:

kb3dow:
Serial << F("This is a test string");

Try

Serial.print( F("This is a test string") );

or

Serial.println( F("This is a test string") );

On my copy of the Arduino 1.0 IDE this code:

#include <Streaming.h>

void setup ()
{
  Serial << F("This is a test string");
  Serial.println( F("This is a test string") );
}
void loop () {}

Gives no errors:

Binary sketch size: 1716 bytes (of a 32256 byte maximum)

Works on both OS/X and Windows XP versions.

Nick, he's not using the same compiler.

mkwired:
Do you really need to store data in FLASH? Doing so isn't "free." You will pay a performance penalty in terms of the time it takes to read from FLASH as well as the complexity in terms of the code necessary to access FLASH.

It's not that bad. In terms of time, the processor can read flash memory quickly. After all, it is getting instructions from it at the rate of a byte every clock cycle. Compare:

Flash "strcpy":

000000be <strcpy_P>:
  be:	fb 01       	movw	r30, r22
  c0:	dc 01       	movw	r26, r24
  c2:	05 90       	lpm	r0, Z+
  c4:	0d 92       	st	X+, r0
  c6:	00 20       	and	r0, r0
  c8:	e1 f7       	brne	.-8      	; 0xc2 <strcpy_P+0x4>
  ca:	08 95       	ret

To normal "strcpy":

000000cc <strcpy>:
  cc:	fb 01       	movw	r30, r22
  ce:	dc 01       	movw	r26, r24
  d0:	01 90       	ld	r0, Z+
  d2:	0d 92       	st	X+, r0
  d4:	00 20       	and	r0, r0
  d6:	e1 f7       	brne	.-8      	; 0xd0 <strcpy+0x4>
  d8:	08 95       	ret

The only difference is changing "ld" to "lpm". The LPM instruction takes 3 clock cycles compared to 2 for LD. So, you lose one clock cycle (62.5 nS) per byte copied.

Nick, How did you reveal that assembler code?