|
34 | 34 | #include "py/objarray.h"
|
35 | 35 | #include "py/qstr.h"
|
36 | 36 | #include "py/runtime.h"
|
| 37 | +#include "py/stackctrl.h" |
37 | 38 | #include "extmod/modbluetooth.h"
|
38 | 39 | #include <string.h>
|
39 | 40 |
|
@@ -1135,7 +1136,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(bluetooth_ble_invoke_irq_obj, bluetooth_ble_inv
|
1135 | 1136 |
|
1136 | 1137 | #if MICROPY_PY_BLUETOOTH_USE_SYNC_EVENTS
|
1137 | 1138 |
|
1138 |
| -STATIC mp_obj_t invoke_irq_handler(uint16_t event, |
| 1139 | +STATIC mp_obj_t invoke_irq_handler_run(uint16_t event, |
1139 | 1140 | const mp_int_t *numeric, size_t n_unsigned, size_t n_signed,
|
1140 | 1141 | const uint8_t *addr,
|
1141 | 1142 | const mp_obj_bluetooth_uuid_t *uuid,
|
@@ -1185,6 +1186,76 @@ STATIC mp_obj_t invoke_irq_handler(uint16_t event,
|
1185 | 1186 | return result;
|
1186 | 1187 | }
|
1187 | 1188 |
|
| 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 | + |
1188 | 1259 | #define NULL_NUMERIC NULL
|
1189 | 1260 | #define NULL_ADDR NULL
|
1190 | 1261 | #define NULL_UUID NULL
|
|
0 commit comments