-
-
Notifications
You must be signed in to change notification settings - Fork 8.2k
esp32: Writing data to flash files stalls everything including interrupts for 80ms #3782
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
This seems like an issue with the operating system, not micropython. The definition for |
Why don't you place your code in Internal ROM?
|
const int array[] = {1, 2, 3, 4, 5};
void func(int n)
{
int i;
for(int i = 0; i < n; i++)
{
array[i] = something();
}
}
|
Not an expert on flash memory but even on my micro, manual says
Which strongly implies you cannot simulatenously read and write to same flash "block". So, unless you can move your code to IRAM and/or internal ROM, you're stuck. @dpgeorge issue closed. |
I think the only way to make this work is to provide a function written in C that lives in IRAM (with data in DRAM) and does the reading of the ADC, storing it in a buffer (in DRAM) for Python code to read periodically and write to flash. For this to work, everything involved in the ISR and ADC reading must be in IRAM. It doesn't look like Basically the architecture of the ESP32 means you cannot write to flash while also doing timing-critical things. A way around this would be to provide a second external SPI flash (or even SD card) dedicated to storage, as writing to that wouldn't interfere with the running of the code. |
So the recommendation is that the internal flash is not to be used for sub-1second data logging. I wonder how to make this obscure fact known to anyone else who gets excited by the amount of on-board memory and tries it. I've been trialing using an external micro-SD card on SPI using that pretty neat file mounting. On an ESP8266 sing the code above saving to an SD file, most file writes take 2ms, except every 64th (512 bytes) takes 15ms, and every 256th file write (2048 bytes) takes 50ms. When I use machine.Timer(0) with period=10 and save to the SD card, then the timings are spaced mostly between 6ms and 14ms, so we are not encountering the 80ms stall you get when using the internal flash. I get about the same when running an external SD card on an ESP32 -- 15ms and 50ms stalls when you run the writes inline with the data acquisition, but this time variations of only 1ms either side of 10ms every 2kbs of data when you do the data acquisition using an irq Timer. So this works adequately, but it is annoying having to bolt on this external memory unit as a work-around. It would be much handier if espressif declared only half of its internal memory was to be used for executable code so that the other half could be used for data without having to worry about freezing everything for the program cache. Is there a good forum for letting them know of application/issues like this |
Ther are quite a few technical details about the ESP32 (and any chip in fact) which you can only really know once you start playing with it and seeing if it's suited to your particular application (see eg #2972). What is a show-stopper for some (eg logging to flash) may be no problem at all for others. But in microcontroller applications, I agree that you expect some level of real-time capability/behaviour.
That wouldn't help. The point is (as mentioned above) that it's a limitation of the SPI flash itself, that if you are erasing a page then the entire flash is stalled (can't read or write) until it's done erasing. So the CPU can't execute anything from the external memory when it's erasing.
Espressif have a forum and active Github account. |
Is the internal ROM too small to put your entire code? |
The internal ROM is .. ROM, part of the silicon, changeable only by making new silicon. |
@robert-hh IROM (code executed from Flash) https://dl.espressif.com/doc/esp-idf/latest/api-guides/general-notes.html#memory-layout Code can be placed there during programming. |
That's how I read the datasheet: The device has 448k of internal ROM, containing the bootloader and support library code. And is has external flash, which is either called IROM (for code and data) or DROM (data only). This flash is up to four devices with a SPI interface, size up to 16 MByte each. This flash memory (and external PsRAM) is mapped by the MMU into the address space of the CPU, and code in the internal ROM copies the required blocks from the external flash or RAM into the cache, whenever needed. That takes about 300µs per block and can be observed, e.g. as a jitter of ISR's. The total address space
8000
provided for external memory is about 20 MBytes. |
When you build the image, there should be a |
If I look into the map file of a ESP32 build, the memory regions used are those of internal RAM and external flash, which matches the settings in esp_out-ld . It shows no use of internal ROM.
Do you have the experience that the internal ROM area is writable by the flash loader? |
If you mean on the ESP32, not I do not. It is possible your ESP32 build tools disallow you from writing to the IROM because that's where the OS is placed . . . and I think I found the doc that confirms it: IROM (code executed from Flash):
and if you look at the technical manual, that range is in the external memory section. Also, IROM (from the webpage) isn't the same thing as internal ROM (from the manual): IROM refers to external flash that is read via SPI (or something) while internal ROM is the area YOU would like to be able to save your code to so you don't have debilitating 80ms freeze when you write to the SPI flash. They really don't want you to touch the internal ROM
|
Yes, I totally agree. So we talked about the same thing, just looking at it differently. |
@goatchurchprime or @dpgeorge you may close this issue. Summary |
Theres's not much that can be done about this from the MicroPython side, so closing. |
I'm trying to log bursts of analog values to the internal flash file system on an ESP32 (at the period of 10ms).
Unfortunately for every 4096bytes of data everything freezes for about 80ms while spi_flash_write() executes.
I've tried implementing the data collection and storage of values into ringbuffer at a 10ms period using machine.Timer(), but the problem was not solved. When the main loop retrieves these values and stores them into a file everything freezes for 80ms at the page boundary -- including those Timer() interrupts, which seem to get queued up and executed consecutively.
I think the problem is down to the function call spi_flash_write(), which is made here:
micropython/ports/esp32/modesp.c
Line 75 in 0593d6f
The espressif documentation https://dl.espressif.com/doc/esp-idf/latest/api-reference/storage/spi_flash.html states:
According to the memory layout not much can be run from the IRAM; our code is generally running from the IROM (flash memory), so all execution gets disabled during the write.
It's a long shot, but is there a version of spi_flash_write() that does not have this effect by assuming it's saving only data, not program code?
As far as I can know, the only time program code is written to flash is via the esptool.py, (Micropython files don't count as they are interpreted), so I don't see why the crazy assumption that spi_flash_write() would be writing stuff under the program counter?
The issue is a bit of a show-stopper in terms of making use of the copious on-board flash for datalogging purposes.
(The discussion began here https://forum.micropython.org/viewtopic.php?f=18&t=4725&p=27620#p27620 but I'm posting it as a ticket as it seems to relate to a fundamental firmware issue and application limitation.)
Potentially related tickets: Add accurate interrupt counter #3775, Benchmarking SDCard Write Speeds #2648
The text was updated successfully, but these errors were encountered: