Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions src/MessageStore.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,12 @@
// How many messages are stored (RAM + flash).
// Define -DMESSAGE_HISTORY_LIMIT=N in build_flags to control memory usage.
#ifndef MESSAGE_HISTORY_LIMIT
#if defined(ARCH_ESP32) && \
!(defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32S2))
// Baseline ESP32 (non-PSRAM variants) has limited heap; reduce message history on resource-constrained builds.
// Override with -DMESSAGE_HISTORY_LIMIT=N if needed.
#if (defined(ARCH_ESP32) && \
!(defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32S2))) || \
defined(NRF52840_XXAA)
// Baseline ESP32 (non-PSRAM variants) and nRF52840 (~115 KB heap arena shared with SoftDevice +
// FreeRTOS stacks; 2.8.0 field reports hit 99% use) have limited heap; reduce message history on
// resource-constrained builds. Override with -DMESSAGE_HISTORY_LIMIT=N if needed.
#define MESSAGE_HISTORY_LIMIT 10
#else
#define MESSAGE_HISTORY_LIMIT 20
Expand Down
33 changes: 24 additions & 9 deletions src/mesh/mesh-pb-constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@
#ifndef MAX_RX_TOPHONE
#if defined(ARCH_ESP32) && !(defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32S3))
#define MAX_RX_TOPHONE 8
#elif defined(NRF52840_XXAA)
// Each slot is a ~340 B MeshPacket in the static pool (Router.cpp MAX_PACKETS_STATIC), so 32 slots
// cost ~11 KB of .bss on the RAM-tightest platform (2.8.0 field reports: 99% heap). 16 still doubles
// the 8 classic ESP32 has shipped with for years; drops start when a stalled phone/serial client has
// 16 packets queued.
#define MAX_RX_TOPHONE 16
#else
#define MAX_RX_TOPHONE 32
#endif
Expand Down Expand Up @@ -126,7 +132,10 @@ static inline int get_max_num_nodes()
// Keyed on the NRF52840_XXAA build flag, not ARCH_NRF52: the latter (from
// architecture.h via configuration.h) isn't defined this early in every include
// chain. Backed by the raw-flash ring below LittleFS - see WarmNodeStore.h.
#define WARM_NODE_COUNT 200
// 100 (was 200): the RAM cache is 40 B/entry calloc'd from the ~115 KB heap
// arena, which 2.8.0 field reports showed at 99% use; 120 hot + 100 warm
// identities still covers meshes well past the hot cap.
#define WARM_NODE_COUNT 100
#elif (defined(CONFIG_IDF_TARGET_ESP32S3) && defined(BOARD_HAS_PSRAM)) || defined(ARCH_PORTDUINO)
#define WARM_NODE_COUNT 2000 // PSRAM-equipped ESP32-S3 / native host; warm cache in PSRAM (~80 KB)
#elif defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32P4)
Expand All @@ -136,10 +145,11 @@ static inline int get_max_num_nodes()
#elif defined(ARCH_RP2040)
#define WARM_NODE_COUNT 150 // RP2040 (264 KB) / RP2350 (520 KB): bounded so warm.dat write fits the 8s watchdog (#10746)
#else
// nRF52840 is handled explicitly above (200, raw-flash ring). Any other nRF52 (non-XXAA) and any
// future non-ESP32/non-RP LittleFS part fall through to this 320 default - flag for review if such a
// RAM-constrained nRF52 target is ever added.
#define WARM_NODE_COUNT 320 // other LittleFS-backed parts (e.g. non-nRF52840 nRF52)
// nRF52840 is handled explicitly above (raw-flash ring). Any other nRF52 (non-XXAA) and any future
// non-ESP32/non-RP LittleFS part lands here. Reviewed after the 2.8.0 nRF52840 heap-exhaustion
// reports: fail small (match nRF52840) so an unclassified RAM-constrained part can't boot-allocate
// 12.8 KB; RAM-rich targets should opt up explicitly in their variant.
#define WARM_NODE_COUNT 100 // other LittleFS-backed parts (e.g. non-nRF52840 nRF52)
#endif // platform
#endif // WARM_NODE_COUNT

