From b6b23bd423d492d3b4f0b4f2f7e15bf72f205e2e Mon Sep 17 00:00:00 2001 From: Florian Date: Sun, 23 Aug 2026 14:15:48 -0500 Subject: [PATCH] [RF] Move RTL_433 / SX127x envs to the shipped ESP32 platform (#2360) Eight environments were still pinned to espressif32@6.1.0 (arduino-esp32 2.0.7 / IDF 4.4) while the rest of the tree had moved to the shared ${com.esp32_platform} definition. Align them so they build against the platform that actually ships, rather than silently keeping an old toolchain alive: esp32doitv1-aithinker-r01-sx1278 esp32dev-rtl_433, esp32dev-rtl_433-fsk heltec-rtl_433, heltec-rtl_433-fsk lilygo-rtl_433, lilygo-rtl_433-fsk esp32dev-multi_receiver The stray "* copy.c" duplicate in rtl_433_ESP that previously blocked these envs on a modern toolchain is gone as of rtl_433_ESP v0.6.0, which development already pulls in, so no build workaround is needed. The move alone is not sufficient: the newer core leaves ~35 KB less heap on BT-less ESP32 builds, which pushes the memory-constrained RTL_433 boards into a boot loop at the first TLS handshake. That is fixed here too, in main.cpp. On ESP32-classic builds without ZgatewayBT, arduino-esp32 3.x leaves most of the Bluetooth controller's reserved DRAM (CONFIG_BTDM_RESERVE_DRAM = 0xdb5c, 56156 B) stranded. arduino-esp32 2.x released the whole BTDM region unconditionally in initArduino(): if (!btInUse()) esp_bt_controller_mem_release(ESP_BT_MODE_BTDM); 3.x releases CLASSIC and BLE separately, and the CLASSIC pass silently short-circuits. cores/esp32/esp32-hal-bt.c has: #if defined(CONFIG_BT_CLASSIC_ENABLED) static bool _classicMemReleased = false; #else static bool _classicMemReleased = true; // "No Classic BT on this chip" #endif With a BLE-only controller build CONFIG_BT_CLASSIC_ENABLED is unset, so _classicMemReleased starts true and btMemRelease(BT_MODE_CLASSIC_BT) returns "already released" without reaching IDF. Only the ~5 KB BLE slice is freed. The guard is wrong for this part: ESP32 does have Classic BT hardware (CONFIG_SOC_BT_CLASSIC_SUPPORTED) and the DRAM is reserved regardless of the controller's configured mode; the correct guard would be CONFIG_SOC_BT_CLASSIC_SUPPORTED. Reported upstream separately. Release the whole BTDM region explicitly. esp_bt_mem_release() is used rather than esp_bt_controller_mem_release() because it is a superset that also frees the linker _bt_data / _bt_controller_* sections. The guard is compile-time and authoritative: OMG knows via ZgatewayBT whether it uses BT, whereas the core infers it from link-time flags that NimBLE-Arduino does not set. Safe no-op if the memory was already released or once the core is fixed. Note this makes btStart() permanently unavailable in these builds, which is already the case for a !ZgatewayBT build. Measured on a Heltec WiFi LoRa32 V2 running heltec-rtl_433 (WiFi + MQTT + TLS + rtl_433 + SSD1306, no BT), pioarduino 55.03.39 / esp32-arduino-libs 0.1.8: BT DRAM reclaimed: 209928 -> 245048 (+35120 B) Update check, free heap: 49868 -> 89484 Without it, the boot-time HTTPS update check fails its TLS handshake ("Dynamic Impl: alloc(4437 bytes) failed", then X509 -9984) because the largest free block is too small, and the MinimumMemory watchdog then reboots the board in a loop. With it: no allocation failure, handshake succeeds, freemem ~85 KB / minmem 53432 against the 40000 threshold, 0 reboots over a 3 min soak with live RTL_433 decodes. The memory fix affects every ESP32-classic env without ZgatewayBT, not just the ones moved here. The RTL_433 envs fail loudly because they carry the MinimumMemory watchdog; others (esp32dev-ir, esp32dev-pilight, ttgo-lora32-v21, heltec-wifi-lora-32, ...) simply run ~35 KB short. Builds with ZgatewayBT are unaffected. Hardware validation, two boards: heltec-rtl_433 (OOK 433.92 MHz, Heltec WiFi LoRa32 V2) boots, joins WiFi/MQTT, RadioLib/SX127x RSSI calibration completes, HA discovery publishes, decodes live ambient sensors (Ambientweather-F007TH, Prologue-TH, WEC-2103). heltec-rtl_433-fsk (FSK 915 MHz, second Heltec) same boot path, decodes a live Fineoffset-WH51 soil sensor. The other six envs have no matching board on hand and are compile-only. Co-authored-by: Claude Opus 5 --- environments.ini | 24 ++++++++++++++++-------- main/main.cpp | 21 +++++++++++++++++++++ 2 files changed, 37 insertions(+), 8 deletions(-) diff --git a/environments.ini b/environments.ini index 179992a..ac3c070 100644 --- a/environments.ini +++ b/environments.ini @@ -851,7 +851,8 @@ custom_hardware = M5 ATOM Lite custom_img = img/boards/m5atom-lite.webp [env:esp32doitv1-aithinker-r01-sx1278] -platform = espressif32@6.1.0 +platform = ${com.esp32_platform} +platform_packages = ${com.esp32_platform_packages} board = esp32doit-devkit-v1 board_build.partitions = min_spiffs.csv lib_deps = @@ -931,7 +932,8 @@ upload_flags = --port=8266 [env:esp32dev-rtl_433] -platform = espressif32@6.1.0 +platform = ${com.esp32_platform} +platform_packages = ${com.esp32_platform_packages} board = esp32dev board_build.partitions = min_spiffs.csv lib_deps = @@ -972,7 +974,8 @@ custom_description = Gateway using RTL_433_ESP library, need CC1101 custom_img = img/boards/esp32dev.jpg [env:esp32dev-rtl_433-fsk] -platform = espressif32@6.1.0 +platform = ${com.esp32_platform} +platform_packages = ${com.esp32_platform_packages} board = esp32dev board_build.partitions = min_spiffs.csv lib_deps = @@ -1017,7 +1020,8 @@ custom_description = Gateway using RTL_433_ESP library and RadioLib with FSK mod custom_img = img/boards/esp32dev.jpg [env:heltec-rtl_433] -platform = espressif32@6.1.0 +platform = ${com.esp32_platform} +platform_packages = ${com.esp32_platform_packages} board = heltec_wifi_lora_32_V2 ; ~/.platformio/packages/framework-arduinoespressif32/variants/.../pins_arduino.h board_build.partitions = min_spiffs.csv @@ -1047,7 +1051,8 @@ custom_hardware = ESP32 HELTEC LORA32 V2 custom_img = img/boards/heltec-wifi-lora-32.png [env:heltec-rtl_433-fsk] -platform = espressif32@6.1.0 +platform = ${com.esp32_platform} +platform_packages = ${com.esp32_platform_packages} board = heltec_wifi_lora_32_V2 ; ~/.platformio/packages/framework-arduinoespressif32/variants/.../pins_arduino.h board_build.partitions = min_spiffs.csv @@ -1107,7 +1112,8 @@ custom_hardware = ESP32 HELTEC LORA32 V2 custom_img = img/boards/heltec-wifi-lora-32.png [env:lilygo-rtl_433] -platform = espressif32@6.1.0 +platform = ${com.esp32_platform} +platform_packages = ${com.esp32_platform_packages} board = ttgo-lora32-v21 ; ~/.platformio/packages/framework-arduinoespressif32/variants/.../pins_arduino.h board_build.partitions = min_spiffs.csv @@ -1137,7 +1143,8 @@ custom_hardware = ESP32 LILYGO LoRa32 V2.1 custom_img = img/boards/lilygo-lora32-v21.jpg [env:lilygo-rtl_433-fsk] -platform = espressif32@6.1.0 +platform = ${com.esp32_platform} +platform_packages = ${com.esp32_platform_packages} board = ttgo-lora32-v21 ; ~/.platformio/packages/framework-arduinoespressif32/variants/.../pins_arduino.h board_build.partitions = min_spiffs.csv @@ -1295,7 +1302,8 @@ custom_hardware = ESP32 LILYGO LoRa32 V2.1 custom_img = img/boards/lilygo-lora32-v21.jpg [env:esp32dev-multi_receiver] -platform = espressif32@6.1.0 +platform = ${com.esp32_platform} +platform_packages = ${com.esp32_platform_packages} board = esp32dev board_build.partitions = min_spiffs.csv lib_deps = diff --git a/main/main.cpp b/main/main.cpp index 9bcb68e..3a40c4b 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -35,6 +35,10 @@ #include "TheengsCommon.h" #include "TheengsUtils.h" +#if defined(CONFIG_IDF_TARGET_ESP32) && !defined(ZgatewayBT) && !defined(USE_BLUFI) +# include "esp_bt.h" // esp_bt_mem_release() — BT DRAM reclaim in setup() +#endif + GatewayState gatewayState = GatewayState::WAITING_ONBOARDING; static GatewayState previousGatewayState = gatewayState; @@ -1340,6 +1344,23 @@ void setup() { Serial.begin(SERIAL_BAUD); Log.begin(LOG_LEVEL, &Serial); THEENGS_LOG_NOTICE(F(CR "************* WELCOME TO OpenMQTTGateway **************" CR)); +#if defined(CONFIG_IDF_TARGET_ESP32) && !defined(ZgatewayBT) && !defined(USE_BLUFI) + // Reclaim the Bluetooth controller's reserved DRAM on BT-less ESP32 builds. + // arduino-esp32 3.x releases only the BLE slice: esp32-hal-bt.c initialises + // _classicMemReleased = true whenever CONFIG_BT_CLASSIC_ENABLED is unset, + // which is the case for a BLE-only controller build — so its + // btMemRelease(BT_MODE_CLASSIC_BT) call short-circuits and ~33 KB of the + // 0xdb5c reservation is never returned to the heap. ESP32 has Classic BT + // hardware (CONFIG_SOC_BT_CLASSIC_SUPPORTED) and the DRAM is reserved + // regardless of the configured controller mode. arduino-esp32 2.x released + // the whole BTDM region unconditionally here. + // Safe no-op if the core ever releases it correctly, or if BT is later started. + { + uint32_t heapBeforeBtRelease = ESP.getFreeHeap(); + esp_bt_mem_release(ESP_BT_MODE_BTDM); + THEENGS_LOG_NOTICE(F("BT DRAM reclaimed: %d -> %d" CR), heapBeforeBtRelease, ESP.getFreeHeap()); + } +#endif #if defined(TRIGGER_GPIO) && !defined(ESPWifiManualSetup) pinMode(TRIGGER_GPIO, INPUT_PULLUP); checkButton();