Skip to content

cpu/esp_common: erase block/sector-wise to leave interrupt time - #22945

Open
crasbe wants to merge 5 commits into
RIOT-OS:masterfrom
crasbe:pr/esp32_flash_crash
Open

crasbe wants to merge 5 commits into
RIOT-OS:masterfrom
crasbe:pr/esp32_flash_crash

Conversation

@crasbe

@crasbe crasbe commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

Contribution description

With the migration to ESP-IDF v5.4 in #21261, the erase function now erases a whole region instead of individual sectors/blocks. Depending on the size of the region, this can take a couple of seconds or more.
Since in that time, the interrupts have to be disabled, the interrupt that retriggers the watchdog is also disabled, causing a watchdog reset.

This PR changes the approach to erase the flash block- or sectorwise, leaving some space in between for interrupts.

Testing procedure

I extended the tests/drivers/mtd_raw test to write and erase a large section of the flash, which takes some seconds. This will trigger the watchdog reset reliably.

The rest ran on an esp32-wemos-d1-r32 board, Claude ran the tests for seeedstudio-xiao-esp32c3, seeedstudio-xiao-esp32s3, esp32h2-devkit and esp32c6-devkit as well cuz I'm lazy. Can prove traces if wished.

Behavior on master

Cherry-pick the commit with the test:

chris@ThinkPias:~/RIOTstuff/riot-upstream3/RIOT$ git log --oneline -n1
aa5db4178e (HEAD -> pr/esp32_flash_crash, origin/pr/esp32_flash_crash) tests/drivers/mtd_raw: add test for larger writes and erases
chris@ThinkPias:~/RIOTstuff/riot-upstream3/RIOT$ git checkout master
Zu Zweig »master« gewechselt
Ihr Branch ist auf demselben Stand wie 'origin/master'.
chris@ThinkPias:~/RIOTstuff/riot-upstream3/RIOT$ git cherry-pick aa5db4178e
[master b6b7537c2f] tests/drivers/mtd_raw: add test for larger writes and erases
 Date: Mon Oct 19 23:05:38 2026 +0200
 2 files changed, 44 insertions(+)
Welcome to pyterm!
Type '/exit' to exit.

> 
> mtd info
mtd info
mtd devices: 1
test 0
 -=[ MTD_0 ]=-
sectors: 763
pages per sector: 16
page size: 256
total: 3052 kiB
> test 0
[START]
[SUCCESS]
> test_erase_all 0
test_erase_all 0
[START]
ets Jul 29 2019 12:21:46

rst:0x7 (TG0WDT_SYS_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DOUT, clock div:2
load:0x3fff0030,len:1552
load:0x40078000,len:13736
load:0x40080400,len:4
ho 8 tail 4 room 4
load:0x40080404,len:2916
entry 0x40080414
Unicore app
Single core mode
detected chip: generic
flash io: dout

main(): This is RIOT! (Version: b6b7)
Manual MTD test
Timeout in expect script at "child.expect_exact("[SUCCESS]")" (tests/drivers/mtd_raw/tests/01-run.py:21)

Behavior with this PR

Welcome to pyterm!
Type '/exit' to exit.

> 
> mtd info
mtd info
mtd devices: 1
test 0
 -=[ MTD_0 ]=-
sectors: 763
pages per sector: 16
page size: 256
total: 3052 kiB
> test 0
[START]
[SUCCESS]
> test_erase_all 0
test_erase_all 0
[START]
[SUCCESS]
> 
make: Verzeichnis „/home/chris/RIOTstuff/riot-upstream3/RIOT/tests/drivers/mtd_raw“ wird verlassen

Issues/PRs references

Fixes the new issue raised in #14506.
Also fixes #16130 and reverts #16131.

Declaration of AI-Tools / LLMs usage:

AI-Tools / LLMs that were used are:

Erasing a big region can stall interrupts for too long
which can trigger the watchdog and cause a reset. Therefore we
erase sector- or blockwise, depending on the flash.

Assisted-By: Claude Code Opus 5.5
Large writes and/or erases can lead to watchdog timeouts if
the MTD subsystem does not leave enough interrupt time.
Add a large write and erase to check for that.

Assisted-By: Claude Code Opus 5.5
@crasbe
crasbe requested a review from benpicco October 19, 2026 21:13
@crasbe crasbe added Type: bug The issue reports a bug / The PR fixes a bug (including spelling errors) CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR AI: Co-Authored PR/Issue relies on AI. Documentation / Code was partly generated by AI. labels Oct 19, 2026
@github-actions github-actions Bot added Area: tests Area: tests and testing framework Platform: ESP Platform: This PR/issue effects ESP-based platforms Area: cpu Area: CPU/MCU ports labels Oct 19, 2026
@crasbe

crasbe commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor Author

Here comes the trust me bro Test Matrix:

Board MTD master this PR
seeedstudio-xiao-esp32c3 3052 KiB Watchdog-Reset [SUCCESS]
seeedstudio-xiao-esp32s3 7148 KiB Watchdog-Reset [SUCCESS]
esp32c6-devkit 7148 KiB Watchdog-Reset [SUCCESS]
esp32h2-devkit 3052 KiB [SUCCESS] [SUCCESS]
esp32-wemos-d1-r32 3052 KiB Watchdog-Reset [SUCCESS]
esp32s2-devkit 3052 KiB Watchdog-Reset [SUCCESS]

The H2 is too fast for the watchdog to trigger.

@gschorcht

Copy link
Copy Markdown
Contributor

I added the results for an ESP32-S2 board in comment #22945 (comment).

Comment thread tests/drivers/mtd_raw/main.c Outdated
return 0;
}

