Skip to content

Commit 335ad93

Browse files
committed
Workaround ulTaskNotifyTake not blocking. (#326)
The new FreeRTOS version used in newer IDF versions does not always clear the task notification value. This resulted in calls to block using ulTaskNotifyTake returning immediately and causing various crashes.
1 parent d160571 commit 335ad93

File tree

5 files changed

+65
-10
lines changed

5 files changed

+65
-10
lines changed

src/NimBLEClient.cpp

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,8 @@ bool NimBLEClient::connect(const NimBLEAddress &address, bool deleteAttibutes) {
206206
m_peerAddress = address;
207207
}
208208

209-
ble_task_data_t taskData = {this, xTaskGetCurrentTaskHandle(), 0, nullptr};
209+
TaskHandle_t cur_task = xTaskGetCurrentTaskHandle();
210+
ble_task_data_t taskData = {this, cur_task, 0, nullptr};
210211
m_pTaskData = &taskData;
211212
int rc = 0;
212213

@@ -259,6 +260,10 @@ bool NimBLEClient::connect(const NimBLEAddress &address, bool deleteAttibutes) {
259260
return false;
260261
}
261262

263+
#ifdef ulTaskNotifyValueClear
264+
// Clear the task notification value to ensure we block
265+
ulTaskNotifyValueClear(cur_task, ULONG_MAX);
266+
#endif
262267
// Wait for the connect timeout time +1 second for the connection to complete
263268
if(ulTaskNotifyTake(pdTRUE, pdMS_TO_TICKS(m_connectTimeout + 1000)) == pdFALSE) {
264269
m_pTaskData = nullptr;
@@ -309,7 +314,8 @@ bool NimBLEClient::connect(const NimBLEAddress &address, bool deleteAttibutes) {
309314
* @return True on success.
310315
*/
311316
bool NimBLEClient::secureConnection() {
312-
ble_task_data_t taskData = {this, xTaskGetCurrentTaskHandle(), 0, nullptr};
317+
TaskHandle_t cur_task = xTaskGetCurrentTaskHandle();
318+
ble_task_data_t taskData = {this, cur_task, 0, nullptr};
313319

314320
int retryCount = 1;
315321

@@ -323,6 +329,10 @@ bool NimBLEClient::secureConnection() {
323329
return false;
324330
}
325331

332+
#ifdef ulTaskNotifyValueClear
333+
// Clear the task notification value to ensure we block
334+
ulTaskNotifyValueClear(cur_task, ULONG_MAX);
335+
#endif
326336
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
327337
} while (taskData.rc == (BLE_HS_ERR_HCI_BASE + BLE_ERR_PINKEY_MISSING) && retryCount--);
328338

@@ -647,7 +657,8 @@ bool NimBLEClient::retrieveServices(const NimBLEUUID *uuid_filter) {
647657
}
648658

649659
int rc = 0;
650-
ble_task_data_t taskData = {this, xTaskGetCurrentTaskHandle(), 0, nullptr};
660+
TaskHandle_t cur_task = xTaskGetCurrentTaskHandle();
661+
ble_task_data_t taskData = {this, cur_task, 0, nullptr};
651662

652663
if(uuid_filter == nullptr) {
653664
rc = ble_gattc_disc_all_svcs(m_conn_id, NimBLEClient::serviceDiscoveredCB, &taskData);
@@ -662,6 +673,11 @@ bool NimBLEClient::retrieveServices(const NimBLEUUID *uuid_filter) {
662673
return false;
663674
}
664675

676+
#ifdef ulTaskNotifyValueClear
677+
// Clear the task notification value to ensure we block
678+
ulTaskNotifyValueClear(cur_task, ULONG_MAX);
679+
#endif
680+
665681
// wait until we have all the services
666682
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
667683
m_lastErr = taskData.rc;

src/NimBLERemoteCharacteristic.cpp

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,8 @@ bool NimBLERemoteCharacteristic::retrieveDescriptors(const NimBLEUUID *uuid_filt
241241
}
242242

243243
int rc = 0;
244-
ble_task_data_t taskData = {this, xTaskGetCurrentTaskHandle(), 0, nullptr};
244+
TaskHandle_t cur_task = xTaskGetCurrentTaskHandle();
245+
ble_task_data_t taskData = {this, cur_task, 0, nullptr};
245246

246247
// If we don't know the end handle of this characteristic retrieve the next one in the service
247248
// The end handle is the next characteristic definition handle -1.
@@ -256,6 +257,10 @@ bool NimBLERemoteCharacteristic::retrieveDescriptors(const NimBLEUUID *uuid_filt
256257
return false;
257258
}
258259

260+
#ifdef ulTaskNotifyValueClear
261+
// Clear the task notification value to ensure we block
262+
ulTaskNotifyValueClear(cur_task, ULONG_MAX);
263+
#endif
259264
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
260265

261266
if (taskData.rc != 0) {
@@ -277,6 +282,10 @@ bool NimBLERemoteCharacteristic::retrieveDescriptors(const NimBLEUUID *uuid_filt
277282
return false;
278283
}
279284

285+
#ifdef ulTaskNotifyValueClear
286+
// Clear the task notification value to ensure we block
287+
ulTaskNotifyValueClear(cur_task, ULONG_MAX);
288+
#endif
280289
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
281290

282291
if (taskData.rc != 0) {
@@ -477,7 +486,8 @@ std::string NimBLERemoteCharacteristic::readValue(time_t *timestamp) {
477486

478487
int rc = 0;
479488
int retryCount = 1;
480-
ble_task_data_t taskData = {this, xTaskGetCurrentTaskHandle(),0, &value};
489+
TaskHandle_t cur_task = xTaskGetCurrentTaskHandle();
490+
ble_task_data_t taskData = {this, cur_task, 0, &value};
481491

482492
do {
483493
rc = ble_gattc_read_long(pClient->getConnId(), m_handle, 0,
@@ -489,6 +499,10 @@ std::string NimBLERemoteCharacteristic::readValue(time_t *timestamp) {
489499
return value;
490500
}
491501

502+
#ifdef ulTaskNotifyValueClear
503+
// Clear the task notification value to ensure we block
504+
ulTaskNotifyValueClear(cur_task, ULONG_MAX);
505+
#endif
492506
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
493507
rc = taskData.rc;
494508

@@ -746,7 +760,8 @@ bool NimBLERemoteCharacteristic::writeValue(const uint8_t* data, size_t length,
746760
return (rc==0);
747761
}
748762

749-
ble_task_data_t taskData = {this, xTaskGetCurrentTaskHandle(), 0, nullptr};
763+
TaskHandle_t cur_task = xTaskGetCurrentTaskHandle();
764+
ble_task_data_t taskData = {this, cur_task, 0, nullptr};
750765

751766
do {
752767
if(length > mtu) {
@@ -766,6 +781,10 @@ bool NimBLERemoteCharacteristic::writeValue(const uint8_t* data, size_t length,
766781
return false;
767782
}
768783

784+
#ifdef ulTaskNotifyValueClear
785+
// Clear the task notification value to ensure we block
786+
ulTaskNotifyValueClear(cur_task, ULONG_MAX);
787+
#endif
769788
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
770789
rc = taskData.rc;
771790

src/NimBLERemoteDescriptor.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,8 @@ std::string NimBLERemoteDescriptor::readValue() {
139139

140140
int rc = 0;
141141
int retryCount = 1;
142-
ble_task_data_t taskData = {this, xTaskGetCurrentTaskHandle(),0, &value};
142+
TaskHandle_t cur_task = xTaskGetCurrentTaskHandle();
143+
ble_task_data_t taskData = {this, cur_task, 0, &value};
143144

144145
do {
145146
rc = ble_gattc_read_long(pClient->getConnId(), m_handle, 0,
@@ -151,6 +152,10 @@ std::string NimBLERemoteDescriptor::readValue() {
151152
return value;
152153
}
153154

155+
#ifdef ulTaskNotifyValueClear
156+
// Clear the task notification value to ensure we block
157+
ulTaskNotifyValueClear(cur_task, ULONG_MAX);
158+
#endif
154159
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
155160
rc = taskData.rc;
156161

@@ -290,7 +295,8 @@ bool NimBLERemoteDescriptor::writeValue(const uint8_t* data, size_t length, bool
290295
return (rc == 0);
291296
}
292297

293-
ble_task_data_t taskData = {this, xTaskGetCurrentTaskHandle(), 0, nullptr};
298+
TaskHandle_t cur_task = xTaskGetCurrentTaskHandle();
299+
ble_task_data_t taskData = {this, cur_task, 0, nullptr};
294300

295301
do {
296302
if(length > mtu) {
@@ -311,6 +317,10 @@ bool NimBLERemoteDescriptor::writeValue(const uint8_t* data, size_t length, bool
311317
return false;
312318
}
313319

320+
#ifdef ulTaskNotifyValueClear
321+
// Clear the task notification value to ensure we block
322+
ulTaskNotifyValueClear(cur_task, ULONG_MAX);
323+
#endif
314324
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
315325
rc = taskData.rc;
316326

src/NimBLERemoteService.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,8 @@ bool NimBLERemoteService::retrieveCharacteristics(const NimBLEUUID *uuid_filter)
198198
NIMBLE_LOGD(LOG_TAG, ">> retrieveCharacteristics() for service: %s", getUUID().toString().c_str());
199199

200200
int rc = 0;
201-
ble_task_data_t taskData = {this, xTaskGetCurrentTaskHandle(), 0, nullptr};
201+
TaskHandle_t cur_task = xTaskGetCurrentTaskHandle();
202+
ble_task_data_t taskData = {this, cur_task, 0, nullptr};
202203

203204
if(uuid_filter == nullptr) {
204205
rc = ble_gattc_disc_all_chrs(m_pClient->getConnId(),
@@ -220,6 +221,10 @@ bool NimBLERemoteService::retrieveCharacteristics(const NimBLEUUID *uuid_filter)
220221
return false;
221222
}
222223

224+
#ifdef ulTaskNotifyValueClear
225+
// Clear the task notification value to ensure we block
226+
ulTaskNotifyValueClear(cur_task, ULONG_MAX);
227+
#endif
223228
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
224229

225230
if(taskData.rc == 0){

src/NimBLEScan.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -358,10 +358,15 @@ NimBLEScanResults NimBLEScan::start(uint32_t duration, bool is_continue) {
358358
NIMBLE_LOGW(LOG_TAG, "Blocking scan called with duration = forever");
359359
}
360360

361-
ble_task_data_t taskData = {nullptr, xTaskGetCurrentTaskHandle(),0, nullptr};
361+
TaskHandle_t cur_task = xTaskGetCurrentTaskHandle();
362+
ble_task_data_t taskData = {nullptr, cur_task, 0, nullptr};
362363
m_pTaskData = &taskData;
363364

364365
if(start(duration, nullptr, is_continue)) {
366+
#ifdef ulTaskNotifyValueClear
367+
// Clear the task notification value to ensure we block
368+
ulTaskNotifyValueClear(cur_task, ULONG_MAX);
369+
#endif
365370
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
366371
}
367372

0 commit comments

Comments
 (0)