Beginners Question: Does using F() destroy your Flash in time

Hello.

First time Arduino programmer here.
I've been reading a lot about the different memory inside the Arduino. Myself I have a Rev3 Uno.
Bumping into the very limited storage of Arduino micro's I've been searching for ways to reduce my SRAM usage. One of the options is to use F() macro that moves all string (or char[]) into the flash.

However as a hardware guy, reading about this, sends chills down my spine.

A lot of programs (as does mine) use the F() macro in their loop program defining each F() string once every milliseconds. Knowing about flash you know about the limited writing cycles flash has and the destructive side of writing cycles.

Does using F() destroy your flash in the long run? How does the storage to flash work? Does it write to flash each time it encounters F() each few milliseconds or does it just write once during programming, for which it uses just pointers to read the F() statements during the loop program?

Yes, it reduces the the life of your flash, but at exactly the same rate as uploading executable code to flash does.

A lot of programs (as does mine) use the F() macro in their loop program defining each F() string once every milliseconds.

The F() macro is a compile-time construct, so no, it doesn't do anything at run-time, much less at a rate of once every few milliseconds.

F() reads from flash. It causes no extra wear on the memory.

What would happen if F() isn't used? All strings must be in flash in any case so they will survive a power cycle. If you don't use F(), how does a string get copied into ram in the first place. There's nothing in the skectch to that effect. So does the compiler actually add its own code that copies all the strings to ram?

Sorry if this is a nonsense question. I've come to Arduino from the MSP430 world where these distinctions between flash memory and ram don't exist, and don't yet understand exactly how it all works here.

Yes. The compiler puts the string in flash, along with the rest of the program.

If you don't use F(), the strings would be copied to RAM by crt0.

At power up, the values are sent to RAM from flash.

This is obviously done by added code by the compiler.

You have much less RAM than Flash so it is wise to use F() if you are running low on RAM.

larryd:
You have much less RAM than Flash so it is wise to use F() if you are running low on RAM.

Yes

Thanks guys.
There's loads of info on F(). However I did not find conclusive evidence online on how it worked on compiler level. I was under the impression that each pass of loop() the F() would write my string data to the flash and that my flash would be suffering in 6 months time running non stop.

From your guidance I learned his is not the case. Thanks to you all and lets lock this topic.

The idea of the macro is to ensure that the string remains in flash - it is already there, and we don't want it to write it to RAM.

AWOL:
Yes, it reduces the the life of your flash, but at exactly the same rate as uploading executable code to flash does.

That is an EXTREMELY misleading way of stating this. The issue at hand here is whether F() causes more wear on the flash than not using it, so leading off with "yes" gives a completely false answer. The remaining explanation isn't clarifying the answer, it's contradicting it.

The correct answer is no. Using F() does not introduce ANY extra wear on Flash memory than not using it. Period.

FuzzballJack:
Thanks guys.
There's loads of info on F(). However I did not find conclusive evidence online on how it worked on compiler level. I was under the impression that each pass of loop() the F() would write my string data to the flash and that my flash would be suffering in 6 months time running non stop.

From your guidance I learned his is not the case. Thanks to you all and lets lock this topic.

The F() macro is defined in the Arduino code like so:

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

The reason for casting it to the strange pointer type is to that the printing functions (like Serial.print) can differentiate between a normal string and a flash string, since a flash string requires a special function to read. The built in Arduino libraries handle the difference automatically, but if you want to use the F() strings with your own functions you would need to know how to read them.

The Arduino code is built on top of another code base called AVRLibc. The pgmspace module in that library contains the various functions and data types used to read data from flash memory. If you want to learn more about flash memory access you can try to study the Arduino code and see how it uses the pgmspace functions.

With an AVR chip, it is not even easy to write to flash memory at runtime. E.g.
https://www.avrfreaks.net/forum/write-flash-memory-atmega128
EEPROM is a different matter. You could quite easily and quickly destroy this by attempting to treat it as ram memory.

Jiggy-Ninja:
That is an EXTREMELY misleading way of stating this.

I prefer the term "differently informative" :smiley:

AWOL:
I prefer the term "differently informative" :smiley:

alternative truth ? :slight_smile:

Fake gnus