Skip to content

Fix(ble): restore BLE bring-up on boards without the SDR bank - #3080

Merged
pr3y merged 1 commit into
BruceDevices:devfrom
salikisazazil:fix/ble-low-ram-gate
Nov 14, 2026
Merged

pr3y merged 1 commit into
BruceDevices:devfrom
salikisazazil:fix/ble-low-ram-gate

Conversation

@salikisazazil

@salikisazazil salikisazazil commented Nov 13, 2026 •

Copy link
Copy Markdown
Contributor

Target: BruceDevices/firmware (post-1.17)
Scope: 1 file changed, ~10 lines (src/core/radio_mem.h)
Related: #3078 (T-Embed CC1101 Plus: all BLE features fail right after boot)


Summary

Since 1.17, every BLE feature (BLE Suite, BLE Scan, BLE Spam, Ducky BLE)
fails immediately after boot on boards other than Cardputer with:

Low RAM: free WiFi/SD first
Failed to init BLE

even when WiFi is off. The error text is misleading: the gate is not about
WiFi being active, it is radioHasMemForBle() in src/core/radio_mem.h,
which requires the largest contiguous DMA-capable internal RAM block
to be at least RADIO_BLE_MIN_DMA_BLOCK before the BLE stack is touched.

Root cause

Two 1.17 changes interact:

  1. Commit ec014ad1 ("fix ble cardputer") raised RADIO_BLE_MIN_DMA_BLOCK
    from 15 kB to 48 kB. That number was measured on Cardputer ADV,
    where the new SDR feature reserves a 64 KiB SRAM bank out of the heap at
    boot ("restrict SDR"), leaving only ~15.8 kB contiguous at the menu. The
    same commit added an SDR bank hand-off (sdrBankReleaseForRadio())
    that returns those 64 KiB to the heap when the radio needs them — this
    is what makes a 48 kB gate reachable on Cardputer.

  2. Commit 3e9bc11f ("restrict SDR") added -D BRUCE_NO_SDR_JAMMER=1 to
    the global build_flags in platformio.ini, so the SDR bank (and
    therefore the hand-off) only exists on the Cardputer env, whose ini
    removes the define via build_unflags. On every other board
    (T-Embed, T-Deck, T-Stick, ...) the hand-off functions compile to no-ops.

Net effect: all non-Cardputer boards now require a 48 kB contiguous DMA
block with no mechanism to ever satisfy it, where 1.16 required 15 kB
(the value BLE shipped with and worked with everywhere). On T-Embed the
menu heap never reaches 48 kB contiguous, so BLE is dead from boot —
matching #3078.

Serial confirmation on an affected board (1.17):

[RAM] Low contiguous DMA memory for BLE, attempting to free WiFi...
[RAM] Still only <N> bytes DMA block, minimum 49152 needed

Fix

Make the BLE gate conditional on whether the SDR bank is actually
reserved out of the heap — the only configuration the 48 kB number was
calibrated for, and the only one where the hand-off can satisfy it:

#if !defined(LITE_VERSION) && !defined(BRUCE_NO_SDR_JAMMER)
constexpr size_t RADIO_BLE_MIN_DMA_BLOCK = 48 * 1024;
#else
constexpr size_t RADIO_BLE_MIN_DMA_BLOCK = RADIO_WIFI_MIN_DMA_BLOCK; // 15 kB, pre-1.17 gate
#endif
  • The #if guard is deliberately identical to the guard that makes
    sdrBankReleaseForRadio() real (a few lines below), so the threshold
    and the hand-off can never disagree.
  • Cardputer / Cardputer ADV (bank reserved): unchanged, still 48 kB +
    hand-off.
  • LITE builds: unchanged vs 1.16 (they never had the bank).
  • All other boards: exact 1.16 behavior restored (15 kB gate, same as the
    Wi-Fi threshold, which was never raised).
  • WiFi path untouched (RADIO_WIFI_MIN_DMA_BLOCK unchanged).

