diff --git a/extmod/btstack/modbluetooth_btstack.c b/extmod/btstack/modbluetooth_btstack.c index c9cc0a8864..523dba5589 100644 --- a/extmod/btstack/modbluetooth_btstack.c +++ b/extmod/btstack/modbluetooth_btstack.c @@ -160,29 +160,30 @@ STATIC void btstack_packet_handler(uint8_t packet_type, uint16_t channel, uint8_ uint16_t value_handle = gatt_event_characteristic_value_query_result_get_value_handle(packet); uint16_t len = gatt_event_characteristic_value_query_result_get_value_length(packet); const uint8_t *data = gatt_event_characteristic_value_query_result_get_value(packet); - MICROPY_PY_BLUETOOTH_ENTER - len = mp_bluetooth_gattc_on_data_available_start(MP_BLUETOOTH_IRQ_GATTC_READ_RESULT, conn_handle, value_handle, len); + mp_uint_t atomic_state; + len = mp_bluetooth_gattc_on_data_available_start(MP_BLUETOOTH_IRQ_GATTC_READ_RESULT, conn_handle, value_handle, len, &atomic_state); mp_bluetooth_gattc_on_data_available_chunk(data, len); - mp_bluetooth_gattc_on_data_available_end(); - MICROPY_PY_BLUETOOTH_EXIT + mp_bluetooth_gattc_on_data_available_end(atomic_state); } else if (event_type == GATT_EVENT_NOTIFICATION) { DEBUG_EVENT_printf(" --> gatt notification\n"); uint16_t conn_handle = gatt_event_notification_get_handle(packet); uint16_t value_handle = gatt_event_notification_get_value_handle(packet); uint16_t len = gatt_event_notification_get_value_length(packet); const uint8_t *data = gatt_event_notification_get_value(packet); - len = mp_bluetooth_gattc_on_data_available_start(MP_BLUETOOTH_IRQ_GATTC_NOTIFY, conn_handle, value_handle, len); + mp_uint_t atomic_state; + len = mp_bluetooth_gattc_on_data_available_start(MP_BLUETOOTH_IRQ_GATTC_NOTIFY, conn_handle, value_handle, len, &atomic_state); mp_bluetooth_gattc_on_data_available_chunk(data, len); - mp_bluetooth_gattc_on_data_available_end(); + mp_bluetooth_gattc_on_data_available_end(atomic_state); } else if (event_type == GATT_EVENT_INDICATION) { DEBUG_EVENT_printf(" --> gatt indication\n"); uint16_t conn_handle = gatt_event_indication_get_handle(packet); uint16_t value_handle = gatt_event_indication_get_value_handle(packet); uint16_t len = gatt_event_indication_get_value_length(packet); const uint8_t *data = gatt_event_indication_get_value(packet); - len = mp_bluetooth_gattc_on_data_available_start(MP_BLUETOOTH_IRQ_GATTC_INDICATE, conn_handle, value_handle, len); + mp_uint_t atomic_state; + len = mp_bluetooth_gattc_on_data_available_start(MP_BLUETOOTH_IRQ_GATTC_INDICATE, conn_handle, value_handle, len, &atomic_state); mp_bluetooth_gattc_on_data_available_chunk(data, len); - mp_bluetooth_gattc_on_data_available_end(); + mp_bluetooth_gattc_on_data_available_end(atomic_state); #endif } else { DEBUG_EVENT_printf(" --> hci event type: unknown (0x%02x)\n", event_type); diff --git a/extmod/modbluetooth.c b/extmod/modbluetooth.c index 41e46b2f36..cb5900873d 100644 --- a/extmod/modbluetooth.c +++ b/extmod/modbluetooth.c @@ -918,11 +918,15 @@ STATIC bool enqueue_irq(mp_obj_bluetooth_ble_t *o, size_t len, uint16_t event) { return true; } -STATIC void schedule_ringbuf(void) { +// Must hold the atomic section before calling this (MICROPY_PY_BLUETOOTH_ENTER). +STATIC void schedule_ringbuf(mp_uint_t atomic_state) { mp_obj_bluetooth_ble_t *o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth)); if (!o->irq_scheduled) { o->irq_scheduled = true; + MICROPY_PY_BLUETOOTH_EXIT mp_sched_schedule(MP_OBJ_FROM_PTR(&bluetooth_ble_invoke_irq_obj), mp_const_none); + } else { + MICROPY_PY_BLUETOOTH_EXIT } } @@ -936,8 +940,7 @@ void mp_bluetooth_gap_on_connected_disconnected(uint16_t event, uint16_t conn_ha ringbuf_put(&o->ringbuf, addr[i]); } } - schedule_ringbuf(); - MICROPY_PY_BLUETOOTH_EXIT + schedule_ringbuf(atomic_state); } void mp_bluetooth_gatts_on_write(uint16_t conn_handle, uint16_t value_handle) { @@ -947,8 +950,7 @@ void mp_bluetooth_gatts_on_write(uint16_t conn_handle, uint16_t value_handle) { ringbuf_put16(&o->ringbuf, conn_handle); ringbuf_put16(&o->ringbuf, value_handle); } - schedule_ringbuf(); - MICROPY_PY_BLUETOOTH_EXIT + schedule_ringbuf(atomic_state); } #if MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE @@ -957,8 +959,7 @@ void mp_bluetooth_gap_on_scan_complete(void) { mp_obj_bluetooth_ble_t *o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth)); if (enqueue_irq(o, 0, MP_BLUETOOTH_IRQ_SCAN_COMPLETE)) { } - schedule_ringbuf(); - MICROPY_PY_BLUETOOTH_EXIT + schedule_ringbuf(atomic_state); } void mp_bluetooth_gap_on_scan_result(uint8_t addr_type, const uint8_t *addr, uint8_t adv_type, const int8_t rssi, const uint8_t *data, size_t data_len) { @@ -979,8 +980,7 @@ void mp_bluetooth_gap_on_scan_result(uint8_t addr_type, const uint8_t *addr, uin ringbuf_put(&o->ringbuf, data[i]); } } - schedule_ringbuf(); - MICROPY_PY_BLUETOOTH_EXIT + schedule_ringbuf(atomic_state); } void mp_bluetooth_gattc_on_primary_service_result(uint16_t conn_handle, uint16_t start_handle, uint16_t end_handle, mp_obj_bluetooth_uuid_t *service_uuid) { @@ -992,8 +992,7 @@ void mp_bluetooth_gattc_on_primary_service_result(uint16_t conn_handle, uint16_t ringbuf_put16(&o->ringbuf, end_handle); ringbuf_put_uuid(&o->ringbuf, service_uuid); } - schedule_ringbuf(); - MICROPY_PY_BLUETOOTH_EXIT + schedule_ringbuf(atomic_state); } void mp_bluetooth_gattc_on_characteristic_result(uint16_t conn_handle, uint16_t def_handle, uint16_t value_handle, uint8_t properties, mp_obj_bluetooth_uuid_t *characteristic_uuid) { @@ -1006,8 +1005,7 @@ void mp_bluetooth_gattc_on_characteristic_result(uint16_t conn_handle, uint16_t ringbuf_put(&o->ringbuf, properties); ringbuf_put_uuid(&o->ringbuf, characteristic_uuid); } - schedule_ringbuf(); - MICROPY_PY_BLUETOOTH_EXIT + schedule_ringbuf(atomic_state); } void mp_bluetooth_gattc_on_descriptor_result(uint16_t conn_handle, uint16_t handle, mp_obj_bluetooth_uuid_t *descriptor_uuid) { @@ -1018,11 +1016,12 @@ void mp_bluetooth_gattc_on_descriptor_result(uint16_t conn_handle, uint16_t hand ringbuf_put16(&o->ringbuf, handle); ringbuf_put_uuid(&o->ringbuf, descriptor_uuid); } - schedule_ringbuf(); - MICROPY_PY_BLUETOOTH_EXIT + schedule_ringbuf(atomic_state); } -size_t mp_bluetooth_gattc_on_data_available_start(uint16_t event, uint16_t conn_handle, uint16_t value_handle, size_t data_len) { +size_t mp_bluetooth_gattc_on_data_available_start(uint16_t event, uint16_t conn_handle, uint16_t value_handle, size_t data_len, mp_uint_t *atomic_state_out) { + MICROPY_PY_BLUETOOTH_ENTER + *atomic_state_out = atomic_state; mp_obj_bluetooth_ble_t *o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth)); data_len = MIN(o->irq_data_data_alloc, data_len); if (enqueue_irq(o, 2 + 2 + 1 + data_len, event)) { @@ -1042,8 +1041,8 @@ void mp_bluetooth_gattc_on_data_available_chunk(const uint8_t *data, size_t data } } -void mp_bluetooth_gattc_on_data_available_end(void) { - schedule_ringbuf(); +void mp_bluetooth_gattc_on_data_available_end(mp_uint_t atomic_state) { + schedule_ringbuf(atomic_state); } void mp_bluetooth_gattc_on_write_status(uint16_t conn_handle, uint16_t value_handle, uint16_t status) { @@ -1054,8 +1053,7 @@ void mp_bluetooth_gattc_on_write_status(uint16_t conn_handle, uint16_t value_han ringbuf_put16(&o->ringbuf, value_handle); ringbuf_put16(&o->ringbuf, status); } - schedule_ringbuf(); - MICROPY_PY_BLUETOOTH_EXIT + schedule_ringbuf(atomic_state); } #endif // MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE diff --git a/extmod/modbluetooth.h b/extmod/modbluetooth.h index 376d3f5acb..96c9c4b9a6 100644 --- a/extmod/modbluetooth.h +++ b/extmod/modbluetooth.h @@ -263,9 +263,9 @@ void mp_bluetooth_gattc_on_descriptor_result(uint16_t conn_handle, uint16_t hand // Notify modbluetooth that a read has completed with data (or notify/indicate data available, use `event` to disambiguate). // Note: these functions are to be called in a group protected by MICROPY_PY_BLUETOOTH_ENTER/EXIT. // _start returns the number of bytes to submit to the calls to _chunk, followed by a call to _end. -size_t mp_bluetooth_gattc_on_data_available_start(uint16_t event, uint16_t conn_handle, uint16_t value_handle, size_t data_len); +size_t mp_bluetooth_gattc_on_data_available_start(uint16_t event, uint16_t conn_handle, uint16_t value_handle, size_t data_len, mp_uint_t *atomic_state_out); void mp_bluetooth_gattc_on_data_available_chunk(const uint8_t *data, size_t data_len); -void mp_bluetooth_gattc_on_data_available_end(void); +void mp_bluetooth_gattc_on_data_available_end(mp_uint_t atomic_state); // Notify modbluetooth that a write has completed. void mp_bluetooth_gattc_on_write_status(uint16_t conn_handle, uint16_t value_handle, uint16_t status); diff --git a/extmod/nimble/modbluetooth_nimble.c b/extmod/nimble/modbluetooth_nimble.c index 334a00b5e7..9498e998b4 100644 --- a/extmod/nimble/modbluetooth_nimble.c +++ b/extmod/nimble/modbluetooth_nimble.c @@ -613,17 +613,16 @@ int mp_bluetooth_gatts_set_buffer(uint16_t value_handle, size_t len, bool append #if MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE STATIC void gattc_on_data_available(uint16_t event, uint16_t conn_handle, uint16_t value_handle, const struct os_mbuf *om) { - MICROPY_PY_BLUETOOTH_ENTER size_t len = OS_MBUF_PKTLEN(om); - len = mp_bluetooth_gattc_on_data_available_start(event, conn_handle, value_handle, len); + mp_uint_t atomic_state; + len = mp_bluetooth_gattc_on_data_available_start(event, conn_handle, value_handle, len, &atomic_state); while (len > 0 && om != NULL) { size_t n = MIN(om->om_len, len); mp_bluetooth_gattc_on_data_available_chunk(OS_MBUF_DATA(om, const uint8_t *), n); len -= n; om = SLIST_NEXT(om, om_next); } - mp_bluetooth_gattc_on_data_available_end(); - MICROPY_PY_BLUETOOTH_EXIT + mp_bluetooth_gattc_on_data_available_end(atomic_state); } STATIC int gap_scan_cb(struct ble_gap_event *event, void *arg) { diff --git a/ports/stm32/mpconfigport.h b/ports/stm32/mpconfigport.h index aa9e04f765..13dce6e96d 100644 --- a/ports/stm32/mpconfigport.h +++ b/ports/stm32/mpconfigport.h @@ -402,9 +402,9 @@ static inline mp_uint_t disable_irq(void) { #endif // The LwIP interface must run at a raised IRQ priority -#define MICROPY_PY_LWIP_ENTER uint32_t irq_state = raise_irq_pri(IRQ_PRI_PENDSV); -#define MICROPY_PY_LWIP_REENTER irq_state = raise_irq_pri(IRQ_PRI_PENDSV); -#define MICROPY_PY_LWIP_EXIT restore_irq_pri(irq_state); +#define MICROPY_PY_LWIP_ENTER uint32_t atomic_state = raise_irq_pri(IRQ_PRI_PENDSV); +#define MICROPY_PY_LWIP_REENTER atomic_state = raise_irq_pri(IRQ_PRI_PENDSV); +#define MICROPY_PY_LWIP_EXIT restore_irq_pri(atomic_state); // Bluetooth calls must run at a raised IRQ priority #define MICROPY_PY_BLUETOOTH_ENTER MICROPY_PY_LWIP_ENTER