diff --git a/src/omv/common/tinyusb_debug.c b/src/omv/common/tinyusb_debug.c new file mode 100644 index 000000000..3d437cb59 --- /dev/null +++ b/src/omv/common/tinyusb_debug.c @@ -0,0 +1,142 @@ +/* + * This file is part of the OpenMV project. + * + * Copyright (c) 2022 Ibrahim Abdelkader + * Copyright (c) 2022 Kwabena W. Agyeman + * + * This work is licensed under the MIT license, see the file LICENSE for details. + * + * Tinyusb CDC debugger helper code. + */ + +#include "omv_boardconfig.h" +#if (OMV_ENABLE_TUSBDBG == 1) +#include "py/runtime.h" +#include "py/stream.h" +#include "py/mphal.h" +#include "py/ringbuf.h" +#include "pendsv.h" + +#include "tusb.h" +#include "usbdbg.h" +#include "tinyusb_debug.h" + +#define DEBUG_MAX_PACKET (64) +#define DEBUG_BAUDRATE_SLOW (921600) +#define DEBUG_BAUDRATE_FAST (12000000) + +extern void __fatal_error(); + +typedef struct __attribute__((packed)) { + uint8_t cmd; + uint8_t request; + uint32_t xfer_length; +} usbdbg_cmd_t; + +STATIC uint8_t debug_ringbuf_array[512]; +static volatile uint8_t tinyusb_debug_mode = false; +ringbuf_t debug_ringbuf = { debug_ringbuf_array, sizeof(debug_ringbuf_array) }; + +uint32_t usb_cdc_buf_len() +{ + return ringbuf_avail((ringbuf_t*) &debug_ringbuf); +} + +uint32_t usb_cdc_get_buf(uint8_t *buf, uint32_t len) +{ + for (int i=0; ibit_rate == 1200) { + MICROPY_RESET_TO_BOOTLOADER(); + #endif + } else if (coding->bit_rate == DEBUG_BAUDRATE_SLOW + || coding->bit_rate == DEBUG_BAUDRATE_FAST) { + tinyusb_debug_mode = true; + } else { + tinyusb_debug_mode = false; + } +} + +bool tinyusb_debug_enabled(void) +{ + return tinyusb_debug_mode; +} + +void tinyusb_debug_tx_strn(const char *str, mp_uint_t len) +{ + // TODO can be faster. + if (tinyusb_debug_enabled() && tud_cdc_connected()) { + for (int i=0; i= 6) { + uint32_t count = tud_cdc_read(dbg_buf, 6); + if (count < 6 || dbg_buf[0] != 0x30) { + //This shouldn't happen + __fatal_error(); + usbdbg_control(NULL, USBDBG_NONE, 0); + return; + } + usbdbg_cmd_t *cmd = (usbdbg_cmd_t *) dbg_buf; + uint8_t request = cmd->request; + uint32_t xfer_length = cmd->xfer_length; + usbdbg_control(NULL, request, xfer_length); + + while (xfer_length) { // && tud_cdc_connected()) + if (tud_task_event_ready()) { + tud_task(); + } + if (request & 0x80) { + // Device-to-host data phase + int bytes = MIN(xfer_length, DEBUG_MAX_PACKET); + if (bytes <= tud_cdc_write_available()) { + xfer_length -= bytes; + usbdbg_data_in(dbg_buf, bytes); + tud_cdc_write(dbg_buf, bytes); + } + tud_cdc_write_flush(); + } else { + // Host-to-device data phase + int bytes = MIN(xfer_length, DEBUG_MAX_PACKET); + uint32_t count = tud_cdc_read(dbg_buf, bytes); + if (count == bytes) { + xfer_length -= count; + usbdbg_data_out(dbg_buf, count); + } + } + } + } +} + +// For the nRF port, this replaces the default weak USB IRQ handler. +// And for the RP2 port, this handler is installed in main.c +void USBD_IRQHandler(void) +{ + dcd_int_handler(0); + // If there are any event to process, schedule a call to cdc loop. + if (tinyusb_debug_enabled()) { // if (cdc_tx_any() || tud_task_event_ready()) + pendsv_schedule_dispatch(PENDSV_DISPATCH_CDC, tinyusb_debug_task); + } +} +#endif //OMV_TINYUSB_DEBUG diff --git a/src/omv/common/tinyusb_debug.h b/src/omv/common/tinyusb_debug.h new file mode 100644 index 000000000..4af0067ba --- /dev/null +++ b/src/omv/common/tinyusb_debug.h @@ -0,0 +1,16 @@ +/* + * This file is part of the OpenMV project. + * + * Copyright (c) 2022 Ibrahim Abdelkader + * Copyright (c) 2022 Kwabena W. Agyeman + * + * This work is licensed under the MIT license, see the file LICENSE for details. + * + * Tinyusb CDC debugger helper code. + */ +#ifndef __TUSBDBG_H__ +void USBD_IRQHandler(void); +int tinyusb_debug_init(void); +bool tinyusb_debug_enabled(void); +void tinyusb_debug_tx_strn(const char *str, mp_uint_t len); +#endif // __TUSBDBG_H__