Thanks to visit codestin.com
Credit goes to github.com

Skip to content

esp32: Fix stack margin for bluetooth irq task, remove extra ESP32-C3 margin #15664

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

Merged
merged 2 commits into from
Aug 16, 2024

Conversation

projectgus
Copy link
Contributor

@projectgus projectgus commented Aug 15, 2024

Summary

This is a fix for the bluetooth irq stack size failure accidentally introduced by #15605 (as reported by @dpgeorge #15605 (comment)). In the course of fixing this I also looked closely at the additional stack margin for ESP32-C3 and concluded it's no longer needed.

The two fixes are included as separate commits in one PR as without both the Bluetooth task stack is too small on ESP32-C3.

Bluetooth fix

This value should have been adjusted when the new cstack API was adopted in #15605, as otherwise the stack limit is too small especially on ESP32-C3 where the stack limit was 6144 - 2048 - 2048. My bad, I didn't notice the other call to mp_thread_init_state.

Some extra margin is needed for bluetooth irq because invoke_irq_handler() isn't a top-level task function, NimBLE calls through multiple layers first. Measuring this overhead on IDF V5.2.2 (by putting an abort() in invoke_irq_handler() and then measuring the stack size) yielded 672 bytes on ESP32-S3 and 612 bytes on ESP32-C3, similar to the size reported in
cd66aa0.

Sticking with 1024 bytes for added safety margin. This means on Xtensa the total margin for the BLE task stays the same (2048 bytes) as before switching to cstack.

Removing ESP32-C3 extra margin

This was a surprise. The extra limit for C3 dates from 6823514 which added C3 support.

Measuring the minimum stack margins that can pass the stress tests I measured 768 bytes for ESP32-S3 and 512 bytes for ESP32-C3 on ESP-IDF V5.2.2 and similar on V5.0.4. i.e. The ESP32-C3 actually needs less stack margin not more!

I think the extra margin for ESP32-C3 probably arose from:

  1. Some toolchain inefficiency in the IDF V4.x RISC-V compiler codegen, that has since been improved.

    OR

  2. The race condition that was fixed in e3955f4 where sometimes the margin wasn't applied correctly at all, so the limit would be set to the full RTOS stack. This seems to trigger more on C3, I guess some timing artifact, and I'd believe that some binaries might be more susceptible than others due to random factors.

🤷

Testing

To find the minimum stack margin that works without crashing, I ran:

./run-tests.py --target esp32 --device /dev/ttyUSB0 -i stress_recurse -i stress/recurs

... with various margin values in a pseudo-binary search, and stopped when I got to 64 byte increments.

To verify this fix, I ran all unit tests, multi_bluetooth tests, and multi_net tests (Wi-Fi only) on:

  • ESP-IDF V5.0.4 ESP32-S3 and ESP32-C3. All passing.
  • ESP-IDF V5.2.2 ESP32-S3, ESP32-C3, and ESP32. All passing, except multi_bluetooth/stress_log_filesystem.py is failing on the original ESP32 only because it seems to print an additional weird line of output ("ELx2000") . I don't know what this is, where it's coming from, and it didn't do this when I tested it with V5.2.2 last. However I don't think it's related to this PR. Will debug later if I've got time.

Trade-offs and Alternatives

I guess the alternative would be to keep the extra C3 stack margin just in case, and grow the NimBLE task stack to match. However as far as I can tell it's not needed any more.

@projectgus projectgus changed the title Bugfix/esp32 bluetooth stack esp32: Fix stack margin for bluetooth irq task, remove extra ESP32-C3 margin Aug 15, 2024
@dpgeorge
Copy link
Member

Thanks for this, and for the thorough testing.

I think the stack on RISC-V was reduced due to the recent change to custom NLR code: 6007f3e

This value should have been adjusted when the new cstack API was adopted in
e3955f4, as otherwise the stack limit is too small especially on
ESP32-C3 where the stack limit was 6144 - 2048 - 2048.

Some extra margin is needed for bluetooth irq because invoke_irq_handler()
isn't a top-level task function, NimBLE calls through multiple layers
first. Measuring this overhead on IDF V5.2.2 (by putting an abort() in
invoke_irq_handler() and then measuring the stack size) yielded 672 bytes
on ESP32-S3 and 612 bytes on ESP32-C3, similar to the size reported in
cd66aa0.

Sticking with 1024 bytes for added safety margin. This means on Xtensa the
total margin for the BLE task stays the same (2048 bytes) as before
switching to cstack.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <[email protected]>
The extra limit for C3 dates from 6823514 which added C3 support.
Measuring the minimum stack margins that can pass the stress tests I
measured 768 bytes for ESP32-S3 and 512 bytes for ESP32-C3 on ESP-IDF
V5.2.2 and similar on V5.0.4. i.e. The ESP32-C3 actually needs less stack
margin not more!

I think the extra margin for ESP32-C3 probably arose from:

1. Some toolchain inefficiency in the IDF V4.x RISC-V compiler codegen,
that has since been improved.

OR

2. The race condition that was fixed in e3955f4 where sometimes the limit
wasn't set correctly at all. This seems to trigger more on C3, presumably
some timing artifact, and I'd believe that some binaries might be more
susceptible than others due to random factors.

OR

3. Commit 6007f3e which enabled custom
NLR handling for ESP32-C3.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <[email protected]>
@dpgeorge dpgeorge force-pushed the bugfix/esp32_bluetooth_stack branch from b956ddc to b6a3aa1 Compare August 16, 2024 04:24
@dpgeorge
Copy link
Member

I tested this on ESP32 and ESP32-C3, the bluetooth multitests and the standard test suite. All tests pass.

@dpgeorge dpgeorge merged commit b6a3aa1 into micropython:master Aug 16, 2024
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants