[ESP8266] `F()` macro is unnecessary on ESP chips?

Hey, I’m trying to understand PROGMEM.

How is that it DOES work to use PSTR() strings with “normal” functions, not the dedicated _P versions?

Is it because ESP8266 is NOT harvard architecture, so in fact “normal” function can access the “flash” addresses?

Then, I guess, F() macro is unnecessary on ESP chips, as normal functions can access data stored in FLASH with PSTR()?

ESP32 Programmers’ Memory Model. Internal memory of the MCU is probably… | by Amey Inamdar | The ESP Journal (espressif.com)

I believe the _P functions are AVR-specific

Well, according to the docs I should be using them on ESP8266 anyway.

I don't really see the answer to my question there. Maybe I should be able to draw sone kind of conclusions, but I'm a hardware newbie. And that's assuming that ESP32 has the same deal as ESP8266…

Someone may correct me, but I think all ESP have no flash memory, only a bootloader to load firmware from external flash, into internal RAM. Also most ESP have a healthy amount of RAM for a microcontroller.

So, in the vast majority of cases, although const data might actually reside in RAM, the overhead is more than acceptable.

I was not aware that PROGMEM did anything special in an ESP, I thought it was simply a neutral emulation. So harmless, but not restrictive either. I think if there is any difference between the handling of PROGMEM and const data, it is unlikely to make any difference except maybe in cases where the memory is almost full to the maximum.

I don't favour the idea of using it for backwards compatibility. AVR based Arduinos are on the way out, believe me. Code that doesn't use it is actually more portable in a general sense.

1 Like

IROM (code executed from flash)(Memory Types - ESP32 - — ESP-IDF Programming Guide latest documentation)

If a function is not explicitly placed into IRAM (Instruction RAM) or RTC memory, it is placed into flash. As IRAM is limited, most of an application’s binary code must be placed into IROM instead.

The mechanism by which Flash MMU is used to allow code execution from flash is described in ESP32 Technical Reference Manual > Memory Management and Protection Units (MMU, MPU) [PDF].

During Application Startup Flow, the bootloader (which runs from IRAM) configures the MMU flash cache to map the app’s instruction code region to the instruction space. Flash accessed via the MMU is cached using some internal SRAM and accessing cached flash data is as fast as accessing other types of internal memory.

DROM (data stored in flash)

By default, constant data is placed by the linker into a region mapped to the MMU flash cache. This is the same as the IROM (code executed from flash) section, but is for read-only data not executable code.

The only constant data not placed into this memory type by default are literal constants which are embedded by the compiler into application code. These are placed as the surrounding function’s executable instructions.

The DRAM_ATTR attribute can be used to force constants from DROM into the DRAM (Data RAM) section (see above).

The ROM is mask ROM which is baked into the chip as part of the fabrication process. This is entirely read-only in all contexts. If you call a ROM function then it will run as fast as a function in IRAM, but the ROM functions are determined at chip fabrication time so user application code can't go here.
There is some potential for confusion here because flash mapped into the instruction address space via the flash cache (which is also read-only at chip run-time but can be reflashed) is sometimes referred to as "IROM" in ESP-IDF code, as a shorter way to say "mapped flash instruction memory".

ESP performance and cache - ESP32 Forum

PROGMEM is a Arduino AVR feature that has been ported to ESP8266 to ensure compatibility with existing Arduino libraries, as well as, saving RAM. On the esp8266 declaring a string such as const char * xyz = "this is a string" will place this string in RAM, not flash. It is possible to place a String into flash, and then load it into RAM when it is needed. On an 8bit AVR this process is very simple. On the 32bit ESP8266 there are conditions that must be met to read back from flash.

On the ESP8266 PROGMEM is a macro:

#define PROGMEM ICACHE_RODATA_ATTR

ICACHE_RODATA_ATTR is defined by:

#define ICACHE_RODATA_ATTR __attribute__((section(".irom.text")))

Which places the variable in the .irom.text section in flash. Placing strings in flash requires using any of the methods above.

Guide to PROGMEM on ESP8266 and Arduino IDE — ESP8266 Arduino Core 3.1.0-7-g7e2da8b2 documentation (arduino-esp8266.readthedocs.io)

I am able to google. I've read all of that. I've also read the real source code to figure out what's going on. I understand most of it, but not necessarily all of it.

So… instead of copy–pasting docs, are you able to give a simple yes/no answer to my question?

As you can see, it really has no definitive yes/no answer. Also it's a big turn off when someone rejects information that has been offered, very much information about microcomputers really is documentary, so of course it's better to link to it directly than to attempt to paraphrase it.

You're demonstrating petulance, so you will go on my ignore list now.

1 Like

I've "easily" exhausted my RAM while doing a "simple" web page (HTML+CSS+JS). I was forced to split it into multiple "resources" (http requests), so that I don't take up all my RAM with one request.

And now I'm moving all the strings to PROGMEM ofc.

Put another way, messing with it is probably not worth the trouble. Especially since it appears @Daveet is not trying to solve an actual problem. And if he is, he'll have to take the initiative to dig deeply into the documentation himself.

Then you'd be better off using littlefs.

1 Like

If, when using a ESP32 and freeRTOS and loop() is empty the OS will do String clean ups. I still use a String buffer with the ESP32.

One can use a ESP32 WROVER and, under the Arduino, have an extra 4MB of RAM to put strings into.

Well, I think there is an answer. There is RAM saving with PROGMEM, I measured it. According to the docs, I should be using _P functions for it to work, but it works with "normal" functions.

The question is: why.

My suspicion is: because it is not AVR, code and data is the same memory, not separate.

I would like someone to confirm that, or tell me otherwise, as that is just my deduction.

My problem is that I am using normal functions, it works. I wonder if it is a bad idea after all.

PLUS, the other question is: is using PSTR() enough, or should I use F() after all – my guess is that F() does not make any difference on ESP8266.

Yeah, I have it in my "todo" list. I will, for sure.

In the meantime I'm applying F() and PSTR() everywhere I can. Hence, the question.

I'm using ESP8266 with Arduino… framework (library?), not RTOS. I will switch to OS some day, probably :wink:

At first I was thinking that I should ignore those comments. But, well, anyway, I'm sorry if you misunderstood my replies/intentions.

First thing, English is my second language – I try my best, but something that sounds good in my mind, might not sound the best translated to English.

Second thing, I am asking about specific macros on specific microcontroller. I've already gave a link to official docs, so quoting them as the answer is… hmm… not helpful? :wink:

Third thing: as I said: I've already read the docs, I've read the source code, I've tried to google it. Finally, I've come here to ask the question. I woudn't want to waste your guys time in any way by not – at least – having read the official docs :slight_smile:

The answer to
On an ESP32: Is using the F()Macro as pointless as using PROGMEM?
is Yes.

I'm going to study, test and use

sometime so I can add some non-volatile features to one of my libraries.
Looks easy enough.

2 Likes