SHELL_COMMAND(test_erase_all, "Write to every sector & erase them at once", cmd_test_erase_all);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't the command simply be called test_erase, since you can specify the size to be deleted as the second argument?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This started as a command that erases everything, but for e.g. a multi-gigabyte SD card this would take forever, that's why it got changed.

Comment thread tests/drivers/mtd_raw/main.c Outdated
Comment thread tests/drivers/mtd_raw/main.c Outdated
Comment thread tests/drivers/mtd_raw/tests/01-run.py Outdated
Co-authored-by: Gunar Schorcht <gunar@schorcht.net>
Co-authored-by: crasbe <crasbe@gmail.com>
Comment thread tests/drivers/mtd_raw/main.c Outdated

@benpicco benpicco left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just some minor comments from my side.

uint32_t limit_mib = (argc > 2) ? strtoul(argv[2], NULL, 10) : 16;

if (dev == NULL || limit_mib == 0) {
printf("usage: %s <dev> [size in MiB, default 16, max flash size]\n", argv[0]);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
printf("usage: %s <dev> [size in MiB, default 16, max flash size]\n", argv[0]);
printf("usage: %s <dev> [size in MiB, default 16]\n", argv[0]);

I think max flash size just adds confusion, at least it confused me.
You can't erase more than is there anyway.

@@ -79,10 +80,27 @@ extern uint32_t spi_flash_get_id(void);

static inline esp_err_t spi_flash_erase_range(size_t start_address, size_t size)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
static inline esp_err_t spi_flash_erase_range(size_t start_address, size_t size)
static esp_err_t spi_flash_erase_range(size_t start_address, size_t size)

* is erased block- or sectorwise. */
while ((res == ESP_OK) && size) {
size_t chunk = ((start_address % block_size) == 0) && (size >= block_size)
? block_size : sector_size;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume block_size >= sector_size?
Does it have an advantage to switch between the two? The esp8266 variant only uses sectors, but maybe that's all there is.

Just a short comment as to why this was done that way would be nice.

@riot-ci

riot-ci commented Oct 19, 2026

Copy link
Copy Markdown

Murdock results

❌ FAILED

2ae5d12 fixup! fixup! tests/drivers/mtd_raw: add test for larger writes and erases

Success Failures Total Runtime
2166 0 13104 03m:07s

Artifacts

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

AI: Co-Authored PR/Issue relies on AI. Documentation / Code was partly generated by AI. Area: cpu Area: CPU/MCU ports Area: tests Area: tests and testing framework CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR Platform: ESP Platform: This PR/issue effects ESP-based platforms Type: bug The issue reports a bug / The PR fixes a bug (including spelling errors)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

boards/esp32-wroom-32: tests/mtd_raw flakey mdt_erase success, but vfs_format resets board (esp32-heltec-lora32-v2)

4 participants