From 985ffd7f6e709f384f4d815869589e878d691d53 Mon Sep 17 00:00:00 2001 From: iabdalkader Date: Fri, 7 Apr 2023 13:07:49 +0200 Subject: [PATCH] misc/usbdbg: Refactor USB debugger code. * Switch to statically allocated exception. * Refactor common code. * Misc fixes to harden the exec/stop commands. --- src/omv/common/usbdbg.c | 88 ++++++++++++++++++++++++----------------- 1 file changed, 51 insertions(+), 37 deletions(-) diff --git a/src/omv/common/usbdbg.c b/src/omv/common/usbdbg.c index 7ff3f9512..e786c0b0b 100644 --- a/src/omv/common/usbdbg.c +++ b/src/omv/common/usbdbg.c @@ -14,6 +14,7 @@ #include "py/gc.h" #include "py/mphal.h" #include "py/obj.h" +#include "py/objstr.h" #include "py/runtime.h" #include "pendsv.h" @@ -36,7 +37,13 @@ static volatile bool script_ready; static volatile bool script_running; static volatile bool irq_enabled; static vstr_t script_buf; -static mp_obj_t mp_const_ide_interrupt = MP_OBJ_NULL; + +static mp_obj_exception_t ide_exception; +static const MP_DEFINE_STR_OBJ(ide_exception_msg, "IDE interrupt"); +static const mp_rom_obj_tuple_t ide_exception_args_obj = { + {&mp_type_tuple}, 1, {MP_ROM_PTR(&ide_exception_msg)} +}; + // These functions must be implemented in MicroPython CDC driver. extern uint32_t usb_cdc_buf_len(); @@ -52,8 +59,15 @@ void usbdbg_init() script_ready=false; script_running=false; irq_enabled = false; + vstr_init(&script_buf, 32); - mp_const_ide_interrupt = mp_obj_new_exception_msg(&mp_type_Exception, MP_ERROR_TEXT("IDE interrupt")); + + // Initialize the IDE exception object. + ide_exception.base.type = &mp_type_Exception; + ide_exception.traceback_alloc = 0; + ide_exception.traceback_len = 0; + ide_exception.traceback_data = NULL; + ide_exception.args = (mp_obj_tuple_t *) &ide_exception_args_obj; } void usbdbg_wait_for_command(uint32_t timeout) @@ -88,6 +102,29 @@ inline void usbdbg_set_irq_enabled(bool enabled) irq_enabled = enabled; } +static void usbdbg_interrupt_vm(bool ready) +{ + // Set script ready flag + script_ready = ready; + + // Set script running flag + script_running = ready; + + // Disable IDE IRQ (re-enabled by pyexec or main). + usbdbg_set_irq_enabled(false); + + // Clear interrupt traceback + mp_obj_exception_clear_traceback(&ide_exception); + + // Remove the BASEPRI masking (if any) + __set_BASEPRI(0); + + // Interrupt running REPL + // Note: setting pendsv explicitly here because the VM is probably + // waiting in REPL and the soft interrupt flag will not be checked. + pendsv_nlr_jump(&ide_exception); +} + bool usbdbg_get_irq_enabled() { return irq_enabled; @@ -209,29 +246,17 @@ void usbdbg_data_out(void *buffer, int length) // check if GC is locked before allocating memory for vstr. If GC was locked // at least once before the script is fully uploaded xfer_bytes will be less // than the total length (xfer_length) and the script will Not be executed. - if (!script_running && !gc_is_locked()) { - vstr_add_strn(&script_buf, buffer, length); + if (!script_running) { + nlr_buf_t nlr; + if (!gc_is_locked() && nlr_push(&nlr) == 0) { + vstr_add_strn(&script_buf, buffer, length); + nlr_pop(); + } xfer_bytes += length; if (xfer_bytes == xfer_length) { - // Set script ready flag - script_ready = true; - - // Set script running flag - script_running = true; - - // Disable IDE IRQ (re-enabled by pyexec or main). - usbdbg_set_irq_enabled(false); - - // Clear interrupt traceback - mp_obj_exception_clear_traceback(mp_const_ide_interrupt); - - // Remove the BASEPRI masking (if any) - __set_BASEPRI(0); - - // Interrupt running REPL - // Note: setting pendsv explicitly here because the VM is probably - // waiting in REPL and the soft interrupt flag will not be checked. - pendsv_nlr_jump(mp_const_ide_interrupt); + cmd = USBDBG_NONE; + // Schedule the IDE exception to interrupt the VM. + usbdbg_interrupt_vm(true); } } break; @@ -364,22 +389,11 @@ void usbdbg_control(void *buffer, uint8_t request, uint32_t length) case USBDBG_SCRIPT_STOP: if (script_running) { - // Set script running flag - script_running = false; - - // Disable IDE IRQ (re-enabled by pyexec or main). - usbdbg_set_irq_enabled(false); - - // Reset CDC buffers after disabling IRQs. + // Reset CDC buffers. usb_cdc_reset_buffers(); - // interrupt running code by raising an exception - mp_obj_exception_clear_traceback(mp_const_ide_interrupt); - - // Remove the BASEPRI masking (if any) - __set_BASEPRI(0); - - pendsv_nlr_jump(mp_const_ide_interrupt); + // Schedule the IDE exception to interrupt the VM. + usbdbg_interrupt_vm(false); } cmd = USBDBG_NONE; break;