[feature] Free a little memory used by bluetooth if wifi is enabled or bluetooth is disabled (#10398)
* esp32: release BTDM heap when Bluetooth inactive Release ESP-IDF BTDM memory after config load when Bluetooth is disabled or WiFi is enabled, recovering heap on ESP32 targets where BLE won’t be used for this boot. * Address BT memory release review comments --------- Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
This commit is contained in:
co-authored by
GitHub
Ben Meadors
parent
f1b1e35a79
commit
98fa4a67db
@@ -792,6 +792,11 @@ void setup()
|
|||||||
// We do this as early as possible because this loads preferences from flash
|
// We do this as early as possible because this loads preferences from flash
|
||||||
// but we need to do this after main cpu init (esp32setup), because we need the random seed set
|
// but we need to do this after main cpu init (esp32setup), because we need the random seed set
|
||||||
nodeDB = new NodeDB;
|
nodeDB = new NodeDB;
|
||||||
|
#ifdef ARCH_ESP32
|
||||||
|
// Config is loaded now, and Bluetooth has not been initialized yet. If the
|
||||||
|
// saved config will keep Bluetooth inactive, return its reserved memory early.
|
||||||
|
esp32ReleaseBluetoothMemoryIfUnused();
|
||||||
|
#endif
|
||||||
|
|
||||||
// Initialize transmit history to persist broadcast throttle timers across reboots
|
// Initialize transmit history to persist broadcast throttle timers across reboots
|
||||||
TransmitHistory::getInstance()->loadFromDisk();
|
TransmitHistory::getInstance()->loadFromDisk();
|
||||||
|
|||||||
+4
-1
@@ -11,7 +11,7 @@
|
|||||||
#include "mesh/generated/meshtastic/telemetry.pb.h"
|
#include "mesh/generated/meshtastic/telemetry.pb.h"
|
||||||
#include <SPI.h>
|
#include <SPI.h>
|
||||||
#include <map>
|
#include <map>
|
||||||
#if defined(ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2)
|
#if defined(ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2) && !MESHTASTIC_EXCLUDE_BLUETOOTH
|
||||||
#include "nimble/NimbleBluetooth.h"
|
#include "nimble/NimbleBluetooth.h"
|
||||||
extern NimbleBluetooth *nimbleBluetooth;
|
extern NimbleBluetooth *nimbleBluetooth;
|
||||||
#endif
|
#endif
|
||||||
@@ -114,6 +114,9 @@ extern bool runASAP;
|
|||||||
extern bool pauseBluetoothLogging;
|
extern bool pauseBluetoothLogging;
|
||||||
|
|
||||||
void nrf52Setup(), esp32Setup(), nrf52Loop(), esp32Loop(), rp2040Setup(), clearBonds(), enterDfuMode();
|
void nrf52Setup(), esp32Setup(), nrf52Loop(), esp32Loop(), rp2040Setup(), clearBonds(), enterDfuMode();
|
||||||
|
#ifdef ARCH_ESP32
|
||||||
|
void esp32ReleaseBluetoothMemoryIfUnused();
|
||||||
|
#endif
|
||||||
|
|
||||||
meshtastic_DeviceMetadata getDeviceMetadata();
|
meshtastic_DeviceMetadata getDeviceMetadata();
|
||||||
#if !MESHTASTIC_EXCLUDE_I2C
|
#if !MESHTASTIC_EXCLUDE_I2C
|
||||||
|
|||||||
@@ -1753,6 +1753,7 @@ void disableBluetooth()
|
|||||||
#ifdef ARCH_ESP32
|
#ifdef ARCH_ESP32
|
||||||
if (nimbleBluetooth)
|
if (nimbleBluetooth)
|
||||||
nimbleBluetooth->deinit();
|
nimbleBluetooth->deinit();
|
||||||
|
esp32ReleaseBluetoothMemoryIfUnused();
|
||||||
#elif defined(ARCH_NRF52)
|
#elif defined(ARCH_NRF52)
|
||||||
if (nrf52Bluetooth)
|
if (nrf52Bluetooth)
|
||||||
nrf52Bluetooth->shutdown();
|
nrf52Bluetooth->shutdown();
|
||||||
|
|||||||
@@ -8,6 +8,11 @@
|
|||||||
#include "nimble/NimbleBluetooth.h"
|
#include "nimble/NimbleBluetooth.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !MESHTASTIC_EXCLUDE_BLUETOOTH && __has_include(<esp_bt.h>)
|
||||||
|
#include <esp_bt.h>
|
||||||
|
#define CAN_RELEASE_BT_MEMORY 1
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <MeshtasticOTA.h>
|
#include <MeshtasticOTA.h>
|
||||||
|
|
||||||
#if HAS_WIFI
|
#if HAS_WIFI
|
||||||
@@ -30,9 +35,53 @@
|
|||||||
void variant_shutdown() __attribute__((weak));
|
void variant_shutdown() __attribute__((weak));
|
||||||
void variant_shutdown() {}
|
void variant_shutdown() {}
|
||||||
|
|
||||||
|
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !MESHTASTIC_EXCLUDE_BLUETOOTH
|
||||||
|
static bool bluetoothMemoryReleased;
|
||||||
|
static bool bluetoothMemoryReleaseWarned;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !MESHTASTIC_EXCLUDE_BLUETOOTH
|
||||||
|
static bool isNetworkConfiguredToDisableBluetooth()
|
||||||
|
{
|
||||||
|
#if HAS_WIFI
|
||||||
|
return isWifiAvailable();
|
||||||
|
#elif defined(USE_WS5500) || defined(USE_CH390D)
|
||||||
|
return config.network.wifi_enabled;
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool shouldReleaseBluetoothMemory()
|
||||||
|
{
|
||||||
|
// On ESP32 targets WiFi and BLE share radio resources. When WiFi is configured for this boot,
|
||||||
|
// BLE will not be started, so its reserved memory can be returned to the heap until reboot.
|
||||||
|
if (isNetworkConfiguredToDisableBluetooth()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return !config.bluetooth.enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *getBluetoothReleaseReason()
|
||||||
|
{
|
||||||
|
if (isNetworkConfiguredToDisableBluetooth()) {
|
||||||
|
return "WiFi is enabled";
|
||||||
|
}
|
||||||
|
return "Bluetooth is disabled";
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !MESHTASTIC_EXCLUDE_BLUETOOTH
|
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !MESHTASTIC_EXCLUDE_BLUETOOTH
|
||||||
void setBluetoothEnable(bool enable)
|
void setBluetoothEnable(bool enable)
|
||||||
{
|
{
|
||||||
|
if (enable && bluetoothMemoryReleased) {
|
||||||
|
if (!shouldReleaseBluetoothMemory() && !bluetoothMemoryReleaseWarned) {
|
||||||
|
bluetoothMemoryReleaseWarned = true;
|
||||||
|
LOG_WARN("Bluetooth memory has been released; reboot to re-enable Bluetooth");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(USE_WS5500) || defined(USE_CH390D)
|
#if defined(USE_WS5500) || defined(USE_CH390D)
|
||||||
if ((config.bluetooth.enabled == true) && (config.network.wifi_enabled == false))
|
if ((config.bluetooth.enabled == true) && (config.network.wifi_enabled == false))
|
||||||
#elif HAS_WIFI
|
#elif HAS_WIFI
|
||||||
@@ -58,6 +107,29 @@ void setBluetoothEnable(bool enable) {}
|
|||||||
void updateBatteryLevel(uint8_t level) {}
|
void updateBatteryLevel(uint8_t level) {}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void esp32ReleaseBluetoothMemoryIfUnused()
|
||||||
|
{
|
||||||
|
#ifdef CAN_RELEASE_BT_MEMORY
|
||||||
|
if (bluetoothMemoryReleased || !shouldReleaseBluetoothMemory()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const int32_t heapBefore = ESP.getHeapSize();
|
||||||
|
const int32_t freeBefore = ESP.getFreeHeap();
|
||||||
|
|
||||||
|
// ESP_BT_MODE_BTDM releases all BT/BLE controller and host memory for this boot.
|
||||||
|
// It is intentionally irreversible until reboot, matching the runtime config behavior.
|
||||||
|
esp_err_t err = esp_bt_mem_release(ESP_BT_MODE_BTDM);
|
||||||
|
if (err == ESP_OK) {
|
||||||
|
bluetoothMemoryReleased = true;
|
||||||
|
LOG_INFO("Released BTDM memory because %s: heap %+d, free %+d", getBluetoothReleaseReason(),
|
||||||
|
(int32_t)ESP.getHeapSize() - heapBefore, (int32_t)ESP.getFreeHeap() - freeBefore);
|
||||||
|
} else {
|
||||||
|
LOG_WARN("BTDM memory release failed: %d", err);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void getMacAddr(uint8_t *dmac)
|
void getMacAddr(uint8_t *dmac)
|
||||||
{
|
{
|
||||||
#if defined(CONFIG_IDF_TARGET_ESP32C6) && defined(CONFIG_SOC_IEEE802154_SUPPORTED)
|
#if defined(CONFIG_IDF_TARGET_ESP32C6) && defined(CONFIG_SOC_IEEE802154_SUPPORTED)
|
||||||
|
|||||||
Reference in New Issue
Block a user