From 00685a4e613e6d294e606ee02ed7f88fa258d7df Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Mon, 6 Jul 2026 14:13:18 -0500 Subject: [PATCH] nrf52840: right-size the SoftDevice RAM reservation (+8 KB heap arena) (#10903) The app RAM ORIGIN in both nrf52840 linker scripts has been a hard-coded 0x20006000 (24 KB reserved for S140) since they were introduced, but sd_ble_enable() with our fixed Bluefruit configuration (one peripheral link, BANDWIDTH_MAX / ATT MTU 247, 0x1000 attribute table) requires substantially less. The SoftDevice cannot use the gap and the app image is linked above it, so every byte between the true requirement and the ORIGIN is simply unusable RAM - on a part where 2.8.0 field reports showed the heap arena at 99% use. Lower the ORIGIN to 0x20004000 in both s140 v6 and v7 scripts. The heap arena is the linker gap on this platform, so the change is worth exactly +8,192 B of free heap on every nRF52840 board (verified: rak4631 .heap section 124,572 -> 132,764 B; both v6- and v7-script boards link with .data at 0x20004000). Safety net: Bluefruit.begin()'s return value - previously discarded - is now checked. If a future SoftDevice or Bluefruit config change raises the requirement past the reservation, the node logs a critical error instead of silently running without BLE, with instructions to re-measure via CFG_DEBUG=1 ("SoftDevice's RAM requires: 0x..."). --- src/platform/nrf52/NRF52Bluetooth.cpp | 12 +++++++++++- src/platform/nrf52/nrf52840_s140_v6.ld | 11 ++++++++++- src/platform/nrf52/nrf52840_s140_v7.ld | 13 +++++++++++-- 3 files changed, 32 insertions(+), 4 deletions(-) diff --git a/src/platform/nrf52/NRF52Bluetooth.cpp b/src/platform/nrf52/NRF52Bluetooth.cpp index deecf65ec..dd0230100 100644 --- a/src/platform/nrf52/NRF52Bluetooth.cpp +++ b/src/platform/nrf52/NRF52Bluetooth.cpp @@ -4,6 +4,7 @@ #include "HardwareRNG.h" #include "PowerFSM.h" #include "configuration.h" +#include "error.h" #include "main.h" #include "mesh/PhoneAPI.h" #include "mesh/mesh-pb-constants.h" @@ -275,7 +276,16 @@ void NRF52Bluetooth::setup() LOG_INFO("Init the Bluefruit nRF52 module"); Bluefruit.autoConnLed(false); Bluefruit.configPrphBandwidth(BANDWIDTH_MAX); - Bluefruit.begin(); + if (!Bluefruit.begin()) { + // sd_ble_enable() rejected our RAM base: the linker RAM ORIGIN + // (src/platform/nrf52/nrf52840_s140_v*.ld) is below what the SoftDevice needs for the + // current Bluefruit config. Without this check the node would silently run without BLE. + // Rebuild with -DCFG_DEBUG=1 to get "SoftDevice's RAM requires: 0x..." in the log, then + // raise the ORIGIN accordingly. + LOG_ERROR("Bluefruit.begin failed - SoftDevice RAM reservation too small for this config"); + RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_UNSPECIFIED); + return; + } // Clear existing data. Bluefruit.Advertising.stop(); Bluefruit.Advertising.clearData(); diff --git a/src/platform/nrf52/nrf52840_s140_v6.ld b/src/platform/nrf52/nrf52840_s140_v6.ld index c8dac4e55..a956c6583 100644 --- a/src/platform/nrf52/nrf52840_s140_v6.ld +++ b/src/platform/nrf52/nrf52840_s140_v6.ld @@ -21,8 +21,17 @@ MEMORY * - Max ATT MTU * - Concurrent connection peripheral + central + secure links * - Event Len, HVN queue, Write CMD queue + * + * With our fixed Bluefruit config (1 peripheral link, BANDWIDTH_MAX / MTU 247, + * 0x1000 attr table) sd_ble_enable() reports a requirement well below the old + * 0x20006000 ORIGIN; every byte of gap is unusable RAM. 0x20004000 keeps a + * ~2+ KB margin over the reported base. NRF52Bluetooth::setup() now checks + * Bluefruit.begin() and records a critical error if the SoftDevice ever + * rejects this base (e.g. after an SD/Bluefruit config change) - re-measure + * with CFG_DEBUG=1 (Bluefruit logs "SoftDevice's RAM requires: 0x...") + * before raising bandwidth/MTU/link settings. */ - RAM (rwx) : ORIGIN = 0x20006000, LENGTH = 0x20040000 - 0x20006000 + RAM (rwx) : ORIGIN = 0x20004000, LENGTH = 0x20040000 - 0x20004000 } SECTIONS diff --git a/src/platform/nrf52/nrf52840_s140_v7.ld b/src/platform/nrf52/nrf52840_s140_v7.ld index 4546b4a7a..dbaf7dfb7 100644 --- a/src/platform/nrf52/nrf52840_s140_v7.ld +++ b/src/platform/nrf52/nrf52840_s140_v7.ld @@ -18,8 +18,17 @@ MEMORY * - Max ATT MTU * - Concurrent connection peripheral + central + secure links * - Event Len, HVN queue, Write CMD queue - */ - RAM (rwx) : ORIGIN = 0x20006000, LENGTH = 0x20040000 - 0x20006000 + * + * With our fixed Bluefruit config (1 peripheral link, BANDWIDTH_MAX / MTU 247, + * 0x1000 attr table) sd_ble_enable() reports a requirement well below the old + * 0x20006000 ORIGIN; every byte of gap is unusable RAM. 0x20004000 keeps a + * ~2+ KB margin over the reported base. NRF52Bluetooth::setup() now checks + * Bluefruit.begin() and records a critical error if the SoftDevice ever + * rejects this base (e.g. after an SD/Bluefruit config change) - re-measure + * with CFG_DEBUG=1 (Bluefruit logs "SoftDevice's RAM requires: 0x...") + * before raising bandwidth/MTU/link settings. + */ + RAM (rwx) : ORIGIN = 0x20004000, LENGTH = 0x20040000 - 0x20004000 } SECTIONS