From f8aa4b3ff3e3db71e752d9278bc248fb9e066f75 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Wed, 3 Mar 2021 10:14:41 +0100 Subject: [PATCH 01/36] Add sketchy SAME70 DCD driver. --- .../device/cdc_dual_ports/src/tusb_config.h | 2 +- .../cdc_dual_ports/src/usb_descriptors.c | 32 +- src/portable/microchip/same70/dcd_same70.c | 564 ++++++++++++++++++ 3 files changed, 589 insertions(+), 9 deletions(-) create mode 100644 src/portable/microchip/same70/dcd_same70.c diff --git a/examples/device/cdc_dual_ports/src/tusb_config.h b/examples/device/cdc_dual_ports/src/tusb_config.h index c7e87bf6..45167da8 100644 --- a/examples/device/cdc_dual_ports/src/tusb_config.h +++ b/examples/device/cdc_dual_ports/src/tusb_config.h @@ -48,7 +48,7 @@ // Default to Highspeed for MCU with internal HighSpeed PHY (can be port specific), otherwise FullSpeed #ifndef BOARD_DEVICE_RHPORT_SPEED #if (CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || \ - CFG_TUSB_MCU == OPT_MCU_NUC505 || CFG_TUSB_MCU == OPT_MCU_CXD56) + CFG_TUSB_MCU == OPT_MCU_NUC505 || CFG_TUSB_MCU == OPT_MCU_CXD56 || CFG_TUSB_MCU == OPT_MCU_SAME70) #define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_HIGH_SPEED #else #define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_FULL_SPEED diff --git a/examples/device/cdc_dual_ports/src/usb_descriptors.c b/examples/device/cdc_dual_ports/src/usb_descriptors.c index 8e19678e..e39c140c 100644 --- a/examples/device/cdc_dual_ports/src/usb_descriptors.c +++ b/examples/device/cdc_dual_ports/src/usb_descriptors.c @@ -87,16 +87,32 @@ enum // LPC 17xx and 40xx endpoint type (bulk/interrupt/iso) are fixed by its number // 0 control, 1 In, 2 Bulk, 3 Iso, 4 In etc ... #define EPNUM_CDC_0_NOTIF 0x81 - #define EPNUM_CDC_0_DATA 0x02 + #define EPNUM_CDC_0_OUT 0x02 + #define EPNUM_CDC_0_IN 0x82 #define EPNUM_CDC_1_NOTIF 0x84 - #define EPNUM_CDC_1_DATA 0x05 + #define EPNUM_CDC_1_OUT 0x05 + #define EPNUM_CDC_1_IN 0x85 + +#elif CFG_TUSB_MCU == OPT_MCU_SAMG || CFG_TUSB_MCU == OPT_MCU_SAME70 + // SAMG & SAME70 don't support a same endpoint number with different direction IN and OUT + // e.g EP1 OUT & EP1 IN cannot exist together + #define EPNUM_CDC_0_NOTIF 0x81 + #define EPNUM_CDC_0_OUT 0x02 + #define EPNUM_CDC_0_IN 0x83 + + #define EPNUM_CDC_1_NOTIF 0x84 + #define EPNUM_CDC_1_OUT 0x05 + #define EPNUM_CDC_1_IN 0x86 + #else #define EPNUM_CDC_0_NOTIF 0x81 - #define EPNUM_CDC_0_DATA 0x02 + #define EPNUM_CDC_0_OUT 0x02 + #define EPNUM_CDC_0_IN 0x82 #define EPNUM_CDC_1_NOTIF 0x83 - #define EPNUM_CDC_1_DATA 0x04 + #define EPNUM_CDC_1_OUT 0x04 + #define EPNUM_CDC_1_IN 0x84 #endif uint8_t const desc_fs_configuration[] = @@ -105,10 +121,10 @@ uint8_t const desc_fs_configuration[] = TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), // 1st CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size. - TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_0, 4, EPNUM_CDC_0_NOTIF, 8, EPNUM_CDC_0_DATA, 0x80 | EPNUM_CDC_0_DATA, 64), + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_0, 4, EPNUM_CDC_0_NOTIF, 8, EPNUM_CDC_0_OUT, EPNUM_CDC_0_IN, 64), // 2nd CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size. - TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_1, 4, EPNUM_CDC_1_NOTIF, 8, EPNUM_CDC_1_DATA, 0x80 | EPNUM_CDC_1_DATA, 64), + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_1, 4, EPNUM_CDC_1_NOTIF, 8, EPNUM_CDC_1_OUT, EPNUM_CDC_1_IN, 64), }; #if TUD_OPT_HIGH_SPEED @@ -118,10 +134,10 @@ uint8_t const desc_hs_configuration[] = TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), // 1st CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size. - TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_0, 4, EPNUM_CDC_0_NOTIF, 8, EPNUM_CDC_0_DATA, 0x80 | EPNUM_CDC_0_DATA, 512), + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_0, 4, EPNUM_CDC_0_NOTIF, 8, EPNUM_CDC_0_OUT, EPNUM_CDC_0_IN, 512), // 2nd CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size. - TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_1, 4, EPNUM_CDC_1_NOTIF, 8, EPNUM_CDC_1_DATA, 0x80 | EPNUM_CDC_1_DATA, 512), + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_1, 4, EPNUM_CDC_1_NOTIF, 8, EPNUM_CDC_1_OUT, EPNUM_CDC_1_IN, 512), }; #endif diff --git a/src/portable/microchip/same70/dcd_same70.c b/src/portable/microchip/same70/dcd_same70.c new file mode 100644 index 00000000..7fdc9dd0 --- /dev/null +++ b/src/portable/microchip/same70/dcd_same70.c @@ -0,0 +1,564 @@ +/* +* The MIT License (MIT) +* +* Copyright (c) 2018, hathach (tinyusb.org) +* Copyright (c) 2020, HiFiPhile +* +* 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" + +#if CFG_TUSB_MCU == OPT_MCU_SAME70 + +#include "device/dcd.h" + +#include "sam.h" + +#include "SEGGER_RTT.h" +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM DECLARATION +//--------------------------------------------------------------------+ + +// Since TinyUSB doesn't use SOF for now, and this interrupt too often (1ms interval) +// We disable SOF for now until needed later on +#ifndef USE_SOF +# define USE_SOF 0 +#endif + +#ifndef USBHS_RAM_ADDR +# define USBHS_RAM_ADDR 0xA0100000u +#endif + +#define get_ep_fifo_ptr(ep, scale) (((volatile TU_XSTRCAT(TU_STRCAT(uint, scale),_t) (*)[0x8000 / ((scale) / 8)])USBHS_RAM_ADDR)[(ep)]) + +#define EP_MAX 10 + +typedef struct { + uint8_t * buffer; + uint16_t total_len; + uint16_t queued_len; + uint16_t max_packet_size; + uint8_t interval; +} xfer_ctl_t; + +xfer_ctl_t xfer_status[EP_MAX+1]; + +static const tusb_desc_endpoint_t ep0_desc = +{ + .bLength = sizeof(tusb_desc_endpoint_t), + .bDescriptorType = TUSB_DESC_ENDPOINT, + + .bEndpointAddress = 0x00, + .bmAttributes = { .xfer = TUSB_XFER_CONTROL }, + .wMaxPacketSize = { .size = CFG_TUD_ENDPOINT0_SIZE }, + .bInterval = 0 +}; + +static tusb_speed_t get_speed(void); +static void dcd_transmit_packet(xfer_ctl_t * xfer, uint8_t ep_ix); +//------------------------------------------------------------------ +// Device API +//------------------------------------------------------------------ + +// Initialize controller to device mode +void dcd_init (uint8_t rhport) +{ + // Enable USBPLL + PMC->CKGR_UCKR = CKGR_UCKR_UPLLEN | CKGR_UCKR_UPLLCOUNT(0x3fU); + // Wait until USB UTMI stabilize + while (!(PMC->PMC_SR & PMC_SR_LOCKU)); + // Enable USB FS clk + PMC->PMC_USB = PMC_USB_USBS | PMC_USB_USBDIV(10 - 1); + PMC->PMC_SCER = PMC_SCER_USBCLK; + dcd_connect(rhport); +} + +// Enable device interrupt +void dcd_int_enable (uint8_t rhport) +{ + (void) rhport; + NVIC_EnableIRQ((IRQn_Type) ID_USBHS); +} + +// Disable device interrupt +void dcd_int_disable (uint8_t rhport) +{ + (void) rhport; + NVIC_DisableIRQ((IRQn_Type) ID_USBHS); +} + +// Receive Set Address request, mcu port must also include status IN response +void dcd_set_address (uint8_t rhport, uint8_t dev_addr) +{ + (void) rhport; + // Set the address but keep it disabled for now. It should be enabled + // only after the ack to the host completes. + USBHS->USBHS_DEVCTRL &= ~(USBHS_DEVCTRL_UADD_Msk | USBHS_DEVCTRL_ADDEN); + USBHS->USBHS_DEVCTRL |= USBHS_DEVCTRL_UADD(dev_addr); + + // Respond with status + dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0); +} + +// Wake up host +void dcd_remote_wakeup (uint8_t rhport) +{ + (void) rhport; + USBHS->USBHS_DEVCTRL |= USBHS_DEVCTRL_RMWKUP; +} + +// Connect by enabling internal pull-up resistor on D+/D- +void dcd_connect(uint8_t rhport) +{ + uint32_t irq_state = __get_PRIMASK(); + __disable_irq(); + // Enable USB clock + PMC->PMC_PCER1 = 1 << (ID_USBHS - 32); + // Enable the USB controller in device mode + USBHS->USBHS_CTRL = USBHS_CTRL_UIMOD | USBHS_CTRL_USBE; + // Wait to unfreeze clock + while(USBHS_SR_CLKUSABLE != (USBHS->USBHS_SR & USBHS_SR_CLKUSABLE)); + // Attach the device + USBHS->USBHS_DEVCTRL &= ~USBHS_DEVCTRL_DETACH; + // Enable the End Of Reset, Suspend & Wakeup interrupts + USBHS->USBHS_DEVIER = (USBHS_DEVIER_EORSTES | USBHS_DEVIER_SUSPES | USBHS_DEVIER_WAKEUPES); +#if USE_SOF + USBHS->USBHS_DEVIER = USBHS_DEVIER_SOFES; +#endif + // Clear the End Of Reset, SOF & Wakeup interrupts + USBHS->USBHS_DEVICR = (USBHS_DEVICR_EORSTC | USBHS_DEVICR_SOFC | USBHS_DEVICR_WAKEUPC); + // Manually set the Suspend Interrupt + USBHS->USBHS_DEVIFR |= USBHS_DEVIFR_SUSPS; + // Ack the Wakeup Interrupt + USBHS->USBHS_DEVICR = USBHS_DEVICR_WAKEUPC; + // Freeze USB clock + USBHS->USBHS_CTRL |= USBHS_CTRL_FRZCLK; + __set_PRIMASK(irq_state); +} + +// Disconnect by disabling internal pull-up resistor on D+/D- +void dcd_disconnect(uint8_t rhport) +{ + (void) rhport; + uint32_t irq_state = __get_PRIMASK(); + __disable_irq(); + // Disable all endpoints + USBHS->USBHS_DEVEPT &= ~(0x3FF << USBHS_DEVEPT_EPEN0_Pos); + // Unfreeze USB clock + USBHS->USBHS_CTRL &= ~USBHS_CTRL_FRZCLK; + // Wait to unfreeze clock + while(USBHS_SR_CLKUSABLE != (USBHS->USBHS_SR & USBHS_SR_CLKUSABLE)); + // Clear all the pending interrupts + USBHS->USBHS_DEVICR = USBHS_DEVICR_Msk; + // Disable all interrupts + USBHS->USBHS_DEVIDR = USBHS_DEVCTRL_UADD_Msk; + // Detach the device + USBHS->USBHS_DEVCTRL |= USBHS_DEVCTRL_DETACH; + // Disable the device address + USBHS->USBHS_DEVCTRL &=~(USBHS_DEVCTRL_ADDEN | USBHS_DEVCTRL_UADD_Msk); + __set_PRIMASK(irq_state); +} + +static tusb_speed_t get_speed(void) +{ + switch((USBHS->USBHS_SR & USBHS_SR_SPEED_Msk) >> USBHS_SR_SPEED_Pos) + { + case USBHS_SR_SPEED_FULL_SPEED_Val: + default: + return TUSB_SPEED_FULL; + case USBHS_SR_SPEED_HIGH_SPEED_Val: + return TUSB_SPEED_HIGH; + case USBHS_SR_SPEED_LOW_SPEED_Val: + return TUSB_SPEED_LOW; + } +} + +static void dcd_ep_handler(uint8_t ep_ix) +{ + uint32_t int_status = USBHS->USBHS_DEVEPTISR[ep_ix] & USBHS->USBHS_DEVEPTIMR[ep_ix]; + uint32_t dev_ctrl = USBHS->USBHS_DEVCTRL; + uint16_t count = (USBHS->USBHS_DEVEPTISR[ep_ix] & + USBHS_DEVEPTISR_BYCT_Msk) >> USBHS_DEVEPTISR_BYCT_Pos; + SEGGER_RTT_printf(0, "ep: %u %u %u \r\n", ep_ix, count, int_status); + if(ep_ix == 0U) + { + if (int_status & USBHS_DEVEPTISR_CTRL_RXSTPI) { + + // Get 8-bit access to endpoint 0 FIFO from USB RAM address + volatile uint8_t *ptr = get_ep_fifo_ptr(0,8); + SCB_InvalidateDCache_by_Addr((uint32_t *) ptr, 8); + dcd_event_setup_received(0, (uint8_t*)ptr, true); + + // Acknowledge the interrupt + USBHS->USBHS_DEVEPTICR[0] = USBHS_DEVEPTICR_RXSTPIC; + } + if (int_status & USBHS_DEVEPTISR_RXOUTI) { + // Disable the interrupt + //USBHS->USBHS_DEVEPTIDR[ep_ix] = USBHS_DEVEPTIDR_RXOUTEC; + + xfer_ctl_t *xfer = &xfer_status[0]; + + if(count) + { + volatile uint8_t *ptr = get_ep_fifo_ptr(0,8); + for (int i = 0; i < count; i++) { + xfer->buffer[xfer->queued_len + i] = ptr[i]; + } + xfer->queued_len = (uint16_t)(xfer->queued_len + count); + } + + USBHS->USBHS_DEVEPTICR[0] = USBHS_DEVEPTICR_RXOUTIC; + + if ((count < xfer->max_packet_size) || (xfer->queued_len == xfer->total_len)) + { + // RX COMPLETE + dcd_event_xfer_complete(0, 0, xfer->queued_len, XFER_RESULT_SUCCESS, true); + xfer->queued_len = 0; + SEGGER_RTT_printf(0, "rx: %u \r\n", xfer->queued_len); + // Though the host could still send, we don't know. + } + + + } + if (int_status & USBHS_DEVEPTISR_TXINI) { + // Disable the interrupt + USBHS->USBHS_DEVEPTIDR[0] = USBHS_DEVEPTIDR_TXINEC; + if (!(dev_ctrl & USBHS_DEVCTRL_ADDEN) && + (dev_ctrl & USBHS_DEVCTRL_UADD_Msk) != 0U) { + // Commit the pending address update. This + // must be done after the ack to the host + // completes else the ack will get dropped. + USBHS->USBHS_DEVCTRL = dev_ctrl | USBHS_DEVCTRL_ADDEN; + } + xfer_ctl_t * xfer = &xfer_status[EP_MAX]; + if((xfer->total_len != xfer->queued_len)) // TX not complete + { + dcd_transmit_packet(xfer, 0); + } + else // TX Complete + { + dcd_event_xfer_complete(0, (uint8_t)(0x80 + 0), xfer->total_len, XFER_RESULT_SUCCESS, true); + } + } + } + else + { + if (int_status & USBHS_DEVEPTISR_RXOUTI) { + // Acknowledge the interrupt + USBHS->USBHS_DEVEPTICR[ep_ix] = USBHS_DEVEPTICR_RXOUTIC; + + xfer_ctl_t *xfer = &xfer_status[ep_ix]; + + if(count) + { + volatile uint8_t *ptr = get_ep_fifo_ptr(ep_ix,8); + for (int i = 0; i < count; i++) { + xfer->buffer[xfer->queued_len + i] = ptr[i]; + } + xfer->queued_len = (uint16_t)(xfer->queued_len + count); + } + // Clear the FIFO control flag to receive more data. + USBHS->USBHS_DEVEPTIDR[ep_ix] = USBHS_DEVEPTIDR_FIFOCONC; + if ((count < xfer->max_packet_size) || (xfer->queued_len == xfer->total_len)) + { + // RX COMPLETE + dcd_event_xfer_complete(0, ep_ix, xfer->queued_len, XFER_RESULT_SUCCESS, true); + xfer->queued_len = 0; + // Though the host could still send, we don't know. + } + } + if (int_status & USBHS_DEVEPTISR_TXINI) { + // Acknowledge the interrupt + USBHS->USBHS_DEVEPTICR[ep_ix] = USBHS_DEVEPTICR_TXINIC; + xfer_ctl_t * xfer = &xfer_status[ep_ix];; + if((xfer->total_len != xfer->queued_len)) // TX not complete + { + dcd_transmit_packet(xfer, ep_ix); + } + else // TX Complete + { + dcd_event_xfer_complete(0, (uint8_t)(0x80 + ep_ix), xfer->total_len, XFER_RESULT_SUCCESS, true); + } + } + } +} + +void dcd_int_handler(uint8_t rhport) +{ + (void) rhport; + uint32_t int_status = USBHS->USBHS_DEVISR; + // End of reset interrupt + if (int_status & USBHS_DEVISR_EORST) { + // Unfreeze USB clock + USBHS->USBHS_CTRL &= ~USBHS_CTRL_FRZCLK; + while(USBHS_SR_CLKUSABLE != (USBHS->USBHS_SR & USBHS_SR_CLKUSABLE)); + // Reset all endpoints + for (int ep_ix = 1; ep_ix < EP_MAX; ep_ix++) + { + // Disable endpoint interrupt + USBHS->USBHS_DEVIDR = 1 << (USBHS_DEVIDR_PEP_0_Pos + ep_ix); + // Disable endpoint and SETUP, IN or OUT interrupts + USBHS->USBHS_DEVEPT &= ~ (1 << (USBHS_DEVEPT_EPEN0_Pos + ep_ix)); + // Free all endpoint memory + USBHS->USBHS_DEVEPTCFG[ep_ix] &= ~USBHS_DEVEPTCFG_ALLOC; + } + dcd_edpt_open (0, &ep0_desc); + // Acknowledge the End of Reset interrupt + USBHS->USBHS_DEVICR = USBHS_DEVICR_EORSTC; + // Acknowledge the Wakeup interrupt + USBHS->USBHS_DEVICR = USBHS_DEVICR_WAKEUPC; + // Acknowledge the suspend interrupt + USBHS->USBHS_DEVICR = USBHS_DEVICR_SUSPC; + // Enable Suspend Interrupt + USBHS->USBHS_DEVIER = USBHS_DEVIER_SUSPES; + + dcd_event_bus_reset(rhport, get_speed(), true); + } + // End of Wakeup interrupt + if (int_status & USBHS_DEVISR_WAKEUP) { + // Unfreeze USB clock + USBHS->USBHS_CTRL &= ~USBHS_CTRL_FRZCLK; + // Wait to unfreeze clock + while(USBHS_SR_CLKUSABLE != (USBHS->USBHS_SR & USBHS_SR_CLKUSABLE)); + // Acknowledge the Wakeup interrupt + USBHS->USBHS_DEVICR = USBHS_DEVICR_WAKEUPC; + // Disable Wakeup Interrupt + USBHS->USBHS_DEVIDR = USBHS_DEVIDR_WAKEUPEC; + // Enable Suspend Interrupt + USBHS->USBHS_DEVIER = USBHS_DEVIER_SUSPES; + + dcd_event_bus_signal(0, DCD_EVENT_RESUME, true); + } + // Suspend interrupt + if (int_status & USBHS_DEVISR_SUSP) { + // Unfreeze USB clock + USBHS->USBHS_CTRL &= ~USBHS_CTRL_FRZCLK; + // Wait to unfreeze clock + while(USBHS_SR_CLKUSABLE != (USBHS->USBHS_SR & USBHS_SR_CLKUSABLE)); + // Acknowledge the suspend interrupt + USBHS->USBHS_DEVICR = USBHS_DEVICR_SUSPC; + // Disable Suspend Interrupt + USBHS->USBHS_DEVIDR = USBHS_DEVIDR_SUSPEC; + // Enable Wakeup Interrupt + USBHS->USBHS_DEVIER = USBHS_DEVIER_WAKEUPES; + // Freeze USB clock + USBHS->USBHS_CTRL |= USBHS_CTRL_FRZCLK; + + dcd_event_bus_signal(0, DCD_EVENT_SUSPEND, true); + } +#if USE_SOF + if(int_status & USBHS_DEVISR_SOF) { + USBHS->USBHS_DEVICR = USBHS_DEVICR_SOFC; + + dcd_event_bus_signal(0, DCD_EVENT_SOF, true); + } +#endif + // Endpoints interrupt + for (int ep_ix = 0; ep_ix < EP_MAX; ep_ix++) { + if (int_status & (1 << (USBHS_DEVISR_PEP_0_Pos + ep_ix))) { + dcd_ep_handler(ep_ix); + } + } +} + +//--------------------------------------------------------------------+ +// Endpoint API +//--------------------------------------------------------------------+ + +// Configure endpoint's registers according to descriptor +bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) +{ + (void) rhport; + uint8_t const epnum = tu_edpt_number(ep_desc->bEndpointAddress); + uint8_t const dir = tu_edpt_dir(ep_desc->bEndpointAddress); + uint16_t const epMaxPktSize = ep_desc->wMaxPacketSize.size; + tusb_xfer_type_t const eptype = (tusb_xfer_type_t)ep_desc->bmAttributes.xfer; + uint8_t fifoSize = 0; // FIFO size + uint16_t defaultEndpointSize = 8; // Default size of Endpoint + // Find upper 2 power number of epMaxPktSize + if(epMaxPktSize) + { + while (defaultEndpointSize < epMaxPktSize) + { + fifoSize++; + defaultEndpointSize <<= 1; + } + } + xfer_status[epnum].max_packet_size = epMaxPktSize; + + if(epnum == 0) + { + xfer_status[EP_MAX].max_packet_size = epMaxPktSize; + // Enable the control endpoint - Endpoint 0 + USBHS->USBHS_DEVEPT |= USBHS_DEVEPT_EPEN0; + // Configure the Endpoint 0 configuration register + USBHS->USBHS_DEVEPTCFG[0] = + ( + USBHS_DEVEPTCFG_EPSIZE(fifoSize) | + USBHS_DEVEPTCFG_EPTYPE(TUSB_XFER_CONTROL) | + USBHS_DEVEPTCFG_EPBK(USBHS_DEVEPTCFG_EPBK_1_BANK) | + USBHS_DEVEPTCFG_ALLOC + ); + USBHS->USBHS_DEVEPTIER[0] = USBHS_DEVEPTIER_RSTDTS; + USBHS->USBHS_DEVEPTIDR[0] = USBHS_DEVEPTIDR_STALLRQC; + if(USBHS_DEVEPTISR_CFGOK == (USBHS->USBHS_DEVEPTISR[0] & USBHS_DEVEPTISR_CFGOK)) + { + // Endpoint configuration is successful + USBHS->USBHS_DEVEPTIER[0] = USBHS_DEVEPTIER_RXSTPES | USBHS_DEVEPTIER_RXOUTES; + // Enable Endpoint 0 Interrupts + USBHS->USBHS_DEVIER = USBHS_DEVIER_PEP_0; + return true; + } + else + { + // Endpoint configuration is not successful + return false; + } + } + else + { + // Enable the endpoint + USBHS->USBHS_DEVEPT |= ((0x01 << epnum) << USBHS_DEVEPT_EPEN0_Pos); + // Set up the maxpacket size, fifo start address fifosize + // and enable the interrupt. CLear the data toggle. + USBHS->USBHS_DEVEPTCFG[epnum] = + ( + USBHS_DEVEPTCFG_EPSIZE(fifoSize) | + USBHS_DEVEPTCFG_EPTYPE(eptype) | + USBHS_DEVEPTCFG_EPBK(USBHS_DEVEPTCFG_EPBK_1_BANK) | + USBHS_DEVEPTCFG_ALLOC | + ((dir & 0x01) << USBHS_DEVEPTCFG_EPDIR_Pos) + ); + + if (eptype == TUSB_XFER_ISOCHRONOUS) + { + USBHS->USBHS_DEVEPTCFG[epnum] |= USBHS_DEVEPTCFG_NBTRANS(1); + } + USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_RSTDTS; + USBHS->USBHS_DEVEPTIDR[epnum] = USBHS_DEVEPTIDR_STALLRQC; + if(USBHS_DEVEPTISR_CFGOK == (USBHS->USBHS_DEVEPTISR[epnum] & USBHS_DEVEPTISR_CFGOK)) + { + // Endpoint configuration is successful. Enable Endpoint Interrupts + if(dir == TUSB_DIR_OUT) + { + USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_RXOUTES; + } + else + { + USBHS->USBHS_DEVEPTICR[epnum] = USBHS_DEVEPTICR_TXINIC; + USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_TXINES; + } + USBHS->USBHS_DEVIER = ((0x01 << epnum) << USBHS_DEVIER_PEP_0_Pos); + return true; + } + else + { + // Endpoint configuration is not successful + return false; + } + } +} + +static void dcd_transmit_packet(xfer_ctl_t * xfer, uint8_t ep_ix) +{ + uint16_t len = (uint16_t)(xfer->total_len - xfer->queued_len); + + if(len > xfer->max_packet_size) // max packet size for FS transfer + { + len = xfer->max_packet_size; + } + + volatile uint8_t *ptr = get_ep_fifo_ptr(ep_ix,8); + for (int i = 0; i < len; i++) { + ptr[i] = xfer->buffer[xfer->queued_len + i]; + } + + xfer->queued_len = (uint16_t)(xfer->queued_len + len); + + if (ep_ix == 0U) { + + // Control endpoint: clear the interrupt flag to send the data, + // and re-enable the interrupts to trigger an interrupt at the + // end of the transfer. + USBHS->USBHS_DEVEPTICR[0] = USBHS_DEVEPTICR_TXINIC; + USBHS->USBHS_DEVEPTIER[0] = USBHS_DEVEPTIER_TXINES; + } else { + + // Other endpoint types: clear the FIFO control flag to send the data. + USBHS->USBHS_DEVEPTIDR[ep_ix] = USBHS_DEVEPTIDR_FIFOCONC; + } +} + + +// Submit a transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack +bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) +{ + (void) rhport; + + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + xfer_ctl_t * xfer = &xfer_status[epnum]; + if(ep_addr == 0x80) + xfer = &xfer_status[EP_MAX]; + + xfer->buffer = buffer; + xfer->total_len = total_bytes; + xfer->queued_len = 0; + + SEGGER_RTT_printf(0, "xfer: %u %u %u \r\n", epnum, dir, total_bytes); + + if ( dir == TUSB_DIR_OUT ) + { + // Endpoint configuration is successful + // Acknowledge the interrupt + //USBHS->USBHS_DEVEPTICR[epnum] = USBHS_DEVEPTICR_RXOUTIC; + + //USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_RXOUTES; + } + else // IN + { + dcd_transmit_packet(xfer,epnum); + } + return true; +} + +// Stall endpoint +void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr) +{ + (void) rhport; + uint8_t const epnum = tu_edpt_number(ep_addr); + USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_STALLRQS; +} + +// clear stall, data toggle is also reset to DATA0 +void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) +{ + (void) rhport; + uint8_t const epnum = tu_edpt_number(ep_addr); + USBHS->USBHS_DEVEPTIDR[epnum] = USBHS_DEVEPTIDR_STALLRQC; + USBHS->USBHS_DEVEPTIER[epnum] = USBHS_HSTPIPIER_RSTDTS; +} + +#endif From e7bee80948bdb5132e815eaaf957b75f691cfaa3 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Wed, 3 Mar 2021 19:33:36 +0100 Subject: [PATCH 02/36] Add OPT_MCU_SAME70 option value. --- src/tusb_option.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tusb_option.h b/src/tusb_option.h index 5cfcc08e..fb86d7f9 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -61,6 +61,7 @@ #define OPT_MCU_SAME5X 203 ///< MicroChip SAM E5x #define OPT_MCU_SAMD11 204 ///< MicroChip SAMD11 #define OPT_MCU_SAML22 205 ///< MicroChip SAML22 +#define OPT_MCU_SAME70 206 ///< MicroChip SAME70 series // STM32 #define OPT_MCU_STM32F0 300 ///< ST STM32F0 From 4f4a33b3784729ff4d7bc91224350291d2367ea3 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Wed, 3 Mar 2021 19:34:53 +0100 Subject: [PATCH 03/36] Seems like fixed ep0 issues, code format. Signed-off-by: HiFiPhile --- src/portable/microchip/same70/dcd_same70.c | 747 ++++++++++----------- 1 file changed, 349 insertions(+), 398 deletions(-) diff --git a/src/portable/microchip/same70/dcd_same70.c b/src/portable/microchip/same70/dcd_same70.c index 7fdc9dd0..98fe6136 100644 --- a/src/portable/microchip/same70/dcd_same70.c +++ b/src/portable/microchip/same70/dcd_same70.c @@ -2,7 +2,7 @@ * The MIT License (MIT) * * Copyright (c) 2018, hathach (tinyusb.org) -* Copyright (c) 2020, HiFiPhile +* Copyright (c) 2021, HiFiPhile * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -35,7 +35,6 @@ #include "sam.h" -#include "SEGGER_RTT.h" //--------------------------------------------------------------------+ // MACRO TYPEDEF CONSTANT ENUM DECLARATION //--------------------------------------------------------------------+ @@ -50,7 +49,7 @@ # define USBHS_RAM_ADDR 0xA0100000u #endif -#define get_ep_fifo_ptr(ep, scale) (((volatile TU_XSTRCAT(TU_STRCAT(uint, scale),_t) (*)[0x8000 / ((scale) / 8)])USBHS_RAM_ADDR)[(ep)]) +#define get_ep_fifo_ptr(ep, scale) (((TU_XSTRCAT(TU_STRCAT(uint, scale),_t) (*)[0x8000 / ((scale) / 8)])USBHS_RAM_ADDR)[(ep)]) #define EP_MAX 10 @@ -66,13 +65,8 @@ xfer_ctl_t xfer_status[EP_MAX+1]; static const tusb_desc_endpoint_t ep0_desc = { - .bLength = sizeof(tusb_desc_endpoint_t), - .bDescriptorType = TUSB_DESC_ENDPOINT, - .bEndpointAddress = 0x00, - .bmAttributes = { .xfer = TUSB_XFER_CONTROL }, .wMaxPacketSize = { .size = CFG_TUD_ENDPOINT0_SIZE }, - .bInterval = 0 }; static tusb_speed_t get_speed(void); @@ -84,481 +78,438 @@ static void dcd_transmit_packet(xfer_ctl_t * xfer, uint8_t ep_ix); // Initialize controller to device mode void dcd_init (uint8_t rhport) { - // Enable USBPLL - PMC->CKGR_UCKR = CKGR_UCKR_UPLLEN | CKGR_UCKR_UPLLCOUNT(0x3fU); - // Wait until USB UTMI stabilize - while (!(PMC->PMC_SR & PMC_SR_LOCKU)); - // Enable USB FS clk - PMC->PMC_USB = PMC_USB_USBS | PMC_USB_USBDIV(10 - 1); - PMC->PMC_SCER = PMC_SCER_USBCLK; - dcd_connect(rhport); + // Enable USBPLL + PMC->CKGR_UCKR = CKGR_UCKR_UPLLEN | CKGR_UCKR_UPLLCOUNT(0x3fU); + // Wait until USB UTMI stabilize + while (!(PMC->PMC_SR & PMC_SR_LOCKU)); + // Enable USB FS clk + PMC->PMC_USB = PMC_USB_USBS | PMC_USB_USBDIV(10 - 1); + PMC->PMC_SCER = PMC_SCER_USBCLK; + dcd_connect(rhport); } // Enable device interrupt void dcd_int_enable (uint8_t rhport) { - (void) rhport; - NVIC_EnableIRQ((IRQn_Type) ID_USBHS); + (void) rhport; + NVIC_EnableIRQ((IRQn_Type) ID_USBHS); } // Disable device interrupt void dcd_int_disable (uint8_t rhport) { - (void) rhport; - NVIC_DisableIRQ((IRQn_Type) ID_USBHS); + (void) rhport; + NVIC_DisableIRQ((IRQn_Type) ID_USBHS); } // Receive Set Address request, mcu port must also include status IN response void dcd_set_address (uint8_t rhport, uint8_t dev_addr) { - (void) rhport; - // Set the address but keep it disabled for now. It should be enabled - // only after the ack to the host completes. - USBHS->USBHS_DEVCTRL &= ~(USBHS_DEVCTRL_UADD_Msk | USBHS_DEVCTRL_ADDEN); - USBHS->USBHS_DEVCTRL |= USBHS_DEVCTRL_UADD(dev_addr); - - // Respond with status - dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0); + // DCD can only set address after status for this request is complete + // do it at dcd_edpt0_status_complete() + + // Response with zlp status + dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0); } // Wake up host void dcd_remote_wakeup (uint8_t rhport) { - (void) rhport; - USBHS->USBHS_DEVCTRL |= USBHS_DEVCTRL_RMWKUP; + (void) rhport; + USBHS->USBHS_DEVCTRL |= USBHS_DEVCTRL_RMWKUP; } // Connect by enabling internal pull-up resistor on D+/D- void dcd_connect(uint8_t rhport) { - uint32_t irq_state = __get_PRIMASK(); - __disable_irq(); - // Enable USB clock - PMC->PMC_PCER1 = 1 << (ID_USBHS - 32); - // Enable the USB controller in device mode - USBHS->USBHS_CTRL = USBHS_CTRL_UIMOD | USBHS_CTRL_USBE; - // Wait to unfreeze clock - while(USBHS_SR_CLKUSABLE != (USBHS->USBHS_SR & USBHS_SR_CLKUSABLE)); - // Attach the device - USBHS->USBHS_DEVCTRL &= ~USBHS_DEVCTRL_DETACH; - // Enable the End Of Reset, Suspend & Wakeup interrupts - USBHS->USBHS_DEVIER = (USBHS_DEVIER_EORSTES | USBHS_DEVIER_SUSPES | USBHS_DEVIER_WAKEUPES); + uint32_t irq_state = __get_PRIMASK(); + __disable_irq(); + // Enable USB clock + PMC->PMC_PCER1 = 1 << (ID_USBHS - 32); + // Enable the USB controller in device mode + USBHS->USBHS_CTRL = USBHS_CTRL_UIMOD | USBHS_CTRL_USBE; + // Wait to unfreeze clock + while(USBHS_SR_CLKUSABLE != (USBHS->USBHS_SR & USBHS_SR_CLKUSABLE)); + // Attach the device + USBHS->USBHS_DEVCTRL &= ~USBHS_DEVCTRL_DETACH; + // Enable the End Of Reset, Suspend & Wakeup interrupts + USBHS->USBHS_DEVIER = (USBHS_DEVIER_EORSTES | USBHS_DEVIER_SUSPES | USBHS_DEVIER_WAKEUPES); #if USE_SOF - USBHS->USBHS_DEVIER = USBHS_DEVIER_SOFES; + USBHS->USBHS_DEVIER = USBHS_DEVIER_SOFES; #endif - // Clear the End Of Reset, SOF & Wakeup interrupts - USBHS->USBHS_DEVICR = (USBHS_DEVICR_EORSTC | USBHS_DEVICR_SOFC | USBHS_DEVICR_WAKEUPC); - // Manually set the Suspend Interrupt - USBHS->USBHS_DEVIFR |= USBHS_DEVIFR_SUSPS; - // Ack the Wakeup Interrupt - USBHS->USBHS_DEVICR = USBHS_DEVICR_WAKEUPC; - // Freeze USB clock - USBHS->USBHS_CTRL |= USBHS_CTRL_FRZCLK; - __set_PRIMASK(irq_state); + // Clear the End Of Reset, SOF & Wakeup interrupts + USBHS->USBHS_DEVICR = (USBHS_DEVICR_EORSTC | USBHS_DEVICR_SOFC | USBHS_DEVICR_WAKEUPC); + // Manually set the Suspend Interrupt + USBHS->USBHS_DEVIFR |= USBHS_DEVIFR_SUSPS; + // Ack the Wakeup Interrupt + USBHS->USBHS_DEVICR = USBHS_DEVICR_WAKEUPC; + // Freeze USB clock + USBHS->USBHS_CTRL |= USBHS_CTRL_FRZCLK; + __set_PRIMASK(irq_state); } // Disconnect by disabling internal pull-up resistor on D+/D- void dcd_disconnect(uint8_t rhport) { - (void) rhport; - uint32_t irq_state = __get_PRIMASK(); - __disable_irq(); - // Disable all endpoints - USBHS->USBHS_DEVEPT &= ~(0x3FF << USBHS_DEVEPT_EPEN0_Pos); - // Unfreeze USB clock - USBHS->USBHS_CTRL &= ~USBHS_CTRL_FRZCLK; - // Wait to unfreeze clock - while(USBHS_SR_CLKUSABLE != (USBHS->USBHS_SR & USBHS_SR_CLKUSABLE)); - // Clear all the pending interrupts - USBHS->USBHS_DEVICR = USBHS_DEVICR_Msk; - // Disable all interrupts - USBHS->USBHS_DEVIDR = USBHS_DEVCTRL_UADD_Msk; - // Detach the device - USBHS->USBHS_DEVCTRL |= USBHS_DEVCTRL_DETACH; - // Disable the device address - USBHS->USBHS_DEVCTRL &=~(USBHS_DEVCTRL_ADDEN | USBHS_DEVCTRL_UADD_Msk); - __set_PRIMASK(irq_state); + (void) rhport; + uint32_t irq_state = __get_PRIMASK(); + __disable_irq(); + // Disable all endpoints + USBHS->USBHS_DEVEPT &= ~(0x3FF << USBHS_DEVEPT_EPEN0_Pos); + // Unfreeze USB clock + USBHS->USBHS_CTRL &= ~USBHS_CTRL_FRZCLK; + // Wait to unfreeze clock + while (USBHS_SR_CLKUSABLE != (USBHS->USBHS_SR & USBHS_SR_CLKUSABLE)); + // Clear all the pending interrupts + USBHS->USBHS_DEVICR = USBHS_DEVICR_Msk; + // Disable all interrupts + USBHS->USBHS_DEVIDR = USBHS_DEVCTRL_UADD_Msk; + // Detach the device + USBHS->USBHS_DEVCTRL |= USBHS_DEVCTRL_DETACH; + // Disable the device address + USBHS->USBHS_DEVCTRL &=~(USBHS_DEVCTRL_ADDEN | USBHS_DEVCTRL_UADD_Msk); + __set_PRIMASK(irq_state); } static tusb_speed_t get_speed(void) { - switch((USBHS->USBHS_SR & USBHS_SR_SPEED_Msk) >> USBHS_SR_SPEED_Pos) - { - case USBHS_SR_SPEED_FULL_SPEED_Val: - default: - return TUSB_SPEED_FULL; - case USBHS_SR_SPEED_HIGH_SPEED_Val: - return TUSB_SPEED_HIGH; - case USBHS_SR_SPEED_LOW_SPEED_Val: - return TUSB_SPEED_LOW; + switch ((USBHS->USBHS_SR & USBHS_SR_SPEED_Msk) >> USBHS_SR_SPEED_Pos) { + case USBHS_SR_SPEED_FULL_SPEED_Val: + default: + return TUSB_SPEED_FULL; + case USBHS_SR_SPEED_HIGH_SPEED_Val: + return TUSB_SPEED_HIGH; + case USBHS_SR_SPEED_LOW_SPEED_Val: + return TUSB_SPEED_LOW; } } static void dcd_ep_handler(uint8_t ep_ix) { - uint32_t int_status = USBHS->USBHS_DEVEPTISR[ep_ix] & USBHS->USBHS_DEVEPTIMR[ep_ix]; - uint32_t dev_ctrl = USBHS->USBHS_DEVCTRL; - uint16_t count = (USBHS->USBHS_DEVEPTISR[ep_ix] & - USBHS_DEVEPTISR_BYCT_Msk) >> USBHS_DEVEPTISR_BYCT_Pos; - SEGGER_RTT_printf(0, "ep: %u %u %u \r\n", ep_ix, count, int_status); - if(ep_ix == 0U) - { - if (int_status & USBHS_DEVEPTISR_CTRL_RXSTPI) { - - // Get 8-bit access to endpoint 0 FIFO from USB RAM address - volatile uint8_t *ptr = get_ep_fifo_ptr(0,8); - SCB_InvalidateDCache_by_Addr((uint32_t *) ptr, 8); - dcd_event_setup_received(0, (uint8_t*)ptr, true); - - // Acknowledge the interrupt - USBHS->USBHS_DEVEPTICR[0] = USBHS_DEVEPTICR_RXSTPIC; - } - if (int_status & USBHS_DEVEPTISR_RXOUTI) { - // Disable the interrupt - //USBHS->USBHS_DEVEPTIDR[ep_ix] = USBHS_DEVEPTIDR_RXOUTEC; - - xfer_ctl_t *xfer = &xfer_status[0]; - - if(count) - { - volatile uint8_t *ptr = get_ep_fifo_ptr(0,8); - for (int i = 0; i < count; i++) { - xfer->buffer[xfer->queued_len + i] = ptr[i]; - } - xfer->queued_len = (uint16_t)(xfer->queued_len + count); - } - - USBHS->USBHS_DEVEPTICR[0] = USBHS_DEVEPTICR_RXOUTIC; - - if ((count < xfer->max_packet_size) || (xfer->queued_len == xfer->total_len)) - { - // RX COMPLETE - dcd_event_xfer_complete(0, 0, xfer->queued_len, XFER_RESULT_SUCCESS, true); - xfer->queued_len = 0; - SEGGER_RTT_printf(0, "rx: %u \r\n", xfer->queued_len); - // Though the host could still send, we don't know. - } - - - } - if (int_status & USBHS_DEVEPTISR_TXINI) { - // Disable the interrupt - USBHS->USBHS_DEVEPTIDR[0] = USBHS_DEVEPTIDR_TXINEC; - if (!(dev_ctrl & USBHS_DEVCTRL_ADDEN) && - (dev_ctrl & USBHS_DEVCTRL_UADD_Msk) != 0U) { - // Commit the pending address update. This - // must be done after the ack to the host - // completes else the ack will get dropped. - USBHS->USBHS_DEVCTRL = dev_ctrl | USBHS_DEVCTRL_ADDEN; - } - xfer_ctl_t * xfer = &xfer_status[EP_MAX]; - if((xfer->total_len != xfer->queued_len)) // TX not complete - { - dcd_transmit_packet(xfer, 0); - } - else // TX Complete - { - dcd_event_xfer_complete(0, (uint8_t)(0x80 + 0), xfer->total_len, XFER_RESULT_SUCCESS, true); - } - } + uint32_t int_status = USBHS->USBHS_DEVEPTISR[ep_ix]; + int_status &= USBHS->USBHS_DEVEPTIMR[ep_ix]; + uint16_t count = (USBHS->USBHS_DEVEPTISR[ep_ix] & + USBHS_DEVEPTISR_BYCT_Msk) >> USBHS_DEVEPTISR_BYCT_Pos; + if (ep_ix == 0U) { + if (int_status & USBHS_DEVEPTISR_CTRL_RXSTPI) { + // Setup packet should always be 8 bytes. If not, ignore it, and try again. + if (count == 8) + { + uint8_t *ptr = get_ep_fifo_ptr(0,8); + dcd_event_setup_received(0, ptr, true); + } + // Acknowledge the interrupt + USBHS->USBHS_DEVEPTICR[0] = USBHS_DEVEPTICR_RXSTPIC; } - else - { - if (int_status & USBHS_DEVEPTISR_RXOUTI) { - // Acknowledge the interrupt - USBHS->USBHS_DEVEPTICR[ep_ix] = USBHS_DEVEPTICR_RXOUTIC; - - xfer_ctl_t *xfer = &xfer_status[ep_ix]; - - if(count) - { - volatile uint8_t *ptr = get_ep_fifo_ptr(ep_ix,8); - for (int i = 0; i < count; i++) { - xfer->buffer[xfer->queued_len + i] = ptr[i]; - } - xfer->queued_len = (uint16_t)(xfer->queued_len + count); - } - // Clear the FIFO control flag to receive more data. - USBHS->USBHS_DEVEPTIDR[ep_ix] = USBHS_DEVEPTIDR_FIFOCONC; - if ((count < xfer->max_packet_size) || (xfer->queued_len == xfer->total_len)) - { - // RX COMPLETE - dcd_event_xfer_complete(0, ep_ix, xfer->queued_len, XFER_RESULT_SUCCESS, true); - xfer->queued_len = 0; - // Though the host could still send, we don't know. - } - } - if (int_status & USBHS_DEVEPTISR_TXINI) { - // Acknowledge the interrupt - USBHS->USBHS_DEVEPTICR[ep_ix] = USBHS_DEVEPTICR_TXINIC; - xfer_ctl_t * xfer = &xfer_status[ep_ix];; - if((xfer->total_len != xfer->queued_len)) // TX not complete - { - dcd_transmit_packet(xfer, ep_ix); - } - else // TX Complete - { - dcd_event_xfer_complete(0, (uint8_t)(0x80 + ep_ix), xfer->total_len, XFER_RESULT_SUCCESS, true); - } + if (int_status & USBHS_DEVEPTISR_RXOUTI) { + xfer_ctl_t *xfer = &xfer_status[0]; + if (count) { + uint8_t *ptr = get_ep_fifo_ptr(0,8); + for (int i = 0; i < count; i++) { + xfer->buffer[xfer->queued_len + i] = ptr[i]; } + xfer->queued_len = (uint16_t)(xfer->queued_len + count); + } + // Acknowledge the interrupt + USBHS->USBHS_DEVEPTICR[0] = USBHS_DEVEPTICR_RXOUTIC; + if ((count < xfer->max_packet_size) || (xfer->queued_len == xfer->total_len)) { + // RX COMPLETE + dcd_event_xfer_complete(0, 0, xfer->queued_len, XFER_RESULT_SUCCESS, true); + // Disable the interrupt + USBHS->USBHS_DEVEPTIDR[0] = USBHS_DEVEPTIDR_RXOUTEC; + // Though the host could still send, we don't know. + } } + if (int_status & USBHS_DEVEPTISR_TXINI) { + // Disable the interrupt + USBHS->USBHS_DEVEPTIDR[0] = USBHS_DEVEPTIDR_TXINEC; + xfer_ctl_t * xfer = &xfer_status[EP_MAX]; + if ((xfer->total_len != xfer->queued_len)) { + // TX not complete + dcd_transmit_packet(xfer, 0); + } + else { + // TX complete + dcd_event_xfer_complete(0, (uint8_t)(0x80 + 0), xfer->total_len, XFER_RESULT_SUCCESS, true); + } + } + } + else { + if (int_status & USBHS_DEVEPTISR_RXOUTI) { + xfer_ctl_t *xfer = &xfer_status[ep_ix]; + if (count) { + uint8_t *ptr = get_ep_fifo_ptr(ep_ix,8); + memcpy(xfer->buffer + xfer->queued_len, ptr, count); + xfer->queued_len = (uint16_t)(xfer->queued_len + count); + } + // Acknowledge the interrupt + USBHS->USBHS_DEVEPTICR[ep_ix] = USBHS_DEVEPTICR_RXOUTIC; + // Clear the FIFO control flag to receive more data. + USBHS->USBHS_DEVEPTIDR[ep_ix] = USBHS_DEVEPTIDR_FIFOCONC; + if ((count < xfer->max_packet_size) || (xfer->queued_len == xfer->total_len)) { + // RX COMPLETE + dcd_event_xfer_complete(0, ep_ix, xfer->queued_len, XFER_RESULT_SUCCESS, true); + // Disable the interrupt + USBHS->USBHS_DEVEPTIDR[ep_ix] = USBHS_DEVEPTIDR_RXOUTEC; + // Though the host could still send, we don't know. + } + } + if (int_status & USBHS_DEVEPTISR_TXINI) { + // Acknowledge the interrupt + USBHS->USBHS_DEVEPTICR[ep_ix] = USBHS_DEVEPTICR_TXINIC; + xfer_ctl_t * xfer = &xfer_status[ep_ix];; + if ((xfer->total_len != xfer->queued_len)) { + // TX not complete + dcd_transmit_packet(xfer, ep_ix); + } + else { + // TX complete + dcd_event_xfer_complete(0, (uint8_t)(0x80 + ep_ix), xfer->total_len, XFER_RESULT_SUCCESS, true); + } + } + } } void dcd_int_handler(uint8_t rhport) { - (void) rhport; - uint32_t int_status = USBHS->USBHS_DEVISR; - // End of reset interrupt - if (int_status & USBHS_DEVISR_EORST) { - // Unfreeze USB clock - USBHS->USBHS_CTRL &= ~USBHS_CTRL_FRZCLK; - while(USBHS_SR_CLKUSABLE != (USBHS->USBHS_SR & USBHS_SR_CLKUSABLE)); - // Reset all endpoints - for (int ep_ix = 1; ep_ix < EP_MAX; ep_ix++) - { - // Disable endpoint interrupt - USBHS->USBHS_DEVIDR = 1 << (USBHS_DEVIDR_PEP_0_Pos + ep_ix); - // Disable endpoint and SETUP, IN or OUT interrupts - USBHS->USBHS_DEVEPT &= ~ (1 << (USBHS_DEVEPT_EPEN0_Pos + ep_ix)); - // Free all endpoint memory - USBHS->USBHS_DEVEPTCFG[ep_ix] &= ~USBHS_DEVEPTCFG_ALLOC; - } - dcd_edpt_open (0, &ep0_desc); - // Acknowledge the End of Reset interrupt - USBHS->USBHS_DEVICR = USBHS_DEVICR_EORSTC; - // Acknowledge the Wakeup interrupt - USBHS->USBHS_DEVICR = USBHS_DEVICR_WAKEUPC; - // Acknowledge the suspend interrupt - USBHS->USBHS_DEVICR = USBHS_DEVICR_SUSPC; - // Enable Suspend Interrupt - USBHS->USBHS_DEVIER = USBHS_DEVIER_SUSPES; - - dcd_event_bus_reset(rhport, get_speed(), true); - } - // End of Wakeup interrupt - if (int_status & USBHS_DEVISR_WAKEUP) { - // Unfreeze USB clock - USBHS->USBHS_CTRL &= ~USBHS_CTRL_FRZCLK; - // Wait to unfreeze clock - while(USBHS_SR_CLKUSABLE != (USBHS->USBHS_SR & USBHS_SR_CLKUSABLE)); - // Acknowledge the Wakeup interrupt - USBHS->USBHS_DEVICR = USBHS_DEVICR_WAKEUPC; - // Disable Wakeup Interrupt - USBHS->USBHS_DEVIDR = USBHS_DEVIDR_WAKEUPEC; - // Enable Suspend Interrupt - USBHS->USBHS_DEVIER = USBHS_DEVIER_SUSPES; - - dcd_event_bus_signal(0, DCD_EVENT_RESUME, true); - } - // Suspend interrupt - if (int_status & USBHS_DEVISR_SUSP) { - // Unfreeze USB clock - USBHS->USBHS_CTRL &= ~USBHS_CTRL_FRZCLK; - // Wait to unfreeze clock - while(USBHS_SR_CLKUSABLE != (USBHS->USBHS_SR & USBHS_SR_CLKUSABLE)); - // Acknowledge the suspend interrupt - USBHS->USBHS_DEVICR = USBHS_DEVICR_SUSPC; - // Disable Suspend Interrupt - USBHS->USBHS_DEVIDR = USBHS_DEVIDR_SUSPEC; - // Enable Wakeup Interrupt - USBHS->USBHS_DEVIER = USBHS_DEVIER_WAKEUPES; - // Freeze USB clock - USBHS->USBHS_CTRL |= USBHS_CTRL_FRZCLK; - - dcd_event_bus_signal(0, DCD_EVENT_SUSPEND, true); + (void) rhport; + uint32_t int_status = USBHS->USBHS_DEVISR; + // End of reset interrupt + if (int_status & USBHS_DEVISR_EORST) { + // Unfreeze USB clock + USBHS->USBHS_CTRL &= ~USBHS_CTRL_FRZCLK; + while(USBHS_SR_CLKUSABLE != (USBHS->USBHS_SR & USBHS_SR_CLKUSABLE)); + // Reset all endpoints + for (int ep_ix = 1; ep_ix < EP_MAX; ep_ix++) { + USBHS->USBHS_DEVEPT |= 1 << (USBHS_DEVEPT_EPRST0_Pos + ep_ix); + USBHS->USBHS_DEVEPT &=~(1 << (USBHS_DEVEPT_EPRST0_Pos + ep_ix)); } + dcd_edpt_open (0, &ep0_desc); + // Acknowledge the End of Reset interrupt + USBHS->USBHS_DEVICR = USBHS_DEVICR_EORSTC; + // Acknowledge the Wakeup interrupt + USBHS->USBHS_DEVICR = USBHS_DEVICR_WAKEUPC; + // Acknowledge the suspend interrupt + USBHS->USBHS_DEVICR = USBHS_DEVICR_SUSPC; + // Enable Suspend Interrupt + USBHS->USBHS_DEVIER = USBHS_DEVIER_SUSPES; + + dcd_event_bus_reset(rhport, get_speed(), true); + } + // End of Wakeup interrupt + if (int_status & USBHS_DEVISR_WAKEUP) { + // Unfreeze USB clock + USBHS->USBHS_CTRL &= ~USBHS_CTRL_FRZCLK; + // Wait to unfreeze clock + while (USBHS_SR_CLKUSABLE != (USBHS->USBHS_SR & USBHS_SR_CLKUSABLE)); + // Acknowledge the Wakeup interrupt + USBHS->USBHS_DEVICR = USBHS_DEVICR_WAKEUPC; + // Disable Wakeup Interrupt + USBHS->USBHS_DEVIDR = USBHS_DEVIDR_WAKEUPEC; + // Enable Suspend Interrupt + USBHS->USBHS_DEVIER = USBHS_DEVIER_SUSPES; + + dcd_event_bus_signal(0, DCD_EVENT_RESUME, true); + } + // Suspend interrupt + if (int_status & USBHS_DEVISR_SUSP) { + // Unfreeze USB clock + USBHS->USBHS_CTRL &= ~USBHS_CTRL_FRZCLK; + // Wait to unfreeze clock + while (USBHS_SR_CLKUSABLE != (USBHS->USBHS_SR & USBHS_SR_CLKUSABLE)); + // Acknowledge the suspend interrupt + USBHS->USBHS_DEVICR = USBHS_DEVICR_SUSPC; + // Disable Suspend Interrupt + USBHS->USBHS_DEVIDR = USBHS_DEVIDR_SUSPEC; + // Enable Wakeup Interrupt + USBHS->USBHS_DEVIER = USBHS_DEVIER_WAKEUPES; + // Freeze USB clock + USBHS->USBHS_CTRL |= USBHS_CTRL_FRZCLK; + + dcd_event_bus_signal(0, DCD_EVENT_SUSPEND, true); + } #if USE_SOF - if(int_status & USBHS_DEVISR_SOF) { - USBHS->USBHS_DEVICR = USBHS_DEVICR_SOFC; - - dcd_event_bus_signal(0, DCD_EVENT_SOF, true); - } + if(int_status & USBHS_DEVISR_SOF) { + USBHS->USBHS_DEVICR = USBHS_DEVICR_SOFC; + + dcd_event_bus_signal(0, DCD_EVENT_SOF, true); + } #endif - // Endpoints interrupt - for (int ep_ix = 0; ep_ix < EP_MAX; ep_ix++) { - if (int_status & (1 << (USBHS_DEVISR_PEP_0_Pos + ep_ix))) { - dcd_ep_handler(ep_ix); - } + // Endpoints interrupt + for (int ep_ix = 0; ep_ix < EP_MAX; ep_ix++) { + if (int_status & (1 << (USBHS_DEVISR_PEP_0_Pos + ep_ix))) { + dcd_ep_handler(ep_ix); } + } } //--------------------------------------------------------------------+ // Endpoint API //--------------------------------------------------------------------+ +// Invoked when a control transfer's status stage is complete. +// May help DCD to prepare for next control transfer, this API is optional. +void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * request) +{ + (void) rhport; + + if (request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_DEVICE && + request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD && + request->bRequest == TUSB_REQ_SET_ADDRESS ) + { + uint8_t const dev_addr = (uint8_t) request->wValue; + + USBHS->USBHS_DEVCTRL |= dev_addr | USBHS_DEVCTRL_ADDEN; + } +} // Configure endpoint's registers according to descriptor bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) { - (void) rhport; - uint8_t const epnum = tu_edpt_number(ep_desc->bEndpointAddress); - uint8_t const dir = tu_edpt_dir(ep_desc->bEndpointAddress); - uint16_t const epMaxPktSize = ep_desc->wMaxPacketSize.size; - tusb_xfer_type_t const eptype = (tusb_xfer_type_t)ep_desc->bmAttributes.xfer; - uint8_t fifoSize = 0; // FIFO size - uint16_t defaultEndpointSize = 8; // Default size of Endpoint - // Find upper 2 power number of epMaxPktSize - if(epMaxPktSize) - { - while (defaultEndpointSize < epMaxPktSize) - { - fifoSize++; - defaultEndpointSize <<= 1; - } + (void) rhport; + uint8_t const epnum = tu_edpt_number(ep_desc->bEndpointAddress); + uint8_t const dir = tu_edpt_dir(ep_desc->bEndpointAddress); + uint16_t const epMaxPktSize = ep_desc->wMaxPacketSize.size; + tusb_xfer_type_t const eptype = (tusb_xfer_type_t)ep_desc->bmAttributes.xfer; + uint8_t fifoSize = 0; // FIFO size + uint16_t defaultEndpointSize = 8; // Default size of Endpoint + // Find upper 2 power number of epMaxPktSize + if (epMaxPktSize) { + while (defaultEndpointSize < epMaxPktSize) { + fifoSize++; + defaultEndpointSize <<= 1; } - xfer_status[epnum].max_packet_size = epMaxPktSize; + } + xfer_status[epnum].max_packet_size = epMaxPktSize; + + USBHS->USBHS_DEVEPT |= 1 << (USBHS_DEVEPT_EPRST0_Pos + epnum); + USBHS->USBHS_DEVEPT &=~(1 << (USBHS_DEVEPT_EPRST0_Pos + epnum)); - if(epnum == 0) - { - xfer_status[EP_MAX].max_packet_size = epMaxPktSize; - // Enable the control endpoint - Endpoint 0 - USBHS->USBHS_DEVEPT |= USBHS_DEVEPT_EPEN0; - // Configure the Endpoint 0 configuration register - USBHS->USBHS_DEVEPTCFG[0] = - ( - USBHS_DEVEPTCFG_EPSIZE(fifoSize) | - USBHS_DEVEPTCFG_EPTYPE(TUSB_XFER_CONTROL) | - USBHS_DEVEPTCFG_EPBK(USBHS_DEVEPTCFG_EPBK_1_BANK) | - USBHS_DEVEPTCFG_ALLOC - ); - USBHS->USBHS_DEVEPTIER[0] = USBHS_DEVEPTIER_RSTDTS; - USBHS->USBHS_DEVEPTIDR[0] = USBHS_DEVEPTIDR_STALLRQC; - if(USBHS_DEVEPTISR_CFGOK == (USBHS->USBHS_DEVEPTISR[0] & USBHS_DEVEPTISR_CFGOK)) - { - // Endpoint configuration is successful - USBHS->USBHS_DEVEPTIER[0] = USBHS_DEVEPTIER_RXSTPES | USBHS_DEVEPTIER_RXOUTES; - // Enable Endpoint 0 Interrupts - USBHS->USBHS_DEVIER = USBHS_DEVIER_PEP_0; - return true; - } - else - { - // Endpoint configuration is not successful - return false; - } + if (epnum == 0) { + xfer_status[EP_MAX].max_packet_size = epMaxPktSize; + // Enable the control endpoint - Endpoint 0 + USBHS->USBHS_DEVEPT |= USBHS_DEVEPT_EPEN0; + // Configure the Endpoint 0 configuration register + USBHS->USBHS_DEVEPTCFG[0] = + ( + USBHS_DEVEPTCFG_EPSIZE(fifoSize) | + USBHS_DEVEPTCFG_EPTYPE(TUSB_XFER_CONTROL) | + USBHS_DEVEPTCFG_EPBK(USBHS_DEVEPTCFG_EPBK_1_BANK) | + USBHS_DEVEPTCFG_ALLOC + ); + USBHS->USBHS_DEVEPTIER[0] = USBHS_DEVEPTIER_RSTDTS; + USBHS->USBHS_DEVEPTIDR[0] = USBHS_DEVEPTIDR_STALLRQC; + if (USBHS_DEVEPTISR_CFGOK == (USBHS->USBHS_DEVEPTISR[0] & USBHS_DEVEPTISR_CFGOK)) { + // Endpoint configuration is successful + USBHS->USBHS_DEVEPTIER[0] = USBHS_DEVEPTIER_RXSTPES; + // Enable Endpoint 0 Interrupts + USBHS->USBHS_DEVIER = USBHS_DEVIER_PEP_0; + return true; } - else - { - // Enable the endpoint - USBHS->USBHS_DEVEPT |= ((0x01 << epnum) << USBHS_DEVEPT_EPEN0_Pos); - // Set up the maxpacket size, fifo start address fifosize - // and enable the interrupt. CLear the data toggle. - USBHS->USBHS_DEVEPTCFG[epnum] = - ( - USBHS_DEVEPTCFG_EPSIZE(fifoSize) | - USBHS_DEVEPTCFG_EPTYPE(eptype) | - USBHS_DEVEPTCFG_EPBK(USBHS_DEVEPTCFG_EPBK_1_BANK) | - USBHS_DEVEPTCFG_ALLOC | - ((dir & 0x01) << USBHS_DEVEPTCFG_EPDIR_Pos) - ); - - if (eptype == TUSB_XFER_ISOCHRONOUS) - { - USBHS->USBHS_DEVEPTCFG[epnum] |= USBHS_DEVEPTCFG_NBTRANS(1); - } - USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_RSTDTS; - USBHS->USBHS_DEVEPTIDR[epnum] = USBHS_DEVEPTIDR_STALLRQC; - if(USBHS_DEVEPTISR_CFGOK == (USBHS->USBHS_DEVEPTISR[epnum] & USBHS_DEVEPTISR_CFGOK)) - { - // Endpoint configuration is successful. Enable Endpoint Interrupts - if(dir == TUSB_DIR_OUT) - { - USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_RXOUTES; - } - else - { - USBHS->USBHS_DEVEPTICR[epnum] = USBHS_DEVEPTICR_TXINIC; + else { + // Endpoint configuration is not successful + return false; + } + } + else { + // Enable the endpoint + USBHS->USBHS_DEVEPT |= ((0x01 << epnum) << USBHS_DEVEPT_EPEN0_Pos); + // Set up the maxpacket size, fifo start address fifosize + // and enable the interrupt. CLear the data toggle. + USBHS->USBHS_DEVEPTCFG[epnum] = + ( + USBHS_DEVEPTCFG_EPSIZE(fifoSize) | + USBHS_DEVEPTCFG_EPTYPE(eptype) | + USBHS_DEVEPTCFG_EPBK(USBHS_DEVEPTCFG_EPBK_1_BANK) | + ((dir & 0x01) << USBHS_DEVEPTCFG_EPDIR_Pos) + ); + + if (eptype == TUSB_XFER_ISOCHRONOUS){ + USBHS->USBHS_DEVEPTCFG[epnum] |= USBHS_DEVEPTCFG_NBTRANS(1) | USBHS_DEVEPTCFG_EPBK_2_BANK; + } + USBHS->USBHS_DEVEPTCFG[epnum] |= USBHS_DEVEPTCFG_ALLOC; + USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_RSTDTS; + USBHS->USBHS_DEVEPTIDR[epnum] = USBHS_DEVEPTIDR_STALLRQC; + if (USBHS_DEVEPTISR_CFGOK == (USBHS->USBHS_DEVEPTISR[epnum] & USBHS_DEVEPTISR_CFGOK)) { + // Endpoint configuration is successful. Enable Endpoint Interrupts + if (dir == TUSB_DIR_IN) { + USBHS->USBHS_DEVEPTICR[epnum] = USBHS_DEVEPTICR_TXINIC; USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_TXINES; - } - USBHS->USBHS_DEVIER = ((0x01 << epnum) << USBHS_DEVIER_PEP_0_Pos); - return true; - } - else - { - // Endpoint configuration is not successful - return false; - } + } + USBHS->USBHS_DEVIER = ((0x01 << epnum) << USBHS_DEVIER_PEP_0_Pos); + return true; } + else { + // Endpoint configuration is not successful + return false; + } + } } static void dcd_transmit_packet(xfer_ctl_t * xfer, uint8_t ep_ix) { - uint16_t len = (uint16_t)(xfer->total_len - xfer->queued_len); - - if(len > xfer->max_packet_size) // max packet size for FS transfer - { - len = xfer->max_packet_size; - } - - volatile uint8_t *ptr = get_ep_fifo_ptr(ep_ix,8); - for (int i = 0; i < len; i++) { - ptr[i] = xfer->buffer[xfer->queued_len + i]; - } - - xfer->queued_len = (uint16_t)(xfer->queued_len + len); - - if (ep_ix == 0U) { - - // Control endpoint: clear the interrupt flag to send the data, - // and re-enable the interrupts to trigger an interrupt at the - // end of the transfer. - USBHS->USBHS_DEVEPTICR[0] = USBHS_DEVEPTICR_TXINIC; - USBHS->USBHS_DEVEPTIER[0] = USBHS_DEVEPTIER_TXINES; - } else { - - // Other endpoint types: clear the FIFO control flag to send the data. - USBHS->USBHS_DEVEPTIDR[ep_ix] = USBHS_DEVEPTIDR_FIFOCONC; - } + uint16_t len = (uint16_t)(xfer->total_len - xfer->queued_len); + + if (len > xfer->max_packet_size) { + len = xfer->max_packet_size; + } + + uint8_t *ptr = get_ep_fifo_ptr(ep_ix,8); + memcpy(ptr, xfer->buffer + xfer->queued_len, len); + + xfer->queued_len = (uint16_t)(xfer->queued_len + len); + + if (ep_ix == 0U) { + // Control endpoint: clear the interrupt flag to send the data, + // and re-enable the interrupts to trigger an interrupt at the + // end of the transfer. + USBHS->USBHS_DEVEPTICR[0] = USBHS_DEVEPTICR_TXINIC; + USBHS->USBHS_DEVEPTIER[0] = USBHS_DEVEPTIER_TXINES; + } else { + // Other endpoint types: clear the FIFO control flag to send the data. + USBHS->USBHS_DEVEPTIDR[ep_ix] = USBHS_DEVEPTIDR_FIFOCONC; + } } - // Submit a transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) { - (void) rhport; - - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - - xfer_ctl_t * xfer = &xfer_status[epnum]; - if(ep_addr == 0x80) - xfer = &xfer_status[EP_MAX]; - - xfer->buffer = buffer; - xfer->total_len = total_bytes; - xfer->queued_len = 0; - - SEGGER_RTT_printf(0, "xfer: %u %u %u \r\n", epnum, dir, total_bytes); - - if ( dir == TUSB_DIR_OUT ) - { - // Endpoint configuration is successful - // Acknowledge the interrupt - //USBHS->USBHS_DEVEPTICR[epnum] = USBHS_DEVEPTICR_RXOUTIC; - - //USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_RXOUTES; - } - else // IN - { - dcd_transmit_packet(xfer,epnum); - } - return true; + (void) rhport; + + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + xfer_ctl_t * xfer = &xfer_status[epnum]; + if(ep_addr == 0x80) + xfer = &xfer_status[EP_MAX]; + + xfer->buffer = buffer; + xfer->total_len = total_bytes; + xfer->queued_len = 0; + + if (dir == TUSB_DIR_OUT){ + USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_RXOUTES; + } + else { + dcd_transmit_packet(xfer,epnum); + } + return true; } // Stall endpoint void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr) { - (void) rhport; - uint8_t const epnum = tu_edpt_number(ep_addr); - USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_STALLRQS; + (void) rhport; + uint8_t const epnum = tu_edpt_number(ep_addr); + USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_STALLRQS; } // clear stall, data toggle is also reset to DATA0 void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) { - (void) rhport; - uint8_t const epnum = tu_edpt_number(ep_addr); - USBHS->USBHS_DEVEPTIDR[epnum] = USBHS_DEVEPTIDR_STALLRQC; - USBHS->USBHS_DEVEPTIER[epnum] = USBHS_HSTPIPIER_RSTDTS; + (void) rhport; + uint8_t const epnum = tu_edpt_number(ep_addr); + USBHS->USBHS_DEVEPTIDR[epnum] = USBHS_DEVEPTIDR_STALLRQC; + USBHS->USBHS_DEVEPTIER[epnum] = USBHS_HSTPIPIER_RSTDTS; } #endif From 1dafcd1132deb10c824a0587b333e646b102e8aa Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Fri, 5 Mar 2021 17:15:02 +0100 Subject: [PATCH 04/36] - Add Full Speed switch - Add DMA support - Add Dual bank support Signed-off-by: HiFiPhile --- src/portable/microchip/same70/dcd_same70.c | 145 ++++++++++++++++----- 1 file changed, 111 insertions(+), 34 deletions(-) diff --git a/src/portable/microchip/same70/dcd_same70.c b/src/portable/microchip/same70/dcd_same70.c index 98fe6136..89ef6366 100644 --- a/src/portable/microchip/same70/dcd_same70.c +++ b/src/portable/microchip/same70/dcd_same70.c @@ -34,7 +34,6 @@ #include "device/dcd.h" #include "sam.h" - //--------------------------------------------------------------------+ // MACRO TYPEDEF CONSTANT ENUM DECLARATION //--------------------------------------------------------------------+ @@ -42,17 +41,29 @@ // Since TinyUSB doesn't use SOF for now, and this interrupt too often (1ms interval) // We disable SOF for now until needed later on #ifndef USE_SOF -# define USE_SOF 0 +# define USE_SOF 0 #endif -#ifndef USBHS_RAM_ADDR -# define USBHS_RAM_ADDR 0xA0100000u +// Dual bank can imporve performance, but need 2 times bigger packet buffer +// As SAME70 has only 4KB packet buffer, use with caution ! +// Enable in FS mode as packets are smaller +#ifndef USE_DUAL_BANK +# if TUD_OPT_HIGH_SPEED +# define USE_DUAL_BANK 0 +# else +# define USE_DUAL_BANK 1 +# endif #endif -#define get_ep_fifo_ptr(ep, scale) (((TU_XSTRCAT(TU_STRCAT(uint, scale),_t) (*)[0x8000 / ((scale) / 8)])USBHS_RAM_ADDR)[(ep)]) - #define EP_MAX 10 +#define USBHS_RAM_ADDR 0xA0100000u + +#define EP_GET_FIFO_PTR(ep, scale) (((TU_XSTRCAT(TU_STRCAT(uint, scale),_t) (*)[0x8000 / ((scale) / 8)])USBHS_RAM_ADDR)[(ep)]) + +// Errata: The DMA feature is not available for Pipe/Endpoint 7 +#define EP_DMA_SUPPORT(epnum) (epnum >= 1 && epnum <= 6) + typedef struct { uint8_t * buffer; uint16_t total_len; @@ -82,9 +93,12 @@ void dcd_init (uint8_t rhport) PMC->CKGR_UCKR = CKGR_UCKR_UPLLEN | CKGR_UCKR_UPLLCOUNT(0x3fU); // Wait until USB UTMI stabilize while (!(PMC->PMC_SR & PMC_SR_LOCKU)); +#if !TUD_OPT_HIGH_SPEED // Enable USB FS clk + PMC->PMC_MCKR &= ~PMC_MCKR_UPLLDIV2; PMC->PMC_USB = PMC_USB_USBS | PMC_USB_USBDIV(10 - 1); PMC->PMC_SCER = PMC_SCER_USBCLK; +#endif dcd_connect(rhport); } @@ -128,10 +142,12 @@ void dcd_connect(uint8_t rhport) PMC->PMC_PCER1 = 1 << (ID_USBHS - 32); // Enable the USB controller in device mode USBHS->USBHS_CTRL = USBHS_CTRL_UIMOD | USBHS_CTRL_USBE; - // Wait to unfreeze clock - while(USBHS_SR_CLKUSABLE != (USBHS->USBHS_SR & USBHS_SR_CLKUSABLE)); - // Attach the device - USBHS->USBHS_DEVCTRL &= ~USBHS_DEVCTRL_DETACH; + while (USBHS_SR_CLKUSABLE != (USBHS->USBHS_SR & USBHS_SR_CLKUSABLE)); +#if TUD_OPT_HIGH_SPEED + USBHS->USBHS_DEVCTRL &= ~USBHS_DEVCTRL_SPDCONF_Msk; +#else + USBHS->USBHS_DEVCTRL |= USBHS_DEVCTRL_SPDCONF_LOW_POWER; +#endif // Enable the End Of Reset, Suspend & Wakeup interrupts USBHS->USBHS_DEVIER = (USBHS_DEVIER_EORSTES | USBHS_DEVIER_SUSPES | USBHS_DEVIER_WAKEUPES); #if USE_SOF @@ -143,6 +159,8 @@ void dcd_connect(uint8_t rhport) USBHS->USBHS_DEVIFR |= USBHS_DEVIFR_SUSPS; // Ack the Wakeup Interrupt USBHS->USBHS_DEVICR = USBHS_DEVICR_WAKEUPC; + // Attach the device + USBHS->USBHS_DEVCTRL &= ~USBHS_DEVCTRL_DETACH; // Freeze USB clock USBHS->USBHS_CTRL |= USBHS_CTRL_FRZCLK; __set_PRIMASK(irq_state); @@ -158,7 +176,6 @@ void dcd_disconnect(uint8_t rhport) USBHS->USBHS_DEVEPT &= ~(0x3FF << USBHS_DEVEPT_EPEN0_Pos); // Unfreeze USB clock USBHS->USBHS_CTRL &= ~USBHS_CTRL_FRZCLK; - // Wait to unfreeze clock while (USBHS_SR_CLKUSABLE != (USBHS->USBHS_SR & USBHS_SR_CLKUSABLE)); // Clear all the pending interrupts USBHS->USBHS_DEVICR = USBHS_DEVICR_Msk; @@ -195,7 +212,7 @@ static void dcd_ep_handler(uint8_t ep_ix) // Setup packet should always be 8 bytes. If not, ignore it, and try again. if (count == 8) { - uint8_t *ptr = get_ep_fifo_ptr(0,8); + uint8_t *ptr = EP_GET_FIFO_PTR(0,8); dcd_event_setup_received(0, ptr, true); } // Acknowledge the interrupt @@ -204,7 +221,7 @@ static void dcd_ep_handler(uint8_t ep_ix) if (int_status & USBHS_DEVEPTISR_RXOUTI) { xfer_ctl_t *xfer = &xfer_status[0]; if (count) { - uint8_t *ptr = get_ep_fifo_ptr(0,8); + uint8_t *ptr = EP_GET_FIFO_PTR(0,8); for (int i = 0; i < count; i++) { xfer->buffer[xfer->queued_len + i] = ptr[i]; } @@ -230,7 +247,7 @@ static void dcd_ep_handler(uint8_t ep_ix) } else { // TX complete - dcd_event_xfer_complete(0, (uint8_t)(0x80 + 0), xfer->total_len, XFER_RESULT_SUCCESS, true); + dcd_event_xfer_complete(0, 0x80 + 0, xfer->total_len, XFER_RESULT_SUCCESS, true); } } } @@ -238,7 +255,7 @@ static void dcd_ep_handler(uint8_t ep_ix) if (int_status & USBHS_DEVEPTISR_RXOUTI) { xfer_ctl_t *xfer = &xfer_status[ep_ix]; if (count) { - uint8_t *ptr = get_ep_fifo_ptr(ep_ix,8); + uint8_t *ptr = EP_GET_FIFO_PTR(ep_ix,8); memcpy(xfer->buffer + xfer->queued_len, ptr, count); xfer->queued_len = (uint16_t)(xfer->queued_len + count); } @@ -264,12 +281,34 @@ static void dcd_ep_handler(uint8_t ep_ix) } else { // TX complete - dcd_event_xfer_complete(0, (uint8_t)(0x80 + ep_ix), xfer->total_len, XFER_RESULT_SUCCESS, true); + dcd_event_xfer_complete(0, 0x80 + ep_ix, xfer->total_len, XFER_RESULT_SUCCESS, true); + USBHS->USBHS_DEVEPTIDR[ep_ix] = USBHS_DEVEPTIDR_TXINEC; } } } } +static void dcd_dma_handler(uint8_t ep_ix) +{ + uint32_t status = USBHS->UsbhsDevdma[ep_ix - 1].USBHS_DEVDMASTATUS; + if (status & USBHS_DEVDMASTATUS_CHANN_ENB) { + return; // Ignore EOT_STA interrupt + } + // Disable DMA interrupt + USBHS->USBHS_DEVIDR = USBHS_DEVIDR_DMA_1 << (ep_ix - 1); + + xfer_ctl_t *xfer = &xfer_status[ep_ix]; + uint16_t count = xfer->total_len - ((status & USBHS_DEVDMASTATUS_BUFF_COUNT_Msk) >> USBHS_DEVDMASTATUS_BUFF_COUNT_Pos); + if(USBHS->USBHS_DEVEPTCFG[ep_ix] & USBHS_DEVEPTCFG_EPDIR) + { + dcd_event_xfer_complete(0, 0x80 + ep_ix, count, XFER_RESULT_SUCCESS, true); + } + else + { + dcd_event_xfer_complete(0, ep_ix, count, XFER_RESULT_SUCCESS, true); + } +} + void dcd_int_handler(uint8_t rhport) { (void) rhport; @@ -337,10 +376,18 @@ void dcd_int_handler(uint8_t rhport) #endif // Endpoints interrupt for (int ep_ix = 0; ep_ix < EP_MAX; ep_ix++) { - if (int_status & (1 << (USBHS_DEVISR_PEP_0_Pos + ep_ix))) { + if (int_status & (USBHS_DEVISR_PEP_0 << ep_ix)) { dcd_ep_handler(ep_ix); } } + // Endpoints DMA interrupt + for (int ep_ix = 0; ep_ix < EP_MAX; ep_ix++) { + if (EP_DMA_SUPPORT(ep_ix)) { + if (int_status & (USBHS_DEVISR_DMA_1 << (ep_ix - 1))) { + dcd_dma_handler(ep_ix); + } + } + } } //--------------------------------------------------------------------+ @@ -415,26 +462,27 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) USBHS->USBHS_DEVEPT |= ((0x01 << epnum) << USBHS_DEVEPT_EPEN0_Pos); // Set up the maxpacket size, fifo start address fifosize // and enable the interrupt. CLear the data toggle. + // AUTOSW is needed for DMA ack ! USBHS->USBHS_DEVEPTCFG[epnum] = ( USBHS_DEVEPTCFG_EPSIZE(fifoSize) | USBHS_DEVEPTCFG_EPTYPE(eptype) | USBHS_DEVEPTCFG_EPBK(USBHS_DEVEPTCFG_EPBK_1_BANK) | + USBHS_DEVEPTCFG_AUTOSW | ((dir & 0x01) << USBHS_DEVEPTCFG_EPDIR_Pos) ); - if (eptype == TUSB_XFER_ISOCHRONOUS){ - USBHS->USBHS_DEVEPTCFG[epnum] |= USBHS_DEVEPTCFG_NBTRANS(1) | USBHS_DEVEPTCFG_EPBK_2_BANK; + USBHS->USBHS_DEVEPTCFG[epnum] |= USBHS_DEVEPTCFG_NBTRANS(1); } +#if USE_DUAL_BANK + if (eptype == TUSB_XFER_ISOCHRONOUS || eptype == TUSB_XFER_BULK){ + USBHS->USBHS_DEVEPTCFG[epnum] |= USBHS_DEVEPTCFG_EPBK_2_BANK; + } +#endif USBHS->USBHS_DEVEPTCFG[epnum] |= USBHS_DEVEPTCFG_ALLOC; USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_RSTDTS; USBHS->USBHS_DEVEPTIDR[epnum] = USBHS_DEVEPTIDR_STALLRQC; if (USBHS_DEVEPTISR_CFGOK == (USBHS->USBHS_DEVEPTISR[epnum] & USBHS_DEVEPTISR_CFGOK)) { - // Endpoint configuration is successful. Enable Endpoint Interrupts - if (dir == TUSB_DIR_IN) { - USBHS->USBHS_DEVEPTICR[epnum] = USBHS_DEVEPTICR_TXINIC; - USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_TXINES; - } USBHS->USBHS_DEVIER = ((0x01 << epnum) << USBHS_DEVIER_PEP_0_Pos); return true; } @@ -453,28 +501,26 @@ static void dcd_transmit_packet(xfer_ctl_t * xfer, uint8_t ep_ix) len = xfer->max_packet_size; } - uint8_t *ptr = get_ep_fifo_ptr(ep_ix,8); + uint8_t *ptr = EP_GET_FIFO_PTR(ep_ix,8); memcpy(ptr, xfer->buffer + xfer->queued_len, len); xfer->queued_len = (uint16_t)(xfer->queued_len + len); if (ep_ix == 0U) { - // Control endpoint: clear the interrupt flag to send the data, - // and re-enable the interrupts to trigger an interrupt at the - // end of the transfer. + // Control endpoint: clear the interrupt flag to send the data USBHS->USBHS_DEVEPTICR[0] = USBHS_DEVEPTICR_TXINIC; - USBHS->USBHS_DEVEPTIER[0] = USBHS_DEVEPTIER_TXINES; + } else { - // Other endpoint types: clear the FIFO control flag to send the data. + // Other endpoint types: clear the FIFO control flag to send the data USBHS->USBHS_DEVEPTIDR[ep_ix] = USBHS_DEVEPTIDR_FIFOCONC; } + USBHS->USBHS_DEVEPTIER[ep_ix] = USBHS_DEVEPTIER_TXINES; } // Submit a transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) { (void) rhport; - uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); @@ -486,11 +532,42 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t xfer->total_len = total_bytes; xfer->queued_len = 0; - if (dir == TUSB_DIR_OUT){ - USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_RXOUTES; + if(EP_DMA_SUPPORT(epnum) && total_bytes != 0) { + uint32_t udd_dma_ctrl = 0; + udd_dma_ctrl = USBHS_DEVDMACONTROL_BUFF_LENGTH(total_bytes); + if (dir == TUSB_DIR_OUT){ + udd_dma_ctrl |= USBHS_DEVDMACONTROL_END_TR_IT | USBHS_DEVDMACONTROL_END_TR_EN; + } + else { + udd_dma_ctrl |= USBHS_DEVDMACONTROL_END_B_EN; + } + // Start USB DMA to fill or read fifo of the selected endpoint + USBHS->UsbhsDevdma[epnum - 1].USBHS_DEVDMAADDRESS = (uint32_t)buffer; + udd_dma_ctrl |= USBHS_DEVDMACONTROL_END_BUFFIT | USBHS_DEVDMACONTROL_CHANN_ENB; + // Disable IRQs to have a short sequence + // between read of EOT_STA and DMA enable + uint32_t irq_state = __get_PRIMASK(); + __disable_irq(); + if (!(USBHS->UsbhsDevdma[epnum - 1].USBHS_DEVDMASTATUS & USBHS_DEVDMASTATUS_END_TR_ST)) { + USBHS->UsbhsDevdma[epnum - 1].USBHS_DEVDMACONTROL = udd_dma_ctrl; + USBHS->USBHS_DEVIER = USBHS_DEVIER_DMA_1 << (epnum - 1); + __set_PRIMASK(irq_state); + return true; + } + __set_PRIMASK(irq_state); + + // Here a ZLP has been recieved + // and the DMA transfer must be not started. + // It is the end of transfer + return false; } else { - dcd_transmit_packet(xfer,epnum); + if (dir == TUSB_DIR_OUT){ + USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_RXOUTES; + } + else { + dcd_transmit_packet(xfer,epnum); + } } return true; } From 24de9d39af9c7f015dc00295a1d9f8c5bf428d34 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Thu, 11 Mar 2021 20:47:53 +0100 Subject: [PATCH 05/36] Format. --- src/portable/microchip/same70/dcd_same70.c | 155 +++++++++++++-------- 1 file changed, 95 insertions(+), 60 deletions(-) diff --git a/src/portable/microchip/same70/dcd_same70.c b/src/portable/microchip/same70/dcd_same70.c index 89ef6366..72d91e46 100644 --- a/src/portable/microchip/same70/dcd_same70.c +++ b/src/portable/microchip/same70/dcd_same70.c @@ -25,8 +25,6 @@ * This file is part of the TinyUSB stack. */ - - #include "tusb_option.h" #if CFG_TUSB_MCU == OPT_MCU_SAME70 @@ -207,8 +205,10 @@ static void dcd_ep_handler(uint8_t ep_ix) int_status &= USBHS->USBHS_DEVEPTIMR[ep_ix]; uint16_t count = (USBHS->USBHS_DEVEPTISR[ep_ix] & USBHS_DEVEPTISR_BYCT_Msk) >> USBHS_DEVEPTISR_BYCT_Pos; - if (ep_ix == 0U) { - if (int_status & USBHS_DEVEPTISR_CTRL_RXSTPI) { + if (ep_ix == 0U) + { + if (int_status & USBHS_DEVEPTISR_CTRL_RXSTPI) + { // Setup packet should always be 8 bytes. If not, ignore it, and try again. if (count == 8) { @@ -218,18 +218,22 @@ static void dcd_ep_handler(uint8_t ep_ix) // Acknowledge the interrupt USBHS->USBHS_DEVEPTICR[0] = USBHS_DEVEPTICR_RXSTPIC; } - if (int_status & USBHS_DEVEPTISR_RXOUTI) { + if (int_status & USBHS_DEVEPTISR_RXOUTI) + { xfer_ctl_t *xfer = &xfer_status[0]; - if (count) { + if (count) + { uint8_t *ptr = EP_GET_FIFO_PTR(0,8); - for (int i = 0; i < count; i++) { + for (int i = 0; i < count; i++) + { xfer->buffer[xfer->queued_len + i] = ptr[i]; } xfer->queued_len = (uint16_t)(xfer->queued_len + count); } // Acknowledge the interrupt USBHS->USBHS_DEVEPTICR[0] = USBHS_DEVEPTICR_RXOUTIC; - if ((count < xfer->max_packet_size) || (xfer->queued_len == xfer->total_len)) { + if ((count < xfer->max_packet_size) || (xfer->queued_len == xfer->total_len)) + { // RX COMPLETE dcd_event_xfer_complete(0, 0, xfer->queued_len, XFER_RESULT_SUCCESS, true); // Disable the interrupt @@ -237,24 +241,28 @@ static void dcd_ep_handler(uint8_t ep_ix) // Though the host could still send, we don't know. } } - if (int_status & USBHS_DEVEPTISR_TXINI) { + if (int_status & USBHS_DEVEPTISR_TXINI) + { // Disable the interrupt USBHS->USBHS_DEVEPTIDR[0] = USBHS_DEVEPTIDR_TXINEC; xfer_ctl_t * xfer = &xfer_status[EP_MAX]; - if ((xfer->total_len != xfer->queued_len)) { + if ((xfer->total_len != xfer->queued_len)) + { // TX not complete dcd_transmit_packet(xfer, 0); - } - else { + } else + { // TX complete dcd_event_xfer_complete(0, 0x80 + 0, xfer->total_len, XFER_RESULT_SUCCESS, true); } } - } - else { - if (int_status & USBHS_DEVEPTISR_RXOUTI) { + } else + { + if (int_status & USBHS_DEVEPTISR_RXOUTI) + { xfer_ctl_t *xfer = &xfer_status[ep_ix]; - if (count) { + if (count) + { uint8_t *ptr = EP_GET_FIFO_PTR(ep_ix,8); memcpy(xfer->buffer + xfer->queued_len, ptr, count); xfer->queued_len = (uint16_t)(xfer->queued_len + count); @@ -263,7 +271,8 @@ static void dcd_ep_handler(uint8_t ep_ix) USBHS->USBHS_DEVEPTICR[ep_ix] = USBHS_DEVEPTICR_RXOUTIC; // Clear the FIFO control flag to receive more data. USBHS->USBHS_DEVEPTIDR[ep_ix] = USBHS_DEVEPTIDR_FIFOCONC; - if ((count < xfer->max_packet_size) || (xfer->queued_len == xfer->total_len)) { + if ((count < xfer->max_packet_size) || (xfer->queued_len == xfer->total_len)) + { // RX COMPLETE dcd_event_xfer_complete(0, ep_ix, xfer->queued_len, XFER_RESULT_SUCCESS, true); // Disable the interrupt @@ -271,15 +280,17 @@ static void dcd_ep_handler(uint8_t ep_ix) // Though the host could still send, we don't know. } } - if (int_status & USBHS_DEVEPTISR_TXINI) { + if (int_status & USBHS_DEVEPTISR_TXINI) + { // Acknowledge the interrupt USBHS->USBHS_DEVEPTICR[ep_ix] = USBHS_DEVEPTICR_TXINIC; xfer_ctl_t * xfer = &xfer_status[ep_ix];; - if ((xfer->total_len != xfer->queued_len)) { + if ((xfer->total_len != xfer->queued_len)) + { // TX not complete dcd_transmit_packet(xfer, ep_ix); - } - else { + } else + { // TX complete dcd_event_xfer_complete(0, 0x80 + ep_ix, xfer->total_len, XFER_RESULT_SUCCESS, true); USBHS->USBHS_DEVEPTIDR[ep_ix] = USBHS_DEVEPTIDR_TXINEC; @@ -291,7 +302,8 @@ static void dcd_ep_handler(uint8_t ep_ix) static void dcd_dma_handler(uint8_t ep_ix) { uint32_t status = USBHS->UsbhsDevdma[ep_ix - 1].USBHS_DEVDMASTATUS; - if (status & USBHS_DEVDMASTATUS_CHANN_ENB) { + if (status & USBHS_DEVDMASTATUS_CHANN_ENB) + { return; // Ignore EOT_STA interrupt } // Disable DMA interrupt @@ -302,8 +314,7 @@ static void dcd_dma_handler(uint8_t ep_ix) if(USBHS->USBHS_DEVEPTCFG[ep_ix] & USBHS_DEVEPTCFG_EPDIR) { dcd_event_xfer_complete(0, 0x80 + ep_ix, count, XFER_RESULT_SUCCESS, true); - } - else + } else { dcd_event_xfer_complete(0, ep_ix, count, XFER_RESULT_SUCCESS, true); } @@ -314,12 +325,14 @@ void dcd_int_handler(uint8_t rhport) (void) rhport; uint32_t int_status = USBHS->USBHS_DEVISR; // End of reset interrupt - if (int_status & USBHS_DEVISR_EORST) { + if (int_status & USBHS_DEVISR_EORST) + { // Unfreeze USB clock USBHS->USBHS_CTRL &= ~USBHS_CTRL_FRZCLK; while(USBHS_SR_CLKUSABLE != (USBHS->USBHS_SR & USBHS_SR_CLKUSABLE)); // Reset all endpoints - for (int ep_ix = 1; ep_ix < EP_MAX; ep_ix++) { + for (int ep_ix = 1; ep_ix < EP_MAX; ep_ix++) + { USBHS->USBHS_DEVEPT |= 1 << (USBHS_DEVEPT_EPRST0_Pos + ep_ix); USBHS->USBHS_DEVEPT &=~(1 << (USBHS_DEVEPT_EPRST0_Pos + ep_ix)); } @@ -336,7 +349,8 @@ void dcd_int_handler(uint8_t rhport) dcd_event_bus_reset(rhport, get_speed(), true); } // End of Wakeup interrupt - if (int_status & USBHS_DEVISR_WAKEUP) { + if (int_status & USBHS_DEVISR_WAKEUP) + { // Unfreeze USB clock USBHS->USBHS_CTRL &= ~USBHS_CTRL_FRZCLK; // Wait to unfreeze clock @@ -351,7 +365,8 @@ void dcd_int_handler(uint8_t rhport) dcd_event_bus_signal(0, DCD_EVENT_RESUME, true); } // Suspend interrupt - if (int_status & USBHS_DEVISR_SUSP) { + if (int_status & USBHS_DEVISR_SUSP) + { // Unfreeze USB clock USBHS->USBHS_CTRL &= ~USBHS_CTRL_FRZCLK; // Wait to unfreeze clock @@ -368,22 +383,28 @@ void dcd_int_handler(uint8_t rhport) dcd_event_bus_signal(0, DCD_EVENT_SUSPEND, true); } #if USE_SOF - if(int_status & USBHS_DEVISR_SOF) { + if(int_status & USBHS_DEVISR_SOF) + { USBHS->USBHS_DEVICR = USBHS_DEVICR_SOFC; dcd_event_bus_signal(0, DCD_EVENT_SOF, true); } #endif // Endpoints interrupt - for (int ep_ix = 0; ep_ix < EP_MAX; ep_ix++) { - if (int_status & (USBHS_DEVISR_PEP_0 << ep_ix)) { + for (int ep_ix = 0; ep_ix < EP_MAX; ep_ix++) + { + if (int_status & (USBHS_DEVISR_PEP_0 << ep_ix)) + { dcd_ep_handler(ep_ix); } } // Endpoints DMA interrupt - for (int ep_ix = 0; ep_ix < EP_MAX; ep_ix++) { - if (EP_DMA_SUPPORT(ep_ix)) { - if (int_status & (USBHS_DEVISR_DMA_1 << (ep_ix - 1))) { + for (int ep_ix = 0; ep_ix < EP_MAX; ep_ix++) + { + if (EP_DMA_SUPPORT(ep_ix)) + { + if (int_status & (USBHS_DEVISR_DMA_1 << (ep_ix - 1))) + { dcd_dma_handler(ep_ix); } } @@ -420,8 +441,10 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) uint8_t fifoSize = 0; // FIFO size uint16_t defaultEndpointSize = 8; // Default size of Endpoint // Find upper 2 power number of epMaxPktSize - if (epMaxPktSize) { - while (defaultEndpointSize < epMaxPktSize) { + if (epMaxPktSize) + { + while (defaultEndpointSize < epMaxPktSize) + { fifoSize++; defaultEndpointSize <<= 1; } @@ -431,7 +454,8 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) USBHS->USBHS_DEVEPT |= 1 << (USBHS_DEVEPT_EPRST0_Pos + epnum); USBHS->USBHS_DEVEPT &=~(1 << (USBHS_DEVEPT_EPRST0_Pos + epnum)); - if (epnum == 0) { + if (epnum == 0) + { xfer_status[EP_MAX].max_packet_size = epMaxPktSize; // Enable the control endpoint - Endpoint 0 USBHS->USBHS_DEVEPT |= USBHS_DEVEPT_EPEN0; @@ -445,19 +469,20 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) ); USBHS->USBHS_DEVEPTIER[0] = USBHS_DEVEPTIER_RSTDTS; USBHS->USBHS_DEVEPTIDR[0] = USBHS_DEVEPTIDR_STALLRQC; - if (USBHS_DEVEPTISR_CFGOK == (USBHS->USBHS_DEVEPTISR[0] & USBHS_DEVEPTISR_CFGOK)) { + if (USBHS_DEVEPTISR_CFGOK == (USBHS->USBHS_DEVEPTISR[0] & USBHS_DEVEPTISR_CFGOK)) + { // Endpoint configuration is successful USBHS->USBHS_DEVEPTIER[0] = USBHS_DEVEPTIER_RXSTPES; // Enable Endpoint 0 Interrupts USBHS->USBHS_DEVIER = USBHS_DEVIER_PEP_0; return true; - } - else { + } else + { // Endpoint configuration is not successful return false; } - } - else { + } else + { // Enable the endpoint USBHS->USBHS_DEVEPT |= ((0x01 << epnum) << USBHS_DEVEPT_EPEN0_Pos); // Set up the maxpacket size, fifo start address fifosize @@ -471,22 +496,25 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) USBHS_DEVEPTCFG_AUTOSW | ((dir & 0x01) << USBHS_DEVEPTCFG_EPDIR_Pos) ); - if (eptype == TUSB_XFER_ISOCHRONOUS){ + if (eptype == TUSB_XFER_ISOCHRONOUS) + { USBHS->USBHS_DEVEPTCFG[epnum] |= USBHS_DEVEPTCFG_NBTRANS(1); } #if USE_DUAL_BANK - if (eptype == TUSB_XFER_ISOCHRONOUS || eptype == TUSB_XFER_BULK){ + if (eptype == TUSB_XFER_ISOCHRONOUS || eptype == TUSB_XFER_BULK) + { USBHS->USBHS_DEVEPTCFG[epnum] |= USBHS_DEVEPTCFG_EPBK_2_BANK; } #endif USBHS->USBHS_DEVEPTCFG[epnum] |= USBHS_DEVEPTCFG_ALLOC; USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_RSTDTS; USBHS->USBHS_DEVEPTIDR[epnum] = USBHS_DEVEPTIDR_STALLRQC; - if (USBHS_DEVEPTISR_CFGOK == (USBHS->USBHS_DEVEPTISR[epnum] & USBHS_DEVEPTISR_CFGOK)) { + if (USBHS_DEVEPTISR_CFGOK == (USBHS->USBHS_DEVEPTISR[epnum] & USBHS_DEVEPTISR_CFGOK)) + { USBHS->USBHS_DEVIER = ((0x01 << epnum) << USBHS_DEVIER_PEP_0_Pos); return true; - } - else { + } else + { // Endpoint configuration is not successful return false; } @@ -497,7 +525,8 @@ static void dcd_transmit_packet(xfer_ctl_t * xfer, uint8_t ep_ix) { uint16_t len = (uint16_t)(xfer->total_len - xfer->queued_len); - if (len > xfer->max_packet_size) { + if (len > xfer->max_packet_size) + { len = xfer->max_packet_size; } @@ -506,11 +535,13 @@ static void dcd_transmit_packet(xfer_ctl_t * xfer, uint8_t ep_ix) xfer->queued_len = (uint16_t)(xfer->queued_len + len); - if (ep_ix == 0U) { + if (ep_ix == 0U) + { // Control endpoint: clear the interrupt flag to send the data USBHS->USBHS_DEVEPTICR[0] = USBHS_DEVEPTICR_TXINIC; - } else { + } else + { // Other endpoint types: clear the FIFO control flag to send the data USBHS->USBHS_DEVEPTIDR[ep_ix] = USBHS_DEVEPTIDR_FIFOCONC; } @@ -532,13 +563,15 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t xfer->total_len = total_bytes; xfer->queued_len = 0; - if(EP_DMA_SUPPORT(epnum) && total_bytes != 0) { + if(EP_DMA_SUPPORT(epnum) && total_bytes != 0) + { uint32_t udd_dma_ctrl = 0; udd_dma_ctrl = USBHS_DEVDMACONTROL_BUFF_LENGTH(total_bytes); - if (dir == TUSB_DIR_OUT){ + if (dir == TUSB_DIR_OUT) + { udd_dma_ctrl |= USBHS_DEVDMACONTROL_END_TR_IT | USBHS_DEVDMACONTROL_END_TR_EN; - } - else { + } else + { udd_dma_ctrl |= USBHS_DEVDMACONTROL_END_B_EN; } // Start USB DMA to fill or read fifo of the selected endpoint @@ -548,7 +581,8 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t // between read of EOT_STA and DMA enable uint32_t irq_state = __get_PRIMASK(); __disable_irq(); - if (!(USBHS->UsbhsDevdma[epnum - 1].USBHS_DEVDMASTATUS & USBHS_DEVDMASTATUS_END_TR_ST)) { + if (!(USBHS->UsbhsDevdma[epnum - 1].USBHS_DEVDMASTATUS & USBHS_DEVDMASTATUS_END_TR_ST)) + { USBHS->UsbhsDevdma[epnum - 1].USBHS_DEVDMACONTROL = udd_dma_ctrl; USBHS->USBHS_DEVIER = USBHS_DEVIER_DMA_1 << (epnum - 1); __set_PRIMASK(irq_state); @@ -560,12 +594,13 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t // and the DMA transfer must be not started. // It is the end of transfer return false; - } - else { - if (dir == TUSB_DIR_OUT){ + } else + { + if (dir == TUSB_DIR_OUT) + { USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_RXOUTES; - } - else { + } else + { dcd_transmit_packet(xfer,epnum); } } From c291deccfac7725a4e1f26357e133f32887e65aa Mon Sep 17 00:00:00 2001 From: MasterPhi Date: Fri, 11 Jun 2021 12:14:14 +0200 Subject: [PATCH 06/36] Add fifo & DMA linked list mode support. --- examples/device/cdc_msc/src/tusb_config.h | 2 +- examples/device/cdc_msc/src/usb_descriptors.c | 4 +- src/portable/microchip/same70/dcd_same70.c | 177 +++++++++++++----- 3 files changed, 132 insertions(+), 51 deletions(-) diff --git a/examples/device/cdc_msc/src/tusb_config.h b/examples/device/cdc_msc/src/tusb_config.h index 9a0262d3..f9e98b0f 100644 --- a/examples/device/cdc_msc/src/tusb_config.h +++ b/examples/device/cdc_msc/src/tusb_config.h @@ -48,7 +48,7 @@ // Default to Highspeed for MCU with internal HighSpeed PHY (can be port specific), otherwise FullSpeed #ifndef BOARD_DEVICE_RHPORT_SPEED #if (CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || \ - CFG_TUSB_MCU == OPT_MCU_NUC505 || CFG_TUSB_MCU == OPT_MCU_CXD56) + CFG_TUSB_MCU == OPT_MCU_NUC505 || CFG_TUSB_MCU == OPT_MCU_CXD56 || CFG_TUSB_MCU == OPT_MCU_SAME70) #define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_HIGH_SPEED #else #define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_FULL_SPEED diff --git a/examples/device/cdc_msc/src/usb_descriptors.c b/examples/device/cdc_msc/src/usb_descriptors.c index fa434216..46b57f7e 100644 --- a/examples/device/cdc_msc/src/usb_descriptors.c +++ b/examples/device/cdc_msc/src/usb_descriptors.c @@ -94,8 +94,8 @@ enum #define EPNUM_MSC_OUT 0x05 #define EPNUM_MSC_IN 0x85 -#elif CFG_TUSB_MCU == OPT_MCU_SAMG - // SAMG doesn't support a same endpoint number with different direction IN and OUT +#elif CFG_TUSB_MCU == OPT_MCU_SAMG || CFG_TUSB_MCU == OPT_MCU_SAME70 + // SAMG & SAME70 don't support a same endpoint number with different direction IN and OUT // e.g EP1 OUT & EP1 IN cannot exist together #define EPNUM_CDC_NOTIF 0x81 #define EPNUM_CDC_OUT 0x02 diff --git a/src/portable/microchip/same70/dcd_same70.c b/src/portable/microchip/same70/dcd_same70.c index 72d91e46..eb716182 100644 --- a/src/portable/microchip/same70/dcd_same70.c +++ b/src/portable/microchip/same70/dcd_same70.c @@ -62,14 +62,33 @@ // Errata: The DMA feature is not available for Pipe/Endpoint 7 #define EP_DMA_SUPPORT(epnum) (epnum >= 1 && epnum <= 6) +// DMA Channel Transfer Descriptor +typedef struct { + volatile uint32_t next_desc; + volatile uint32_t buff_addr; + volatile uint32_t chnl_ctrl; + uint32_t padding; +} dma_desc_t; + +// Transfer control context typedef struct { uint8_t * buffer; uint16_t total_len; uint16_t queued_len; uint16_t max_packet_size; uint8_t interval; + tu_fifo_t * fifo; } xfer_ctl_t; +static tusb_speed_t get_speed(void); +static void dcd_transmit_packet(xfer_ctl_t * xfer, uint8_t ep_ix); + +// DMA descriptors shouldn't be placed in ITCM +#if defined(USB_DMA_DESC_SECTION) +TU_ATTR_SECTION(TU_XSTRING(USB_DMA_DESC_SECTION)) +#endif +dma_desc_t dma_desc[6]; + xfer_ctl_t xfer_status[EP_MAX+1]; static const tusb_desc_endpoint_t ep0_desc = @@ -78,8 +97,6 @@ static const tusb_desc_endpoint_t ep0_desc = .wMaxPacketSize = { .size = CFG_TUD_ENDPOINT0_SIZE }, }; -static tusb_speed_t get_speed(void); -static void dcd_transmit_packet(xfer_ctl_t * xfer, uint8_t ep_ix); //------------------------------------------------------------------ // Device API //------------------------------------------------------------------ @@ -224,9 +241,11 @@ static void dcd_ep_handler(uint8_t ep_ix) if (count) { uint8_t *ptr = EP_GET_FIFO_PTR(0,8); - for (int i = 0; i < count; i++) + if (xfer->buffer) { - xfer->buffer[xfer->queued_len + i] = ptr[i]; + memcpy(xfer->buffer + xfer->queued_len, ptr, count); + } else { + tu_fifo_write_n(xfer->fifo, ptr, count); } xfer->queued_len = (uint16_t)(xfer->queued_len + count); } @@ -250,21 +269,24 @@ static void dcd_ep_handler(uint8_t ep_ix) { // TX not complete dcd_transmit_packet(xfer, 0); - } else - { + } else { // TX complete dcd_event_xfer_complete(0, 0x80 + 0, xfer->total_len, XFER_RESULT_SUCCESS, true); } } - } else - { + } else { if (int_status & USBHS_DEVEPTISR_RXOUTI) { xfer_ctl_t *xfer = &xfer_status[ep_ix]; if (count) { uint8_t *ptr = EP_GET_FIFO_PTR(ep_ix,8); - memcpy(xfer->buffer + xfer->queued_len, ptr, count); + if (xfer->buffer) + { + memcpy(xfer->buffer + xfer->queued_len, ptr, count); + } else { + tu_fifo_write_n(xfer->fifo, ptr, count); + } xfer->queued_len = (uint16_t)(xfer->queued_len + count); } // Acknowledge the interrupt @@ -289,8 +311,7 @@ static void dcd_ep_handler(uint8_t ep_ix) { // TX not complete dcd_transmit_packet(xfer, ep_ix); - } else - { + } else { // TX complete dcd_event_xfer_complete(0, 0x80 + ep_ix, xfer->total_len, XFER_RESULT_SUCCESS, true); USBHS->USBHS_DEVEPTIDR[ep_ix] = USBHS_DEVEPTIDR_TXINEC; @@ -314,8 +335,7 @@ static void dcd_dma_handler(uint8_t ep_ix) if(USBHS->USBHS_DEVEPTCFG[ep_ix] & USBHS_DEVEPTCFG_EPDIR) { dcd_event_xfer_complete(0, 0x80 + ep_ix, count, XFER_RESULT_SUCCESS, true); - } else - { + } else { dcd_event_xfer_complete(0, ep_ix, count, XFER_RESULT_SUCCESS, true); } } @@ -337,13 +357,9 @@ void dcd_int_handler(uint8_t rhport) USBHS->USBHS_DEVEPT &=~(1 << (USBHS_DEVEPT_EPRST0_Pos + ep_ix)); } dcd_edpt_open (0, &ep0_desc); - // Acknowledge the End of Reset interrupt USBHS->USBHS_DEVICR = USBHS_DEVICR_EORSTC; - // Acknowledge the Wakeup interrupt USBHS->USBHS_DEVICR = USBHS_DEVICR_WAKEUPC; - // Acknowledge the suspend interrupt USBHS->USBHS_DEVICR = USBHS_DEVICR_SUSPC; - // Enable Suspend Interrupt USBHS->USBHS_DEVIER = USBHS_DEVIER_SUSPES; dcd_event_bus_reset(rhport, get_speed(), true); @@ -351,15 +367,10 @@ void dcd_int_handler(uint8_t rhport) // End of Wakeup interrupt if (int_status & USBHS_DEVISR_WAKEUP) { - // Unfreeze USB clock USBHS->USBHS_CTRL &= ~USBHS_CTRL_FRZCLK; - // Wait to unfreeze clock while (USBHS_SR_CLKUSABLE != (USBHS->USBHS_SR & USBHS_SR_CLKUSABLE)); - // Acknowledge the Wakeup interrupt USBHS->USBHS_DEVICR = USBHS_DEVICR_WAKEUPC; - // Disable Wakeup Interrupt USBHS->USBHS_DEVIDR = USBHS_DEVIDR_WAKEUPEC; - // Enable Suspend Interrupt USBHS->USBHS_DEVIER = USBHS_DEVIER_SUSPES; dcd_event_bus_signal(0, DCD_EVENT_RESUME, true); @@ -369,15 +380,10 @@ void dcd_int_handler(uint8_t rhport) { // Unfreeze USB clock USBHS->USBHS_CTRL &= ~USBHS_CTRL_FRZCLK; - // Wait to unfreeze clock while (USBHS_SR_CLKUSABLE != (USBHS->USBHS_SR & USBHS_SR_CLKUSABLE)); - // Acknowledge the suspend interrupt USBHS->USBHS_DEVICR = USBHS_DEVICR_SUSPC; - // Disable Suspend Interrupt USBHS->USBHS_DEVIDR = USBHS_DEVIDR_SUSPEC; - // Enable Wakeup Interrupt USBHS->USBHS_DEVIER = USBHS_DEVIER_WAKEUPES; - // Freeze USB clock USBHS->USBHS_CTRL |= USBHS_CTRL_FRZCLK; dcd_event_bus_signal(0, DCD_EVENT_SUSPEND, true); @@ -476,13 +482,11 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) // Enable Endpoint 0 Interrupts USBHS->USBHS_DEVIER = USBHS_DEVIER_PEP_0; return true; - } else - { + } else { // Endpoint configuration is not successful return false; } - } else - { + } else { // Enable the endpoint USBHS->USBHS_DEVEPT |= ((0x01 << epnum) << USBHS_DEVEPT_EPEN0_Pos); // Set up the maxpacket size, fifo start address fifosize @@ -513,8 +517,7 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) { USBHS->USBHS_DEVIER = ((0x01 << epnum) << USBHS_DEVIER_PEP_0_Pos); return true; - } else - { + } else { // Endpoint configuration is not successful return false; } @@ -524,24 +527,25 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) static void dcd_transmit_packet(xfer_ctl_t * xfer, uint8_t ep_ix) { uint16_t len = (uint16_t)(xfer->total_len - xfer->queued_len); - if (len > xfer->max_packet_size) { len = xfer->max_packet_size; } - uint8_t *ptr = EP_GET_FIFO_PTR(ep_ix,8); - memcpy(ptr, xfer->buffer + xfer->queued_len, len); - + if(xfer->buffer) + { + memcpy(ptr, xfer->buffer + xfer->queued_len, len); + } + else { + tu_fifo_read_n(xfer->fifo, ptr, len); + } xfer->queued_len = (uint16_t)(xfer->queued_len + len); - if (ep_ix == 0U) { // Control endpoint: clear the interrupt flag to send the data USBHS->USBHS_DEVEPTICR[0] = USBHS_DEVEPTICR_TXINIC; - } else - { + } else { // Other endpoint types: clear the FIFO control flag to send the data USBHS->USBHS_DEVEPTIDR[ep_ix] = USBHS_DEVEPTIDR_FIFOCONC; } @@ -562,19 +566,17 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t xfer->buffer = buffer; xfer->total_len = total_bytes; xfer->queued_len = 0; + xfer->fifo = NULL; if(EP_DMA_SUPPORT(epnum) && total_bytes != 0) { - uint32_t udd_dma_ctrl = 0; - udd_dma_ctrl = USBHS_DEVDMACONTROL_BUFF_LENGTH(total_bytes); + uint32_t udd_dma_ctrl = USBHS_DEVDMACONTROL_BUFF_LENGTH(total_bytes); if (dir == TUSB_DIR_OUT) { udd_dma_ctrl |= USBHS_DEVDMACONTROL_END_TR_IT | USBHS_DEVDMACONTROL_END_TR_EN; - } else - { + } else { udd_dma_ctrl |= USBHS_DEVDMACONTROL_END_B_EN; } - // Start USB DMA to fill or read fifo of the selected endpoint USBHS->UsbhsDevdma[epnum - 1].USBHS_DEVDMAADDRESS = (uint32_t)buffer; udd_dma_ctrl |= USBHS_DEVDMACONTROL_END_BUFFIT | USBHS_DEVDMACONTROL_CHANN_ENB; // Disable IRQs to have a short sequence @@ -594,13 +596,92 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t // and the DMA transfer must be not started. // It is the end of transfer return false; - } else - { + } else { if (dir == TUSB_DIR_OUT) { USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_RXOUTES; - } else + } else { + dcd_transmit_packet(xfer,epnum); + } + } + return true; +} + +// The number of bytes has to be given explicitly to allow more flexible control of how many +// bytes should be written and second to keep the return value free to give back a boolean +// success message. If total_bytes is too big, the FIFO will copy only what is available +// into the USB buffer! +bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +{ + (void) rhport; + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + xfer_ctl_t * xfer = &xfer_status[epnum]; + if(epnum == 0x80) + xfer = &xfer_status[EP_MAX]; + + xfer->buffer = NULL; + xfer->total_len = total_bytes; + xfer->queued_len = 0; + xfer->fifo = ff; + + if (EP_DMA_SUPPORT(epnum) && total_bytes != 0) + { + tu_fifo_buffer_info_t info; + uint32_t udd_dma_ctrl_lin = USBHS_DEVDMACONTROL_CHANN_ENB; + uint32_t udd_dma_ctrl_wrap = USBHS_DEVDMACONTROL_CHANN_ENB | USBHS_DEVDMACONTROL_END_BUFFIT; + if (dir == TUSB_DIR_OUT) { + tu_fifo_get_write_info(ff, &info); + udd_dma_ctrl_lin |= USBHS_DEVDMACONTROL_END_TR_IT | USBHS_DEVDMACONTROL_END_TR_EN; + udd_dma_ctrl_wrap |= USBHS_DEVDMACONTROL_END_TR_IT | USBHS_DEVDMACONTROL_END_TR_EN; + } else { + tu_fifo_get_read_info(ff, &info); + if(info.len_wrap == 0) + { + udd_dma_ctrl_lin |= USBHS_DEVDMACONTROL_END_B_EN; + } + udd_dma_ctrl_wrap |= USBHS_DEVDMACONTROL_END_B_EN; + } + + USBHS->UsbhsDevdma[epnum - 1].USBHS_DEVDMAADDRESS = (uint32_t)info.ptr_lin; + if (info.len_wrap) + { + dma_desc[epnum - 1].next_desc = 0; + dma_desc[epnum - 1].buff_addr = (uint32_t)info.ptr_wrap; + dma_desc[epnum - 1].chnl_ctrl = + udd_dma_ctrl_wrap | USBHS_DEVDMACONTROL_BUFF_LENGTH(info.len_wrap); + udd_dma_ctrl_lin |= USBHS_DEVDMASTATUS_DESC_LDST; + __DSB(); + __ISB(); + USBHS->UsbhsDevdma[epnum - 1].USBHS_DEVDMANXTDSC = (uint32_t)&dma_desc[epnum - 1]; + } else { + udd_dma_ctrl_lin |= USBHS_DEVDMACONTROL_END_BUFFIT; + } + udd_dma_ctrl_lin |= USBHS_DEVDMACONTROL_BUFF_LENGTH(info.len_lin); + // Disable IRQs to have a short sequence + // between read of EOT_STA and DMA enable + uint32_t irq_state = __get_PRIMASK(); + __disable_irq(); + if (!(USBHS->UsbhsDevdma[epnum - 1].USBHS_DEVDMASTATUS & USBHS_DEVDMASTATUS_END_TR_ST)) + { + USBHS->UsbhsDevdma[epnum - 1].USBHS_DEVDMACONTROL = udd_dma_ctrl_lin; + USBHS->USBHS_DEVIER = USBHS_DEVIER_DMA_1 << (epnum - 1); + __set_PRIMASK(irq_state); + return true; + } + __set_PRIMASK(irq_state); + + // Here a ZLP has been recieved + // and the DMA transfer must be not started. + // It is the end of transfer + return false; + } else { + if (dir == TUSB_DIR_OUT) + { + USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_RXOUTES; + } else { dcd_transmit_packet(xfer,epnum); } } From 9a03ab9dfadb4f5a93df02b76a84c44edc6fc9f4 Mon Sep 17 00:00:00 2001 From: Rafael Silva Date: Fri, 11 Jun 2021 20:52:22 +0100 Subject: [PATCH 07/36] dcd: same70: change cmsis deprecated macros Signed-off-by: Rafael Silva --- src/portable/microchip/same70/dcd_same70.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/portable/microchip/same70/dcd_same70.c b/src/portable/microchip/same70/dcd_same70.c index eb716182..284010e5 100644 --- a/src/portable/microchip/same70/dcd_same70.c +++ b/src/portable/microchip/same70/dcd_same70.c @@ -233,7 +233,7 @@ static void dcd_ep_handler(uint8_t ep_ix) dcd_event_setup_received(0, ptr, true); } // Acknowledge the interrupt - USBHS->USBHS_DEVEPTICR[0] = USBHS_DEVEPTICR_RXSTPIC; + USBHS->USBHS_DEVEPTICR[0] = USBHS_DEVEPTICR_CTRL_RXSTPIC; } if (int_status & USBHS_DEVEPTISR_RXOUTI) { @@ -474,11 +474,11 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) USBHS_DEVEPTCFG_ALLOC ); USBHS->USBHS_DEVEPTIER[0] = USBHS_DEVEPTIER_RSTDTS; - USBHS->USBHS_DEVEPTIDR[0] = USBHS_DEVEPTIDR_STALLRQC; + USBHS->USBHS_DEVEPTIDR[0] = USBHS_DEVEPTIDR_CTRL_STALLRQC; if (USBHS_DEVEPTISR_CFGOK == (USBHS->USBHS_DEVEPTISR[0] & USBHS_DEVEPTISR_CFGOK)) { // Endpoint configuration is successful - USBHS->USBHS_DEVEPTIER[0] = USBHS_DEVEPTIER_RXSTPES; + USBHS->USBHS_DEVEPTIER[0] = USBHS_DEVEPTIER_CTRL_RXSTPES; // Enable Endpoint 0 Interrupts USBHS->USBHS_DEVIER = USBHS_DEVIER_PEP_0; return true; @@ -512,7 +512,7 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) #endif USBHS->USBHS_DEVEPTCFG[epnum] |= USBHS_DEVEPTCFG_ALLOC; USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_RSTDTS; - USBHS->USBHS_DEVEPTIDR[epnum] = USBHS_DEVEPTIDR_STALLRQC; + USBHS->USBHS_DEVEPTIDR[epnum] = USBHS_DEVEPTIDR_CTRL_STALLRQC; if (USBHS_DEVEPTISR_CFGOK == (USBHS->USBHS_DEVEPTISR[epnum] & USBHS_DEVEPTISR_CFGOK)) { USBHS->USBHS_DEVIER = ((0x01 << epnum) << USBHS_DEVIER_PEP_0_Pos); @@ -693,7 +693,7 @@ void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr) { (void) rhport; uint8_t const epnum = tu_edpt_number(ep_addr); - USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_STALLRQS; + USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_CTRL_STALLRQS; } // clear stall, data toggle is also reset to DATA0 @@ -701,7 +701,7 @@ void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) { (void) rhport; uint8_t const epnum = tu_edpt_number(ep_addr); - USBHS->USBHS_DEVEPTIDR[epnum] = USBHS_DEVEPTIDR_STALLRQC; + USBHS->USBHS_DEVEPTIDR[epnum] = USBHS_DEVEPTIDR_CTRL_STALLRQC; USBHS->USBHS_DEVEPTIER[epnum] = USBHS_HSTPIPIER_RSTDTS; } From bcd3e31bd678053918898a29136cf787e72a534b Mon Sep 17 00:00:00 2001 From: Rafael Silva Date: Fri, 11 Jun 2021 20:59:48 +0100 Subject: [PATCH 08/36] dcd: same70: fix unused variable warning Signed-off-by: Rafael Silva --- src/portable/microchip/same70/dcd_same70.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/portable/microchip/same70/dcd_same70.c b/src/portable/microchip/same70/dcd_same70.c index 284010e5..d4430ce9 100644 --- a/src/portable/microchip/same70/dcd_same70.c +++ b/src/portable/microchip/same70/dcd_same70.c @@ -134,6 +134,7 @@ void dcd_int_disable (uint8_t rhport) // Receive Set Address request, mcu port must also include status IN response void dcd_set_address (uint8_t rhport, uint8_t dev_addr) { + (void) dev_addr; // DCD can only set address after status for this request is complete // do it at dcd_edpt0_status_complete() @@ -151,6 +152,7 @@ void dcd_remote_wakeup (uint8_t rhport) // Connect by enabling internal pull-up resistor on D+/D- void dcd_connect(uint8_t rhport) { + (void) rhport; uint32_t irq_state = __get_PRIMASK(); __disable_irq(); // Enable USB clock From 71aae2743c2e3704411c2c6cbab3cbcb0f8144d1 Mon Sep 17 00:00:00 2001 From: Rafael Silva Date: Fri, 11 Jun 2021 21:01:12 +0100 Subject: [PATCH 09/36] bsp: same70_xplained: fix unused variable warning Signed-off-by: Rafael Silva --- hw/bsp/same70_xplained/same70_xplained.c | 1 + 1 file changed, 1 insertion(+) diff --git a/hw/bsp/same70_xplained/same70_xplained.c b/hw/bsp/same70_xplained/same70_xplained.c index fb8855f5..e34b5d35 100644 --- a/hw/bsp/same70_xplained/same70_xplained.c +++ b/hw/bsp/same70_xplained/same70_xplained.c @@ -52,6 +52,7 @@ static volatile bool uart_busy = false; static void tx_cb_EDBG_COM(const struct usart_async_descriptor *const io_descr) { + (void) io_descr; uart_busy = false; } From 28875c431b783ba1a552a9a1cd3df077445c8435 Mon Sep 17 00:00:00 2001 From: Rafael Silva Date: Fri, 11 Jun 2021 21:02:23 +0100 Subject: [PATCH 10/36] bsp: same70_xplained: replace template vars from make Signed-off-by: Rafael Silva --- hw/bsp/same70_xplained/board.mk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/bsp/same70_xplained/board.mk b/hw/bsp/same70_xplained/board.mk index 90ffbb70..13c552f9 100644 --- a/hw/bsp/same70_xplained/board.mk +++ b/hw/bsp/same70_xplained/board.mk @@ -8,7 +8,7 @@ CFLAGS += \ -mfpu=fpv4-sp-d16 \ -nostdlib -nostartfiles \ -D__SAME70Q21B__ \ - -DCFG_TUSB_MCU=OPT_MCU_NONE + -DCFG_TUSB_MCU=OPT_MCU_SAME70 # suppress following warnings from mcu driver CFLAGS += -Wno-error=unused-parameter -Wno-error=cast-align @@ -19,7 +19,7 @@ ASF_DIR = hw/mcu/microchip/same70 LD_FILE = $(ASF_DIR)/same70b/gcc/gcc/same70q21b_flash.ld SRC_C += \ - src/portable/template/dcd_template.c \ + src/portable/microchip/same70/dcd_same70.c \ $(ASF_DIR)/same70b/gcc/gcc/startup_same70q21b.c \ $(ASF_DIR)/same70b/gcc/system_same70q21b.c \ $(ASF_DIR)/hpl/core/hpl_init.c \ From 2196991df31f27dcf2bf71cc4bf743774ea395e8 Mon Sep 17 00:00:00 2001 From: Rafael Silva Date: Fri, 11 Jun 2021 21:03:36 +0100 Subject: [PATCH 11/36] dcd: same70: trim trailling spaces Signed-off-by: Rafael Silva --- src/portable/microchip/same70/dcd_same70.c | 108 ++++++++++----------- 1 file changed, 54 insertions(+), 54 deletions(-) diff --git a/src/portable/microchip/same70/dcd_same70.c b/src/portable/microchip/same70/dcd_same70.c index d4430ce9..0ad9ad62 100644 --- a/src/portable/microchip/same70/dcd_same70.c +++ b/src/portable/microchip/same70/dcd_same70.c @@ -1,4 +1,4 @@ -/* +/* * The MIT License (MIT) * * Copyright (c) 2018, hathach (tinyusb.org) @@ -137,7 +137,7 @@ void dcd_set_address (uint8_t rhport, uint8_t dev_addr) (void) dev_addr; // DCD can only set address after status for this request is complete // do it at dcd_edpt0_status_complete() - + // Response with zlp status dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0); } @@ -234,7 +234,7 @@ static void dcd_ep_handler(uint8_t ep_ix) uint8_t *ptr = EP_GET_FIFO_PTR(0,8); dcd_event_setup_received(0, ptr, true); } - // Acknowledge the interrupt + // Acknowledge the interrupt USBHS->USBHS_DEVEPTICR[0] = USBHS_DEVEPTICR_CTRL_RXSTPIC; } if (int_status & USBHS_DEVEPTISR_RXOUTI) @@ -251,34 +251,34 @@ static void dcd_ep_handler(uint8_t ep_ix) } xfer->queued_len = (uint16_t)(xfer->queued_len + count); } - // Acknowledge the interrupt + // Acknowledge the interrupt USBHS->USBHS_DEVEPTICR[0] = USBHS_DEVEPTICR_RXOUTIC; if ((count < xfer->max_packet_size) || (xfer->queued_len == xfer->total_len)) { - // RX COMPLETE + // RX COMPLETE dcd_event_xfer_complete(0, 0, xfer->queued_len, XFER_RESULT_SUCCESS, true); - // Disable the interrupt + // Disable the interrupt USBHS->USBHS_DEVEPTIDR[0] = USBHS_DEVEPTIDR_RXOUTEC; // Though the host could still send, we don't know. } } if (int_status & USBHS_DEVEPTISR_TXINI) { - // Disable the interrupt + // Disable the interrupt USBHS->USBHS_DEVEPTIDR[0] = USBHS_DEVEPTIDR_TXINEC; xfer_ctl_t * xfer = &xfer_status[EP_MAX]; if ((xfer->total_len != xfer->queued_len)) { - // TX not complete + // TX not complete dcd_transmit_packet(xfer, 0); } else { - // TX complete + // TX complete dcd_event_xfer_complete(0, 0x80 + 0, xfer->total_len, XFER_RESULT_SUCCESS, true); } } } else { if (int_status & USBHS_DEVEPTISR_RXOUTI) - { + { xfer_ctl_t *xfer = &xfer_status[ep_ix]; if (count) { @@ -291,27 +291,27 @@ static void dcd_ep_handler(uint8_t ep_ix) } xfer->queued_len = (uint16_t)(xfer->queued_len + count); } - // Acknowledge the interrupt + // Acknowledge the interrupt USBHS->USBHS_DEVEPTICR[ep_ix] = USBHS_DEVEPTICR_RXOUTIC; // Clear the FIFO control flag to receive more data. USBHS->USBHS_DEVEPTIDR[ep_ix] = USBHS_DEVEPTIDR_FIFOCONC; if ((count < xfer->max_packet_size) || (xfer->queued_len == xfer->total_len)) { - // RX COMPLETE + // RX COMPLETE dcd_event_xfer_complete(0, ep_ix, xfer->queued_len, XFER_RESULT_SUCCESS, true); - // Disable the interrupt + // Disable the interrupt USBHS->USBHS_DEVEPTIDR[ep_ix] = USBHS_DEVEPTIDR_RXOUTEC; // Though the host could still send, we don't know. } } if (int_status & USBHS_DEVEPTISR_TXINI) { - // Acknowledge the interrupt + // Acknowledge the interrupt USBHS->USBHS_DEVEPTICR[ep_ix] = USBHS_DEVEPTICR_TXINIC; xfer_ctl_t * xfer = &xfer_status[ep_ix];; if ((xfer->total_len != xfer->queued_len)) { - // TX not complete + // TX not complete dcd_transmit_packet(xfer, ep_ix); } else { // TX complete @@ -331,7 +331,7 @@ static void dcd_dma_handler(uint8_t ep_ix) } // Disable DMA interrupt USBHS->USBHS_DEVIDR = USBHS_DEVIDR_DMA_1 << (ep_ix - 1); - + xfer_ctl_t *xfer = &xfer_status[ep_ix]; uint16_t count = xfer->total_len - ((status & USBHS_DEVDMASTATUS_BUFF_COUNT_Msk) >> USBHS_DEVDMASTATUS_BUFF_COUNT_Pos); if(USBHS->USBHS_DEVEPTCFG[ep_ix] & USBHS_DEVEPTCFG_EPDIR) @@ -346,10 +346,10 @@ void dcd_int_handler(uint8_t rhport) { (void) rhport; uint32_t int_status = USBHS->USBHS_DEVISR; - // End of reset interrupt + // End of reset interrupt if (int_status & USBHS_DEVISR_EORST) { - // Unfreeze USB clock + // Unfreeze USB clock USBHS->USBHS_CTRL &= ~USBHS_CTRL_FRZCLK; while(USBHS_SR_CLKUSABLE != (USBHS->USBHS_SR & USBHS_SR_CLKUSABLE)); // Reset all endpoints @@ -363,10 +363,10 @@ void dcd_int_handler(uint8_t rhport) USBHS->USBHS_DEVICR = USBHS_DEVICR_WAKEUPC; USBHS->USBHS_DEVICR = USBHS_DEVICR_SUSPC; USBHS->USBHS_DEVIER = USBHS_DEVIER_SUSPES; - + dcd_event_bus_reset(rhport, get_speed(), true); } - // End of Wakeup interrupt + // End of Wakeup interrupt if (int_status & USBHS_DEVISR_WAKEUP) { USBHS->USBHS_CTRL &= ~USBHS_CTRL_FRZCLK; @@ -374,31 +374,31 @@ void dcd_int_handler(uint8_t rhport) USBHS->USBHS_DEVICR = USBHS_DEVICR_WAKEUPC; USBHS->USBHS_DEVIDR = USBHS_DEVIDR_WAKEUPEC; USBHS->USBHS_DEVIER = USBHS_DEVIER_SUSPES; - + dcd_event_bus_signal(0, DCD_EVENT_RESUME, true); } - // Suspend interrupt + // Suspend interrupt if (int_status & USBHS_DEVISR_SUSP) { - // Unfreeze USB clock + // Unfreeze USB clock USBHS->USBHS_CTRL &= ~USBHS_CTRL_FRZCLK; while (USBHS_SR_CLKUSABLE != (USBHS->USBHS_SR & USBHS_SR_CLKUSABLE)); USBHS->USBHS_DEVICR = USBHS_DEVICR_SUSPC; USBHS->USBHS_DEVIDR = USBHS_DEVIDR_SUSPEC; USBHS->USBHS_DEVIER = USBHS_DEVIER_WAKEUPES; USBHS->USBHS_CTRL |= USBHS_CTRL_FRZCLK; - + dcd_event_bus_signal(0, DCD_EVENT_SUSPEND, true); } #if USE_SOF if(int_status & USBHS_DEVISR_SOF) { USBHS->USBHS_DEVICR = USBHS_DEVICR_SOFC; - + dcd_event_bus_signal(0, DCD_EVENT_SOF, true); } -#endif - // Endpoints interrupt +#endif + // Endpoints interrupt for (int ep_ix = 0; ep_ix < EP_MAX; ep_ix++) { if (int_status & (USBHS_DEVISR_PEP_0 << ep_ix)) @@ -406,7 +406,7 @@ void dcd_int_handler(uint8_t rhport) dcd_ep_handler(ep_ix); } } - // Endpoints DMA interrupt + // Endpoints DMA interrupt for (int ep_ix = 0; ep_ix < EP_MAX; ep_ix++) { if (EP_DMA_SUPPORT(ep_ix)) @@ -433,7 +433,7 @@ void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * re request->bRequest == TUSB_REQ_SET_ADDRESS ) { uint8_t const dev_addr = (uint8_t) request->wValue; - + USBHS->USBHS_DEVCTRL |= dev_addr | USBHS_DEVCTRL_ADDEN; } } @@ -446,9 +446,9 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) uint8_t const dir = tu_edpt_dir(ep_desc->bEndpointAddress); uint16_t const epMaxPktSize = ep_desc->wMaxPacketSize.size; tusb_xfer_type_t const eptype = (tusb_xfer_type_t)ep_desc->bmAttributes.xfer; - uint8_t fifoSize = 0; // FIFO size - uint16_t defaultEndpointSize = 8; // Default size of Endpoint - // Find upper 2 power number of epMaxPktSize + uint8_t fifoSize = 0; // FIFO size + uint16_t defaultEndpointSize = 8; // Default size of Endpoint + // Find upper 2 power number of epMaxPktSize if (epMaxPktSize) { while (defaultEndpointSize < epMaxPktSize) @@ -458,16 +458,16 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) } } xfer_status[epnum].max_packet_size = epMaxPktSize; - + USBHS->USBHS_DEVEPT |= 1 << (USBHS_DEVEPT_EPRST0_Pos + epnum); USBHS->USBHS_DEVEPT &=~(1 << (USBHS_DEVEPT_EPRST0_Pos + epnum)); - - if (epnum == 0) + + if (epnum == 0) { xfer_status[EP_MAX].max_packet_size = epMaxPktSize; - // Enable the control endpoint - Endpoint 0 + // Enable the control endpoint - Endpoint 0 USBHS->USBHS_DEVEPT |= USBHS_DEVEPT_EPEN0; - // Configure the Endpoint 0 configuration register + // Configure the Endpoint 0 configuration register USBHS->USBHS_DEVEPTCFG[0] = ( USBHS_DEVEPTCFG_EPSIZE(fifoSize) | @@ -479,20 +479,20 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) USBHS->USBHS_DEVEPTIDR[0] = USBHS_DEVEPTIDR_CTRL_STALLRQC; if (USBHS_DEVEPTISR_CFGOK == (USBHS->USBHS_DEVEPTISR[0] & USBHS_DEVEPTISR_CFGOK)) { - // Endpoint configuration is successful + // Endpoint configuration is successful USBHS->USBHS_DEVEPTIER[0] = USBHS_DEVEPTIER_CTRL_RXSTPES; - // Enable Endpoint 0 Interrupts + // Enable Endpoint 0 Interrupts USBHS->USBHS_DEVIER = USBHS_DEVIER_PEP_0; return true; } else { - // Endpoint configuration is not successful + // Endpoint configuration is not successful return false; } } else { - // Enable the endpoint + // Enable the endpoint USBHS->USBHS_DEVEPT |= ((0x01 << epnum) << USBHS_DEVEPT_EPEN0_Pos); // Set up the maxpacket size, fifo start address fifosize - // and enable the interrupt. CLear the data toggle. + // and enable the interrupt. CLear the data toggle. // AUTOSW is needed for DMA ack ! USBHS->USBHS_DEVEPTCFG[epnum] = ( @@ -504,12 +504,12 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) ); if (eptype == TUSB_XFER_ISOCHRONOUS) { - USBHS->USBHS_DEVEPTCFG[epnum] |= USBHS_DEVEPTCFG_NBTRANS(1); + USBHS->USBHS_DEVEPTCFG[epnum] |= USBHS_DEVEPTCFG_NBTRANS(1); } #if USE_DUAL_BANK if (eptype == TUSB_XFER_ISOCHRONOUS || eptype == TUSB_XFER_BULK) { - USBHS->USBHS_DEVEPTCFG[epnum] |= USBHS_DEVEPTCFG_EPBK_2_BANK; + USBHS->USBHS_DEVEPTCFG[epnum] |= USBHS_DEVEPTCFG_EPBK_2_BANK; } #endif USBHS->USBHS_DEVEPTCFG[epnum] |= USBHS_DEVEPTCFG_ALLOC; @@ -520,7 +520,7 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) USBHS->USBHS_DEVIER = ((0x01 << epnum) << USBHS_DEVIER_PEP_0_Pos); return true; } else { - // Endpoint configuration is not successful + // Endpoint configuration is not successful return false; } } @@ -546,7 +546,7 @@ static void dcd_transmit_packet(xfer_ctl_t * xfer, uint8_t ep_ix) { // Control endpoint: clear the interrupt flag to send the data USBHS->USBHS_DEVEPTICR[0] = USBHS_DEVEPTICR_TXINIC; - + } else { // Other endpoint types: clear the FIFO control flag to send the data USBHS->USBHS_DEVEPTIDR[ep_ix] = USBHS_DEVEPTIDR_FIFOCONC; @@ -560,16 +560,16 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t (void) rhport; uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); - + xfer_ctl_t * xfer = &xfer_status[epnum]; if(ep_addr == 0x80) xfer = &xfer_status[EP_MAX]; - + xfer->buffer = buffer; xfer->total_len = total_bytes; xfer->queued_len = 0; xfer->fifo = NULL; - + if(EP_DMA_SUPPORT(epnum) && total_bytes != 0) { uint32_t udd_dma_ctrl = USBHS_DEVDMACONTROL_BUFF_LENGTH(total_bytes); @@ -618,16 +618,16 @@ bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16 (void) rhport; uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); - + xfer_ctl_t * xfer = &xfer_status[epnum]; if(epnum == 0x80) xfer = &xfer_status[EP_MAX]; - + xfer->buffer = NULL; xfer->total_len = total_bytes; xfer->queued_len = 0; xfer->fifo = ff; - + if (EP_DMA_SUPPORT(epnum) && total_bytes != 0) { tu_fifo_buffer_info_t info; @@ -646,13 +646,13 @@ bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16 } udd_dma_ctrl_wrap |= USBHS_DEVDMACONTROL_END_B_EN; } - + USBHS->UsbhsDevdma[epnum - 1].USBHS_DEVDMAADDRESS = (uint32_t)info.ptr_lin; if (info.len_wrap) { dma_desc[epnum - 1].next_desc = 0; dma_desc[epnum - 1].buff_addr = (uint32_t)info.ptr_wrap; - dma_desc[epnum - 1].chnl_ctrl = + dma_desc[epnum - 1].chnl_ctrl = udd_dma_ctrl_wrap | USBHS_DEVDMACONTROL_BUFF_LENGTH(info.len_wrap); udd_dma_ctrl_lin |= USBHS_DEVDMASTATUS_DESC_LDST; __DSB(); From 776a7709474a0736ed21218c2ff84208745c58cc Mon Sep 17 00:00:00 2001 From: Rafael Silva Date: Fri, 11 Jun 2021 22:50:00 +0100 Subject: [PATCH 12/36] dcd: sam7x: rename family dcd to include the whole family Signed-off-by: Rafael Silva --- examples/device/cdc_dual_ports/src/tusb_config.h | 2 +- examples/device/cdc_dual_ports/src/usb_descriptors.c | 2 +- examples/device/cdc_msc/src/tusb_config.h | 2 +- examples/device/cdc_msc/src/usb_descriptors.c | 2 +- hw/bsp/same70_xplained/board.mk | 4 ++-- .../microchip/{same70/dcd_same70.c => sam7x/dcd_sam7x.c} | 4 ++-- src/tusb_option.h | 3 ++- 7 files changed, 10 insertions(+), 9 deletions(-) rename src/portable/microchip/{same70/dcd_same70.c => sam7x/dcd_sam7x.c} (99%) diff --git a/examples/device/cdc_dual_ports/src/tusb_config.h b/examples/device/cdc_dual_ports/src/tusb_config.h index 45167da8..19b6925b 100644 --- a/examples/device/cdc_dual_ports/src/tusb_config.h +++ b/examples/device/cdc_dual_ports/src/tusb_config.h @@ -48,7 +48,7 @@ // Default to Highspeed for MCU with internal HighSpeed PHY (can be port specific), otherwise FullSpeed #ifndef BOARD_DEVICE_RHPORT_SPEED #if (CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || \ - CFG_TUSB_MCU == OPT_MCU_NUC505 || CFG_TUSB_MCU == OPT_MCU_CXD56 || CFG_TUSB_MCU == OPT_MCU_SAME70) + CFG_TUSB_MCU == OPT_MCU_NUC505 || CFG_TUSB_MCU == OPT_MCU_CXD56 || CFG_TUSB_MCU == OPT_MCU_SAM7X) #define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_HIGH_SPEED #else #define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_FULL_SPEED diff --git a/examples/device/cdc_dual_ports/src/usb_descriptors.c b/examples/device/cdc_dual_ports/src/usb_descriptors.c index e39c140c..f1f71a77 100644 --- a/examples/device/cdc_dual_ports/src/usb_descriptors.c +++ b/examples/device/cdc_dual_ports/src/usb_descriptors.c @@ -94,7 +94,7 @@ enum #define EPNUM_CDC_1_OUT 0x05 #define EPNUM_CDC_1_IN 0x85 -#elif CFG_TUSB_MCU == OPT_MCU_SAMG || CFG_TUSB_MCU == OPT_MCU_SAME70 +#elif CFG_TUSB_MCU == OPT_MCU_SAMG || CFG_TUSB_MCU == OPT_MCU_SAM7X // SAMG & SAME70 don't support a same endpoint number with different direction IN and OUT // e.g EP1 OUT & EP1 IN cannot exist together #define EPNUM_CDC_0_NOTIF 0x81 diff --git a/examples/device/cdc_msc/src/tusb_config.h b/examples/device/cdc_msc/src/tusb_config.h index f9e98b0f..950f3c42 100644 --- a/examples/device/cdc_msc/src/tusb_config.h +++ b/examples/device/cdc_msc/src/tusb_config.h @@ -48,7 +48,7 @@ // Default to Highspeed for MCU with internal HighSpeed PHY (can be port specific), otherwise FullSpeed #ifndef BOARD_DEVICE_RHPORT_SPEED #if (CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || \ - CFG_TUSB_MCU == OPT_MCU_NUC505 || CFG_TUSB_MCU == OPT_MCU_CXD56 || CFG_TUSB_MCU == OPT_MCU_SAME70) + CFG_TUSB_MCU == OPT_MCU_NUC505 || CFG_TUSB_MCU == OPT_MCU_CXD56 || CFG_TUSB_MCU == OPT_MCU_SAM7X) #define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_HIGH_SPEED #else #define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_FULL_SPEED diff --git a/examples/device/cdc_msc/src/usb_descriptors.c b/examples/device/cdc_msc/src/usb_descriptors.c index 46b57f7e..6ac34e85 100644 --- a/examples/device/cdc_msc/src/usb_descriptors.c +++ b/examples/device/cdc_msc/src/usb_descriptors.c @@ -94,7 +94,7 @@ enum #define EPNUM_MSC_OUT 0x05 #define EPNUM_MSC_IN 0x85 -#elif CFG_TUSB_MCU == OPT_MCU_SAMG || CFG_TUSB_MCU == OPT_MCU_SAME70 +#elif CFG_TUSB_MCU == OPT_MCU_SAMG || CFG_TUSB_MCU == OPT_MCU_SAM7X // SAMG & SAME70 don't support a same endpoint number with different direction IN and OUT // e.g EP1 OUT & EP1 IN cannot exist together #define EPNUM_CDC_NOTIF 0x81 diff --git a/hw/bsp/same70_xplained/board.mk b/hw/bsp/same70_xplained/board.mk index 13c552f9..031b536b 100644 --- a/hw/bsp/same70_xplained/board.mk +++ b/hw/bsp/same70_xplained/board.mk @@ -8,7 +8,7 @@ CFLAGS += \ -mfpu=fpv4-sp-d16 \ -nostdlib -nostartfiles \ -D__SAME70Q21B__ \ - -DCFG_TUSB_MCU=OPT_MCU_SAME70 + -DCFG_TUSB_MCU=OPT_MCU_SAM7X # suppress following warnings from mcu driver CFLAGS += -Wno-error=unused-parameter -Wno-error=cast-align @@ -19,7 +19,7 @@ ASF_DIR = hw/mcu/microchip/same70 LD_FILE = $(ASF_DIR)/same70b/gcc/gcc/same70q21b_flash.ld SRC_C += \ - src/portable/microchip/same70/dcd_same70.c \ + src/portable/microchip/sam7x/dcd_sam7x.c \ $(ASF_DIR)/same70b/gcc/gcc/startup_same70q21b.c \ $(ASF_DIR)/same70b/gcc/system_same70q21b.c \ $(ASF_DIR)/hpl/core/hpl_init.c \ diff --git a/src/portable/microchip/same70/dcd_same70.c b/src/portable/microchip/sam7x/dcd_sam7x.c similarity index 99% rename from src/portable/microchip/same70/dcd_same70.c rename to src/portable/microchip/sam7x/dcd_sam7x.c index 0ad9ad62..53ea796b 100644 --- a/src/portable/microchip/same70/dcd_same70.c +++ b/src/portable/microchip/sam7x/dcd_sam7x.c @@ -27,7 +27,7 @@ #include "tusb_option.h" -#if CFG_TUSB_MCU == OPT_MCU_SAME70 +#if TUSB_OPT_DEVICE_ENABLED && CFG_TUSB_MCU == OPT_MCU_SAM7X #include "device/dcd.h" @@ -43,7 +43,7 @@ #endif // Dual bank can imporve performance, but need 2 times bigger packet buffer -// As SAME70 has only 4KB packet buffer, use with caution ! +// As SAM7x has only 4KB packet buffer, use with caution ! // Enable in FS mode as packets are smaller #ifndef USE_DUAL_BANK # if TUD_OPT_HIGH_SPEED diff --git a/src/tusb_option.h b/src/tusb_option.h index fb86d7f9..2e1678cc 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -61,7 +61,8 @@ #define OPT_MCU_SAME5X 203 ///< MicroChip SAM E5x #define OPT_MCU_SAMD11 204 ///< MicroChip SAMD11 #define OPT_MCU_SAML22 205 ///< MicroChip SAML22 -#define OPT_MCU_SAME70 206 ///< MicroChip SAME70 series +#define OPT_MCU_SAM7X 206 ///< MicroChip SAME70, S70, V70, V71 family + // STM32 #define OPT_MCU_STM32F0 300 ///< ST STM32F0 From 0066e2b3444e549e7bc7f6ea757548688d46ddc9 Mon Sep 17 00:00:00 2001 From: Rafael Silva Date: Fri, 11 Jun 2021 23:31:38 +0100 Subject: [PATCH 13/36] examples: freertos: add skip for same70 Signed-off-by: Rafael Silva --- examples/device/cdc_msc_freertos/.skip.MCU_SAM7X | 0 examples/device/hid_composite_freertos/.skip.MCU_SAM7X | 0 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 examples/device/cdc_msc_freertos/.skip.MCU_SAM7X create mode 100644 examples/device/hid_composite_freertos/.skip.MCU_SAM7X diff --git a/examples/device/cdc_msc_freertos/.skip.MCU_SAM7X b/examples/device/cdc_msc_freertos/.skip.MCU_SAM7X new file mode 100644 index 00000000..e69de29b diff --git a/examples/device/hid_composite_freertos/.skip.MCU_SAM7X b/examples/device/hid_composite_freertos/.skip.MCU_SAM7X new file mode 100644 index 00000000..e69de29b From f039607afcf7473ea3869f2e2e7cd763d13f8de0 Mon Sep 17 00:00:00 2001 From: MasterPhi Date: Sat, 12 Jun 2021 11:19:08 +0200 Subject: [PATCH 14/36] Fix indent. Signed-off-by: MasterPhi --- src/portable/microchip/sam7x/dcd_sam7x.c | 58 ++++++++++++------------ 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/src/portable/microchip/sam7x/dcd_sam7x.c b/src/portable/microchip/sam7x/dcd_sam7x.c index 53ea796b..6463973b 100644 --- a/src/portable/microchip/sam7x/dcd_sam7x.c +++ b/src/portable/microchip/sam7x/dcd_sam7x.c @@ -430,7 +430,7 @@ void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * re if (request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_DEVICE && request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD && - request->bRequest == TUSB_REQ_SET_ADDRESS ) + request->bRequest == TUSB_REQ_SET_ADDRESS ) { uint8_t const dev_addr = (uint8_t) request->wValue; @@ -474,7 +474,7 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) USBHS_DEVEPTCFG_EPTYPE(TUSB_XFER_CONTROL) | USBHS_DEVEPTCFG_EPBK(USBHS_DEVEPTCFG_EPBK_1_BANK) | USBHS_DEVEPTCFG_ALLOC - ); + ); USBHS->USBHS_DEVEPTIER[0] = USBHS_DEVEPTIER_RSTDTS; USBHS->USBHS_DEVEPTIDR[0] = USBHS_DEVEPTIDR_CTRL_STALLRQC; if (USBHS_DEVEPTISR_CFGOK == (USBHS->USBHS_DEVEPTISR[0] & USBHS_DEVEPTISR_CFGOK)) @@ -501,7 +501,7 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) USBHS_DEVEPTCFG_EPBK(USBHS_DEVEPTCFG_EPBK_1_BANK) | USBHS_DEVEPTCFG_AUTOSW | ((dir & 0x01) << USBHS_DEVEPTCFG_EPDIR_Pos) - ); + ); if (eptype == TUSB_XFER_ISOCHRONOUS) { USBHS->USBHS_DEVEPTCFG[epnum] |= USBHS_DEVEPTCFG_NBTRANS(1); @@ -570,7 +570,7 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t xfer->queued_len = 0; xfer->fifo = NULL; - if(EP_DMA_SUPPORT(epnum) && total_bytes != 0) + if (EP_DMA_SUPPORT(epnum) && total_bytes != 0) { uint32_t udd_dma_ctrl = USBHS_DEVDMACONTROL_BUFF_LENGTH(total_bytes); if (dir == TUSB_DIR_OUT) @@ -579,24 +579,24 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t } else { udd_dma_ctrl |= USBHS_DEVDMACONTROL_END_B_EN; } - USBHS->UsbhsDevdma[epnum - 1].USBHS_DEVDMAADDRESS = (uint32_t)buffer; - udd_dma_ctrl |= USBHS_DEVDMACONTROL_END_BUFFIT | USBHS_DEVDMACONTROL_CHANN_ENB; + USBHS->UsbhsDevdma[epnum - 1].USBHS_DEVDMAADDRESS = (uint32_t)buffer; + udd_dma_ctrl |= USBHS_DEVDMACONTROL_END_BUFFIT | USBHS_DEVDMACONTROL_CHANN_ENB; // Disable IRQs to have a short sequence - // between read of EOT_STA and DMA enable - uint32_t irq_state = __get_PRIMASK(); + // between read of EOT_STA and DMA enable + uint32_t irq_state = __get_PRIMASK(); __disable_irq(); - if (!(USBHS->UsbhsDevdma[epnum - 1].USBHS_DEVDMASTATUS & USBHS_DEVDMASTATUS_END_TR_ST)) + if (!(USBHS->UsbhsDevdma[epnum - 1].USBHS_DEVDMASTATUS & USBHS_DEVDMASTATUS_END_TR_ST)) { USBHS->UsbhsDevdma[epnum - 1].USBHS_DEVDMACONTROL = udd_dma_ctrl; - USBHS->USBHS_DEVIER = USBHS_DEVIER_DMA_1 << (epnum - 1); - __set_PRIMASK(irq_state); - return true; - } - __set_PRIMASK(irq_state); + USBHS->USBHS_DEVIER = USBHS_DEVIER_DMA_1 << (epnum - 1); + __set_PRIMASK(irq_state); + return true; + } + __set_PRIMASK(irq_state); - // Here a ZLP has been recieved - // and the DMA transfer must be not started. - // It is the end of transfer + // Here a ZLP has been recieved + // and the DMA transfer must be not started. + // It is the end of transfer return false; } else { if (dir == TUSB_DIR_OUT) @@ -661,23 +661,23 @@ bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16 } else { udd_dma_ctrl_lin |= USBHS_DEVDMACONTROL_END_BUFFIT; } - udd_dma_ctrl_lin |= USBHS_DEVDMACONTROL_BUFF_LENGTH(info.len_lin); + udd_dma_ctrl_lin |= USBHS_DEVDMACONTROL_BUFF_LENGTH(info.len_lin); // Disable IRQs to have a short sequence - // between read of EOT_STA and DMA enable - uint32_t irq_state = __get_PRIMASK(); + // between read of EOT_STA and DMA enable + uint32_t irq_state = __get_PRIMASK(); __disable_irq(); - if (!(USBHS->UsbhsDevdma[epnum - 1].USBHS_DEVDMASTATUS & USBHS_DEVDMASTATUS_END_TR_ST)) + if (!(USBHS->UsbhsDevdma[epnum - 1].USBHS_DEVDMASTATUS & USBHS_DEVDMASTATUS_END_TR_ST)) { USBHS->UsbhsDevdma[epnum - 1].USBHS_DEVDMACONTROL = udd_dma_ctrl_lin; - USBHS->USBHS_DEVIER = USBHS_DEVIER_DMA_1 << (epnum - 1); - __set_PRIMASK(irq_state); - return true; - } - __set_PRIMASK(irq_state); + USBHS->USBHS_DEVIER = USBHS_DEVIER_DMA_1 << (epnum - 1); + __set_PRIMASK(irq_state); + return true; + } + __set_PRIMASK(irq_state); - // Here a ZLP has been recieved - // and the DMA transfer must be not started. - // It is the end of transfer + // Here a ZLP has been recieved + // and the DMA transfer must be not started. + // It is the end of transfer return false; } else { if (dir == TUSB_DIR_OUT) From 85fc42356977cac4d893c33eff80937e6ff9b45a Mon Sep 17 00:00:00 2001 From: MasterPhi Date: Sat, 12 Jun 2021 12:28:28 +0200 Subject: [PATCH 15/36] Rename SAM7X to SAMX7X Signed-off-by: MasterPhi --- examples/device/cdc_dual_ports/src/tusb_config.h | 2 +- examples/device/cdc_dual_ports/src/usb_descriptors.c | 2 +- examples/device/cdc_msc/src/msc_disk.c | 2 +- examples/device/cdc_msc/src/tusb_config.h | 2 +- examples/device/cdc_msc/src/usb_descriptors.c | 2 +- .../cdc_msc_freertos/{.skip.MCU_SAM7X => .skip.MCU_SAMX7X} | 0 .../{.skip.MCU_SAM7X => .skip.MCU_SAMX7X} | 0 hw/bsp/same70_xplained/board.mk | 4 ++-- .../microchip/{sam7x/dcd_sam7x.c => samx7x/dcd_samx7x.c} | 2 +- src/tusb_option.h | 2 +- 10 files changed, 9 insertions(+), 9 deletions(-) rename examples/device/cdc_msc_freertos/{.skip.MCU_SAM7X => .skip.MCU_SAMX7X} (100%) rename examples/device/hid_composite_freertos/{.skip.MCU_SAM7X => .skip.MCU_SAMX7X} (100%) rename src/portable/microchip/{sam7x/dcd_sam7x.c => samx7x/dcd_samx7x.c} (99%) diff --git a/examples/device/cdc_dual_ports/src/tusb_config.h b/examples/device/cdc_dual_ports/src/tusb_config.h index 19b6925b..ff8535d1 100644 --- a/examples/device/cdc_dual_ports/src/tusb_config.h +++ b/examples/device/cdc_dual_ports/src/tusb_config.h @@ -48,7 +48,7 @@ // Default to Highspeed for MCU with internal HighSpeed PHY (can be port specific), otherwise FullSpeed #ifndef BOARD_DEVICE_RHPORT_SPEED #if (CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || \ - CFG_TUSB_MCU == OPT_MCU_NUC505 || CFG_TUSB_MCU == OPT_MCU_CXD56 || CFG_TUSB_MCU == OPT_MCU_SAM7X) + CFG_TUSB_MCU == OPT_MCU_NUC505 || CFG_TUSB_MCU == OPT_MCU_CXD56 || CFG_TUSB_MCU == OPT_MCU_SAMX7X) #define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_HIGH_SPEED #else #define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_FULL_SPEED diff --git a/examples/device/cdc_dual_ports/src/usb_descriptors.c b/examples/device/cdc_dual_ports/src/usb_descriptors.c index f1f71a77..b935b672 100644 --- a/examples/device/cdc_dual_ports/src/usb_descriptors.c +++ b/examples/device/cdc_dual_ports/src/usb_descriptors.c @@ -94,7 +94,7 @@ enum #define EPNUM_CDC_1_OUT 0x05 #define EPNUM_CDC_1_IN 0x85 -#elif CFG_TUSB_MCU == OPT_MCU_SAMG || CFG_TUSB_MCU == OPT_MCU_SAM7X +#elif CFG_TUSB_MCU == OPT_MCU_SAMG || CFG_TUSB_MCU == OPT_MCU_SAMX7X // SAMG & SAME70 don't support a same endpoint number with different direction IN and OUT // e.g EP1 OUT & EP1 IN cannot exist together #define EPNUM_CDC_0_NOTIF 0x81 diff --git a/examples/device/cdc_msc/src/msc_disk.c b/examples/device/cdc_msc/src/msc_disk.c index 503baace..3caf3fd4 100644 --- a/examples/device/cdc_msc/src/msc_disk.c +++ b/examples/device/cdc_msc/src/msc_disk.c @@ -23,7 +23,7 @@ * */ -#include "bsp/board.h" +//#include "bsp/board.h" #include "tusb.h" #if CFG_TUD_MSC diff --git a/examples/device/cdc_msc/src/tusb_config.h b/examples/device/cdc_msc/src/tusb_config.h index 950f3c42..bf6af06b 100644 --- a/examples/device/cdc_msc/src/tusb_config.h +++ b/examples/device/cdc_msc/src/tusb_config.h @@ -48,7 +48,7 @@ // Default to Highspeed for MCU with internal HighSpeed PHY (can be port specific), otherwise FullSpeed #ifndef BOARD_DEVICE_RHPORT_SPEED #if (CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || \ - CFG_TUSB_MCU == OPT_MCU_NUC505 || CFG_TUSB_MCU == OPT_MCU_CXD56 || CFG_TUSB_MCU == OPT_MCU_SAM7X) + CFG_TUSB_MCU == OPT_MCU_NUC505 || CFG_TUSB_MCU == OPT_MCU_CXD56 || CFG_TUSB_MCU == OPT_MCU_SAMX7X) #define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_HIGH_SPEED #else #define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_FULL_SPEED diff --git a/examples/device/cdc_msc/src/usb_descriptors.c b/examples/device/cdc_msc/src/usb_descriptors.c index 6ac34e85..1a89ce56 100644 --- a/examples/device/cdc_msc/src/usb_descriptors.c +++ b/examples/device/cdc_msc/src/usb_descriptors.c @@ -94,7 +94,7 @@ enum #define EPNUM_MSC_OUT 0x05 #define EPNUM_MSC_IN 0x85 -#elif CFG_TUSB_MCU == OPT_MCU_SAMG || CFG_TUSB_MCU == OPT_MCU_SAM7X +#elif CFG_TUSB_MCU == OPT_MCU_SAMG || CFG_TUSB_MCU == OPT_MCU_SAMX7X // SAMG & SAME70 don't support a same endpoint number with different direction IN and OUT // e.g EP1 OUT & EP1 IN cannot exist together #define EPNUM_CDC_NOTIF 0x81 diff --git a/examples/device/cdc_msc_freertos/.skip.MCU_SAM7X b/examples/device/cdc_msc_freertos/.skip.MCU_SAMX7X similarity index 100% rename from examples/device/cdc_msc_freertos/.skip.MCU_SAM7X rename to examples/device/cdc_msc_freertos/.skip.MCU_SAMX7X diff --git a/examples/device/hid_composite_freertos/.skip.MCU_SAM7X b/examples/device/hid_composite_freertos/.skip.MCU_SAMX7X similarity index 100% rename from examples/device/hid_composite_freertos/.skip.MCU_SAM7X rename to examples/device/hid_composite_freertos/.skip.MCU_SAMX7X diff --git a/hw/bsp/same70_xplained/board.mk b/hw/bsp/same70_xplained/board.mk index 031b536b..94b0bed9 100644 --- a/hw/bsp/same70_xplained/board.mk +++ b/hw/bsp/same70_xplained/board.mk @@ -8,7 +8,7 @@ CFLAGS += \ -mfpu=fpv4-sp-d16 \ -nostdlib -nostartfiles \ -D__SAME70Q21B__ \ - -DCFG_TUSB_MCU=OPT_MCU_SAM7X + -DCFG_TUSB_MCU=OPT_MCU_SAMX7X # suppress following warnings from mcu driver CFLAGS += -Wno-error=unused-parameter -Wno-error=cast-align @@ -19,7 +19,7 @@ ASF_DIR = hw/mcu/microchip/same70 LD_FILE = $(ASF_DIR)/same70b/gcc/gcc/same70q21b_flash.ld SRC_C += \ - src/portable/microchip/sam7x/dcd_sam7x.c \ + src/portable/microchip/samx7x/dcd_samx7x.c \ $(ASF_DIR)/same70b/gcc/gcc/startup_same70q21b.c \ $(ASF_DIR)/same70b/gcc/system_same70q21b.c \ $(ASF_DIR)/hpl/core/hpl_init.c \ diff --git a/src/portable/microchip/sam7x/dcd_sam7x.c b/src/portable/microchip/samx7x/dcd_samx7x.c similarity index 99% rename from src/portable/microchip/sam7x/dcd_sam7x.c rename to src/portable/microchip/samx7x/dcd_samx7x.c index 6463973b..a864fda5 100644 --- a/src/portable/microchip/sam7x/dcd_sam7x.c +++ b/src/portable/microchip/samx7x/dcd_samx7x.c @@ -27,7 +27,7 @@ #include "tusb_option.h" -#if TUSB_OPT_DEVICE_ENABLED && CFG_TUSB_MCU == OPT_MCU_SAM7X +#if TUSB_OPT_DEVICE_ENABLED && CFG_TUSB_MCU == OPT_MCU_SAMX7X #include "device/dcd.h" diff --git a/src/tusb_option.h b/src/tusb_option.h index 2e1678cc..3f571036 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -61,7 +61,7 @@ #define OPT_MCU_SAME5X 203 ///< MicroChip SAM E5x #define OPT_MCU_SAMD11 204 ///< MicroChip SAMD11 #define OPT_MCU_SAML22 205 ///< MicroChip SAML22 -#define OPT_MCU_SAM7X 206 ///< MicroChip SAME70, S70, V70, V71 family +#define OPT_MCU_SAMX7X 206 ///< MicroChip SAME70, S70, V70, V71 family // STM32 From ca8e8041ef05ba06d7d01bf1567106a76a793cab Mon Sep 17 00:00:00 2001 From: MasterPhi Date: Tue, 15 Jun 2021 17:53:09 +0200 Subject: [PATCH 16/36] Fix resume, always init FS clock. Signed-off-by: MasterPhi --- examples/device/hid_composite/src/tusb_config.h | 4 ++-- src/portable/microchip/samx7x/dcd_samx7x.c | 5 ++--- src/tusb_option.h | 2 +- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/examples/device/hid_composite/src/tusb_config.h b/examples/device/hid_composite/src/tusb_config.h index 3e608ed3..31dea4ee 100644 --- a/examples/device/hid_composite/src/tusb_config.h +++ b/examples/device/hid_composite/src/tusb_config.h @@ -48,7 +48,7 @@ // Default to Highspeed for MCU with internal HighSpeed PHY (can be port specific), otherwise FullSpeed #ifndef BOARD_DEVICE_RHPORT_SPEED #if (CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || \ - CFG_TUSB_MCU == OPT_MCU_NUC505 || CFG_TUSB_MCU == OPT_MCU_CXD56) + CFG_TUSB_MCU == OPT_MCU_NUC505 || CFG_TUSB_MCU == OPT_MCU_CXD56 || CFG_TUSB_MCU == OPT_MCU_SAMX7X) #define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_HIGH_SPEED #else #define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_FULL_SPEED @@ -69,7 +69,7 @@ #endif // CFG_TUSB_DEBUG is defined by compiler in DEBUG build -// #define CFG_TUSB_DEBUG 0 +#define CFG_TUSB_DEBUG 0 /* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment. * Tinyusb use follows macros to declare transferring memory so that they can be put diff --git a/src/portable/microchip/samx7x/dcd_samx7x.c b/src/portable/microchip/samx7x/dcd_samx7x.c index a864fda5..f486e0ee 100644 --- a/src/portable/microchip/samx7x/dcd_samx7x.c +++ b/src/portable/microchip/samx7x/dcd_samx7x.c @@ -49,7 +49,7 @@ # if TUD_OPT_HIGH_SPEED # define USE_DUAL_BANK 0 # else -# define USE_DUAL_BANK 1 +# define USE_DUAL_BANK 0 # endif #endif @@ -108,12 +108,10 @@ void dcd_init (uint8_t rhport) PMC->CKGR_UCKR = CKGR_UCKR_UPLLEN | CKGR_UCKR_UPLLCOUNT(0x3fU); // Wait until USB UTMI stabilize while (!(PMC->PMC_SR & PMC_SR_LOCKU)); -#if !TUD_OPT_HIGH_SPEED // Enable USB FS clk PMC->PMC_MCKR &= ~PMC_MCKR_UPLLDIV2; PMC->PMC_USB = PMC_USB_USBS | PMC_USB_USBDIV(10 - 1); PMC->PMC_SCER = PMC_SCER_USBCLK; -#endif dcd_connect(rhport); } @@ -346,6 +344,7 @@ void dcd_int_handler(uint8_t rhport) { (void) rhport; uint32_t int_status = USBHS->USBHS_DEVISR; + int_status &= USBHS->USBHS_DEVIMR; // End of reset interrupt if (int_status & USBHS_DEVISR_EORST) { diff --git a/src/tusb_option.h b/src/tusb_option.h index 3f571036..69c5fb0b 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -61,7 +61,7 @@ #define OPT_MCU_SAME5X 203 ///< MicroChip SAM E5x #define OPT_MCU_SAMD11 204 ///< MicroChip SAMD11 #define OPT_MCU_SAML22 205 ///< MicroChip SAML22 -#define OPT_MCU_SAMX7X 206 ///< MicroChip SAME70, S70, V70, V71 family +#define OPT_MCU_SAMX7X 206 ///< MicroChip SAME70, S70, V70, V71 family // STM32 From 54dc694be4430e51d153405afa3b80d949479558 Mon Sep 17 00:00:00 2001 From: MasterPhi Date: Tue, 15 Jun 2021 19:11:53 +0200 Subject: [PATCH 17/36] Use byte copy. --- src/portable/microchip/samx7x/dcd_samx7x.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/portable/microchip/samx7x/dcd_samx7x.c b/src/portable/microchip/samx7x/dcd_samx7x.c index f486e0ee..a46fa2cf 100644 --- a/src/portable/microchip/samx7x/dcd_samx7x.c +++ b/src/portable/microchip/samx7x/dcd_samx7x.c @@ -243,7 +243,9 @@ static void dcd_ep_handler(uint8_t ep_ix) uint8_t *ptr = EP_GET_FIFO_PTR(0,8); if (xfer->buffer) { - memcpy(xfer->buffer + xfer->queued_len, ptr, count); + //memcpy(xfer->buffer + xfer->queued_len, ptr, count); + for(int i = 0; i < count; i++) + xfer->buffer[i + xfer->queued_len] = ptr[i]; } else { tu_fifo_write_n(xfer->fifo, ptr, count); } @@ -283,7 +285,9 @@ static void dcd_ep_handler(uint8_t ep_ix) uint8_t *ptr = EP_GET_FIFO_PTR(ep_ix,8); if (xfer->buffer) { - memcpy(xfer->buffer + xfer->queued_len, ptr, count); + //memcpy(xfer->buffer + xfer->queued_len, ptr, count); + for(int i = 0; i < count; i++) + xfer->buffer[i + xfer->queued_len] = ptr[i]; } else { tu_fifo_write_n(xfer->fifo, ptr, count); } @@ -535,7 +539,9 @@ static void dcd_transmit_packet(xfer_ctl_t * xfer, uint8_t ep_ix) uint8_t *ptr = EP_GET_FIFO_PTR(ep_ix,8); if(xfer->buffer) { - memcpy(ptr, xfer->buffer + xfer->queued_len, len); + //memcpy(ptr, xfer->buffer + xfer->queued_len, len); + for(int i = 0; i < len; i++) + ptr[i] = xfer->buffer[i + xfer->queued_len]; } else { tu_fifo_read_n(xfer->fifo, ptr, len); @@ -569,6 +575,11 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t xfer->queued_len = 0; xfer->fifo = NULL; + TU_LOG3("Xfer: "); + for(int i = 0; i < total_bytes; i++) + TU_LOG3("%02X ", buffer[i]); + TU_LOG3("\r\n"); + if (EP_DMA_SUPPORT(epnum) && total_bytes != 0) { uint32_t udd_dma_ctrl = USBHS_DEVDMACONTROL_BUFF_LENGTH(total_bytes); From 6cc702e9ece9bbf32ac9ad4283407b4937c671a9 Mon Sep 17 00:00:00 2001 From: MasterPhi Date: Tue, 15 Jun 2021 21:16:51 +0200 Subject: [PATCH 18/36] Prevent buffer overflow. Signed-off-by: MasterPhi --- src/portable/microchip/samx7x/dcd_samx7x.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/portable/microchip/samx7x/dcd_samx7x.c b/src/portable/microchip/samx7x/dcd_samx7x.c index a46fa2cf..848febc6 100644 --- a/src/portable/microchip/samx7x/dcd_samx7x.c +++ b/src/portable/microchip/samx7x/dcd_samx7x.c @@ -238,8 +238,13 @@ static void dcd_ep_handler(uint8_t ep_ix) if (int_status & USBHS_DEVEPTISR_RXOUTI) { xfer_ctl_t *xfer = &xfer_status[0]; - if (count) + if (count && xfer->total_len) { + uint16_t remain = xfer->total_len - xfer->queued_len; + if (count > remain) + { + count = remain; + } uint8_t *ptr = EP_GET_FIFO_PTR(0,8); if (xfer->buffer) { @@ -256,7 +261,7 @@ static void dcd_ep_handler(uint8_t ep_ix) if ((count < xfer->max_packet_size) || (xfer->queued_len == xfer->total_len)) { // RX COMPLETE - dcd_event_xfer_complete(0, 0, xfer->queued_len, XFER_RESULT_SUCCESS, true); + dcd_event_xfer_complete(0, 0, xfer->total_len, XFER_RESULT_SUCCESS, true); // Disable the interrupt USBHS->USBHS_DEVEPTIDR[0] = USBHS_DEVEPTIDR_RXOUTEC; // Though the host could still send, we don't know. @@ -280,8 +285,13 @@ static void dcd_ep_handler(uint8_t ep_ix) if (int_status & USBHS_DEVEPTISR_RXOUTI) { xfer_ctl_t *xfer = &xfer_status[ep_ix]; - if (count) + if (count && xfer->total_len) { + uint16_t remain = xfer->total_len - xfer->queued_len; + if (count > remain) + { + count = remain; + } uint8_t *ptr = EP_GET_FIFO_PTR(ep_ix,8); if (xfer->buffer) { From 67a6560ec9f379418cccc312ee09bb021e464716 Mon Sep 17 00:00:00 2001 From: MasterPhi Date: Tue, 15 Jun 2021 21:34:42 +0200 Subject: [PATCH 19/36] Default use dual bank for FS, use dcd irq switch. --- src/portable/microchip/samx7x/dcd_samx7x.c | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/src/portable/microchip/samx7x/dcd_samx7x.c b/src/portable/microchip/samx7x/dcd_samx7x.c index 848febc6..a9e125b7 100644 --- a/src/portable/microchip/samx7x/dcd_samx7x.c +++ b/src/portable/microchip/samx7x/dcd_samx7x.c @@ -49,7 +49,7 @@ # if TUD_OPT_HIGH_SPEED # define USE_DUAL_BANK 0 # else -# define USE_DUAL_BANK 0 +# define USE_DUAL_BANK 1 # endif #endif @@ -151,8 +151,7 @@ void dcd_remote_wakeup (uint8_t rhport) void dcd_connect(uint8_t rhport) { (void) rhport; - uint32_t irq_state = __get_PRIMASK(); - __disable_irq(); + dcd_int_disable(rhport); // Enable USB clock PMC->PMC_PCER1 = 1 << (ID_USBHS - 32); // Enable the USB controller in device mode @@ -178,15 +177,13 @@ void dcd_connect(uint8_t rhport) USBHS->USBHS_DEVCTRL &= ~USBHS_DEVCTRL_DETACH; // Freeze USB clock USBHS->USBHS_CTRL |= USBHS_CTRL_FRZCLK; - __set_PRIMASK(irq_state); } // Disconnect by disabling internal pull-up resistor on D+/D- void dcd_disconnect(uint8_t rhport) { (void) rhport; - uint32_t irq_state = __get_PRIMASK(); - __disable_irq(); + dcd_int_disable(rhport); // Disable all endpoints USBHS->USBHS_DEVEPT &= ~(0x3FF << USBHS_DEVEPT_EPEN0_Pos); // Unfreeze USB clock @@ -200,7 +197,6 @@ void dcd_disconnect(uint8_t rhport) USBHS->USBHS_DEVCTRL |= USBHS_DEVCTRL_DETACH; // Disable the device address USBHS->USBHS_DEVCTRL &=~(USBHS_DEVCTRL_ADDEN | USBHS_DEVCTRL_UADD_Msk); - __set_PRIMASK(irq_state); } static tusb_speed_t get_speed(void) @@ -584,11 +580,6 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t xfer->total_len = total_bytes; xfer->queued_len = 0; xfer->fifo = NULL; - - TU_LOG3("Xfer: "); - for(int i = 0; i < total_bytes; i++) - TU_LOG3("%02X ", buffer[i]); - TU_LOG3("\r\n"); if (EP_DMA_SUPPORT(epnum) && total_bytes != 0) { From 30fff56aa4b3e75dd14b95cf21484e7342088997 Mon Sep 17 00:00:00 2001 From: MasterPhi Date: Wed, 16 Jun 2021 00:18:38 +0200 Subject: [PATCH 20/36] Revert "Use byte copy.", add barrier after buffer write. Signed-off-by: MasterPhi --- src/portable/microchip/samx7x/dcd_samx7x.c | 38 ++++++++++------------ 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/src/portable/microchip/samx7x/dcd_samx7x.c b/src/portable/microchip/samx7x/dcd_samx7x.c index a9e125b7..0299d12b 100644 --- a/src/portable/microchip/samx7x/dcd_samx7x.c +++ b/src/portable/microchip/samx7x/dcd_samx7x.c @@ -244,9 +244,7 @@ static void dcd_ep_handler(uint8_t ep_ix) uint8_t *ptr = EP_GET_FIFO_PTR(0,8); if (xfer->buffer) { - //memcpy(xfer->buffer + xfer->queued_len, ptr, count); - for(int i = 0; i < count; i++) - xfer->buffer[i + xfer->queued_len] = ptr[i]; + memcpy(xfer->buffer + xfer->queued_len, ptr, count); } else { tu_fifo_write_n(xfer->fifo, ptr, count); } @@ -291,9 +289,7 @@ static void dcd_ep_handler(uint8_t ep_ix) uint8_t *ptr = EP_GET_FIFO_PTR(ep_ix,8); if (xfer->buffer) { - //memcpy(xfer->buffer + xfer->queued_len, ptr, count); - for(int i = 0; i < count; i++) - xfer->buffer[i + xfer->queued_len] = ptr[i]; + memcpy(xfer->buffer + xfer->queued_len, ptr, count); } else { tu_fifo_write_n(xfer->fifo, ptr, count); } @@ -538,26 +534,28 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) static void dcd_transmit_packet(xfer_ctl_t * xfer, uint8_t ep_ix) { uint16_t len = (uint16_t)(xfer->total_len - xfer->queued_len); - if (len > xfer->max_packet_size) + if (len) { - len = xfer->max_packet_size; + if (len > xfer->max_packet_size) + { + len = xfer->max_packet_size; + } + uint8_t *ptr = EP_GET_FIFO_PTR(ep_ix,8); + if(xfer->buffer) + { + memcpy(ptr, xfer->buffer + xfer->queued_len, len); + } + else { + tu_fifo_read_n(xfer->fifo, ptr, len); + } + __DSB(); + __ISB(); + xfer->queued_len = (uint16_t)(xfer->queued_len + len); } - uint8_t *ptr = EP_GET_FIFO_PTR(ep_ix,8); - if(xfer->buffer) - { - //memcpy(ptr, xfer->buffer + xfer->queued_len, len); - for(int i = 0; i < len; i++) - ptr[i] = xfer->buffer[i + xfer->queued_len]; - } - else { - tu_fifo_read_n(xfer->fifo, ptr, len); - } - xfer->queued_len = (uint16_t)(xfer->queued_len + len); if (ep_ix == 0U) { // Control endpoint: clear the interrupt flag to send the data USBHS->USBHS_DEVEPTICR[0] = USBHS_DEVEPTICR_TXINIC; - } else { // Other endpoint types: clear the FIFO control flag to send the data USBHS->USBHS_DEVEPTIDR[ep_ix] = USBHS_DEVEPTIDR_FIFOCONC; From 9d6fd78b632db5b40e84e4c019f00286aae5d1ad Mon Sep 17 00:00:00 2001 From: Mengsk Date: Thu, 24 Jun 2021 11:34:29 +0200 Subject: [PATCH 21/36] Add fifo helper function to CDC class for DMA transfer. --- src/class/cdc/cdc_device.c | 14 ++++++++++++++ src/class/cdc/cdc_device.h | 18 ++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index cac811c4..a926081c 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -483,4 +483,18 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ return true; } +// Get the Receive FIFO (for DMA transfer) +tu_fifo_t* tud_cdc_n_get_rx_ff (uint8_t itf) +{ + TU_ASSERT(itf < CFG_TUD_CDC); + return &_cdcd_itf[itf].rx_ff; +} + +// Get the transmit FIFO (for DMA transfer) +tu_fifo_t* tud_cdc_n_get_tx_ff (uint8_t itf) +{ + TU_ASSERT(itf < CFG_TUD_CDC); + return &_cdcd_itf[itf].tx_ff; +} + #endif diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h index 7ff757ad..94678a66 100644 --- a/src/class/cdc/cdc_device.h +++ b/src/class/cdc/cdc_device.h @@ -104,6 +104,12 @@ uint32_t tud_cdc_n_write_available (uint8_t itf); // Clear the transmit FIFO bool tud_cdc_n_write_clear (uint8_t itf); +// Get the Receive FIFO (for DMA transfer) +tu_fifo_t* tud_cdc_n_get_rx_ff (uint8_t itf); + +// Get the transmit FIFO (for DMA transfer) +tu_fifo_t* tud_cdc_n_get_tx_ff (uint8_t itf); + //--------------------------------------------------------------------+ // Application API (Single Port) //--------------------------------------------------------------------+ @@ -241,6 +247,18 @@ static inline bool tud_cdc_write_clear(void) return tud_cdc_n_write_clear(0); } +// Get the Receive FIFO +static inline tu_fifo_t* tud_cdc_get_rx_ff (uint8_t itf) +{ + return tud_cdc_n_get_rx_ff(0); +} + +// Get the transmit FIFO +static inline tu_fifo_t* tud_cdc_get_tx_ff (uint8_t itf) +{ + return tud_cdc_n_get_tx_ff(0); +} + /** @} */ /** @} */ From b9e9773d04419032d9e8eb8ca568390f74382690 Mon Sep 17 00:00:00 2001 From: Mengsk Date: Thu, 24 Jun 2021 11:35:05 +0200 Subject: [PATCH 22/36] fix warning --- src/class/cdc/cdc_device.h | 4 ++-- src/device/usbd.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h index 94678a66..f8a2216c 100644 --- a/src/class/cdc/cdc_device.h +++ b/src/class/cdc/cdc_device.h @@ -248,13 +248,13 @@ static inline bool tud_cdc_write_clear(void) } // Get the Receive FIFO -static inline tu_fifo_t* tud_cdc_get_rx_ff (uint8_t itf) +static inline tu_fifo_t* tud_cdc_get_rx_ff (void) { return tud_cdc_n_get_rx_ff(0); } // Get the transmit FIFO -static inline tu_fifo_t* tud_cdc_get_tx_ff (uint8_t itf) +static inline tu_fifo_t* tud_cdc_get_tx_ff (void) { return tud_cdc_n_get_tx_ff(0); } diff --git a/src/device/usbd.h b/src/device/usbd.h index 3857295d..0a0f0bf0 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -236,7 +236,7 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb // Interface number, string index, protocol, report descriptor len, EP In address, size & polling interval #define TUD_HID_DESCRIPTOR(_itfnum, _stridx, _boot_protocol, _report_desc_len, _epin, _epsize, _ep_interval) \ /* Interface */\ - 9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUSB_CLASS_HID, (uint8_t)((_boot_protocol) ? HID_SUBCLASS_BOOT : 0), _boot_protocol, _stridx,\ + 9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUSB_CLASS_HID, (uint8_t)((_boot_protocol) ? (uint8_t)HID_SUBCLASS_BOOT : 0), _boot_protocol, _stridx,\ /* HID descriptor */\ 9, HID_DESC_TYPE_HID, U16_TO_U8S_LE(0x0111), 0, 1, HID_DESC_TYPE_REPORT, U16_TO_U8S_LE(_report_desc_len),\ /* Endpoint In */\ @@ -249,7 +249,7 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb // Interface number, string index, protocol, report descriptor len, EP OUT & IN address, size & polling interval #define TUD_HID_INOUT_DESCRIPTOR(_itfnum, _stridx, _boot_protocol, _report_desc_len, _epout, _epin, _epsize, _ep_interval) \ /* Interface */\ - 9, TUSB_DESC_INTERFACE, _itfnum, 0, 2, TUSB_CLASS_HID, (uint8_t)((_boot_protocol) ? HID_SUBCLASS_BOOT : 0), _boot_protocol, _stridx,\ + 9, TUSB_DESC_INTERFACE, _itfnum, 0, 2, TUSB_CLASS_HID, (uint8_t)((_boot_protocol) ? (uint8_t)HID_SUBCLASS_BOOT : 0), _boot_protocol, _stridx,\ /* HID descriptor */\ 9, HID_DESC_TYPE_HID, U16_TO_U8S_LE(0x0111), 0, 1, HID_DESC_TYPE_REPORT, U16_TO_U8S_LE(_report_desc_len),\ /* Endpoint Out */\ From 475742984f4d0f2b95c9c78dfff71814117feb90 Mon Sep 17 00:00:00 2001 From: MasterPhi Date: Sat, 17 Jul 2021 12:08:42 +0200 Subject: [PATCH 23/36] Change OPT_MCU_SAMX7X value. --- src/tusb_option.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/tusb_option.h b/src/tusb_option.h index 69c5fb0b..9b0ea435 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -61,7 +61,8 @@ #define OPT_MCU_SAME5X 203 ///< MicroChip SAM E5x #define OPT_MCU_SAMD11 204 ///< MicroChip SAMD11 #define OPT_MCU_SAML22 205 ///< MicroChip SAML22 -#define OPT_MCU_SAMX7X 206 ///< MicroChip SAME70, S70, V70, V71 family +#define OPT_MCU_SAML21 206 ///< MicroChip SAML21 +#define OPT_MCU_SAMX7X 207 ///< MicroChip SAME70, S70, V70, V71 family // STM32 From 7e3e41952fe4c83a182dfe39e5bab89e65120485 Mon Sep 17 00:00:00 2001 From: MasterPhi Date: Sat, 17 Jul 2021 13:48:21 +0200 Subject: [PATCH 24/36] Fix ISO support. --- .../device/uac2_headset/src/usb_descriptors.c | 16 ++++++++++++---- src/portable/microchip/samx7x/dcd_samx7x.c | 18 +++++++++++++----- 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/examples/device/uac2_headset/src/usb_descriptors.c b/examples/device/uac2_headset/src/usb_descriptors.c index 6a01f893..4a26b0b1 100644 --- a/examples/device/uac2_headset/src/usb_descriptors.c +++ b/examples/device/uac2_headset/src/usb_descriptors.c @@ -79,12 +79,20 @@ uint8_t const * tud_descriptor_device_cb(void) #if CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC40XX // LPC 17xx and 40xx endpoint type (bulk/interrupt/iso) are fixed by its number // 0 control, 1 In, 2 Bulk, 3 Iso, 4 In etc ... -#define EPNUM_AUDIO 0x03 +#define EPNUM_AUDIO_IN 0x03 +#define EPNUM_AUDIO_OUT 0x03 #elif CFG_TUSB_MCU == OPT_MCU_NRF5X // ISO endpoints for NRF5x are fixed to 0x08 (0x88) -#define EPNUM_AUDIO 0x08 +#define EPNUM_AUDIO_IN 0x08 +#define EPNUM_AUDIO_OUT 0x08 +#elif CFG_TUSB_MCU == OPT_MCU_SAMG || CFG_TUSB_MCU == OPT_MCU_SAMX7X +// SAMG & SAME70 don't support a same endpoint number with different direction IN and OUT +// e.g EP1 OUT & EP1 IN cannot exist together +#define EPNUM_AUDIO_IN 0x01 +#define EPNUM_AUDIO_OUT 0x02 #else -#define EPNUM_AUDIO 0x01 +#define EPNUM_AUDIO_IN 0x01 +#define EPNUM_AUDIO_OUT 0x01 #endif uint8_t const desc_configuration[] = @@ -93,7 +101,7 @@ uint8_t const desc_configuration[] = TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), // Interface number, string index, EP Out & EP In address, EP size - TUD_AUDIO_HEADSET_STEREO_DESCRIPTOR(2, EPNUM_AUDIO, EPNUM_AUDIO | 0x80) + TUD_AUDIO_HEADSET_STEREO_DESCRIPTOR(2, EPNUM_AUDIO_OUT, EPNUM_AUDIO_IN | 0x80) }; // Invoked when received GET CONFIGURATION DESCRIPTOR diff --git a/src/portable/microchip/samx7x/dcd_samx7x.c b/src/portable/microchip/samx7x/dcd_samx7x.c index 0299d12b..2a534b95 100644 --- a/src/portable/microchip/samx7x/dcd_samx7x.c +++ b/src/portable/microchip/samx7x/dcd_samx7x.c @@ -83,11 +83,8 @@ typedef struct { static tusb_speed_t get_speed(void); static void dcd_transmit_packet(xfer_ctl_t * xfer, uint8_t ep_ix); -// DMA descriptors shouldn't be placed in ITCM -#if defined(USB_DMA_DESC_SECTION) -TU_ATTR_SECTION(TU_XSTRING(USB_DMA_DESC_SECTION)) -#endif -dma_desc_t dma_desc[6]; +// DMA descriptors shouldn't be placed in ITCM ! +CFG_TUSB_MEM_SECTION dma_desc_t dma_desc[6]; xfer_ctl_t xfer_status[EP_MAX+1]; @@ -531,6 +528,17 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) } } +void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) +{ + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + // Disable endpoint interrupt + USBHS->USBHS_DEVIDR = 1 << (USBHS_DEVIDR_PEP_0_Pos + epnum); + // Disable EP + USBHS->USBHS_DEVEPT &=~(1 << (USBHS_DEVEPT_EPEN0_Pos + epnum)); +} + static void dcd_transmit_packet(xfer_ctl_t * xfer, uint8_t ep_ix) { uint16_t len = (uint16_t)(xfer->total_len - xfer->queued_len); From bae0d3b7bbe5145017ebd08f777fe0b8063f44b7 Mon Sep 17 00:00:00 2001 From: MasterPhi Date: Sat, 17 Jul 2021 14:42:23 +0200 Subject: [PATCH 25/36] Fix build error. --- src/portable/microchip/samx7x/dcd_samx7x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/portable/microchip/samx7x/dcd_samx7x.c b/src/portable/microchip/samx7x/dcd_samx7x.c index 2a534b95..aa9faa5b 100644 --- a/src/portable/microchip/samx7x/dcd_samx7x.c +++ b/src/portable/microchip/samx7x/dcd_samx7x.c @@ -531,7 +531,7 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) { uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); + (void) ep_addr; // Disable endpoint interrupt USBHS->USBHS_DEVIDR = 1 << (USBHS_DEVIDR_PEP_0_Pos + epnum); From f52e1889c7f4bca23311a97b5869eab70c766094 Mon Sep 17 00:00:00 2001 From: MasterPhi Date: Sat, 17 Jul 2021 20:41:19 +0200 Subject: [PATCH 26/36] Fix merge error. --- examples/device/cdc_msc/src/msc_disk.c | 2 +- .../device/hid_composite/src/tusb_config.h | 2 +- src/class/cdc/cdc_device.c | 14 -------------- src/class/cdc/cdc_device.h | 18 ------------------ 4 files changed, 2 insertions(+), 34 deletions(-) diff --git a/examples/device/cdc_msc/src/msc_disk.c b/examples/device/cdc_msc/src/msc_disk.c index 3caf3fd4..503baace 100644 --- a/examples/device/cdc_msc/src/msc_disk.c +++ b/examples/device/cdc_msc/src/msc_disk.c @@ -23,7 +23,7 @@ * */ -//#include "bsp/board.h" +#include "bsp/board.h" #include "tusb.h" #if CFG_TUD_MSC diff --git a/examples/device/hid_composite/src/tusb_config.h b/examples/device/hid_composite/src/tusb_config.h index 31dea4ee..868424e6 100644 --- a/examples/device/hid_composite/src/tusb_config.h +++ b/examples/device/hid_composite/src/tusb_config.h @@ -69,7 +69,7 @@ #endif // CFG_TUSB_DEBUG is defined by compiler in DEBUG build -#define CFG_TUSB_DEBUG 0 +// #define CFG_TUSB_DEBUG 0 /* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment. * Tinyusb use follows macros to declare transferring memory so that they can be put diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 68080c61..e622bd61 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -481,18 +481,4 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ return true; } -// Get the Receive FIFO (for DMA transfer) -tu_fifo_t* tud_cdc_n_get_rx_ff (uint8_t itf) -{ - TU_ASSERT(itf < CFG_TUD_CDC); - return &_cdcd_itf[itf].rx_ff; -} - -// Get the transmit FIFO (for DMA transfer) -tu_fifo_t* tud_cdc_n_get_tx_ff (uint8_t itf) -{ - TU_ASSERT(itf < CFG_TUD_CDC); - return &_cdcd_itf[itf].tx_ff; -} - #endif diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h index f8a2216c..7ff757ad 100644 --- a/src/class/cdc/cdc_device.h +++ b/src/class/cdc/cdc_device.h @@ -104,12 +104,6 @@ uint32_t tud_cdc_n_write_available (uint8_t itf); // Clear the transmit FIFO bool tud_cdc_n_write_clear (uint8_t itf); -// Get the Receive FIFO (for DMA transfer) -tu_fifo_t* tud_cdc_n_get_rx_ff (uint8_t itf); - -// Get the transmit FIFO (for DMA transfer) -tu_fifo_t* tud_cdc_n_get_tx_ff (uint8_t itf); - //--------------------------------------------------------------------+ // Application API (Single Port) //--------------------------------------------------------------------+ @@ -247,18 +241,6 @@ static inline bool tud_cdc_write_clear(void) return tud_cdc_n_write_clear(0); } -// Get the Receive FIFO -static inline tu_fifo_t* tud_cdc_get_rx_ff (void) -{ - return tud_cdc_n_get_rx_ff(0); -} - -// Get the transmit FIFO -static inline tu_fifo_t* tud_cdc_get_tx_ff (void) -{ - return tud_cdc_n_get_tx_ff(0); -} - /** @} */ /** @} */ From d0dd3c77ff7cffddbcc177d0ed48acd7a70f74a8 Mon Sep 17 00:00:00 2001 From: MasterPhi Date: Sun, 18 Jul 2021 22:03:45 +0200 Subject: [PATCH 27/36] Use USBHS_Handler --- hw/bsp/same70_xplained/same70_xplained.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/bsp/same70_xplained/same70_xplained.c b/hw/bsp/same70_xplained/same70_xplained.c index e34b5d35..f897798e 100644 --- a/hw/bsp/same70_xplained/same70_xplained.c +++ b/hw/bsp/same70_xplained/same70_xplained.c @@ -109,7 +109,7 @@ void board_init(void) //--------------------------------------------------------------------+ // USB Interrupt Handler //--------------------------------------------------------------------+ -void UDP_Handler(void) +void USBHS_Handler(void) { #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE tud_int_handler(0); From 8cae17bfc87f49c814827b0a31a4b6b6e8314f69 Mon Sep 17 00:00:00 2001 From: MasterPhi Date: Mon, 19 Jul 2021 01:07:33 +0200 Subject: [PATCH 28/36] Fixing NAKed OUT xfer --- src/portable/microchip/samx7x/dcd_samx7x.c | 53 +++++++++++++++------- 1 file changed, 36 insertions(+), 17 deletions(-) diff --git a/src/portable/microchip/samx7x/dcd_samx7x.c b/src/portable/microchip/samx7x/dcd_samx7x.c index aa9faa5b..3134a059 100644 --- a/src/portable/microchip/samx7x/dcd_samx7x.c +++ b/src/portable/microchip/samx7x/dcd_samx7x.c @@ -60,7 +60,8 @@ #define EP_GET_FIFO_PTR(ep, scale) (((TU_XSTRCAT(TU_STRCAT(uint, scale),_t) (*)[0x8000 / ((scale) / 8)])USBHS_RAM_ADDR)[(ep)]) // Errata: The DMA feature is not available for Pipe/Endpoint 7 -#define EP_DMA_SUPPORT(epnum) (epnum >= 1 && epnum <= 6) +// #define EP_DMA_SUPPORT(epnum) (epnum >= 1 && epnum <= 6) +#define EP_DMA_SUPPORT(epnum) 0 // DMA Channel Transfer Descriptor typedef struct { @@ -294,8 +295,6 @@ static void dcd_ep_handler(uint8_t ep_ix) } // Acknowledge the interrupt USBHS->USBHS_DEVEPTICR[ep_ix] = USBHS_DEVEPTICR_RXOUTIC; - // Clear the FIFO control flag to receive more data. - USBHS->USBHS_DEVEPTIDR[ep_ix] = USBHS_DEVEPTIDR_FIFOCONC; if ((count < xfer->max_packet_size) || (xfer->queued_len == xfer->total_len)) { // RX COMPLETE @@ -314,10 +313,10 @@ static void dcd_ep_handler(uint8_t ep_ix) { // TX not complete dcd_transmit_packet(xfer, ep_ix); - } else { + } else + { // TX complete dcd_event_xfer_complete(0, 0x80 + ep_ix, xfer->total_len, XFER_RESULT_SUCCESS, true); - USBHS->USBHS_DEVEPTIDR[ep_ix] = USBHS_DEVEPTIDR_TXINEC; } } } @@ -338,7 +337,8 @@ static void dcd_dma_handler(uint8_t ep_ix) if(USBHS->USBHS_DEVEPTCFG[ep_ix] & USBHS_DEVEPTCFG_EPDIR) { dcd_event_xfer_complete(0, 0x80 + ep_ix, count, XFER_RESULT_SUCCESS, true); - } else { + } else + { dcd_event_xfer_complete(0, ep_ix, count, XFER_RESULT_SUCCESS, true); } } @@ -483,14 +483,17 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) { // Endpoint configuration is successful USBHS->USBHS_DEVEPTIER[0] = USBHS_DEVEPTIER_CTRL_RXSTPES; + USBHS->USBHS_DEVEPTIER[0] = USBHS_DEVEPTIER_RXOUTES; // Enable Endpoint 0 Interrupts USBHS->USBHS_DEVIER = USBHS_DEVIER_PEP_0; return true; - } else { + } else + { // Endpoint configuration is not successful return false; } - } else { + } else + { // Enable the endpoint USBHS->USBHS_DEVEPT |= ((0x01 << epnum) << USBHS_DEVEPT_EPEN0_Pos); // Set up the maxpacket size, fifo start address fifosize @@ -520,8 +523,17 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) if (USBHS_DEVEPTISR_CFGOK == (USBHS->USBHS_DEVEPTISR[epnum] & USBHS_DEVEPTISR_CFGOK)) { USBHS->USBHS_DEVIER = ((0x01 << epnum) << USBHS_DEVIER_PEP_0_Pos); + if (dir) + { + USBHS->USBHS_DEVEPTICR[epnum] = USBHS_DEVEPTICR_TXINIC; + USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_TXINES; + } else + { + USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_RXOUTES; + } return true; - } else { + } else + { // Endpoint configuration is not successful return false; } @@ -553,7 +565,8 @@ static void dcd_transmit_packet(xfer_ctl_t * xfer, uint8_t ep_ix) { memcpy(ptr, xfer->buffer + xfer->queued_len, len); } - else { + else + { tu_fifo_read_n(xfer->fifo, ptr, len); } __DSB(); @@ -564,11 +577,12 @@ static void dcd_transmit_packet(xfer_ctl_t * xfer, uint8_t ep_ix) { // Control endpoint: clear the interrupt flag to send the data USBHS->USBHS_DEVEPTICR[0] = USBHS_DEVEPTICR_TXINIC; - } else { + USBHS->USBHS_DEVEPTIER[0] = USBHS_DEVEPTIER_TXINES; + } else + { // Other endpoint types: clear the FIFO control flag to send the data USBHS->USBHS_DEVEPTIDR[ep_ix] = USBHS_DEVEPTIDR_FIFOCONC; } - USBHS->USBHS_DEVEPTIER[ep_ix] = USBHS_DEVEPTIER_TXINES; } // Submit a transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack @@ -615,11 +629,14 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t // and the DMA transfer must be not started. // It is the end of transfer return false; - } else { + } else + { if (dir == TUSB_DIR_OUT) { - USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_RXOUTES; - } else { + // Clear the FIFO control flag to receive more data. + USBHS->USBHS_DEVEPTIDR[epnum] = USBHS_DEVEPTIDR_FIFOCONC; + } else + { dcd_transmit_packet(xfer,epnum); } } @@ -696,11 +713,13 @@ bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16 // and the DMA transfer must be not started. // It is the end of transfer return false; - } else { + } else + { if (dir == TUSB_DIR_OUT) { USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_RXOUTES; - } else { + } else + { dcd_transmit_packet(xfer,epnum); } } From 05f59fb8edc301690042821d447c31631be8d911 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 19 Jul 2021 12:08:01 +0700 Subject: [PATCH 29/36] clean up warning --- hw/bsp/same70_xplained/board.mk | 5 ----- hw/bsp/same70_xplained/same70_xplained.c | 4 +--- src/portable/microchip/samx7x/dcd_samx7x.c | 2 +- 3 files changed, 2 insertions(+), 9 deletions(-) diff --git a/hw/bsp/same70_xplained/board.mk b/hw/bsp/same70_xplained/board.mk index 94b0bed9..c9bc0cea 100644 --- a/hw/bsp/same70_xplained/board.mk +++ b/hw/bsp/same70_xplained/board.mk @@ -43,11 +43,6 @@ INC += \ $(TOP)/$(ASF_DIR)/hri \ $(TOP)/$(ASF_DIR)/CMSIS/Core/Include -# For TinyUSB port source -#SRC_C += src/portable/template/dcd_template.c -VENDOR = . -CHIP_FAMILY = template - # For freeRTOS port source FREERTOS_PORT = ARM_CM7 diff --git a/hw/bsp/same70_xplained/same70_xplained.c b/hw/bsp/same70_xplained/same70_xplained.c index f897798e..ac682a89 100644 --- a/hw/bsp/same70_xplained/same70_xplained.c +++ b/hw/bsp/same70_xplained/same70_xplained.c @@ -111,9 +111,7 @@ void board_init(void) //--------------------------------------------------------------------+ void USBHS_Handler(void) { - #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE - tud_int_handler(0); - #endif + tud_int_handler(0); } //--------------------------------------------------------------------+ diff --git a/src/portable/microchip/samx7x/dcd_samx7x.c b/src/portable/microchip/samx7x/dcd_samx7x.c index 3134a059..31628583 100644 --- a/src/portable/microchip/samx7x/dcd_samx7x.c +++ b/src/portable/microchip/samx7x/dcd_samx7x.c @@ -542,8 +542,8 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) { + (void) rhport; uint8_t const epnum = tu_edpt_number(ep_addr); - (void) ep_addr; // Disable endpoint interrupt USBHS->USBHS_DEVIDR = 1 << (USBHS_DEVIDR_PEP_0_Pos + epnum); From 75f61328ea8aaffa0e666c56def4efdafcb63a12 Mon Sep 17 00:00:00 2001 From: MasterPhi Date: Mon, 19 Jul 2021 22:03:47 +0200 Subject: [PATCH 30/36] Remove clock init. --- src/portable/microchip/samx7x/dcd_samx7x.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/portable/microchip/samx7x/dcd_samx7x.c b/src/portable/microchip/samx7x/dcd_samx7x.c index 3134a059..c91702c9 100644 --- a/src/portable/microchip/samx7x/dcd_samx7x.c +++ b/src/portable/microchip/samx7x/dcd_samx7x.c @@ -102,14 +102,14 @@ static const tusb_desc_endpoint_t ep0_desc = // Initialize controller to device mode void dcd_init (uint8_t rhport) { - // Enable USBPLL - PMC->CKGR_UCKR = CKGR_UCKR_UPLLEN | CKGR_UCKR_UPLLCOUNT(0x3fU); - // Wait until USB UTMI stabilize - while (!(PMC->PMC_SR & PMC_SR_LOCKU)); - // Enable USB FS clk - PMC->PMC_MCKR &= ~PMC_MCKR_UPLLDIV2; - PMC->PMC_USB = PMC_USB_USBS | PMC_USB_USBDIV(10 - 1); - PMC->PMC_SCER = PMC_SCER_USBCLK; +// // Enable USBPLL +// PMC->CKGR_UCKR = CKGR_UCKR_UPLLEN | CKGR_UCKR_UPLLCOUNT(0x3fU); +// // Wait until USB UTMI stabilize +// while (!(PMC->PMC_SR & PMC_SR_LOCKU)); +// // Enable USB FS clk +// PMC->PMC_MCKR &= ~PMC_MCKR_UPLLDIV2; +// PMC->PMC_USB = PMC_USB_USBS | PMC_USB_USBDIV(10 - 1); +// PMC->PMC_SCER = PMC_SCER_USBCLK; dcd_connect(rhport); } From fa9a327a7134a53a0a2b1d7c449083110f9a7d37 Mon Sep 17 00:00:00 2001 From: MasterPhi Date: Tue, 20 Jul 2021 13:24:39 +0200 Subject: [PATCH 31/36] Workaround of EP0 issue, clean up. --- src/portable/microchip/samx7x/dcd_samx7x.c | 35 ++++++++++------------ 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/src/portable/microchip/samx7x/dcd_samx7x.c b/src/portable/microchip/samx7x/dcd_samx7x.c index bb69619d..b4972490 100644 --- a/src/portable/microchip/samx7x/dcd_samx7x.c +++ b/src/portable/microchip/samx7x/dcd_samx7x.c @@ -60,8 +60,7 @@ #define EP_GET_FIFO_PTR(ep, scale) (((TU_XSTRCAT(TU_STRCAT(uint, scale),_t) (*)[0x8000 / ((scale) / 8)])USBHS_RAM_ADDR)[(ep)]) // Errata: The DMA feature is not available for Pipe/Endpoint 7 -// #define EP_DMA_SUPPORT(epnum) (epnum >= 1 && epnum <= 6) -#define EP_DMA_SUPPORT(epnum) 0 +#define EP_DMA_SUPPORT(epnum) (epnum >= 1 && epnum <= 6) // DMA Channel Transfer Descriptor typedef struct { @@ -102,14 +101,6 @@ static const tusb_desc_endpoint_t ep0_desc = // Initialize controller to device mode void dcd_init (uint8_t rhport) { -// // Enable USBPLL -// PMC->CKGR_UCKR = CKGR_UCKR_UPLLEN | CKGR_UCKR_UPLLCOUNT(0x3fU); -// // Wait until USB UTMI stabilize -// while (!(PMC->PMC_SR & PMC_SR_LOCKU)); -// // Enable USB FS clk -// PMC->PMC_MCKR &= ~PMC_MCKR_UPLLDIV2; -// PMC->PMC_USB = PMC_USB_USBS | PMC_USB_USBDIV(10 - 1); -// PMC->PMC_SCER = PMC_SCER_USBCLK; dcd_connect(rhport); } @@ -228,9 +219,14 @@ static void dcd_ep_handler(uint8_t ep_ix) } // Acknowledge the interrupt USBHS->USBHS_DEVEPTICR[0] = USBHS_DEVEPTICR_CTRL_RXSTPIC; + // Workaround : + // Clear spurious OUT irq + USBHS->USBHS_DEVEPTIDR[0] = USBHS_DEVEPTIDR_RXOUTEC; + int_status &=~USBHS_DEVEPTISR_RXOUTI; } if (int_status & USBHS_DEVEPTISR_RXOUTI) { + uint8_t *ptr = EP_GET_FIFO_PTR(0,8); xfer_ctl_t *xfer = &xfer_status[0]; if (count && xfer->total_len) { @@ -239,11 +235,11 @@ static void dcd_ep_handler(uint8_t ep_ix) { count = remain; } - uint8_t *ptr = EP_GET_FIFO_PTR(0,8); if (xfer->buffer) { memcpy(xfer->buffer + xfer->queued_len, ptr, count); - } else { + } else + { tu_fifo_write_n(xfer->fifo, ptr, count); } xfer->queued_len = (uint16_t)(xfer->queued_len + count); @@ -253,7 +249,7 @@ static void dcd_ep_handler(uint8_t ep_ix) if ((count < xfer->max_packet_size) || (xfer->queued_len == xfer->total_len)) { // RX COMPLETE - dcd_event_xfer_complete(0, 0, xfer->total_len, XFER_RESULT_SUCCESS, true); + dcd_event_xfer_complete(0, 0, xfer->queued_len, XFER_RESULT_SUCCESS, true); // Disable the interrupt USBHS->USBHS_DEVEPTIDR[0] = USBHS_DEVEPTIDR_RXOUTEC; // Though the host could still send, we don't know. @@ -268,12 +264,14 @@ static void dcd_ep_handler(uint8_t ep_ix) { // TX not complete dcd_transmit_packet(xfer, 0); - } else { + } else + { // TX complete dcd_event_xfer_complete(0, 0x80 + 0, xfer->total_len, XFER_RESULT_SUCCESS, true); } } - } else { + } else + { if (int_status & USBHS_DEVEPTISR_RXOUTI) { xfer_ctl_t *xfer = &xfer_status[ep_ix]; @@ -293,6 +291,8 @@ static void dcd_ep_handler(uint8_t ep_ix) } xfer->queued_len = (uint16_t)(xfer->queued_len + count); } + // Clear the FIFO control flag to receive more data. + USBHS->USBHS_DEVEPTIDR[ep_ix] = USBHS_DEVEPTIDR_FIFOCONC; // Acknowledge the interrupt USBHS->USBHS_DEVEPTICR[ep_ix] = USBHS_DEVEPTICR_RXOUTIC; if ((count < xfer->max_packet_size) || (xfer->queued_len == xfer->total_len)) @@ -483,7 +483,6 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) { // Endpoint configuration is successful USBHS->USBHS_DEVEPTIER[0] = USBHS_DEVEPTIER_CTRL_RXSTPES; - USBHS->USBHS_DEVEPTIER[0] = USBHS_DEVEPTIER_RXOUTES; // Enable Endpoint 0 Interrupts USBHS->USBHS_DEVIER = USBHS_DEVIER_PEP_0; return true; @@ -529,7 +528,6 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_TXINES; } else { - USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_RXOUTES; } return true; } else @@ -633,8 +631,7 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t { if (dir == TUSB_DIR_OUT) { - // Clear the FIFO control flag to receive more data. - USBHS->USBHS_DEVEPTIDR[epnum] = USBHS_DEVEPTIDR_FIFOCONC; + USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_RXOUTES; } else { dcd_transmit_packet(xfer,epnum); From eec927ea959d6d972c62d60fa634df227e196b36 Mon Sep 17 00:00:00 2001 From: MasterPhi Date: Wed, 21 Jul 2021 00:14:28 +0200 Subject: [PATCH 32/36] Fix EP0 issue (again) --- src/portable/microchip/samx7x/dcd_samx7x.c | 34 +++++++++++++--------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/src/portable/microchip/samx7x/dcd_samx7x.c b/src/portable/microchip/samx7x/dcd_samx7x.c index b4972490..de1fd256 100644 --- a/src/portable/microchip/samx7x/dcd_samx7x.c +++ b/src/portable/microchip/samx7x/dcd_samx7x.c @@ -86,7 +86,7 @@ static void dcd_transmit_packet(xfer_ctl_t * xfer, uint8_t ep_ix); // DMA descriptors shouldn't be placed in ITCM ! CFG_TUSB_MEM_SECTION dma_desc_t dma_desc[6]; -xfer_ctl_t xfer_status[EP_MAX+1]; +xfer_ctl_t xfer_status[EP_MAX]; static const tusb_desc_endpoint_t ep0_desc = { @@ -205,29 +205,32 @@ static void dcd_ep_handler(uint8_t ep_ix) { uint32_t int_status = USBHS->USBHS_DEVEPTISR[ep_ix]; int_status &= USBHS->USBHS_DEVEPTIMR[ep_ix]; + uint16_t count = (USBHS->USBHS_DEVEPTISR[ep_ix] & USBHS_DEVEPTISR_BYCT_Msk) >> USBHS_DEVEPTISR_BYCT_Pos; + xfer_ctl_t *xfer = &xfer_status[ep_ix]; + if (ep_ix == 0U) { + static uint8_t ctrl_dir; + if (int_status & USBHS_DEVEPTISR_CTRL_RXSTPI) { + ctrl_dir = (USBHS->USBHS_DEVEPTISR[0] & USBHS_DEVEPTISR_CTRL_CTRLDIR_Msk) >> USBHS_DEVEPTISR_CTRL_CTRLDIR_Pos; // Setup packet should always be 8 bytes. If not, ignore it, and try again. if (count == 8) { uint8_t *ptr = EP_GET_FIFO_PTR(0,8); dcd_event_setup_received(0, ptr, true); } - // Acknowledge the interrupt + // Ack and disable SETUP interrupt USBHS->USBHS_DEVEPTICR[0] = USBHS_DEVEPTICR_CTRL_RXSTPIC; - // Workaround : - // Clear spurious OUT irq - USBHS->USBHS_DEVEPTIDR[0] = USBHS_DEVEPTIDR_RXOUTEC; - int_status &=~USBHS_DEVEPTISR_RXOUTI; + USBHS->USBHS_DEVEPTIDR[0] = USBHS_DEVEPTIDR_CTRL_RXSTPEC; } if (int_status & USBHS_DEVEPTISR_RXOUTI) { uint8_t *ptr = EP_GET_FIFO_PTR(0,8); - xfer_ctl_t *xfer = &xfer_status[0]; + if (count && xfer->total_len) { uint16_t remain = xfer->total_len - xfer->queued_len; @@ -252,14 +255,17 @@ static void dcd_ep_handler(uint8_t ep_ix) dcd_event_xfer_complete(0, 0, xfer->queued_len, XFER_RESULT_SUCCESS, true); // Disable the interrupt USBHS->USBHS_DEVEPTIDR[0] = USBHS_DEVEPTIDR_RXOUTEC; - // Though the host could still send, we don't know. + // Re-enable SETUP interrupt + if (ctrl_dir == 1) + { + USBHS->USBHS_DEVEPTIER[0] = USBHS_DEVEPTIER_CTRL_RXSTPES; + } } } if (int_status & USBHS_DEVEPTISR_TXINI) { // Disable the interrupt USBHS->USBHS_DEVEPTIDR[0] = USBHS_DEVEPTIDR_TXINEC; - xfer_ctl_t * xfer = &xfer_status[EP_MAX]; if ((xfer->total_len != xfer->queued_len)) { // TX not complete @@ -268,13 +274,17 @@ static void dcd_ep_handler(uint8_t ep_ix) { // TX complete dcd_event_xfer_complete(0, 0x80 + 0, xfer->total_len, XFER_RESULT_SUCCESS, true); + // Re-enable SETUP interrupt + if (ctrl_dir == 0) + { + USBHS->USBHS_DEVEPTIER[0] = USBHS_DEVEPTIER_CTRL_RXSTPES; + } } } } else { if (int_status & USBHS_DEVEPTISR_RXOUTI) { - xfer_ctl_t *xfer = &xfer_status[ep_ix]; if (count && xfer->total_len) { uint16_t remain = xfer->total_len - xfer->queued_len; @@ -308,7 +318,6 @@ static void dcd_ep_handler(uint8_t ep_ix) { // Acknowledge the interrupt USBHS->USBHS_DEVEPTICR[ep_ix] = USBHS_DEVEPTICR_TXINIC; - xfer_ctl_t * xfer = &xfer_status[ep_ix];; if ((xfer->total_len != xfer->queued_len)) { // TX not complete @@ -466,7 +475,6 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) if (epnum == 0) { - xfer_status[EP_MAX].max_packet_size = epMaxPktSize; // Enable the control endpoint - Endpoint 0 USBHS->USBHS_DEVEPT |= USBHS_DEVEPT_EPEN0; // Configure the Endpoint 0 configuration register @@ -591,8 +599,6 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t uint8_t const dir = tu_edpt_dir(ep_addr); xfer_ctl_t * xfer = &xfer_status[epnum]; - if(ep_addr == 0x80) - xfer = &xfer_status[EP_MAX]; xfer->buffer = buffer; xfer->total_len = total_bytes; From 9c26c0c01e244310dc0e90573f39be7dc7250ead Mon Sep 17 00:00:00 2001 From: MasterPhi Date: Wed, 21 Jul 2021 09:42:26 +0200 Subject: [PATCH 33/36] Remove redundant TX irq. --- src/portable/microchip/samx7x/dcd_samx7x.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/portable/microchip/samx7x/dcd_samx7x.c b/src/portable/microchip/samx7x/dcd_samx7x.c index de1fd256..35d970b9 100644 --- a/src/portable/microchip/samx7x/dcd_samx7x.c +++ b/src/portable/microchip/samx7x/dcd_samx7x.c @@ -530,13 +530,6 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) if (USBHS_DEVEPTISR_CFGOK == (USBHS->USBHS_DEVEPTISR[epnum] & USBHS_DEVEPTISR_CFGOK)) { USBHS->USBHS_DEVIER = ((0x01 << epnum) << USBHS_DEVIER_PEP_0_Pos); - if (dir) - { - USBHS->USBHS_DEVEPTICR[epnum] = USBHS_DEVEPTICR_TXINIC; - USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_TXINES; - } else - { - } return true; } else { From 5492d9148cbd09d19137b992f9ee51def9bd076f Mon Sep 17 00:00:00 2001 From: MasterPhi Date: Wed, 21 Jul 2021 10:29:47 +0200 Subject: [PATCH 34/36] Re-enable SETUP irq on EP0 stall. --- src/portable/microchip/samx7x/dcd_samx7x.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/portable/microchip/samx7x/dcd_samx7x.c b/src/portable/microchip/samx7x/dcd_samx7x.c index 35d970b9..85197839 100644 --- a/src/portable/microchip/samx7x/dcd_samx7x.c +++ b/src/portable/microchip/samx7x/dcd_samx7x.c @@ -728,6 +728,11 @@ void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr) (void) rhport; uint8_t const epnum = tu_edpt_number(ep_addr); USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_CTRL_STALLRQS; + // Re-enable SETUP interrupt + if (epnum == 0) + { + USBHS->USBHS_DEVEPTIER[0] = USBHS_DEVEPTIER_CTRL_RXSTPES; + } } // clear stall, data toggle is also reset to DATA0 From 8c6cd5396c1276aed12fd3a74825debe136d3ded Mon Sep 17 00:00:00 2001 From: MasterPhi Date: Wed, 21 Jul 2021 10:50:07 +0200 Subject: [PATCH 35/36] Fix non-DMA IN irq. --- src/portable/microchip/samx7x/dcd_samx7x.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/portable/microchip/samx7x/dcd_samx7x.c b/src/portable/microchip/samx7x/dcd_samx7x.c index 85197839..e35cf80a 100644 --- a/src/portable/microchip/samx7x/dcd_samx7x.c +++ b/src/portable/microchip/samx7x/dcd_samx7x.c @@ -326,6 +326,8 @@ static void dcd_ep_handler(uint8_t ep_ix) { // TX complete dcd_event_xfer_complete(0, 0x80 + ep_ix, xfer->total_len, XFER_RESULT_SUCCESS, true); + // Disable the interrupt + USBHS->USBHS_DEVEPTIDR[ep_ix] = USBHS_DEVEPTIDR_TXINEC; } } } @@ -576,12 +578,12 @@ static void dcd_transmit_packet(xfer_ctl_t * xfer, uint8_t ep_ix) { // Control endpoint: clear the interrupt flag to send the data USBHS->USBHS_DEVEPTICR[0] = USBHS_DEVEPTICR_TXINIC; - USBHS->USBHS_DEVEPTIER[0] = USBHS_DEVEPTIER_TXINES; } else { // Other endpoint types: clear the FIFO control flag to send the data USBHS->USBHS_DEVEPTIDR[ep_ix] = USBHS_DEVEPTIDR_FIFOCONC; } + USBHS->USBHS_DEVEPTIER[ep_ix] = USBHS_DEVEPTIER_TXINES; } // Submit a transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack From b192dc0738f0c1d820326127ba0496b54f752414 Mon Sep 17 00:00:00 2001 From: MasterPhi Date: Wed, 21 Jul 2021 14:18:47 +0200 Subject: [PATCH 36/36] Update EPNUM in usb_descriptors.c --- .../net_lwip_webserver/src/usb_descriptors.c | 4 ++-- .../webusb_serial/src/usb_descriptors.c | 23 ++++++++++++++----- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/examples/device/net_lwip_webserver/src/usb_descriptors.c b/examples/device/net_lwip_webserver/src/usb_descriptors.c index 1a77c39d..71e6c458 100644 --- a/examples/device/net_lwip_webserver/src/usb_descriptors.c +++ b/examples/device/net_lwip_webserver/src/usb_descriptors.c @@ -107,8 +107,8 @@ uint8_t const * tud_descriptor_device_cb(void) #define EPNUM_NET_OUT 0x02 #define EPNUM_NET_IN 0x82 -#elif CFG_TUSB_MCU == OPT_MCU_SAMG - // SAMG doesn't support a same endpoint number with different direction IN and OUT +#elif CFG_TUSB_MCU == OPT_MCU_SAMG || CFG_TUSB_MCU == OPT_MCU_SAMX7X + // SAMG & SAME70 don't support a same endpoint number with different direction IN and OUT // e.g EP1 OUT & EP1 IN cannot exist together #define EPNUM_NET_NOTIF 0x81 #define EPNUM_NET_OUT 0x02 diff --git a/examples/device/webusb_serial/src/usb_descriptors.c b/examples/device/webusb_serial/src/usb_descriptors.c index 4aefdb1f..d1539488 100644 --- a/examples/device/webusb_serial/src/usb_descriptors.c +++ b/examples/device/webusb_serial/src/usb_descriptors.c @@ -86,11 +86,22 @@ enum #if CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC40XX // LPC 17xx and 40xx endpoint type (bulk/interrupt/iso) are fixed by its number // 0 control, 1 In, 2 Bulk, 3 Iso, 4 In etc ... - #define EPNUM_CDC 2 - #define EPNUM_VENDOR 5 + #define EPNUM_CDC_IN 2 + #define EPNUM_CDC_OUT 2 + #define EPNUM_VENDOR_IN 5 + #define EPNUM_VENDOR_OUT 5 +#elif CFG_TUSB_MCU == OPT_MCU_SAMG || CFG_TUSB_MCU == OPT_MCU_SAMX7X + // SAMG & SAME70 don't support a same endpoint number with different direction IN and OUT + // e.g EP1 OUT & EP1 IN cannot exist together + #define EPNUM_CDC_IN 2 + #define EPNUM_CDC_OUT 3 + #define EPNUM_VENDOR_IN 4 + #define EPNUM_VENDOR_OUT 5 #else - #define EPNUM_CDC 2 - #define EPNUM_VENDOR 3 + #define EPNUM_CDC_IN 2 + #define EPNUM_CDC_OUT 2 + #define EPNUM_VENDOR_IN 3 + #define EPNUM_VENDOR_OUT 3 #endif uint8_t const desc_configuration[] = @@ -99,10 +110,10 @@ uint8_t const desc_configuration[] = TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), // Interface number, string index, EP notification address and size, EP data address (out, in) and size. - TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, 0x81, 8, EPNUM_CDC, 0x80 | EPNUM_CDC, TUD_OPT_HIGH_SPEED ? 512 : 64), + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, 0x81, 8, EPNUM_CDC_OUT, 0x80 | EPNUM_CDC_IN, TUD_OPT_HIGH_SPEED ? 512 : 64), // Interface number, string index, EP Out & IN address, EP size - TUD_VENDOR_DESCRIPTOR(ITF_NUM_VENDOR, 5, EPNUM_VENDOR, 0x80 | EPNUM_VENDOR, TUD_OPT_HIGH_SPEED ? 512 : 64) + TUD_VENDOR_DESCRIPTOR(ITF_NUM_VENDOR, 5, EPNUM_VENDOR_OUT, 0x80 | EPNUM_VENDOR_IN, TUD_OPT_HIGH_SPEED ? 512 : 64) }; // Invoked when received GET CONFIGURATION DESCRIPTOR