Skip to content

Commit df5814e

Browse files
[ESP32] Implement BLE Manager Shutdown for nimble host (project-chip#33109)
* [ESP32] Implement BLE Manager Shutdown for nimble host - Replace ble deinit imple in Esp32AppServer with BLEMgr().Shutdown() - Replace few ESP_LOG with ChipLog in Esp32AppServer - Move ble deinit kCommissioningComplete switch case - Make USE_BLE_ONLY_FOR_COMMISSIONING depends on BT_ENABLED * Restyled by clang-format * address reviews * Add checks for timer handler --------- Co-authored-by: Restyled.io <[email protected]>
1 parent cb79cf7 commit df5814e

File tree

5 files changed

+85
-48
lines changed

5 files changed

+85
-48
lines changed

config/esp32/components/chip/Kconfig

+7-6
Original file line numberDiff line numberDiff line change
@@ -632,12 +632,13 @@ menu "CHIP Device Layer"
632632
When set, WoBLE advertisements will stop while a WoBLE connection is active.
633633

634634
config USE_BLE_ONLY_FOR_COMMISSIONING
635-
bool "Use BLE only for commissioning"
636-
default y
637-
help
638-
Disable this flag if BLE is used for any other purpose than commissioning.
639-
When enabled, it deinitialized the BLE on successful commissioning, and on
640-
bootup do not initialize the BLE if device is already provisioned with Wi-Fi/Thread credentials.
635+
depends on BT_ENABLED
636+
bool "Use BLE only for commissioning"
637+
default y
638+
help
639+
Disable this flag if BLE is used for any other purpose than commissioning.
640+
When enabled, it deinitialized the BLE on successful commissioning, and on
641+
bootup do not initialize the BLE if device is already provisioned with Wi-Fi/Thread credentials.
641642

642643
endmenu
643644

examples/platform/esp32/common/CommonDeviceCallbacks.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@ void CommonDeviceCallbacks::DeviceEventCallback(const ChipDeviceEvent * event, i
5151

5252
case DeviceEventType::kCHIPoBLEConnectionClosed:
5353
ESP_LOGI(TAG, "CHIPoBLE disconnected");
54-
Esp32AppServer::DeInitBLEIfCommissioned();
5554
break;
5655

5756
case DeviceEventType::kDnssdInitialized:
@@ -67,6 +66,7 @@ void CommonDeviceCallbacks::DeviceEventCallback(const ChipDeviceEvent * event, i
6766

6867
case DeviceEventType::kCommissioningComplete: {
6968
ESP_LOGI(TAG, "Commissioning complete");
69+
Esp32AppServer::DeInitBLEIfCommissioned();
7070
}
7171
break;
7272

examples/platform/esp32/common/Esp32AppServer.cpp

+5-39
Original file line numberDiff line numberDiff line change
@@ -115,46 +115,12 @@ static size_t hex_string_to_binary(const char * hex_string, uint8_t * buf, size_
115115

116116
void Esp32AppServer::DeInitBLEIfCommissioned(void)
117117
{
118-
#if CONFIG_BT_ENABLED && CONFIG_USE_BLE_ONLY_FOR_COMMISSIONING
118+
#ifdef CONFIG_USE_BLE_ONLY_FOR_COMMISSIONING
119119
if (chip::Server::GetInstance().GetFabricTable().FabricCount() > 0)
120120
{
121-
esp_err_t err = ESP_OK;
122-
123-
#if CONFIG_BT_NIMBLE_ENABLED
124-
if (!ble_hs_is_enabled())
125-
{
126-
ESP_LOGI(TAG, "BLE already deinited");
127-
return;
128-
}
129-
if (nimble_port_stop() != 0)
130-
{
131-
ESP_LOGE(TAG, "nimble_port_stop() failed");
132-
return;
133-
}
134-
vTaskDelay(100);
135-
nimble_port_deinit();
136-
137-
#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)
138-
err = esp_nimble_hci_and_controller_deinit();
139-
#endif
140-
#endif /* CONFIG_BT_NIMBLE_ENABLED */
141-
142-
#if CONFIG_IDF_TARGET_ESP32
143-
err |= esp_bt_mem_release(ESP_BT_MODE_BTDM);
144-
#elif CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32H2
145-
err |= esp_bt_mem_release(ESP_BT_MODE_BLE);
146-
#endif
147-
148-
if (err != ESP_OK)
149-
{
150-
ESP_LOGE(TAG, "BLE deinit failed");
151-
}
152-
else
153-
{
154-
ESP_LOGI(TAG, "BLE deinit successful and memory reclaimed");
155-
}
121+
chip::DeviceLayer::Internal::BLEMgr().Shutdown();
156122
}
157-
#endif /* CONFIG_BT_ENABLED && CONFIG_USE_BLE_ONLY_FOR_COMMISSIONING */
123+
#endif /* CONFIG_USE_BLE_ONLY_FOR_COMMISSIONING */
158124
}
159125

160126
void Esp32AppServer::Init(AppDelegate * sAppDelegate)
@@ -165,7 +131,7 @@ void Esp32AppServer::Init(AppDelegate * sAppDelegate)
165131
if (hex_string_to_binary(CONFIG_TEST_EVENT_TRIGGER_ENABLE_KEY, sTestEventTriggerEnableKey,
166132
sizeof(sTestEventTriggerEnableKey)) == 0)
167133
{
168-
ESP_LOGE(TAG, "Failed to convert the EnableKey string to octstr type value");
134+
ChipLogError(DeviceLayer, "Failed to convert the EnableKey string to octstr type value");
169135
memset(sTestEventTriggerEnableKey, 0, sizeof(sTestEventTriggerEnableKey));
170136
}
171137
static OTATestEventTriggerDelegate testEventTriggerDelegate{ ByteSpan(sTestEventTriggerEnableKey) };
@@ -189,7 +155,7 @@ void Esp32AppServer::Init(AppDelegate * sAppDelegate)
189155
if (chip::DeviceLayer::ConnectivityMgr().IsThreadProvisioned() &&
190156
(chip::Server::GetInstance().GetFabricTable().FabricCount() != 0))
191157
{
192-
ESP_LOGI(TAG, "Thread has been provisioned, publish the dns service now");
158+
ChipLogProgress(DeviceLayer, "Thread has been provisioned, publish the dns service now");
193159
chip::app::DnssdServer::Instance().StartServer();
194160
}
195161
#endif

src/platform/ESP32/BLEManagerImpl.h

+5-1
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ class BLEManagerImpl final : public BLEManager,
156156
// ===== Members that implement the BLEManager internal interface.
157157

158158
CHIP_ERROR _Init(void);
159-
void _Shutdown() {}
159+
void _Shutdown();
160160
bool _IsAdvertisingEnabled(void);
161161
CHIP_ERROR _SetAdvertisingEnabled(bool val);
162162
bool _IsAdvertising(void);
@@ -296,6 +296,7 @@ class BLEManagerImpl final : public BLEManager,
296296

297297
void DriveBLEState(void);
298298
CHIP_ERROR InitESPBleLayer(void);
299+
void DeinitESPBleLayer(void);
299300
CHIP_ERROR ConfigureAdvertisingData(void);
300301
CHIP_ERROR StartAdvertising(void);
301302

@@ -330,6 +331,9 @@ class BLEManagerImpl final : public BLEManager,
330331
static void HandleGAPEvent(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t * param);
331332

332333
#elif CONFIG_BT_NIMBLE_ENABLED
334+
CHIP_ERROR DeinitBLE();
335+
static void ClaimBLEMemory(System::Layer *, void *);
336+
333337
void HandleRXCharRead(struct ble_gatt_char_context * param);
334338
void HandleRXCharWrite(struct ble_gatt_char_context * param);
335339
void HandleTXCharWrite(struct ble_gatt_char_context * param);

src/platform/ESP32/nimble/BLEManagerImpl.cpp

+67-1
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,21 @@ CHIP_ERROR BLEManagerImpl::_Init()
246246
return err;
247247
}
248248

249+
void BLEManagerImpl::_Shutdown()
250+
{
251+
BleLayer::Shutdown();
252+
253+
// selectively setting kGATTServiceStarted flag, in order to notify the state machine to stop the CHIPoBLE GATT service
254+
mFlags.ClearAll().Set(Flags::kGATTServiceStarted);
255+
mServiceMode = ConnectivityManager::kCHIPoBLEServiceMode_Disabled;
256+
257+
#if CONFIG_ENABLE_ESP32_BLE_CONTROLLER
258+
OnChipBleConnectReceived = nullptr;
259+
#endif // CONFIG_ENABLE_ESP32_BLE_CONTROLLER
260+
261+
PlatformMgr().ScheduleWork(DriveBLEState, 0);
262+
}
263+
249264
CHIP_ERROR BLEManagerImpl::_SetAdvertisingEnabled(bool val)
250265
{
251266
CHIP_ERROR err = CHIP_NO_ERROR;
@@ -806,7 +821,8 @@ void BLEManagerImpl::DriveBLEState(void)
806821
// Stop the CHIPoBLE GATT service if needed.
807822
if (mServiceMode != ConnectivityManager::kCHIPoBLEServiceMode_Enabled && mFlags.Has(Flags::kGATTServiceStarted))
808823
{
809-
// TODO: Not supported
824+
DeinitESPBleLayer();
825+
mFlags.ClearAll();
810826
}
811827

812828
exit:
@@ -932,6 +948,56 @@ CHIP_ERROR BLEManagerImpl::InitESPBleLayer(void)
932948
return err;
933949
}
934950

951+
void BLEManagerImpl::DeinitESPBleLayer()
952+
{
953+
VerifyOrReturn(DeinitBLE() == CHIP_NO_ERROR);
954+
BLEManagerImpl::ClaimBLEMemory(nullptr, nullptr);
955+
}
956+
957+
void BLEManagerImpl::ClaimBLEMemory(System::Layer *, void *)
958+
{
959+
TaskHandle_t handle = xTaskGetHandle("nimble_host");
960+
if (handle)
961+
{
962+
ChipLogDetail(DeviceLayer, "Schedule ble memory reclaiming since nimble host is still running");
963+
964+
// Rescheduling it for later, 2 seconds is an arbitrary value, keeping it a bit more so that
965+
// we dont have to reschedule it again
966+
SystemLayer().StartTimer(System::Clock::Seconds32(2), ClaimBLEMemory, nullptr);
967+
}
968+
else
969+
{
970+
// Free up all the space occupied by ble and add it to heap
971+
esp_err_t err = ESP_OK;
972+
973+
#if CONFIG_IDF_TARGET_ESP32
974+
err = esp_bt_mem_release(ESP_BT_MODE_BTDM);
975+
#elif CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32H2 || \
976+
CONFIG_IDF_TARGET_ESP32C6
977+
err = esp_bt_mem_release(ESP_BT_MODE_BLE);
978+
#endif
979+
980+
VerifyOrReturn(err == ESP_OK, ChipLogError(DeviceLayer, "BLE deinit failed"));
981+
ChipLogProgress(DeviceLayer, "BLE deinit successful and memory reclaimed");
982+
// TODO: post an event when ble is deinitialized and memory is added to heap
983+
}
984+
}
985+
986+
CHIP_ERROR BLEManagerImpl::DeinitBLE()
987+
{
988+
VerifyOrReturnError(ble_hs_is_enabled(), CHIP_ERROR_INCORRECT_STATE, ChipLogProgress(DeviceLayer, "BLE already deinited"));
989+
VerifyOrReturnError(0 == nimble_port_stop(), MapBLEError(ESP_FAIL), ChipLogError(DeviceLayer, "nimble_port_stop() failed"));
990+
991+
esp_err_t err = nimble_port_deinit();
992+
VerifyOrReturnError(err == ESP_OK, MapBLEError(err));
993+
994+
#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)
995+
err = esp_nimble_hci_and_controller_deinit();
996+
#endif
997+
998+
return MapBLEError(err);
999+
}
1000+
9351001
CHIP_ERROR BLEManagerImpl::ConfigureAdvertisingData(void)
9361002
{
9371003
CHIP_ERROR err;

0 commit comments

Comments
 (0)