← index #4895Issue #12239
Related · high · value 0.648
QUERY · ISSUE

ESP32 crashes when running uPy from ISR

openby amirgonopened 2019-07-04updated 2022-04-15
port-esp32

When MICROPY_PY_THREAD is enabled, ISR cannot be used for anything except mp_sched_schedule.

That's because a call to MP_STATE_THREAD (by nlr_push for example) calls pvTaskGetThreadLocalStoragePointer which is invalid in ISR context.

Perhaps Micropython should allocate state for ISR context as well?

CANDIDATE · ISSUE

esp32/ble: Fatal crashes in BLE ISR handler

closedby DvdGiessenopened 2023-08-15updated 2023-11-09
bug

The ESP32 crashes and reboots when an Python exception is raised in another function as part of the Bluetooth ISR callback. Minimal reproduction:

import ubluetooth
def raises_exception():
    raise RuntimeError('The things! They are wrong!')

def ble_callback(event, data):
    try:
        raises_exception()
    except Exception:
        print('We caught it!')
    print('The end.')

ble = ubluetooth.BLE()
ble.irq(ble_callback)
ble.active(True)
ble.gap_advertise(100 * 1000, adv_data=b'\x02\x01\x06\x08\tExample', connectable=True)

Note: If I raise exception and catch an exception within the same function, everything works fine:

>>> import ubluetooth
>>> def ble_callback(event, data):
...     try:
...         raise RuntimeError('The things! They are wrong!')
...     except Exception:
...         print('We caught it!')
...     print('The end.')
...
>>> ble = ubluetooth.BLE()
>>> ble.irq(ble_callback)
>>> ble.active(True)
We caught it!
The end.
We caught it!
The end.
True
>>> ble.gap_advertise(100 * 1000, adv_data=b'\x02\x01\x06\x08\tExample', connectable=True)
>>>

However, if I raise the exception in a different function, it crashes.

MicroPython v1.20.0-378-g63f46f08d-dirty on 2023-08-15; custom board with ESP32S3
Type "help()" for more information.
>>> import ubluetooth
>>> def raises_exception():
...     raise RuntimeError('The things! They are wrong!')
...
>>> def ble_callback(event, data):
...     try:
...         raises_exception()
...     except Exception:
...         print('We caught it!')
...     print('The end.')
...
>>> ble = ubluetooth.BLE()
>>> ble.irq(ble_callback)
>>> ble.active(True)
We caught it!
The end.
Guru Meditation Error: Core  1 panic'ed (LoadProhibited). Exception was unhandled.

Core  1 register dump:
PC      : 0x42041d62  PS      : 0x00060330  A0      : 0x8200bda9  A1      : 0x3fcb5c90
A2      : 0x3fcb5d50  A3      : 0x3fcb5ff0  A4      : 0x00000002  A5      : 0x00000588
A6      : 0x3c1143f4  A7      : 0x3fcb5cc0  A8      : 0x00002018  A9      : 0x3fcb5c70
A10     : 0x3fcb5ff0  A11     : 0x3fcab95c  A12     : 0x00060320  A13     : 0x3fcb5cf0
A14     : 0x00000192  A15     : 0x3c128838  SAR     : 0x0000001e  EXCCAUSE: 0x0000001c
EXCVADDR: 0x00002018  LBEG    : 0x400570e8  LEND    : 0x400570f3  LCOUNT  : 0x00000000

Backtrace:
0x42041d5f: nlr_pop_jump_callback at <mpy>/py/nlr.c:61
 (inlined by) nlr_call_jump_callbacks at <mpy>/py/nlr.c:79
0x4200bda6: nlr_jump at <mpy>/py/nlrsetjmp.c:32 (discriminator 2)
0x4200eaa8: fun_bc_call at <mpy>/py/objfun.c:330
0x42016081: mp_call_function_n_kw at <mpy>/py/runtime.c:707
0x4037985a: mp_execute_bytecode at <mpy>/py/vm.c:957
0x4200ea88: fun_bc_call at <mpy>/py/objfun.c:273
0x42016081: mp_call_function_n_kw at <mpy>/py/runtime.c:707
0x4201611e: mp_call_function_2 at <mpy>/py/runtime.c:692
0x4201a1fa: invoke_irq_handler_run at <mpy>/extmod/modbluetooth.c:1211
0x4201a27c: invoke_irq_handler_run_protected at <mpy>/extmod/modbluetooth.c:1238
0x4201a31e: invoke_irq_handler at <mpy>/extmod/modbluetooth.c:1286
0x4201a57c: mp_bluetooth_gap_on_set_secret at <mpy>/extmod/modbluetooth.c:1351
0x42021794: load_irk at <mpy>/extmod/nimble/modbluetooth_nimble.c:307
 (inlined by) sync_cb at <mpy>/extmod/nimble/modbluetooth_nimble.c:336
0x42048e29: ble_hs_sync at <idf>/components/bt/host/nimble/nimble/nimble/host/src/ble_hs.c:377
 (inlined by) ble_hs_sync at <idf>/components/bt/host/nimble/nimble/nimble/host/src/ble_hs.c:348
0x420490d6: ble_hs_start at <idf>/components/bt/host/nimble/nimble/nimble/host/src/ble_hs.c:696
0x420490df: ble_hs_event_start_stage2 at <idf>/components/bt/host/nimble/nimble/nimble/host/src/ble_hs.c:596
0x40383de5: npl_freertos_event_run at <idf>/components/bt/host/nimble/nimble/porting/npl/freertos/src/npl_os_freertos.c:450
0x4037a47d: ble_npl_event_run at <idf>/components/bt/host/nimble/nimble/porting/npl/freertos/include/nimble/nimble_npl_os.h:185
 (inlined by) nimble_port_run at <idf>/components/bt/host/nimble/nimble/porting/nimble/src/nimble_port.c:248
0x4202d306: ble_host_task at <mpy>/ports/esp32/mpnimbleport.c:43

Reproduces on both a S3 and C3. Manually bisected: 18caf49a7fab84f55fdf170eb5ca1c27206ccc76 (last version that builds against IDF4 without changes) does not have the issue, e4650125b88a35f074097f16d84a8f49bd22ac06 (builds against IDF5) does have it. Above logs are against latest master.

EDIT: For reference, working log on 18caf49a7fab84f55fdf170eb5ca1c27206ccc76 outputs identical to the version raising the exception within the same function:

>>> import ubluetooth
>>> def raises_exception():
...     raise RuntimeError('The things! They are wrong!')
...
>>> def ble_callback(event, data):
...     try:
...         raises_exception()
...     except Exception:
...         print('We caught it!')
...     print('The end.')
...
>>> ble = ubluetooth.BLE()
>>> ble.irq(ble_callback)
>>> ble.active(True)
We caught it!
The end.
We caught it!
The end.
True
>>> ble.gap_advertise(100 * 1000, adv_data=b'\x02\x01\x06\x08\tExample', connectable=True)
>>> 

Keyboard

j / / n
next pair
k / / p
previous pair
1 / / h
show query pane
2 / / l
show candidate pane
c
copy suggested comment
r
toggle reasoning
g i
go to index
?
show this help
esc
close overlays

press ? or esc to close

copied