Expand Down Expand Up @@ -177,11 +187,16 @@ static inline int get_max_num_nodes()
#define TRAFFIC_MANAGEMENT_CACHE_SIZE 500 // 512 KB+ SRAM, no PSRAM (S3/C6/P4): ~5 KB heap (#10705)
#elif defined(ARCH_ESP32)
#define TRAFFIC_MANAGEMENT_CACHE_SIZE 400 // classic ESP32 / S2 / C3: tightest free heap, ~4 KB (#10705)
#elif defined(NRF52840_XXAA)
// Keyed on NRF52840_XXAA (not ARCH_NRF52) for the same include-order reason as WARM_NODE_COUNT above.
// The 256 KB part shares its ~115 KB heap arena with SoftDevice and the FreeRTOS task stacks; 2.8.0
// field reports hit 99% heap use with the old 1000-entry (~10 KB) cache. 250 entries (2.5 KB) still
// tracks >2x the 120-node hot store; LRU victim recycling absorbs busier meshes.
#define TRAFFIC_MANAGEMENT_CACHE_SIZE 250
#else
// nRF52 (incl. nRF52840) and RP2040/RP2350 fall through here - there is no nRF/RP branch above,
// by design. These parts have no ESP32-style WiFi+BLE coexistence eating the heap, so the larger
// 1000-entry (~10 KB) cache fits: nRF52840 is BLE-only on 256 KB RAM; RP2040/RP2350 have 264/520 KB.
#define TRAFFIC_MANAGEMENT_CACHE_SIZE 1000 // nRF52 / RP2040 / RP2350 / other non-ESP32
// RP2040/RP2350 and anything unclassified land here: match the classic-ESP32 tier rather than
// defaulting large. RAM-rich targets should opt up explicitly in their variant.
#define TRAFFIC_MANAGEMENT_CACHE_SIZE 400
#endif
#endif // TRAFFIC_MANAGEMENT_CACHE_SIZE

Expand Down
45 changes: 45 additions & 0 deletions test/test_warm_store/test_main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,50 @@ void test_ws_v1_migration_discardsLastHeard()
b.saveIfDirty();
}

// Shrink safety: a warm.dat snapshot recording more entries than this build's
// WARM_NODE_COUNT (e.g. written before a per-platform tier reduction) must be
// rejected cleanly at the header check - load() starts empty instead of reading
// past entries[]. (The nRF52840 raw-flash ring backend has no such cliff: it
// replays records through place(), whose LRU admission keeps the newest.)
void test_ws_load_rejectsOversizedSnapshot()
{
WarmNodeStore a;
a.absorb(0xA00, 111, NULL);
if (!a.saveIfDirty()) {
TEST_IGNORE_MESSAGE("Filesystem not available in this test environment");
return;
}

// Patch the header's count field (offset 8) to one past capacity.
std::vector<uint8_t> buf;
{
auto f = FSCom.open("/prefs/warm.dat", FILE_O_READ);
if (!f) {
TEST_IGNORE_MESSAGE("warm.dat not readable in this environment");
return;
}
buf.resize(f.size());
f.read(buf.data(), buf.size());
f.close();
}
TEST_ASSERT_TRUE(buf.size() >= 16);
const uint16_t oversized = (uint16_t)(WARM_NODE_COUNT + 1);
memcpy(buf.data() + 8, &oversized, sizeof(oversized));
{
auto f = FSCom.open("/prefs/warm.dat", FILE_O_WRITE);
TEST_ASSERT_TRUE((bool)f);
f.write(buf.data(), buf.size());
f.close();
}

WarmNodeStore b;
b.load();
TEST_ASSERT_EQUAL(0, b.count()); // rejected as invalid, started empty

b.clear();
b.saveIfDirty();
}

WS_TEST_ENTRY void setup()
{
initializeTestEnvironment();
Expand All @@ -273,6 +317,7 @@ WS_TEST_ENTRY void setup()
RUN_TEST(test_ws_remove_and_clear);
RUN_TEST(test_ws_persistence_roundTrip);
RUN_TEST(test_ws_v1_migration_discardsLastHeard);
RUN_TEST(test_ws_load_rejectsOversizedSnapshot);
exit(UNITY_END());
}

Expand Down
1 change: 1 addition & 0 deletions variants/nrf52840/heltec_mesh_node_t096/platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ board_level = pr
debug_tool = jlink

