8000 extmod/modbluetooth: Add support for running sync irq on system thread. · micropython/micropython@e05d0a6 · GitHub
[go: up one dir, main page]

Skip to content
8000

Commit e05d0a6

Browse files
committed
extmod/modbluetooth: Add support for running sync irq on system thread.
If the Bluetooth stack runs on another OS thread then synchronous BLE irq callbacks, which block the Bluetooth stack until the callback to Python is complete, must coordinate with the main thread and configure the MicroPython thread-local-state. This commit adds MICROPY_PY_BLUETOOTH_USE_SYNC_EVENTS_WITH_INTERLOCK which can be enabled if the system has these requirements. Signed-off-by: Damien George <damien@micropython.org>
1 parent 4cf9928 commit e05d0a6

File tree

1 file changed

+72
-1
lines changed

1 file changed

+72
-1
lines changed

extmod/modbluetooth.c

Lines changed: 72 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include "py/objarray.h"
3535
#include "py/qstr.h"
3636
#include "py/runtime.h"
37+
#include "py/stackctrl.h"
3738
#include "extmod/modbluetooth.h"
3839
#include <string.h>
3940

@@ -1135,7 +1136,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(bluetooth_ble_invoke_irq_obj, bluetooth_ble_inv
11351136

11361137
#if MICROPY_PY_BLUETOOTH_USE_SYNC_EVENTS
11371138

1138-
STATIC mp_obj_t invoke_irq_handler(uint16_t event,
1139+
STATIC mp_obj_t invoke_irq_handler_run(uint16_t event,
11391140
const mp_int_t *numeric, size_t n_unsigned, size_t n_signed,
11401141
const uint8_t *addr,
11411142
const mp_obj_bluetooth_uuid_t *uuid,
@@ -1185,6 +1186,76 @@ STATIC mp_obj_t invoke_irq_handler(uint16_t event,
11851186
return result;
11861187
}
11871188

1189+
#if MICROPY_PY_BLUETOOTH_USE_SYNC_EVENTS_WITH_INTERLOCK
1190+
1191+
// On some systems the BLE event callbacks may occur on a system thread which is not
1192+
// a MicroPython thread. In such cases the callback must set up relevant MicroPython
1193+
// state and obtain the GIL, to synchronised with the rest of the runtime.
1194+
1195+
#if MICROPY_ENABLE_PYSTACK
1196+
#error not supported
1197+
#endif
1198+
1199+
STATIC mp_obj_t invoke_irq_handler(uint16_t event,
1200+
const mp_int_t *numeric, size_t n_unsigned, size_t n_signed,
1201+
const uint8_t *addr,
1202+
const mp_obj_bluetooth_uuid_t *uuid,
1203+
const uint8_t **data, size_t *data_len, size_t n_data) {
1204+
1205+
// This code may run on an existing MicroPython thread, or a non-MicroPython thread
1206+
// that's not using the mp_thread_get_state() value. In the former case the state
1207+
// must be restored once this callback finishes.
1208+
mp_state_thread_t *ts_orig = mp_thread_get_state();
1209+
1210+
mp_state_thread_t ts;
1211+
if (ts_orig == NULL) {
1212+
mp_thread_set_state(&ts);
1213+
mp_stack_set_top(&ts + 1); // need to include ts in root-pointer scan
1214+
mp_stack_set_limit(MICROPY_PY_BLUETOOTH_SYNC_EVENT_STACK_SIZE - 1024);
1215+
ts.gc_lock_depth = 0;
1216+
ts.mp_pending_exception = MP_OBJ_NULL;
1217+
mp_locals_set(mp_state_ctx.thread.dict_locals); // set from the outer context
1218+
mp_globals_set(mp_state_ctx.thread.dict_globals); // set from the outer context
1219+
MP_THREAD_GIL_ENTER();
1220+
}
1221+
1222+
mp_obj_t result = mp_const_none;
1223+
nlr_buf_t nlr;
1224+
if (nlr_push(&nlr) == 0) {
1225+
mp_sched_lock();
1226+
result = invoke_irq_handler_run(event, numeric, n_unsigned, n_signed, addr, uuid, data, data_len, n_data);
1227+
mp_sched_unlock();
1228+
nlr_pop();
1229+
} else {
1230+
// Uncaught exception, print it out.
1231+
mp_sched_unlock();
1232+
mp_printf(MICROPY_ERROR_PRINTER, "Unhandled exception in IRQ callback handler\n");
1233+
mp_obj_print_exception(MICROPY_ERROR_PRINTER, MP_OBJ_FROM_PTR(nlr.ret_val));
1234+
}
1235+
1236+
if (ts_orig == NULL) {
1237+
MP_THREAD_GIL_EXIT();
1238+
mp_thread_set_state(ts_orig);
1239+
}
1240+
1241+
return result;
1242+
}
1243+
1244+
#else
1245+
1246+
// BLE event callbacks are called directly from the MicroPython runtime, so additional
1247+
// synchronisation is not needed, and BLE event handlers can be called directly.
1248+
1249+
STATIC mp_obj_t invoke_irq_handler(uint16_t event,
1250+
const mp_int_t *numeric, size_t n_unsigned, size_t n_signed,
1251+
const uint8_t *addr,
1252+
const mp_obj_bluetooth_uuid_t *uuid,
1253+
const uint8_t **data, size_t *data_len, size_t n_data) {
1254+
return invoke_irq_handler_run(event, numeric, n_unsigned, n_signed, addr, uuid, data, data_len, n_data);
1255+
}
1256+
1257+
#endif
1258+
11881259
#define NULL_NUMERIC NULL
11891260
#define NULL_ADDR NULL
11901261
#define NULL_UUID NULL

0 commit comments

Comments
 (0)
0