Why this is safe

  • Restores the exact gate 1.16 shipped and was field-tested with on all
    boards; the failure mode it re-introduces (BLE init aborting cleanly
    with an error instead of a half-initialized controller crash) is kept.
  • Single file, no new code paths, no API changes, no behavior change for
    the boards the 48 kB gate was designed for.
  • All four BLE call sites (BLE_Suite.cpp, ble_common.cpp,
    ble_spam.cpp, ducky_typer.cpp) go through radioHasMemForBle(),
    so one constant fixes all of them.

Test plan

  1. pio run -e lilygo-t-embed-cc1101 (and one more non-Cardputer S3 env,
    e.g. lilygo-t-deck) — build must succeed (threshold is a compile-time
    constant, no runtime code change for these boards).
  2. Flash 1.17 + this patch on T-Embed CC1101 Plus:
    • Boot → Bluetooth → BLE Suite: menu opens without the "Low RAM" error.
    • Quick Vulnerability Scan / target scan: no "Failed to init BLE".
    • BLE Scan, BLE Spam, BLE Keyboard: work.
    • Serial shows the old 15 kB minimum in the failure path
      (minimum 15360 needed) and no [RAM] Still only ... line at boot.
  3. Cardputer regression (bank reserved, hand-off active):
    • BLE still starts (48 kB gate + hand-off intact).
    • SDR menu still present; if SDR was used, BLE refuses cleanly with
      "Low RAM: free WiFi/SD first" until reboot (unchanged).
  4. LITE build (env_light): BLE behaves as in 1.16.

Commit message suggestion

fix(ble): restore BLE bring-up on boards without the SDR bank

1.17 raised RADIO_BLE_MIN_DMA_BLOCK from 15 kB to 48 kB, a value
measured on Cardputer where the SDR feature reserves a 64 KiB SRAM bank
out of the heap and the new hand-off releases it when a radio needs it.
"restrict SDR" then made the bank (and the hand-off) Cardputer-only,
leaving every other board with a 48 kB contiguous-DMA requirement that
no mechanism can satisfy; BLE fails right after boot on T-Embed etc.
even with WiFi off (#3078).

Keep the 48 kB gate only where the bank is reserved (same #if guard as
the hand-off itself) and fall back to the pre-1.17 gate elsewhere.

1.17 raised RADIO_BLE_MIN_DMA_BLOCK from 15 kB to 48 kB, a value measured on Cardputer where the SDR feature reserves a 64 KiB SRAM bank out of the heap and the new hand-off releases it when a radio needs it. 'restrict SDR' made the bank (and the hand-off) Cardputer-only, leaving every other board with a 48 kB contiguous-DMA requirement that no mechanism can satisfy; BLE fails right after boot on T-Embed etc. even with WiFi off (see BruceDevices#3078).

Keep the 48 kB gate only where the bank is reserved (same #if guard as the hand-off itself) and fall back to the pre-1.17 gate elsewhere.
Copilot AI balanced review requested due to automatic review settings November 13, 2026 05:22

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota. Try requesting a review at a lower effort level.

An organization owner can choose the repository organization as the billing source for reviews requested by members with a paid Copilot license. Learn about Copilot code review billing.

@derangedabbot

Copy link
Copy Markdown

Confirmed on LilyGO T-Embed CC1101 Plus (nRF24 menu present), built from tag 1.17 with this patch applied as-is:

  • Before: every BLE entry (BLE Suite, Scan, Spam) → Low RAM: free WiFi/SD first immediately after boot, with Wi-Fi off and the SD card removed. free reported ~119 KB free heap and ~8 MB free PSRAM, so the 48 KB contiguous DMA gate was the only thing blocking init.
  • After: BLE Suite opens and runs, no error. BLE Scan and Spam also start normally.
  • T-Embed inherits the global -D BRUCE_NO_SDR_JAMMER=1 (only the Cardputer ini build_unflags it), so the #else branch (15 KB, the pre-1.17 gate) is what takes effect on this board — consistent with the root-cause analysis above.
  • Build: pio run -e lilygo-t-embed-cc1101 -t build-firmware, PlatformIO 6.2.0, merged bin flashed at 0x0 over USB-Serial/JTAG.

Fixes #3078 for this board.

@pr3y
pr3y merged commit 4f434ae into BruceDevices:dev Nov 14, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants