From 5bedc84446a212a4ad9eede240af03af0ce93cb8 Mon Sep 17 00:00:00 2001 From: Andrew Leech Date: Thu, 16 May 2024 14:27:42 +1000 Subject: [PATCH] ports/nrf: Use shared/tinyusb cdc functions. Signed-off-by: Andrew Leech --- ports/nrf/Makefile | 13 ++- ports/nrf/drivers/bluetooth/ble_uart.c | 9 -- ports/nrf/drivers/usb/tusb_config.h | 44 ------- ports/nrf/drivers/usb/usb_cdc.c | 148 +++++++++++------------- ports/nrf/drivers/usb/usb_descriptors.c | 117 ------------------- ports/nrf/mpconfigport.h | 18 ++- ports/nrf/mphalport.c | 12 +- ports/nrf/mphalport.h | 4 + 8 files changed, 99 insertions(+), 266 deletions(-) delete mode 100644 ports/nrf/drivers/usb/tusb_config.h delete mode 100644 ports/nrf/drivers/usb/usb_descriptors.c diff --git a/ports/nrf/Makefile b/ports/nrf/Makefile index 4fe921f0fad88..dbc09c8598321 100644 --- a/ports/nrf/Makefile +++ b/ports/nrf/Makefile @@ -81,6 +81,7 @@ INC += -I./modules/ble INC += -I./modules/board INC += -I./modules/nrf INC += -I../../shared/readline +INC += -I../../shared/tinyusb INC += -I./drivers/bluetooth INC += -I./drivers INC += -I../../lib/nrfx/ @@ -183,9 +184,12 @@ SRC_SHARED_C += $(addprefix shared/,\ libc/string0.c \ readline/readline.c \ runtime/pyexec.c \ + runtime/stdout_helpers.c \ runtime/sys_stdio_mphal.c \ runtime/interrupt_char.c \ - tinyusb/mp_cdc_common.c \ + tinyusb/mp_usbd.c \ + tinyusb/mp_usbd_cdc.c \ + tinyusb/mp_usbd_descriptor.c \ timeutils/timeutils.c \ ) @@ -238,7 +242,6 @@ ifeq ($(MCU_SUB_VARIANT), nrf52840) INC += -I./drivers/usb INC += -I../../lib/tinyusb/src - # If SoftDevice is selected. ifneq ($(SD), ) # For external tinyusb drivers to enable SoftDevice mode. @@ -247,7 +250,6 @@ endif SRC_C += $(addprefix drivers/usb/,\ usb_cdc.c \ - usb_descriptors.c \ ) SRC_C += $(addprefix lib/tinyusb/src/,\ @@ -259,6 +261,11 @@ SRC_C += $(addprefix lib/tinyusb/src/,\ portable/nordic/nrf5x/dcd_nrf5x.c \ ) +CFLAGS += \ + -DCFG_TUSB_MCU=OPT_MCU_NRF5X \ + +LDFLAGS += -Wl,--wrap=dcd_event_handler + endif DRIVERS_SRC_C += $(addprefix modules/,\ diff --git a/ports/nrf/drivers/bluetooth/ble_uart.c b/ports/nrf/drivers/bluetooth/ble_uart.c index a342a1e00610c..db0340cc57de2 100644 --- a/ports/nrf/drivers/bluetooth/ble_uart.c +++ b/ports/nrf/drivers/bluetooth/ble_uart.c @@ -150,15 +150,6 @@ void ble_uart_tx_char(char c) { (uint8_t *)&c); } -void mp_hal_stdout_tx_strn_cooked(const char *str, mp_uint_t len) { - for (const char *top = str + len; str < top; str++) { - if (*str == '\n') { - ble_uart_tx_char('\r'); - } - ble_uart_tx_char(*str); - } -} - #if MICROPY_PY_SYS_STDFILES uintptr_t mp_hal_stdio_poll(uintptr_t poll_flags) { uintptr_t ret = 0; diff --git a/ports/nrf/drivers/usb/tusb_config.h b/ports/nrf/drivers/usb/tusb_config.h deleted file mode 100644 index 619578ad6ee3a..0000000000000 --- a/ports/nrf/drivers/usb/tusb_config.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2019 Damien P. George - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#ifndef MICROPY_INCLUDED_NRF_TUSB_CONFIG_H -#define MICROPY_INCLUDED_NRF_TUSB_CONFIG_H - -// Common configuration - -#define CFG_TUSB_MCU OPT_MCU_NRF5X -#define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE - -#define CFG_TUSB_MEM_SECTION -#define CFG_TUSB_MEM_ALIGN TU_ATTR_ALIGNED(4) - -// Device configuration - -#define CFG_TUD_ENDOINT0_SIZE (64) -#define CFG_TUD_CDC (1) -#define CFG_TUD_CDC_RX_BUFSIZE (64) -#define CFG_TUD_CDC_TX_BUFSIZE (64) - -#endif // MICROPY_INCLUDED_NRF_TUSB_CONFIG_H diff --git a/ports/nrf/drivers/usb/usb_cdc.c b/ports/nrf/drivers/usb/usb_cdc.c index aef7354972722..4106ed0567cb5 100644 --- a/ports/nrf/drivers/usb/usb_cdc.c +++ b/ports/nrf/drivers/usb/usb_cdc.c @@ -37,6 +37,9 @@ #include "py/runtime.h" #include "shared/runtime/interrupt_char.h" #include "shared/tinyusb/mp_usbd.h" +#include "shared/tinyusb/mp_usbd_cdc.h" +#include "extmod/misc.h" +#include #ifdef BLUETOOTH_SD #include "nrf_sdm.h" @@ -46,12 +49,10 @@ extern void tusb_hal_nrf_power_event(uint32_t event); -static void cdc_task(bool tx); +// static void cdc_task(bool tx); -static uint8_t rx_ringbuf_array[1024]; -static uint8_t tx_ringbuf_array[1024]; -static volatile ringbuf_t rx_ringbuf; -static volatile ringbuf_t tx_ringbuf; +static uint8_t stdin_ringbuf_array[1024]; +ringbuf_t stdin_ringbuf; static void board_init(void) { // Config clock source. @@ -105,62 +106,47 @@ static void board_init(void) { #endif } -static bool cdc_rx_any(void) { - return rx_ringbuf.iput != rx_ringbuf.iget; -} - -static int cdc_rx_char(void) { - return ringbuf_get((ringbuf_t*)&rx_ringbuf); -} - -static bool cdc_tx_any(void) { - return tx_ringbuf.iput != tx_ringbuf.iget; -} - -static int cdc_tx_char(void) { - return ringbuf_get((ringbuf_t*)&tx_ringbuf); +void mp_usbd_port_get_serial_number(char *serial_buf) { + uint32_t deviceid[2]; + deviceid[0] = nrf_ficr_deviceid_get(NRF_FICR, 0); + deviceid[1] = nrf_ficr_deviceid_get(NRF_FICR, 1); + MP_STATIC_ASSERT(sizeof(deviceid) * 2 <= MICROPY_HW_USB_DESC_STR_MAX); + mp_usbd_hex_str(serial_buf, (uint8_t *)deviceid, sizeof(deviceid)); } -static void cdc_task(bool tx) -{ - if ( tud_cdc_connected() ) { - // connected and there are data available - while (tud_cdc_available()) { - int c = tud_cdc_read_char(); - if (c == mp_interrupt_char) { - rx_ringbuf.iget = 0; - rx_ringbuf.iput = 0; - mp_sched_keyboard_interrupt(); - } else { - ringbuf_put((ringbuf_t*)&rx_ringbuf, c); - } - } - - if (tx) { - int chars = 0; - while (cdc_tx_any()) { - if (chars < 64) { - tud_cdc_write_char(cdc_tx_char()); - chars++; - } else { - chars = 0; - tud_cdc_write_flush(); - } - } - - tud_cdc_write_flush(); - } - } +static bool cdc_rx_any(void) { + return stdin_ringbuf.iput != stdin_ringbuf.iget; } -static void usb_cdc_loop(void) { - tud_task(); - cdc_task(true); +static int cdc_rx_char(void) { + return ringbuf_get((ringbuf_t*)&stdin_ringbuf); } -void tud_cdc_rx_cb(uint8_t itf) { - cdc_task(false); -} +// static void cdc_task(bool tx) +// { +// if ( tud_cdc_connected() ) { +// // connected and there are data available +// while (tud_cdc_available()) { +// int c = tud_cdc_read_char(); +// if (c == mp_interrupt_char) { +// stdin_ringbuf.iget = 0; +// stdin_ringbuf.iput = 0; +// mp_sched_keyboard_interrupt(); +// } else { +// ringbuf_put((ringbuf_t*)&stdin_ringbuf, c); +// } +// } +// } +// } + +// static void mp_usbd_task(void) { +// tud_task(); +// // cdc_task(true); +// } + +// void tud_cdc_rx_cb(uint8_t itf) { +// cdc_task(false); +// } int usb_cdc_init(void) { @@ -176,15 +162,10 @@ int usb_cdc_init(void) initialized = true; } - rx_ringbuf.buf = rx_ringbuf_array; - rx_ringbuf.size = sizeof(rx_ringbuf_array); - rx_ringbuf.iget = 0; - rx_ringbuf.iput = 0; - - tx_ringbuf.buf = tx_ringbuf_array; - tx_ringbuf.size = sizeof(tx_ringbuf_array); - tx_ringbuf.iget = 0; - tx_ringbuf.iput = 0; + stdin_ringbuf.buf = stdin_ringbuf_array; + stdin_ringbuf.size = sizeof(stdin_ringbuf_array); + stdin_ringbuf.iget = 0; + stdin_ringbuf.iput = 0; mp_usbd_init(); @@ -208,7 +189,7 @@ void usb_cdc_sd_event_handler(uint32_t soc_evt) { uintptr_t mp_hal_stdio_poll(uintptr_t poll_flags) { uintptr_t ret = 0; if (poll_flags & MP_STREAM_POLL_RD) { - usb_cdc_loop(); + mp_usbd_task(); if (cdc_rx_any()) { ret |= MP_STREAM_POLL_RD; } @@ -221,7 +202,7 @@ uintptr_t mp_hal_stdio_poll(uintptr_t poll_flags) { int mp_hal_stdin_rx_chr(void) { for (;;) { - usb_cdc_loop(); + mp_usbd_task(); if (cdc_rx_any()) { return cdc_rx_char(); } @@ -231,24 +212,31 @@ int mp_hal_stdin_rx_chr(void) { return 0; } +// Send string of given length mp_uint_t mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) { - for (const char *top = str + len; str < top; str++) { - ringbuf_put((ringbuf_t*)&tx_ringbuf, *str); - usb_cdc_loop(); + mp_uint_t ret = len; + bool did_write = false; + #if MICROPY_HW_ENABLE_UART_REPL + mp_uart_write_strn(str, len); + did_write = true; + #endif + + #if MICROPY_HW_USB_CDC + mp_uint_t cdc_res = mp_usbd_cdc_tx_strn(str, len); + if (cdc_res > 0) { + did_write = true; + ret = MIN(cdc_res, ret); } - return len; -} + #endif -void mp_hal_stdout_tx_strn_cooked(const char *str, mp_uint_t len) { - - for (const char *top = str + len; str < top; str++) { - if (*str == '\n') { - ringbuf_put((ringbuf_t*)&tx_ringbuf, '\r'); - usb_cdc_loop(); - } - ringbuf_put((ringbuf_t*)&tx_ringbuf, *str); - usb_cdc_loop(); + #if MICROPY_PY_OS_DUPTERM + int dupterm_res = mp_os_dupterm_tx_strn(str, len); + if (dupterm_res >= 0) { + did_write = true; + ret = MIN((mp_uint_t)dupterm_res, ret); } + #endif + return did_write ? ret : 0; } void USBD_IRQHandler(void) { diff --git a/ports/nrf/drivers/usb/usb_descriptors.c b/ports/nrf/drivers/usb/usb_descriptors.c deleted file mode 100644 index b1edfcc18fd8f..0000000000000 --- a/ports/nrf/drivers/usb/usb_descriptors.c +++ /dev/null @@ -1,117 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2019 Damien P. George - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include "tusb.h" - -#ifndef MICROPY_HW_USB_VID -#define MICROPY_HW_USB_VID (0xf055) -#define MICROPY_HW_USB_PID (0x9802) -#endif - -#define USBD_DESC_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN) -#define USBD_MAX_POWER_MA (250) - -#define USBD_ITF_CDC (0) // needs 2 interfaces -#define USBD_ITF_MAX (2) - -#define USBD_CDC_EP_CMD (0x81) -#define USBD_CDC_EP_OUT (0x02) -#define USBD_CDC_EP_IN (0x82) -#define USBD_CDC_CMD_MAX_SIZE (8) -#define USBD_CDC_IN_OUT_MAX_SIZE (64) - -#define USBD_STR_0 (0x00) -#define USBD_STR_MANUF (0x01) -#define USBD_STR_PRODUCT (0x02) -#define USBD_STR_SERIAL (0x03) -#define USBD_STR_CDC (0x04) - -// Note: descriptors returned from callbacks must exist long enough for transfer to complete - -static const tusb_desc_device_t usbd_desc_device = { - .bLength = sizeof(tusb_desc_device_t), - .bDescriptorType = TUSB_DESC_DEVICE, - .bcdUSB = 0x0200, - .bDeviceClass = TUSB_CLASS_MISC, - .bDeviceSubClass = MISC_SUBCLASS_COMMON, - .bDeviceProtocol = MISC_PROTOCOL_IAD, - .bMaxPacketSize0 = CFG_TUD_ENDOINT0_SIZE, - .idVendor = MICROPY_HW_USB_VID, - .idProduct = MICROPY_HW_USB_PID, - .bcdDevice = 0x0100, - .iManufacturer = USBD_STR_MANUF, - .iProduct = USBD_STR_PRODUCT, - .iSerialNumber = USBD_STR_SERIAL, - .bNumConfigurations = 1, -}; - -static const uint8_t usbd_desc_cfg[USBD_DESC_LEN] = { - TUD_CONFIG_DESCRIPTOR(1, USBD_ITF_MAX, USBD_STR_0, USBD_DESC_LEN, - TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, USBD_MAX_POWER_MA), - - TUD_CDC_DESCRIPTOR(USBD_ITF_CDC, USBD_STR_CDC, USBD_CDC_EP_CMD, - USBD_CDC_CMD_MAX_SIZE, USBD_CDC_EP_OUT, USBD_CDC_EP_IN, USBD_CDC_IN_OUT_MAX_SIZE), -}; - -static const char *const usbd_desc_str[] = { - [USBD_STR_MANUF] = "MicroPython", - [USBD_STR_PRODUCT] = "Board in FS mode", - [USBD_STR_SERIAL] = "000000000000", // TODO - [USBD_STR_CDC] = "Board CDC", -}; - -const uint8_t *tud_descriptor_device_cb(void) { - return (const uint8_t*)&usbd_desc_device; -} - -const uint8_t *tud_descriptor_configuration_cb(uint8_t index) { - (void)index; - return usbd_desc_cfg; -} - -const uint16_t *tud_descriptor_string_cb(uint8_t index, uint16_t langid) { - #define DESC_STR_MAX (20) - static uint16_t desc_str[DESC_STR_MAX]; - - uint8_t len; - if (index == 0) { - desc_str[1] = 0x0409; // supported language is English - len = 1; - } else { - if (index >= sizeof(usbd_desc_str) / sizeof(usbd_desc_str[0])) { - return NULL; - } - const char* str = usbd_desc_str[index]; - for (len = 0; len < DESC_STR_MAX - 1 && str[len]; ++len) { - desc_str[1 + len] = str[len]; - } - } - - // first byte is length (including header), second byte is string type - desc_str[0] = (TUSB_DESC_STRING << 8 ) | (2 * len + 2); - - return desc_str; -} diff --git a/ports/nrf/mpconfigport.h b/ports/nrf/mpconfigport.h index 6e92fa876ef4b..c384114f86695 100644 --- a/ports/nrf/mpconfigport.h +++ b/ports/nrf/mpconfigport.h @@ -159,8 +159,7 @@ #define MICROPY_STREAMS_NON_BLOCK (1) #define MICROPY_CAN_OVERRIDE_BUILTINS (1) #define MICROPY_USE_INTERNAL_ERRNO (1) -#if MICROPY_HW_USB_CDC_1200BPS_TOUCH -#define MICROPY_HW_ENABLE_USBDEV (1) +#if MICROPY_HW_ENABLE_USBDEV #define MICROPY_ENABLE_SCHEDULER (1) #define MICROPY_SCHEDULER_STATIC_NODES (1) #endif @@ -333,8 +332,19 @@ long unsigned int rng_generate_random_word(void); #define MP_STATE_PORT MP_STATE_VM #if MICROPY_HW_USB_CDC -#include "device/usbd.h" -#define MICROPY_HW_USBDEV_TASK_HOOK extern void tud_task(void); tud_task(); +// Miscellaneous settings + +#ifndef MICROPY_HW_USB_VID +#define MICROPY_HW_USB_VID (0xf055) +#endif +#ifndef MICROPY_HW_USB_PID +#define MICROPY_HW_USB_PID (0x9802) +#endif + +#ifndef MICROPY_HW_USB_CDC_TX_TIMEOUT +#define MICROPY_HW_USB_CDC_TX_TIMEOUT (500) +#endif +#define MICROPY_HW_USBDEV_TASK_HOOK extern void mp_usbd_task(void); mp_usbd_task(); #else #define MICROPY_HW_USBDEV_TASK_HOOK ; #endif diff --git a/ports/nrf/mphalport.c b/ports/nrf/mphalport.c index 06c6ba5cc2e76..c7927ee0021eb 100644 --- a/ports/nrf/mphalport.c +++ b/ports/nrf/mphalport.c @@ -231,17 +231,11 @@ mp_uint_t mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) { } return 0; } - -void mp_hal_stdout_tx_strn_cooked(const char *str, mp_uint_t len) { - if (MP_STATE_VM(dupterm_objs[0]) != MP_OBJ_NULL) { - uart_tx_strn_cooked(MP_STATE_VM(dupterm_objs[0]), str, len); - } -} #endif -void mp_hal_stdout_tx_str(const char *str) { - mp_hal_stdout_tx_strn(str, strlen(str)); -} +// void mp_hal_stdout_tx_str(const char *str) { +// mp_hal_stdout_tx_strn(str, strlen(str)); +// } #if MICROPY_PY_TIME_TICKS diff --git a/ports/nrf/mphalport.h b/ports/nrf/mphalport.h index 7efe05a15fc8e..d3c31f5ec6b54 100644 --- a/ports/nrf/mphalport.h +++ b/ports/nrf/mphalport.h @@ -28,6 +28,7 @@ #define __NRF52_HAL #include "py/mpconfig.h" +#include "py/ringbuf.h" #include #include "pin.h" #include "nrf_gpio.h" @@ -43,6 +44,9 @@ typedef enum extern const unsigned char mp_hal_status_to_errno_table[4]; +extern int mp_interrupt_char; +extern ringbuf_t stdin_ringbuf; + NORETURN void mp_hal_raise(HAL_StatusTypeDef status); void mp_hal_set_interrupt_char(int c); // -1 to disable