Count runtime WiFi memory in every ESP32 MQTT profile

This commit is contained in:
mikecarper committed 2026-10-10 15:46:53 -07:00
1 parent 937f8610c7
commit d11bf3615d
3 files changed
+50 -1

No files matched your search

+4
View File
@@ -33,6 +33,10 @@ Classic ESP32 additionally retains its existing 8 KiB **static DRAM** check.
The policy adds allowances for task stacks, radio packet pools, screen objects
and pixel buffers, filesystem/sensor allocations, enabled wireless stacks,
MQTT connections, OTA scratch and transient allocations. ESP32 images with
MQTT reserve the same 49,152-byte WiFi allowance even without `WIFI_SSID` or
`WIFI_OTA_SEEDER`: saved runtime credentials can activate WiFi. Multiple WiFi
features count that allowance once; PSRAM-backed TLS does not remove it.
ESP32 images with
RS-232 reserve another 6,656 bytes even when UART defaults off: 2,560 bytes for
the source-bounded bridge object and allocation metadata, plus an unchanged
4 KiB for the UART driver and buffers. This
+4 -1
View File
@@ -142,7 +142,10 @@ def requirements(platform, defines, target):
parts["uart_bridge_and_driver"] = 2560
elif platform == "ESP32_PLATFORM":
parts["core_tasks_usb_filesystems"] = 24576
wifi = 49152 if "WIFI_SSID" in defines or "WIFI_OTA_SEEDER" in defines else 0
# MQTT joins with saved runtime credentials even without a compiled SSID
# or OTA seeder. Count its mandatory WiFi stack once with other WiFi uses.
wifi = 49152 if any(name in defines for name in (
"WIFI_SSID", "WIFI_OTA_SEEDER", "WITH_MQTT_BRIDGE")) else 0
ble = 32768 if "BLE_PIN_CODE" in defines else 0
parts["wireless_stacks"] = max(wifi, ble) if "COMPANION_EXCLUSIVE_WIFI_BLE" in defines else wifi + ble
if "WITH_MQTT_BRIDGE" in defines:
+42
View File
@@ -233,6 +233,48 @@ class FirmwareRamTest(unittest.TestCase):
ordinary = ram.requirements("ESP32_PLATFORM", {"BOARD_HAS_PSRAM": 1}, "v4_companion")
self.assertNotIn("mqtt", ordinary)
def test_mqtt_without_build_time_wifi_credentials_reserves_wifi_stack_exactly_once(self):
# MQTT can use persisted station credentials without either compile-time
# WiFi option. Isolate the wireless budget from optional browser sessions.
base = {"WEBCONFIG_DISABLED": 1}
for target in ("Tbeam_SX1262_repeater_observer_mqtt", "v4_companion"):
ordinary = ram.requirements("ESP32_PLATFORM", base, target)
self.assertEqual(ordinary["components"]["wireless_stacks"], 0)
mqtt = ram.requirements("ESP32_PLATFORM", {**base, "WITH_MQTT_BRIDGE": 1}, target)
self.assertEqual(mqtt["components"]["wireless_stacks"], 49152)
self.assertEqual(mqtt["required_heap_bytes"] - ordinary["required_heap_bytes"],
49152 + 24576)
for extra in ({"WIFI_SSID": ""}, {"WIFI_OTA_SEEDER": 1},
{"WIFI_SSID": "saved-at-runtime", "WIFI_OTA_SEEDER": 1}):
with self.subTest(target=target, extra=extra):
combined = ram.requirements("ESP32_PLATFORM", {
**base, "WITH_MQTT_BRIDGE": 1, **extra,
}, target)
self.assertEqual(combined, mqtt)
def test_mqtt_only_elf_gate_rejects_the_previously_omitted_wifi_allowance(self):
defines = {"WITH_MQTT_BRIDGE": 1, "WEBCONFIG_DISABLED": 1}
target = "Tbeam_SX1262_repeater_observer_mqtt"
policy = ram.requirements("ESP32_PLATFORM", defines, target)
self.assertEqual(policy["components"]["wireless_stacks"], 49152)
required = policy["required_heap_bytes"]
with tempfile.TemporaryDirectory() as temporary:
path = Path(temporary) / "firmware.elf"
report = Path(temporary) / "firmware.memory.json"
# The old WiFi-omitted policy accepted the first linked capacity.
# The corrected gate must reject it and enforce the exact new bound.
for capacity, expected in ((required - 49152, False),
(required - 1, False), (required, True)):
with self.subTest(capacity=capacity), contextlib.redirect_stdout(io.StringIO()), contextlib.redirect_stderr(io.StringIO()):
esp_fixture(path, modern=True, internal_length=capacity + 0x4000)
status = ram.check_firmware(path, "ESP32_PLATFORM", "esp32s3",
defines, target, report)
result = json.loads(report.read_text())
self.assertEqual(status == 0, expected)
self.assertEqual(result["passed"], expected)
self.assertEqual(result["available_internal_bytes"], capacity)
self.assertEqual(result["required_heap_bytes"], required)
def test_mqtt_worker_stack_growth_raises_gate_and_contiguous_requirement(self):
flags = {"WITH_MQTT_BRIDGE": 1, "BOARD_HAS_PSRAM": 1}
base = ram.requirements("ESP32_PLATFORM", flags, "v4_companion")