|
24 | 24 | #include "shared-bindings/_bleio/Connection.h"
|
25 | 25 | #include "shared-bindings/_bleio/ScanEntry.h"
|
26 | 26 | #include "shared-bindings/time/__init__.h"
|
| 27 | +#include "shared/runtime/interrupt_char.h" |
27 | 28 |
|
28 | 29 | #include "controller/ble_ll_adv.h"
|
29 | 30 | #include "nimble/hci_common.h"
|
|
47 | 48 | #include "shared-module/os/__init__.h"
|
48 | 49 | #endif
|
49 | 50 |
|
50 |
| -bleio_connection_internal_t bleio_connections[BLEIO_TOTAL_CONNECTION_COUNT]; |
| 51 | +// Status variables used while busy-waiting for events. |
| 52 | +static volatile bool _nimble_sync; |
| 53 | +static volatile int _connection_status; |
51 | 54 |
|
52 |
| -bool ble_active = false; |
| 55 | +bleio_connection_internal_t bleio_connections[BLEIO_TOTAL_CONNECTION_COUNT]; |
53 | 56 |
|
54 | 57 | static void nimble_host_task(void *param) {
|
55 | 58 | nimble_port_run();
|
56 | 59 | nimble_port_freertos_deinit();
|
57 | 60 | }
|
58 | 61 |
|
59 |
| -static TaskHandle_t cp_task = NULL; |
60 | 62 |
|
61 | 63 | static void _on_sync(void) {
|
62 | 64 | int rc = ble_hs_util_ensure_addr(false);
|
63 | 65 | assert(rc == 0);
|
64 | 66 |
|
65 |
| - xTaskNotifyGive(cp_task); |
| 67 | + _nimble_sync = true; |
66 | 68 | }
|
67 | 69 |
|
68 | 70 | // All examples have this. It'd make sense in a header.
|
@@ -133,15 +135,26 @@ void common_hal_bleio_adapter_set_enabled(bleio_adapter_obj_t *self, bool enable
|
133 | 135 |
|
134 | 136 | ble_store_config_init();
|
135 | 137 |
|
136 |
| - cp_task = xTaskGetCurrentTaskHandle(); |
137 |
| - |
| 138 | + _nimble_sync = false; |
138 | 139 | nimble_port_freertos_init(nimble_host_task);
|
139 |
| - // Wait for sync. |
140 |
| - ulTaskNotifyTake(pdTRUE, pdMS_TO_TICKS(200)); |
| 140 | + // Wait for sync from nimble task. |
| 141 | + const uint64_t timeout_time_ms = common_hal_time_monotonic_ms() + 200; |
| 142 | + while (!_nimble_sync && (common_hal_time_monotonic_ms() < timeout_time_ms)) { |
| 143 | + RUN_BACKGROUND_TASKS; |
| 144 | + if (mp_hal_is_interrupted()) { |
| 145 | + // Return prematurely. Then the interrupt will be raised. |
| 146 | + return; |
| 147 | + } |
| 148 | + } |
| 149 | + |
| 150 | + if (!_nimble_sync) { |
| 151 | + mp_raise_RuntimeError(MP_ERROR_TEXT("Update failed")); |
| 152 | + } |
141 | 153 | } else {
|
142 | 154 | int ret = nimble_port_stop();
|
143 |
| - while (xTaskGetHandle("nimble_host") != NULL) { |
144 |
| - vTaskDelay(pdMS_TO_TICKS(2)); |
| 155 | + while (xTaskGetHandle("nimble_host") != NULL && !mp_hal_is_interrupted()) { |
| 156 | + RUN_BACKGROUND_TASKS; |
| 157 | + common_hal_time_delay_ms(2); |
145 | 158 | }
|
146 | 159 | if (ret == 0) {
|
147 | 160 | nimble_port_deinit();
|
@@ -309,15 +322,16 @@ static int _mtu_reply(uint16_t conn_handle,
|
309 | 322 | if (error->status == 0) {
|
310 | 323 | connection->mtu = mtu;
|
311 | 324 | }
|
312 |
| - xTaskNotify(cp_task, conn_handle, eSetValueWithOverwrite); |
| 325 | + // Set status var to connection handle to report that connection is now established. |
| 326 | + // Another routine is waiting for this. |
| 327 | + _connection_status = conn_handle; |
313 | 328 | return 0;
|
314 | 329 | }
|
315 | 330 |
|
316 | 331 | static void _new_connection(uint16_t conn_handle) {
|
317 | 332 | // Set the tx_power for the connection higher than the advertisement.
|
318 | 333 | esp_ble_tx_power_set(conn_handle, ESP_PWR_LVL_N0);
|
319 | 334 |
|
320 |
| - |
321 | 335 | // Find an empty connection. One should always be available because the SD has the same
|
322 | 336 | // total connection limit.
|
323 | 337 | bleio_connection_internal_t *connection = NULL;
|
@@ -353,13 +367,14 @@ static int _connect_event(struct ble_gap_event *event, void *self_in) {
|
353 | 367 | switch (event->type) {
|
354 | 368 | case BLE_GAP_EVENT_CONNECT:
|
355 | 369 | if (event->connect.status == 0) {
|
356 |
| - // This triggers an MTU exchange. Its reply will unblock CP. |
| 370 | + // This triggers an MTU exchange. Its reply will exit the loop waiting for a connection. |
357 | 371 | _new_connection(event->connect.conn_handle);
|
358 | 372 | // Set connections objs back to NULL since we have a new
|
359 | 373 | // connection and need a new tuple.
|
360 | 374 | self->connection_objs = NULL;
|
361 | 375 | } else {
|
362 |
| - xTaskNotify(cp_task, -event->connect.status, eSetValueWithOverwrite); |
| 376 | + // The loop waiting for the connection to be comnpleted will stop when _connection_status changes. |
| 377 | + _connection_status = -event->connect.status; |
363 | 378 | }
|
364 | 379 | break;
|
365 | 380 |
|
@@ -397,24 +412,31 @@ mp_obj_t common_hal_bleio_adapter_connect(bleio_adapter_obj_t *self, bleio_addre
|
397 | 412 | ble_addr_t addr;
|
398 | 413 | _convert_address(address, &addr);
|
399 | 414 |
|
400 |
| - cp_task = xTaskGetCurrentTaskHandle(); |
401 |
| - // Make sure we don't have a pending notification from a previous time. This |
402 |
| - // can happen if a previous wait timed out before the notification was given. |
403 |
| - xTaskNotifyStateClear(cp_task); |
| 415 | + const int timeout_ms = SEC_TO_UNITS(timeout, UNIT_1_MS) + 0.5f; |
404 | 416 | CHECK_NIMBLE_ERROR(
|
405 | 417 | ble_gap_connect(own_addr_type, &addr,
|
406 |
| - SEC_TO_UNITS(timeout, UNIT_1_MS) + 0.5f, |
| 418 | + timeout_ms, |
407 | 419 | &conn_params,
|
408 | 420 | _connect_event, self));
|
409 | 421 |
|
410 |
| - int error_code; |
411 | 422 | // Wait an extra 50 ms to give the connect method the opportunity to time out.
|
412 |
| - CHECK_NOTIFY(xTaskNotifyWait(0, 0, (uint32_t *)&error_code, pdMS_TO_TICKS(timeout * 1000 + 50))); |
| 423 | + |
| 424 | + const uint64_t timeout_time_ms = common_hal_time_monotonic_ms() + timeout_ms; |
| 425 | + // _connection_status gets set to either a positive connection handle or a negative error code. |
| 426 | + _connection_status = BLEIO_HANDLE_INVALID; |
| 427 | + while (_connection_status == BLEIO_HANDLE_INVALID && (common_hal_time_monotonic_ms() < timeout_time_ms)) { |
| 428 | + RUN_BACKGROUND_TASKS; |
| 429 | + if (mp_hal_is_interrupted()) { |
| 430 | + // Return prematurely. Then the interrupt exception will be raised. |
| 431 | + return mp_const_none; |
| 432 | + } |
| 433 | + } |
| 434 | + |
413 | 435 | // Negative values are error codes, connection handle otherwise.
|
414 |
| - if (error_code < 0) { |
415 |
| - CHECK_BLE_ERROR(-error_code); |
| 436 | + if (_connection_status < 0) { |
| 437 | + CHECK_BLE_ERROR(-_connection_status); |
416 | 438 | }
|
417 |
| - uint16_t conn_handle = error_code; |
| 439 | + const uint16_t conn_handle = _connection_status; |
418 | 440 |
|
419 | 441 | // TODO: If we have keys, then try and encrypt the connection.
|
420 | 442 |
|
|
0 commit comments