From 74330d8d3860cf09275d127986b407d215c751e1 Mon Sep 17 00:00:00 2001 From: tyustli <43946994+tyustli@users.noreply.github.com> Date: Tue, 19 Mar 2024 14:30:35 +0800 Subject: [PATCH] add tlsr dcd and board file --- hw/bsp/board_mcu.h | 3 + hw/bsp/telink/board.h | 46 +++++ hw/bsp/telink/family.c | 99 +++++++++ src/common/tusb_mcu.h | 2 + src/portable/telink/dcd_tlsr.c | 364 +++++++++++++++++++++++++++++++++ src/tusb_option.h | 3 + 6 files changed, 517 insertions(+) create mode 100644 hw/bsp/telink/board.h create mode 100644 hw/bsp/telink/family.c create mode 100644 src/portable/telink/dcd_tlsr.c diff --git a/hw/bsp/board_mcu.h b/hw/bsp/board_mcu.h index 013eb1c834..0c59e36aaa 100644 --- a/hw/bsp/board_mcu.h +++ b/hw/bsp/board_mcu.h @@ -170,6 +170,9 @@ #elif TU_CHECK_MCU(OPT_MCU_BCM2711, OPT_MCU_BCM2835, OPT_MCU_BCM2837) // no header needed +#elif CFG_TUSB_MCU == OPT_MCU_TLSR + #include "driver.h" + #else #error "Missing MCU header" #endif diff --git a/hw/bsp/telink/board.h b/hw/bsp/telink/board.h new file mode 100644 index 0000000000..6eee40d628 --- /dev/null +++ b/hw/bsp/telink/board.h @@ -0,0 +1,46 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * 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. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef _BOARD_H_ +#define _BOARD_H_ + +#include "driver.h" +#include "common.h" + +// LED +#define LED_PIN GPIO_PD0 +#define LED_STATE_ON 1 + +// Button +#define BUTTON_PIN GPIO_PD2 +#define BUTTON_STATE_ACTIVE 1 + +// UART +#define UART_DEV UART0 +#define UART_TX_PIN GPIO_FC_PB1 +#define UART_RX_PIN GPIO_FC_PB2 + +#endif diff --git a/hw/bsp/telink/family.c b/hw/bsp/telink/family.c new file mode 100644 index 0000000000..dc5d8b01ec --- /dev/null +++ b/hw/bsp/telink/family.c @@ -0,0 +1,99 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * 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. + * + * This file is part of the TinyUSB stack. + */ +#include "board.h" +#include "bsp/board_api.h" + +void board_init(void) +{ + PLATFORM_INIT; + CLOCK_INIT; + +#if (MCU_CORE_B91 || MCU_CORE_B92) + // LED + gpio_function_en(LED_PIN); + gpio_output_en(LED_PIN); + gpio_input_dis(LED_PIN); + + // BUTTON + gpio_function_en(BUTTON_PIN); + gpio_output_dis(BUTTON_PIN); + gpio_input_en(BUTTON_PIN); +#elif (MCU_CORE_B80 || MCU_CORE_B85 || MCU_CORE_B87) + // TODO +#endif + board_led_write(false); +} + +//--------------------------------------------------------------------+ +// Board porting API +//--------------------------------------------------------------------+ + +void board_led_write(bool state) +{ +#if (MCU_CORE_B91 || MCU_CORE_B92) + if (state == LED_STATE_ON) + { + gpio_set_high_level(LED_PIN); + } + else + { + gpio_set_low_level(LED_PIN); + } +#elif (MCU_CORE_B80 || MCU_CORE_B85 || MCU_CORE_B87) + // TODO +#endif +} + +uint32_t board_button_read(void) +{ +#if (MCU_CORE_B91 || MCU_CORE_B92) + return gpio_get_level(BUTTON_PIN); +#elif (MCU_CORE_B80 || MCU_CORE_B85 || MCU_CORE_B87) + // TODO + return true; +#endif +} + +int board_uart_read(uint8_t *buf, int len) +{ + (void)buf; + (void)len; + + return len; +} + +int board_uart_write(void const *buf, int len) +{ + (void)buf; + (void)len; + + return len; +} + +uint32_t board_millis(void) +{ + return reg_system_tick / SYSTEM_TIMER_TICK_1MS; +} diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h index 308ee713c3..8c7a01472e 100644 --- a/src/common/tusb_mcu.h +++ b/src/common/tusb_mcu.h @@ -397,6 +397,8 @@ #elif TU_CHECK_MCU(OPT_MCU_CH32F20X) #define TUP_DCD_ENDPOINT_MAX 16 #define TUP_RHPORT_HIGHSPEED 1 +#elif TU_CHECK_MCU(OPT_MCU_TLSR) + #define TUP_DCD_ENDPOINT_MAX 9 #endif diff --git a/src/portable/telink/dcd_tlsr.c b/src/portable/telink/dcd_tlsr.c new file mode 100644 index 0000000000..50f2093ed2 --- /dev/null +++ b/src/portable/telink/dcd_tlsr.c @@ -0,0 +1,364 @@ +/* + * The MIT License (MIT) + * + * 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. + * + * This file is part of the TinyUSB stack. + */ + +#include "tusb_option.h" +#include "device/dcd.h" +#include "driver.h" + +/** + * @brief Control endpoint and data endpoint[0-7]. The control endpoint is a separate set of registers. + * + */ +#define EP_MAX 9 + +typedef struct +{ + unsigned char *buffer; + unsigned short total_len; + unsigned short queued_len; + unsigned short max_size; + bool isochronous; + bool short_packet; + bool stall_flag; +} xfer_ctl_t; + +static xfer_ctl_t xfer_status[EP_MAX][2]; + +#define XFER_CTL_BASE(_ep, _dir) &xfer_status[_ep][_dir] + +static uint8_t _setup_packet[CFG_TUD_ENDPOINT0_SIZE]; +extern void tud_task_ext(uint32_t timeout_ms, bool in_isr); + +void dcd_init(uint8_t rhport) +{ + (void)rhport; + + /* enable global interrupt. */ +#if (MCU_CORE_B91 || MCU_CORE_B92) + core_interrupt_enable(); +#elif (MCU_CORE_B80 || MCU_CORE_B85 || MCU_CORE_B87) + irq_enable(); +#endif + + usbhw_enable_manual_interrupt(FLD_CTRL_EP_AUTO_STD | FLD_CTRL_EP_AUTO_DESC | FLD_CTRL_EP_AUTO_CFG); + + usbhw_set_irq_mask(USB_IRQ_RESET_MASK | USB_IRQ_SUSPEND_MASK); + + usb_set_pin_en(); +} + +void dcd_int_enable(uint8_t rhport) +{ + (void)rhport; + +#if (MCU_CORE_B91 || MCU_CORE_B92) + plic_interrupt_enable(IRQ_USB_CTRL_EP_SETUP); + plic_interrupt_enable(IRQ_USB_CTRL_EP_DATA); + plic_interrupt_enable(IRQ_USB_CTRL_EP_STATUS); + plic_interrupt_enable(IRQ_USB_CTRL_EP_SETINF); + plic_interrupt_enable(IRQ_USB_RESET); + plic_interrupt_enable(IRQ_USB_ENDPOINT); +#elif (MCU_CORE_B80 || MCU_CORE_B85 || MCU_CORE_B87) + // TODO +#endif +} + +void dcd_int_disable(uint8_t rhport) +{ + (void)rhport; + +#if (MCU_CORE_B91 || MCU_CORE_B92) + plic_interrupt_disable(IRQ_USB_CTRL_EP_SETUP); + plic_interrupt_disable(IRQ_USB_CTRL_EP_DATA); + plic_interrupt_disable(IRQ_USB_CTRL_EP_STATUS); + plic_interrupt_disable(IRQ_USB_CTRL_EP_SETINF); + plic_interrupt_disable(IRQ_USB_RESET); + plic_interrupt_disable(IRQ_USB_ENDPOINT); +#elif (MCU_CORE_B80 || MCU_CORE_B85 || MCU_CORE_B87) + // TODO +#endif +} + +void dcd_set_address(uint8_t rhport, uint8_t dev_addr) +{ + (void)rhport; + (void)dev_addr; +} + +void dcd_remote_wakeup(uint8_t rhport) +{ + (void)rhport; + // TODO +} + +void dcd_connect(uint8_t rhport) +{ + (void)rhport; + + usb_dp_pullup_en(1); +} + +void dcd_disconnect(uint8_t rhport) +{ + (void)rhport; + + usb_dp_pullup_en(0); +} + +void dcd_sof_enable(uint8_t rhport, bool en) +{ + (void)rhport; + (void)en; + // TODO +} + +/*------------------------------------------------------------------*/ +/* DCD Endpoint port + *------------------------------------------------------------------*/ + +bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *desc_edpt) +{ + (void)rhport; + (void)desc_edpt; + + uint8_t const epnum = tu_edpt_number(desc_edpt->bEndpointAddress); + + reg_usb_edp_en |= BIT(epnum & 0x07); // endpoint 8 means endpoint 0. + + return true; +} + +void dcd_edpt_close_all(uint8_t rhport) +{ + (void)rhport; + + reg_usb_edp_en = 0; +} + +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes) +{ + (void)rhport; + (void)ep_addr; + (void)buffer; + (void)total_bytes; + + unsigned char const epnum = tu_edpt_number(ep_addr); + unsigned char const dir = tu_edpt_dir(ep_addr); + xfer_ctl_t *xfer = XFER_CTL_BASE(epnum, dir); + xfer->buffer = buffer; + xfer->total_len = total_bytes; + xfer->queued_len = 0; + xfer->short_packet = false; + + return true; +} + +void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) +{ + (void)rhport; + (void)ep_addr; + + unsigned char const epnum = tu_edpt_number(ep_addr); + unsigned char const dir = tu_edpt_dir(ep_addr); + xfer_ctl_t *xfer = XFER_CTL_BASE(epnum, dir); + xfer->stall_flag = 1; + if (0 == epnum) + { + usbhw_write_ctrl_ep_ctrl(FLD_EP_DAT_STALL); + } + else + { + usbhw_data_ep_stall(epnum); + } +} + +void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) +{ + (void)rhport; + (void)ep_addr; + + unsigned char const epnum = tu_edpt_number(ep_addr); + unsigned char const dir = tu_edpt_dir(ep_addr); + xfer_ctl_t *xfer = XFER_CTL_BASE(epnum, dir); + xfer->stall_flag = 0; + + if (0 == epnum) + { + usbhw_write_ctrl_ep_ctrl(FLD_EP_DAT_ACK); + } + else + { + usbhw_data_ep_ack(epnum); + } +} + +#if (MCU_CORE_B91 || MCU_CORE_B92) +_attribute_ram_code_sec_ void usb_ctrl_ep_setup_irq_handler(void) +{ + usbhw_clr_ctrl_ep_irq(FLD_CTRL_EP_IRQ_SETUP); + xfer_status[0][TUSB_DIR_OUT].stall_flag = 0; + xfer_status[0][TUSB_DIR_IN].stall_flag = 0; + + usbhw_reset_ctrl_ep_ptr(); + for (int i = 0; i < CFG_TUD_ENDPOINT0_SIZE; i++) + { + _setup_packet[i] = reg_ctrl_ep_dat; + } + + dcd_event_setup_received(0, (uint8_t *)&_setup_packet[0], true); + tud_task_ext(0, true); + + xfer_ctl_t *xfer = XFER_CTL_BASE(0, TUSB_DIR_IN); + if (xfer->total_len != xfer->queued_len) + { + uint8_t *base = (xfer->buffer + xfer->queued_len); + uint16_t remaining = xfer->total_len - xfer->queued_len; + uint8_t xfer_size = (xfer->max_size < xfer->total_len) ? xfer->max_size : remaining; + + usbhw_reset_ctrl_ep_ptr(); + for (unsigned short i = 0; i < xfer_size; i++) + { + usbhw_write_ctrl_ep_data(base[i]); + } + xfer->queued_len += xfer_size; + dcd_event_xfer_complete(0, 0 | TUSB_DIR_IN_MASK, xfer_size, XFER_RESULT_SUCCESS, true); + tud_task_ext(0, true); + } + if (!xfer->stall_flag) + { + usbhw_write_ctrl_ep_ctrl(FLD_EP_DAT_ACK); + } +} +PLIC_ISR_REGISTER(usb_ctrl_ep_setup_irq_handler, IRQ_USB_CTRL_EP_SETUP); + +_attribute_ram_code_sec_ void usb_ctrl_ep_data_irq_handler(void) +{ + usbhw_clr_ctrl_ep_irq(FLD_CTRL_EP_IRQ_DATA); + + xfer_ctl_t *xfer = XFER_CTL_BASE(0, TUSB_DIR_IN); + if (xfer->total_len != xfer->queued_len) + { + uint8_t *base = (xfer->buffer + xfer->queued_len); + uint16_t remaining = xfer->total_len - xfer->queued_len; + uint8_t xfer_size = (xfer->max_size < xfer->total_len) ? xfer->max_size : remaining; + + usbhw_reset_ctrl_ep_ptr(); + for (unsigned short i = 0; i < xfer_size; i++) + { + usbhw_write_ctrl_ep_data(base[i]); + } + xfer->queued_len += xfer_size; + dcd_event_xfer_complete(0, 0 | TUSB_DIR_IN_MASK, xfer_size, XFER_RESULT_SUCCESS, true); + tud_task_ext(0, true); + } + + if (!xfer->stall_flag) + { + usbhw_write_ctrl_ep_ctrl(FLD_EP_DAT_ACK); + } +} +PLIC_ISR_REGISTER(usb_ctrl_ep_data_irq_handler, IRQ_USB_CTRL_EP_DATA); + +_attribute_ram_code_sec_ void usb_ctrl_ep_status_irq_handler(void) +{ + usbhw_clr_ctrl_ep_irq(FLD_CTRL_EP_IRQ_STA); + + xfer_ctl_t *xfer = XFER_CTL_BASE(0, TUSB_DIR_IN); + if (!xfer->stall_flag) + { + usbhw_write_ctrl_ep_ctrl(FLD_EP_STA_ACK); + } +} +PLIC_ISR_REGISTER(usb_ctrl_ep_status_irq_handler, IRQ_USB_CTRL_EP_STATUS); + +_attribute_ram_code_sec_ void usb_ctrl_ep_setinf_irq_handler(void) +{ + usbhw_clr_ctrl_ep_irq(FLD_CTRL_EP_IRQ_INTF); +} +PLIC_ISR_REGISTER(usb_ctrl_ep_setinf_irq_handler, IRQ_USB_CTRL_EP_SETINF); + +_attribute_ram_code_sec_ void usb_pwdn_irq_handler(void) +{ + usbhw_clr_irq_status(USB_IRQ_SUSPEND_STATUS); +} +PLIC_ISR_REGISTER(usb_pwdn_irq_handler, IRQ_USB_PWDN); + +static void bus_reset(void) +{ + xfer_status[0][TUSB_DIR_OUT].max_size = CFG_TUD_ENDPOINT0_SIZE; + xfer_status[0][TUSB_DIR_IN].max_size = CFG_TUD_ENDPOINT0_SIZE; +} + +_attribute_ram_code_sec_ void usb_reset_irq_handler(void) +{ + usbhw_clr_irq_status(USB_IRQ_RESET_STATUS); /* Clear USB reset flag */ + bus_reset(); + dcd_event_bus_reset(0, TUSB_SPEED_FULL, true); +} +PLIC_ISR_REGISTER(usb_reset_irq_handler, IRQ_USB_RESET); + +_attribute_ram_code_sec_ void usb_endpoint_irq_handler(void) +{ + unsigned char irq = usbhw_get_eps_irq(); + + if (irq & FLD_USB_EDP8_IRQ) + { + usbhw_clr_eps_irq(FLD_USB_EDP8_IRQ); + } + if (irq & FLD_USB_EDP7_IRQ) + { + usbhw_clr_eps_irq(FLD_USB_EDP7_IRQ); + } + if (irq & FLD_USB_EDP6_IRQ) + { + usbhw_clr_eps_irq(FLD_USB_EDP6_IRQ); + } + if (irq & FLD_USB_EDP5_IRQ) + { + usbhw_clr_eps_irq(FLD_USB_EDP5_IRQ); + } + if (irq & FLD_USB_EDP4_IRQ) + { + usbhw_clr_eps_irq(FLD_USB_EDP4_IRQ); + } + if (irq & FLD_USB_EDP3_IRQ) + { + usbhw_clr_eps_irq(FLD_USB_EDP3_IRQ); + } + if (irq & FLD_USB_EDP2_IRQ) + { + usbhw_clr_eps_irq(FLD_USB_EDP2_IRQ); + } + if (irq & FLD_USB_EDP1_IRQ) + { + usbhw_clr_eps_irq(FLD_USB_EDP1_IRQ); + } +} +PLIC_ISR_REGISTER(usb_endpoint_irq_handler, IRQ_USB_ENDPOINT); +#elif (MCU_CORE_B80 || MCU_CORE_B85 || MCU_CORE_B87) +_attribute_ram_code_sec_noinline_ void irq_handler(void) +{ + // TODO +} +#endif diff --git a/src/tusb_option.h b/src/tusb_option.h index 96378cb804..1359ccc8ba 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -177,6 +177,9 @@ // NXP LPC MCX #define OPT_MCU_MCXN9 2300 ///< NXP MCX N9 Series +// TLSR +#define OPT_MCU_TLSR 2400 ///< TLSR Series + // Check if configured MCU is one of listed // Apply _TU_CHECK_MCU with || as separator to list of input #define _TU_CHECK_MCU(_m) (CFG_TUSB_MCU == _m)