Skip to content

Commit 9d42ca9

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 36f991b commit 9d42ca9

File tree

5 files changed

+103
-57
lines changed

5 files changed

+103
-57
lines changed

config/esp32/components/chip/Kconfig

+7-6
Original file line numberDiff line numberDiff line change
@@ -726,12 +726,13 @@ menu "CHIP Device Layer"
726726
should not start advertising automatically after power-up.
727727

728728
config USE_BLE_ONLY_FOR_COMMISSIONING
729-
bool "Use BLE only for commissioning"
730-
default y
731-
help
732-
Disable this flag if BLE is used for any other purpose than commissioning.
733-
When enabled, it deinitialized the BLE on successful commissioning, and on
734-
bootup do not initialize the BLE if device is already provisioned with Wi-Fi/Thread credentials.
729+
depends on BT_ENABLED
730+
bool "Use BLE only for commissioning"
731+
default y
732+
help
733+
Disable this flag if BLE is used for any other purpose than commissioning.
734+
When enabled, it deinitialized the BLE on successful commissioning, and on
735+
bootup do not initialize the BLE if device is already provisioned with Wi-Fi/Thread credentials.
735736

736737
endmenu
737738

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-40
Original file line numberDiff line numberDiff line change
@@ -116,47 +116,12 @@ static size_t hex_string_to_binary(const char * hex_string, uint8_t * buf, size_
116116

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

162127
void Esp32AppServer::Init(AppDelegate * sAppDelegate)
@@ -167,7 +132,7 @@ void Esp32AppServer::Init(AppDelegate * sAppDelegate)
167132
if (hex_string_to_binary(CONFIG_TEST_EVENT_TRIGGER_ENABLE_KEY, sTestEventTriggerEnableKey,
168133
sizeof(sTestEventTriggerEnableKey)) == 0)
169134
{
170-
ESP_LOGE(TAG, "Failed to convert the EnableKey string to octstr type value");
135+
ChipLogError(DeviceLayer, "Failed to convert the EnableKey string to octstr type value");
171136
memset(sTestEventTriggerEnableKey, 0, sizeof(sTestEventTriggerEnableKey));
172137
}
173138
static SimpleTestEventTriggerDelegate sTestEventTriggerDelegate{};
@@ -194,7 +159,7 @@ void Esp32AppServer::Init(AppDelegate * sAppDelegate)
194159
if (chip::DeviceLayer::ConnectivityMgr().IsThreadProvisioned() &&
195160
(chip::Server::GetInstance().GetFabricTable().FabricCount() != 0))
196161
{
197-
ESP_LOGI(TAG, "Thread has been provisioned, publish the dns service now");
162+
ChipLogProgress(DeviceLayer, "Thread has been provisioned, publish the dns service now");
198163
chip::app::DnssdServer::Instance().StartServer();
199164
}
200165
#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);
@@ -297,6 +297,7 @@ class BLEManagerImpl final : public BLEManager,
297297

298298
void DriveBLEState(void);
299299
CHIP_ERROR InitESPBleLayer(void);
300+
void DeinitESPBleLayer(void);
300301
CHIP_ERROR ConfigureAdvertisingData(void);
301302
CHIP_ERROR StartAdvertising(void);
302303
void StartBleAdvTimeoutTimer(uint32_t aTimeoutInMs);
@@ -327,6 +328,9 @@ class BLEManagerImpl final : public BLEManager,
327328
static void HandleGAPEvent(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t * param);
328329

329330
#elif CONFIG_BT_NIMBLE_ENABLED
331+
CHIP_ERROR DeinitBLE();
332+
static void ClaimBLEMemory(System::Layer *, void *);
333+
330334
void HandleRXCharRead(struct ble_gatt_char_context * param);
331335
void HandleRXCharWrite(struct ble_gatt_char_context * param);
332336
void HandleTXCharWrite(struct ble_gatt_char_context * param);

src/platform/ESP32/nimble/BLEManagerImpl.cpp

+85-9
Original file line numberDiff line numberDiff line change
@@ -212,14 +212,6 @@ CHIP_ERROR BLEManagerImpl::_Init()
212212
{
213213
CHIP_ERROR err;
214214

215-
// Initialize the Chip BleLayer.
216-
#if CONFIG_ENABLE_ESP32_BLE_CONTROLLER
217-
err = BleLayer::Init(this, this, this, &DeviceLayer::SystemLayer());
218-
#else
219-
err = BleLayer::Init(this, this, &DeviceLayer::SystemLayer());
220-
#endif
221-
SuccessOrExit(err);
222-
223215
// Create FreeRTOS sw timer for BLE timeouts and interval change.
224216
sbleAdvTimeoutTimer = xTimerCreate("BleAdvTimer", // Just a text name, not used by the RTOS kernel
225217
1, // == default timer period
@@ -228,6 +220,16 @@ CHIP_ERROR BLEManagerImpl::_Init()
228220
BleAdvTimeoutHandler // timer callback handler
229221
);
230222

223+
VerifyOrReturnError(sbleAdvTimeoutTimer != nullptr, CHIP_ERROR_NO_MEMORY);
224+
225+
// Initialize the Chip BleLayer.
226+
#if CONFIG_ENABLE_ESP32_BLE_CONTROLLER
227+
err = BleLayer::Init(this, this, this, &DeviceLayer::SystemLayer());
228+
#else
229+
err = BleLayer::Init(this, this, &DeviceLayer::SystemLayer());
230+
#endif
231+
SuccessOrExit(err);
232+
231233
mRXCharAttrHandle = 0;
232234
#if CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING
233235
mC3CharAttrHandle = 0;
@@ -253,6 +255,25 @@ CHIP_ERROR BLEManagerImpl::_Init()
253255
return err;
254256
}
255257

258+
void BLEManagerImpl::_Shutdown()
259+
{
260+
VerifyOrReturn(sbleAdvTimeoutTimer != nullptr);
261+
xTimerDelete(sbleAdvTimeoutTimer, portMAX_DELAY);
262+
sbleAdvTimeoutTimer = nullptr;
263+
264+
BleLayer::Shutdown();
265+
266+
// selectively setting kGATTServiceStarted flag, in order to notify the state machine to stop the CHIPoBLE GATT service
267+
mFlags.ClearAll().Set(Flags::kGATTServiceStarted);
268+
mServiceMode = ConnectivityManager::kCHIPoBLEServiceMode_Disabled;
269+
270+
#if CONFIG_ENABLE_ESP32_BLE_CONTROLLER
271+
OnChipBleConnectReceived = nullptr;
272+
#endif // CONFIG_ENABLE_ESP32_BLE_CONTROLLER
273+
274+
PlatformMgr().ScheduleWork(DriveBLEState, 0);
275+
}
276+
256277
CHIP_ERROR BLEManagerImpl::_SetAdvertisingEnabled(bool val)
257278
{
258279
CHIP_ERROR err = CHIP_NO_ERROR;
@@ -708,13 +729,17 @@ CHIP_ERROR BLEManagerImpl::MapBLEError(int bleErr)
708729
}
709730
void BLEManagerImpl::CancelBleAdvTimeoutTimer(void)
710731
{
732+
VerifyOrReturn(sbleAdvTimeoutTimer != nullptr);
733+
711734
if (xTimerStop(sbleAdvTimeoutTimer, pdMS_TO_TICKS(0)) == pdFAIL)
712735
{
713736
ChipLogError(DeviceLayer, "Failed to stop BledAdv timeout timer");
714737
}
715738
}
716739
void BLEManagerImpl::StartBleAdvTimeoutTimer(uint32_t aTimeoutInMs)
717740
{
741+
VerifyOrReturn(sbleAdvTimeoutTimer != nullptr);
742+
718743
if (xTimerIsTimerActive(sbleAdvTimeoutTimer))
719744
{
720745
CancelBleAdvTimeoutTimer();
@@ -844,7 +869,8 @@ void BLEManagerImpl::DriveBLEState(void)
844869
// Stop the CHIPoBLE GATT service if needed.
845870
if (mServiceMode != ConnectivityManager::kCHIPoBLEServiceMode_Enabled && mFlags.Has(Flags::kGATTServiceStarted))
846871
{
847-
// TODO: Not supported
872+
DeinitESPBleLayer();
873+
mFlags.ClearAll();
848874
}
849875

850876
exit:
@@ -970,6 +996,56 @@ CHIP_ERROR BLEManagerImpl::InitESPBleLayer(void)
970996
return err;
971997
}
972998

999+
void BLEManagerImpl::DeinitESPBleLayer()
1000+
{
1001+
VerifyOrReturn(DeinitBLE() == CHIP_NO_ERROR);
1002+
BLEManagerImpl::ClaimBLEMemory(nullptr, nullptr);
1003+
}
1004+
1005+
void BLEManagerImpl::ClaimBLEMemory(System::Layer *, void *)
1006+
{
1007+
TaskHandle_t handle = xTaskGetHandle("nimble_host");
1008+
if (handle)
1009+
{
1010+
ChipLogDetail(DeviceLayer, "Schedule ble memory reclaiming since nimble host is still running");
1011+
1012+
// Rescheduling it for later, 2 seconds is an arbitrary value, keeping it a bit more so that
1013+
// we dont have to reschedule it again
1014+
SystemLayer().StartTimer(System::Clock::Seconds32(2), ClaimBLEMemory, nullptr);
1015+
}
1016+
else
1017+
{
1018+
// Free up all the space occupied by ble and add it to heap
1019+
esp_err_t err = ESP_OK;
1020+
1021+
#if CONFIG_IDF_TARGET_ESP32
1022+
err = esp_bt_mem_release(ESP_BT_MODE_BTDM);
1023+
#elif CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32H2 || \
1024+
CONFIG_IDF_TARGET_ESP32C6
1025+
err = esp_bt_mem_release(ESP_BT_MODE_BLE);
1026+
#endif
1027+
1028+
VerifyOrReturn(err == ESP_OK, ChipLogError(DeviceLayer, "BLE deinit failed"));
1029+
ChipLogProgress(DeviceLayer, "BLE deinit successful and memory reclaimed");
1030+
// TODO: post an event when ble is deinitialized and memory is added to heap
1031+
}
1032+
}
1033+
1034+
CHIP_ERROR BLEManagerImpl::DeinitBLE()
1035+
{
1036+
VerifyOrReturnError(ble_hs_is_enabled(), CHIP_ERROR_INCORRECT_STATE, ChipLogProgress(DeviceLayer, "BLE already deinited"));
1037+
VerifyOrReturnError(0 == nimble_port_stop(), MapBLEError(ESP_FAIL), ChipLogError(DeviceLayer, "nimble_port_stop() failed"));
1038+
1039+
esp_err_t err = nimble_port_deinit();
1040+
VerifyOrReturnError(err == ESP_OK, MapBLEError(err));
1041+
1042+
#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)
1043+
err = esp_nimble_hci_and_controller_deinit();
1044+
#endif
1045+
1046+
return MapBLEError(err);
1047+
}
1048+
9731049
CHIP_ERROR BLEManagerImpl::ConfigureAdvertisingData(void)
9741050
{
9751051
CHIP_ERROR err;

0 commit comments

Comments
 (0)