build_flags = ${nrf52840_base.build_flags}
-UOLEDDISPLAY_REDUCE_MEMORY ; TFTDisplay.cpp needs the lib's buffer_back for dirty-window diffing
-Ivariants/nrf52840/heltec_mesh_node_t096
-D HAS_LORA_FEM=1
-D HELTEC_MESH_NODE_T096
Expand Down
1 change: 1 addition & 0 deletions variants/nrf52840/heltec_mesh_node_t1/platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ board_level = pr
debug_tool = jlink

build_flags = ${nrf52840_base.build_flags}
-UOLEDDISPLAY_REDUCE_MEMORY ; TFTDisplay.cpp needs the lib's buffer_back for dirty-window diffing
-Ivariants/nrf52840/heltec_mesh_node_t1
-DHELTEC_MESH_NODE_T1
-DUSE_TFTDISPLAY
Expand Down
1 change: 0 additions & 1 deletion variants/nrf52840/heltec_mesh_node_t114/platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ debug_tool = jlink
build_flags = ${nrf52840_base.build_flags}
-Ivariants/nrf52840/heltec_mesh_node_t114
-DHELTEC_T114
-DOLEDDISPLAY_REDUCE_MEMORY

build_src_filter = ${nrf52_base.build_src_filter} +<../variants/nrf52840/heltec_mesh_node_t114>
lib_deps =
Expand Down
1 change: 0 additions & 1 deletion variants/nrf52840/heltec_mesh_solar/platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,6 @@ extends = heltec_mesh_solar_base
build_flags = ${heltec_mesh_solar_base.build_flags}
-DHELTEC_MESH_SOLAR_TFT
-DSPI_INTERFACES_COUNT=2
-DOLEDDISPLAY_REDUCE_MEMORY
-DHAS_SPI_TFT=1
-DUSE_ST7789
-DST7789_NSS=41
Expand Down
2 changes: 2 additions & 0 deletions variants/nrf52840/nrf52.ini
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ build_flags =
-DLFS_NO_ASSERT ; Disable LFS assertions , see https://github.com/meshtastic/firmware/pull/3818
-DMESHTASTIC_EXCLUDE_AUDIO=1
-DMESHTASTIC_EXCLUDE_PAXCOUNTER=1
-DMESHTASTIC_EXCLUDE_PKT_HISTORY_HASH=1 ; drop PacketHistory's 1 KB hash index; O(n) over ~240 records is negligible at LoRa packet rates
-DOLEDDISPLAY_REDUCE_MEMORY ; drop the ThingPulse OLED back buffer (~1 KB); TFT variants must -U this (TFTDisplay.cpp needs buffer_back)
-Os
-std=gnu++17
-flto ; whole-image LTO (~-60KB) on every nrf52840 target; nrf52_lto.py (pre: extra_script) keeps the interrupt handlers out of LTO so they survive
Expand Down
1 change: 1 addition & 0 deletions variants/nrf52840/rak_wismeshtap/platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ custom_meshtastic_tags = RAK
extends = nrf52840_base
board = wiscore_rak4631
build_flags = ${nrf52840_base.build_flags}
-UOLEDDISPLAY_REDUCE_MEMORY ; TFTDisplay.cpp needs the lib's buffer_back for dirty-window diffing
-Ivariants/nrf52840/rak_wismeshtap
-DWISMESH_TAP
-DRAK_4631
Expand Down
9 changes: 0 additions & 9 deletions variants/nrf52840/tracker-t1000-e/variant.h
Original file line number Diff line number Diff line change
Expand Up @@ -154,15 +154,6 @@ extern "C" {

#define HAS_SCREEN 0

// Enable Traffic Management Module for testing on T1000-E
// NRF52840 has 256KB RAM - 1024 entries uses ~10KB
#ifndef HAS_TRAFFIC_MANAGEMENT
#define HAS_TRAFFIC_MANAGEMENT 1
#endif
#ifndef TRAFFIC_MANAGEMENT_CACHE_SIZE
#define TRAFFIC_MANAGEMENT_CACHE_SIZE 1024
#endif

#ifdef __cplusplus
}
#endif
Expand Down
Loading