esp32: Fix stack margin for bluetooth irq task, remove extra ESP32-C3 margin #15664
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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() ininvoke_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 incd66aa0.
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:
Some toolchain inefficiency in the IDF V4.x RISC-V compiler codegen, that has since been improved.
OR
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:
... 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:
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.