summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Halbert <halbert@halwitz.org>2020-01-30 09:52:06 -0500
committerDan Halbert <halbert@halwitz.org>2020-01-30 09:52:06 -0500
commit87f73e2729be3158ea3bb030644cbc42a4913c4c (patch)
treec57fa99165261f2036ed203a7e5a653786c06792
parent5b6b4eb326ce2f7beca20ccdc81fdef422e45848 (diff)
track vm_used_ble better
-rw-r--r--ports/nrf/bluetooth/ble_drv.c3
-rw-r--r--ports/nrf/common-hal/_bleio/Adapter.c8
-rw-r--r--ports/nrf/common-hal/_bleio/__init__.c10
-rw-r--r--ports/nrf/common-hal/_bleio/bonding.c11
-rw-r--r--ports/nrf/common-hal/microcontroller/__init__.c30
5 files changed, 54 insertions, 8 deletions
diff --git a/ports/nrf/bluetooth/ble_drv.c b/ports/nrf/bluetooth/ble_drv.c
index 28a265b7f..e410ac3b4 100644
--- a/ports/nrf/bluetooth/ble_drv.c
+++ b/ports/nrf/bluetooth/ble_drv.c
@@ -145,6 +145,9 @@ void SD_EVT_IRQHandler(void) {
ble_drv_evt_handler_entry_t *it = MP_STATE_VM(ble_drv_evt_handler_entries);
bool done = false;
while (it != NULL) {
+ #if CIRCUITPY_VERBOSE_BLE
+ // mp_printf(&mp_plat_print, " calling handler: 0x%08lx, param: 0x%08lx\n", it->func-1, it->param);
+ #endif
done = it->func(event, it->param) || done;
it = it->next;
}
diff --git a/ports/nrf/common-hal/_bleio/Adapter.c b/ports/nrf/common-hal/_bleio/Adapter.c
index 361fbbf3b..c92ce12a5 100644
--- a/ports/nrf/common-hal/_bleio/Adapter.c
+++ b/ports/nrf/common-hal/_bleio/Adapter.c
@@ -437,6 +437,7 @@ mp_obj_t common_hal_bleio_adapter_start_scan(bleio_adapter_obj_t *self, uint8_t*
.active = active
};
uint32_t err_code;
+ vm_used_ble = true;
err_code = sd_ble_gap_scan_start(&scan_params, sd_data);
if (err_code != NRF_SUCCESS) {
@@ -511,6 +512,7 @@ mp_obj_t common_hal_bleio_adapter_connect(bleio_adapter_obj_t *self, bleio_addre
ble_drv_add_event_handler(connect_on_ble_evt, &event_info);
event_info.done = false;
+ vm_used_ble = true;
uint32_t err_code = sd_ble_gap_connect(&addr, &scan_params, &conn_params, BLE_CONN_CFG_TAG_CUSTOM);
if (err_code != NRF_SUCCESS) {
@@ -615,6 +617,7 @@ uint32_t _common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self,
return err_code;
}
+ vm_used_ble = true;
err_code = sd_ble_gap_adv_start(adv_handle, BLE_CONN_CFG_TAG_CUSTOM);
if (err_code != NRF_SUCCESS) {
return err_code;
@@ -709,6 +712,11 @@ void bleio_adapter_reset(bleio_adapter_obj_t* adapter) {
adapter->connection_objs = NULL;
for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) {
bleio_connection_internal_t *connection = &bleio_connections[i];
+ // Disconnect all connections with Python state cleanly. Keep any supervisor-only connections.
+ if (connection->connection_obj != mp_const_none &&
+ connection->conn_handle != BLE_CONN_HANDLE_INVALID) {
+ common_hal_bleio_connection_disconnect(connection);
+ }
connection->connection_obj = mp_const_none;
}
}
diff --git a/ports/nrf/common-hal/_bleio/__init__.c b/ports/nrf/common-hal/_bleio/__init__.c
index a000c3e7e..58e28c8c1 100644
--- a/ports/nrf/common-hal/_bleio/__init__.c
+++ b/ports/nrf/common-hal/_bleio/__init__.c
@@ -91,13 +91,14 @@ void check_sec_status(uint8_t sec_status) {
void bleio_reset() {
bleio_adapter_reset(&common_hal_bleio_adapter_obj);
if (!vm_used_ble) {
+ // No user-code BLE operations were done, so we can maintain the supervisor state.
return;
}
if (common_hal_bleio_adapter_get_enabled(&common_hal_bleio_adapter_obj)) {
common_hal_bleio_adapter_set_enabled(&common_hal_bleio_adapter_obj, false);
}
- supervisor_start_bluetooth();
bonding_reset();
+ supervisor_start_bluetooth();
}
// The singleton _bleio.Adapter object, bound to _bleio.adapter
@@ -195,14 +196,17 @@ size_t common_hal_bleio_gattc_read(uint16_t handle, uint16_t conn_handle, uint8_
while (nrf_error == NRF_ERROR_BUSY) {
nrf_error = sd_ble_gattc_read(conn_handle, handle, 0);
}
- check_nrf_error(nrf_error);
+ if (nrf_error != NRF_SUCCESS) {
+ ble_drv_remove_event_handler(_on_gattc_read_rsp_evt, &read_info);
+ check_nrf_error(nrf_error);
+ }
while (!read_info.done) {
RUN_BACKGROUND_TASKS;
}
- check_gatt_status(read_info.status);
ble_drv_remove_event_handler(_on_gattc_read_rsp_evt, &read_info);
+ check_gatt_status(read_info.status);
return read_info.final_len;
}
diff --git a/ports/nrf/common-hal/_bleio/bonding.c b/ports/nrf/common-hal/_bleio/bonding.c
index 9716b3988..081ba992f 100644
--- a/ports/nrf/common-hal/_bleio/bonding.c
+++ b/ports/nrf/common-hal/_bleio/bonding.c
@@ -267,14 +267,15 @@ void bonding_background(void) {
for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) {
bleio_connection_internal_t *connection = &bleio_connections[i];
- uint64_t current_ticks_ms = supervisor_ticks_ms64();
// Wait at least one second before saving CCCD, to consolidate
// writes that involve multiple CCCDs. For instance, for HID,
// three CCCD's are set in short succession by the HID client.
- if (connection->do_bond_cccds &&
- current_ticks_ms - connection->do_bond_cccds_request_time >= 1000) {
- write_sys_attr_block(connection);
- connection->do_bond_cccds = false;
+ if (connection->do_bond_cccds) {
+ uint64_t current_ticks_ms = supervisor_ticks_ms64();
+ if (current_ticks_ms - connection->do_bond_cccds_request_time >= 1000) {
+ write_sys_attr_block(connection);
+ connection->do_bond_cccds = false;
+ }
}
if (connection->do_bond_keys) {
diff --git a/ports/nrf/common-hal/microcontroller/__init__.c b/ports/nrf/common-hal/microcontroller/__init__.c
index de924566c..7eb1c0614 100644
--- a/ports/nrf/common-hal/microcontroller/__init__.c
+++ b/ports/nrf/common-hal/microcontroller/__init__.c
@@ -37,8 +37,10 @@
#include "shared-bindings/microcontroller/Processor.h"
#include "supervisor/filesystem.h"
+#include "supervisor/port.h"
#include "supervisor/shared/safe_mode.h"
#include "nrfx_glue.h"
+#include "nrf_nvic.h"
// This routine should work even when interrupts are disabled. Used by OneWire
// for precise timing.
@@ -46,10 +48,38 @@ void common_hal_mcu_delay_us(uint32_t delay) {
NRFX_DELAY_US(delay);
}
+static volatile uint32_t nesting_count = 0;
+static uint8_t is_nested_critical_region;
+static uint8_t sd_is_enabled = false;
void common_hal_mcu_disable_interrupts() {
+ sd_softdevice_is_enabled(&sd_is_enabled);
+ if (sd_is_enabled) {
+ sd_nvic_critical_region_enter(&is_nested_critical_region);
+ } else {
+ __disable_irq();
+ __DMB();
+ nesting_count++;
+ }
}
void common_hal_mcu_enable_interrupts() {
+ // Don't check here if SD is enabled, because we'll crash if interrupts
+ // were turned off and sd_softdevice_is_enabled is called.
+ if (sd_is_enabled) {
+ sd_nvic_critical_region_exit(is_nested_critical_region);
+ } else {
+ if (nesting_count == 0) {
+ // This is very very bad because it means there was mismatched disable/enables so we
+ // crash.
+ reset_into_safe_mode(HARD_CRASH);
+ }
+ nesting_count--;
+ if (nesting_count > 0) {
+ return;
+ }
+ __DMB();
+ __enable_irq();
+ }
}
void common_hal_mcu_on_next_reset(mcu_runmode_t runmode) {