Skip to content

Commit e1dd279

Browse files
shubhamdprestyled-commits
andauthoredApr 24, 2024
[ESP32] Implement BLE Manager Shutdown for nimble host (#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 <commits@restyled.io>
1 parent 67ac842 commit e1dd279

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
@@ -111,47 +111,12 @@ static size_t hex_string_to_binary(const char * hex_string, uint8_t * buf, size_
111111

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

157122
void Esp32AppServer::Init(AppDelegate * sAppDelegate)
@@ -162,7 +127,7 @@ void Esp32AppServer::Init(AppDelegate * sAppDelegate)
162127
if (hex_string_to_binary(CONFIG_TEST_EVENT_TRIGGER_ENABLE_KEY, sTestEventTriggerEnableKey,
163128
sizeof(sTestEventTriggerEnableKey)) == 0)
164129
{
165-
ESP_LOGE(TAG, "Failed to convert the EnableKey string to octstr type value");
130+
ChipLogError(DeviceLayer, "Failed to convert the EnableKey string to octstr type value");
166131
memset(sTestEventTriggerEnableKey, 0, sizeof(sTestEventTriggerEnableKey));
167132
}
168133
static SimpleTestEventTriggerDelegate sTestEventTriggerDelegate{};
@@ -190,7 +155,7 @@ void Esp32AppServer::Init(AppDelegate * sAppDelegate)
190155
if (chip::DeviceLayer::ConnectivityMgr().IsThreadProvisioned() &&
191156
(chip::Server::GetInstance().GetFabricTable().FabricCount() != 0))
192157
{
193-
ESP_LOGI(TAG, "Thread has been provisioned, publish the dns service now");
158+
ChipLogProgress(DeviceLayer, "Thread has been provisioned, publish the dns service now");
194159
chip::app::DnssdServer::Instance().StartServer();
195160
}
196161
#endif

‎src/platform/ESP32/BLEManagerImpl.h

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

159159
CHIP_ERROR _Init(void);
160-
void _Shutdown() {}
160+
void _Shutdown();
161161
bool _IsAdvertisingEnabled(void);
162162
CHIP_ERROR _SetAdvertisingEnabled(bool val);
163163
bool _IsAdvertising(void);
@@ -298,6 +298,7 @@ class BLEManagerImpl final : public BLEManager,
298298

299299
void DriveBLEState(void);
300300
CHIP_ERROR InitESPBleLayer(void);
301+
void DeinitESPBleLayer(void);
301302
CHIP_ERROR ConfigureAdvertisingData(void);
302303
CHIP_ERROR StartAdvertising(void);
303304
void StartBleAdvTimeoutTimer(uint32_t aTimeoutInMs);
@@ -328,6 +329,9 @@ class BLEManagerImpl final : public BLEManager,
328329
static void HandleGAPEvent(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t * param);
329330

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

‎src/platform/ESP32/nimble/BLEManagerImpl.cpp

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

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

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

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

849875
exit:
@@ -969,6 +995,56 @@ CHIP_ERROR BLEManagerImpl::InitESPBleLayer(void)
969995
return err;
970996
}
971997

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

0 commit comments

Comments
 (0)
Please sign in to comment.