diff options
| author | Valentin Milea <[email protected]> | 2022-01-07 15:12:07 +0200 |
|---|---|---|
| committer | Valentin Milea <[email protected]> | 2022-01-07 15:12:07 +0200 |
| commit | c2533a45bd932d672458cf54d37ac5207a734e41 (patch) | |
| tree | a8d886bdccaed451053262b0d875612338389474 /src | |
| parent | a284e438f1952315631f354dee2b30b264afb324 (diff) | |
| parent | 3b09b82123a50bef6b18cf90c2734ae7581da4a3 (diff) | |
Merge branch 'master' into feature/feedback_format
Diffstat (limited to 'src')
| -rw-r--r-- | src/class/usbtmc/usbtmc_device.c | 18 | ||||
| -rw-r--r-- | src/common/tusb_verify.h | 14 | ||||
| -rw-r--r-- | src/device/dcd_attr.h | 2 | ||||
| -rw-r--r-- | src/portable/mentor/musb/dcd_musb.c | 7 | ||||
| -rw-r--r-- | src/portable/mentor/musb/hcd_musb.c | 876 | ||||
| -rw-r--r-- | src/portable/nordic/nrf5x/dcd_nrf5x.c | 8 | ||||
| -rw-r--r-- | src/portable/raspberrypi/rp2040/dcd_rp2040.c | 38 | ||||
| -rw-r--r-- | src/portable/raspberrypi/rp2040/rp2040_usb.c | 2 | ||||
| -rw-r--r-- | src/portable/synopsys/dwc2/dcd_dwc2.c | 5 | ||||
| -rw-r--r-- | src/portable/synopsys/dwc2/dwc2_bcm.h | 3 | ||||
| -rw-r--r-- | src/portable/valentyusb/eptri/dcd_eptri.c | 8 | ||||
| -rw-r--r-- | src/tusb_option.h | 2 |
12 files changed, 943 insertions, 40 deletions
diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c index 4bd1edf12..26be987cf 100644 --- a/src/class/usbtmc/usbtmc_device.c +++ b/src/class/usbtmc/usbtmc_device.c @@ -235,17 +235,19 @@ void usbtmcd_init_cb(void) usbtmc_state.capabilities = tud_usbtmc_get_capabilities_cb(); #ifndef NDEBUG # if CFG_TUD_USBTMC_ENABLE_488 - if(usbtmc_state.capabilities->bmIntfcCapabilities488.supportsTrigger) - TU_ASSERT(&tud_usbtmc_msg_trigger_cb != NULL,); - // Per USB488 spec: table 8 - TU_ASSERT(!usbtmc_state.capabilities->bmIntfcCapabilities.listenOnly,); - TU_ASSERT(!usbtmc_state.capabilities->bmIntfcCapabilities.talkOnly,); + if (usbtmc_state.capabilities->bmIntfcCapabilities488.supportsTrigger) { + TU_ASSERT(&tud_usbtmc_msg_trigger_cb != NULL,); + } + // Per USB488 spec: table 8 + TU_ASSERT(!usbtmc_state.capabilities->bmIntfcCapabilities.listenOnly,); + TU_ASSERT(!usbtmc_state.capabilities->bmIntfcCapabilities.talkOnly,); # endif - if(usbtmc_state.capabilities->bmIntfcCapabilities.supportsIndicatorPulse) - TU_ASSERT(&tud_usbtmc_indicator_pulse_cb != NULL,); + if (usbtmc_state.capabilities->bmIntfcCapabilities.supportsIndicatorPulse) { + TU_ASSERT(&tud_usbtmc_indicator_pulse_cb != NULL,); + } #endif - usbtmcLock = osal_mutex_create(&usbtmcLockBuffer); + usbtmcLock = osal_mutex_create(&usbtmcLockBuffer); } uint16_t usbtmcd_open_cb(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) diff --git a/src/common/tusb_verify.h b/src/common/tusb_verify.h index 56ba8bcd1..8fef11dc7 100644 --- a/src/common/tusb_verify.h +++ b/src/common/tusb_verify.h @@ -37,31 +37,31 @@ * manipulation that you are told to stay away. * * This contains macros for both VERIFY and ASSERT: - * + * * VERIFY: Used when there is an error condition which is not the * fault of the MCU. For example, bounds checking on data * sent to the micro over USB should use this function. * Another example is checking for buffer overflows, where * returning from the active function causes a NAK. - * + * * ASSERT: Used for error conditions that are caused by MCU firmware * bugs. This is used to discover bugs in the code more * quickly. One example would be adding assertions in library * function calls to confirm a function's (untainted) * parameters are valid. - * + * * The difference in behavior is that ASSERT triggers a breakpoint while * verify does not. * * #define TU_VERIFY(cond) if(cond) return false; * #define TU_VERIFY(cond,ret) if(cond) return ret; - * + * * #define TU_VERIFY_HDLR(cond,handler) if(cond) {handler; return false;} * #define TU_VERIFY_HDLR(cond,ret,handler) if(cond) {handler; return ret;} * * #define TU_ASSERT(cond) if(cond) {_MESS_FAILED(); TU_BREAKPOINT(), return false;} * #define TU_ASSERT(cond,ret) if(cond) {_MESS_FAILED(); TU_BREAKPOINT(), return ret;} - * + * *------------------------------------------------------------------*/ #ifdef __cplusplus @@ -81,8 +81,8 @@ #define _MESS_FAILED() do {} while (0) #endif -// Halt CPU (breakpoint) when hitting error, only apply for Cortex M3, M4, M7 -#if defined(__ARM_ARCH_7M__) || defined (__ARM_ARCH_7EM__) +// Halt CPU (breakpoint) when hitting error, only apply for Cortex M3, M4, M7, M33 +#if defined(__ARM_ARCH_7M__) || defined (__ARM_ARCH_7EM__) || defined(__ARM_ARCH_8M_MAIN__) #define TU_BREAKPOINT() do \ { \ volatile uint32_t* ARM_CM_DHCSR = ((volatile uint32_t*) 0xE000EDF0UL); /* Cortex M CoreDebug->DHCSR */ \ diff --git a/src/device/dcd_attr.h b/src/device/dcd_attr.h index 3c5dadaf4..feba82ea9 100644 --- a/src/device/dcd_attr.h +++ b/src/device/dcd_attr.h @@ -190,7 +190,7 @@ #define DCD_ATTR_ENDPOINT_MAX 4 //------------- Broadcom -------------// -#elif TU_CHECK_MCU(OPT_MCU_BCM2711) +#elif TU_CHECK_MCU(OPT_MCU_BCM2711, OPT_MCU_BCM2835, OPT_MCU_BCM2837) #define DCD_ATTR_ENDPOINT_MAX 8 //------------- Broadcom -------------// diff --git a/src/portable/mentor/musb/dcd_musb.c b/src/portable/mentor/musb/dcd_musb.c index 4b4c2f9b2..f6e05e134 100644 --- a/src/portable/mentor/musb/dcd_musb.c +++ b/src/portable/mentor/musb/dcd_musb.c @@ -26,7 +26,8 @@ #include "tusb_option.h" -#if TU_CHECK_MCU(OPT_MCU_MSP432E4, OPT_MCU_TM4C123, OPT_MCU_TM4C129) +#if TUSB_OPT_DEVICE_ENABLED && \ + TU_CHECK_MCU(OPT_MCU_MSP432E4, OPT_MCU_TM4C123, OPT_MCU_TM4C129) #if __GNUC__ > 8 && defined(__ARM_FEATURE_UNALIGNED) /* GCC warns that an address may be unaligned, even though @@ -250,12 +251,12 @@ static void pipe_read_packet(void *buf, volatile void *fifo, unsigned len) len -= 4; } if (len >= 2) { - *(uint32_t *)addr = reg->u16; + *(uint16_t *)addr = reg->u16; addr += 2; len -= 2; } if (len) { - *(uint32_t *)addr = reg->u8; + *(uint8_t *)addr = reg->u8; } } diff --git a/src/portable/mentor/musb/hcd_musb.c b/src/portable/mentor/musb/hcd_musb.c new file mode 100644 index 000000000..acccb7674 --- /dev/null +++ b/src/portable/mentor/musb/hcd_musb.c @@ -0,0 +1,876 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2021 Koji KITAYAMA + * + * 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 TUSB_OPT_HOST_ENABLED && \ + TU_CHECK_MCU(OPT_MCU_MSP432E4, OPT_MCU_TM4C123, OPT_MCU_TM4C129) + +#if __GNUC__ > 8 && defined(__ARM_FEATURE_UNALIGNED) +/* GCC warns that an address may be unaligned, even though + * the target CPU has the capability for unaligned memory access. */ +_Pragma("GCC diagnostic ignored \"-Waddress-of-packed-member\""); +#endif + +#include "host/hcd.h" + +#if TU_CHECK_MCU(OPT_MCU_MSP432E4) + #include "musb_msp432e.h" + +#elif TU_CHECK_MCU(OPT_MCU_TM4C123, OPT_MCU_TM4C129) + #include "musb_tm4c.h" + + // HACK generalize later + #include "musb_type.h" + #define FIFO0_WORD FIFO0 + +#else + #error "Unsupported MCUs" +#endif + +#ifndef HCD_ATTR_ENDPOINT_MAX +# define HCD_ATTR_ENDPOINT_MAX 8 +#endif + +/*------------------------------------------------------------------ + * MACRO TYPEDEF CONSTANT ENUM DECLARATION + *------------------------------------------------------------------*/ +#define REQUEST_TYPE_INVALID (0xFFu) + +typedef struct { + uint_fast16_t beg; /* offset of including first element */ + uint_fast16_t end; /* offset of excluding the last element */ +} free_block_t; + +typedef struct TU_ATTR_PACKED { + uint8_t TXFUNCADDR; + uint8_t RESERVED0; + uint8_t TXHUBADDR; + uint8_t TXHUBPORT; + uint8_t RXFUNCADDR; + uint8_t RESERVED1; + uint8_t RXHUBADDR; + uint8_t RXHUBPORT; +} hw_addr_t; + +typedef struct TU_ATTR_PACKED { + uint16_t TXMAXP; + uint8_t TXCSRL; + uint8_t TXCSRH; + uint16_t RXMAXP; + uint8_t RXCSRL; + uint8_t RXCSRH; + uint16_t RXCOUNT; + uint8_t TXTYPE; + uint8_t TXINTERVAL; + uint8_t RXTYPE; + uint8_t RXINTERVAL; + uint16_t RESERVED; +} hw_endpoint_t; + +typedef union { + uint8_t u8; + uint16_t u16; + uint32_t u32; +} hw_fifo_t; + +typedef struct TU_ATTR_PACKED +{ + void *buf; /* the start address of a transfer data buffer */ + uint16_t length; /* the number of bytes in the buffer */ + uint16_t remaining; /* the number of bytes remaining in the buffer */ +} pipe_state_t; + +typedef struct TU_ATTR_PACKED +{ + uint8_t dev; + uint8_t ep; +} pipe_addr_t; + +typedef struct +{ + bool need_reset; /* The device has not been reset after connection. */ + uint8_t bmRequestType; + uint8_t ctl_mps[7]; /* EP0 max packet size for each device */ + pipe_state_t pipe0; + pipe_state_t pipe[7][2]; /* pipe[pipe number - 1][direction 0:RX 1:TX] */ + pipe_addr_t addr[7][2]; /* addr[pipe number - 1][direction 0:RX 1:TX] */ +} hcd_data_t; + +/*------------------------------------------------------------------ + * INTERNAL OBJECT & FUNCTION DECLARATION + *------------------------------------------------------------------*/ +static hcd_data_t _hcd; + +static inline free_block_t *find_containing_block(free_block_t *beg, free_block_t *end, uint_fast16_t addr) +{ + free_block_t *cur = beg; + for (; cur < end && ((addr < cur->beg) || (cur->end <= addr)); ++cur) ; + return cur; +} + +static inline int update_free_block_list(free_block_t *blks, unsigned num, uint_fast16_t addr, uint_fast16_t size) +{ + free_block_t *p = find_containing_block(blks, blks + num, addr); + TU_ASSERT(p != blks + num, -2); + if (p->beg == addr) { + /* Shrink block */ + p->beg = addr + size; + if (p->beg != p->end) return 0; + /* remove block */ + free_block_t *end = blks + num; + while (p + 1 < end) { + *p = *(p + 1); + ++p; + } + return -1; + } else { + /* Split into 2 blocks */ + free_block_t tmp = { + .beg = addr + size, + .end = p->end + }; + p->end = addr; + if (p->beg == p->end) { + if (tmp.beg != tmp.end) { + *p = tmp; + return 0; + } + /* remove block */ + free_block_t *end = blks + num; + while (p + 1 < end) { + *p = *(p + 1); + ++p; + } + return -1; + } + if (tmp.beg == tmp.end) return 0; + blks[num] = tmp; + return 1; + } +} + +static inline unsigned free_block_size(free_block_t const *blk) +{ + return blk->end - blk->beg; +} + +static unsigned find_free_memory(uint_fast16_t size_in_log2_minus3) +{ + free_block_t free_blocks[2 * (HCD_ATTR_ENDPOINT_MAX - 1)]; + unsigned num_blocks = 1; + + /* Initialize free memory block list */ + free_blocks[0].beg = 64 / 8; + free_blocks[0].end = (4 << 10) / 8; /* 4KiB / 8 bytes */ + for (int i = 1; i < HCD_ATTR_ENDPOINT_MAX; ++i) { + uint_fast16_t addr; + int num; + USB0->EPIDX = i; + addr = USB0->TXFIFOADD; + if (addr) { + unsigned sz = USB0->TXFIFOSZ; + unsigned sft = (sz & USB_TXFIFOSZ_SIZE_M) + ((sz & USB_TXFIFOSZ_DPB) ? 1: 0); + num = update_free_block_list(free_blocks, num_blocks, addr, 1 << sft); + TU_ASSERT(-2 < num, 0); + num_blocks += num; + } + addr = USB0->RXFIFOADD; + if (addr) { + unsigned sz = USB0->RXFIFOSZ; + unsigned sft = (sz & USB_RXFIFOSZ_SIZE_M) + ((sz & USB_RXFIFOSZ_DPB) ? 1: 0); + num = update_free_block_list(free_blocks, num_blocks, addr, 1 << sft); + TU_ASSERT(-2 < num, 0); + num_blocks += num; + } + } + + /* Find the best fit memory block */ + uint_fast16_t size_in_8byte_unit = 1 << size_in_log2_minus3; + free_block_t const *min = NULL; + uint_fast16_t min_sz = 0xFFFFu; + free_block_t const *end = &free_blocks[num_blocks]; + for (free_block_t const *cur = &free_blocks[0]; cur < end; ++cur) { + uint_fast16_t sz = free_block_size(cur); + if (sz < size_in_8byte_unit) continue; + if (size_in_8byte_unit == sz) return cur->beg; + if (sz < min_sz) min = cur; + } + TU_ASSERT(min, 0); + return min->beg; +} + +static inline volatile hw_endpoint_t* edpt_regs(unsigned epnum_minus1) +{ + volatile hw_endpoint_t *regs = (volatile hw_endpoint_t*)((uintptr_t)&USB0->TXMAXP1); + return regs + epnum_minus1; +} + +static unsigned find_pipe(uint_fast8_t dev_addr, uint_fast8_t ep_addr) +{ + unsigned const dir_tx = tu_edpt_dir(ep_addr) ? 0: 1; + pipe_addr_t const *p = &_hcd.addr[0][dir_tx]; + for (unsigned i = 0; i < sizeof(_hcd.addr)/sizeof(_hcd.addr[0]); ++i, p += 2) { + if ((dev_addr == p->dev) && (ep_addr == p->ep)) + return i + 1; + } + return 0; +} + +static void pipe_write_packet(void *buf, volatile void *fifo, unsigned len) +{ + volatile hw_fifo_t *reg = (volatile hw_fifo_t*)fifo; + uintptr_t addr = (uintptr_t)buf; + while (len >= 4) { + reg->u32 = *(uint32_t const *)addr; + addr += 4; + len -= 4; + } + if (len >= 2) { + reg->u16 = *(uint16_t const *)addr; + addr += 2; + len -= 2; + } + if (len) { + reg->u8 = *(uint8_t const *)addr; + } +} + +static void pipe_read_packet(void *buf, volatile void *fifo, unsigned len) +{ + volatile hw_fifo_t *reg = (volatile hw_fifo_t*)fifo; + uintptr_t addr = (uintptr_t)buf; + while (len >= 4) { + *(uint32_t *)addr = reg->u32; + addr += 4; + len -= 4; + } + if (len >= 2) { + *(uint16_t *)addr = reg->u16; + addr += 2; + len -= 2; + } + if (len) { + *(uint8_t *)addr = reg->u8; + } +} + +static bool edpt0_xfer_out(void) +{ + pipe_state_t *pipe = &_hcd.pipe0; + unsigned const rem = pipe->remaining; + if (!rem) { + pipe->buf = NULL; + return true; + } + unsigned const dev_addr = USB0->TXFUNCADDR0; + unsigned const mps = _hcd.ctl_mps[dev_addr]; + unsigned const len = TU_MIN(rem, mps); + void *buf = pipe->buf; + if (len) { + pipe_write_packet(buf, &USB0->FIFO0_WORD, len); + pipe->buf = (uint8_t*)buf + len; + } + pipe->remaining = rem - len; + USB0->CSRL0 = USB_CSRL0_TXRDY; + return false; +} + +static bool edpt0_xfer_in(void) +{ + pipe_state_t *pipe = &_hcd.pipe0; + unsigned const rem = pipe->remaining; + unsigned const dev_addr = USB0->TXFUNCADDR0; + unsigned const mps = _hcd.ctl_mps[dev_addr]; + unsigned const vld = USB0->COUNT0; + unsigned const len = TU_MIN(TU_MIN(rem, mps), vld); + void *buf = pipe->buf; + if (len) { + pipe_read_packet(buf, &USB0->FIFO0_WORD, len); + pipe->buf = (uint8_t*)buf + len; + } + pipe->remaining = rem - len; + if ((len < mps) || (rem == len)) { + pipe->buf = NULL; + return true; + } + USB0->CSRL0 = USB_CSRL0_REQPKT; + return false; +} + +static bool edpt0_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *buffer, uint16_t buflen) +{ + (void)rhport; + + unsigned const req = _hcd.bmRequestType; + TU_ASSERT(req != REQUEST_TYPE_INVALID); + TU_ASSERT(dev_addr < sizeof(_hcd.ctl_mps)); + + USB0->TXFUNCADDR0 = dev_addr; + const unsigned dir_in = tu_edpt_dir(ep_addr); + if (tu_edpt_dir(req) == dir_in) { /* DATA stage */ + TU_ASSERT(buffer); + _hcd.pipe0.buf = buffer; + _hcd.pipe0.length = buflen; + _hcd.pipe0.remaining = buflen; + if (dir_in) + USB0->CSRL0 = USB_CSRL0_REQPKT; + else + edpt0_xfer_out(); + } else { /* STATUS stage */ + _hcd.pipe0.buf = NULL; + _hcd.pipe0.length = 0; + _hcd.pipe0.remaining = 0; + USB0->CSRL0 = USB_CSRL0_STATUS | (dir_in ? USB_CSRL0_REQPKT: USB_CSRL0_TXRDY); + } + return true; +} + +static bool pipe_xfer_out(uint_fast8_t pipenum) +{ + pipe_state_t *pipe = &_hcd.pipe[pipenum - 1][1]; + unsigned const rem = pipe->remaining; + if (!rem) { + pipe->buf = NULL; + return true; + } + hw_endpoint_t volatile *regs = edpt_regs(pipenum - 1); + unsigned const mps = regs->TXMAXP; + unsigned const len = TU_MIN(rem, mps); + void *buf = pipe->buf; + if (len) { + pipe_write_packet(buf, &USB0->FIFO0_WORD + pipenum, len); + pipe->buf = (uint8_t*)buf + len; + } + pipe->remaining = rem - len; + regs->TXCSRL = USB_TXCSRL1_TXRDY; + return false; +} + +static bool pipe_xfer_in(uint_fast8_t pipenum) +{ + pipe_state_t *pipe = &_hcd.pipe[pipenum - 1][0]; + volatile hw_endpoint_t *regs = edpt_regs(pipenum - 1); + + TU_ASSERT(regs->RXCSRL & USB_RXCSRL1_RXRDY); + + const unsigned mps = regs->RXMAXP; + const unsigned rem = pipe->remaining; + const unsigned vld = regs->RXCOUNT; + const unsigned len = TU_MIN(TU_MIN(rem, mps), vld); + void *buf = pipe->buf; + if (len) { + pipe_read_packet(buf, &USB0->FIFO0_WORD + pipenum, len); + pipe->buf = buf + len; + pipe->remaining = rem - len; + } + if ((len < mps) || (rem == len)) { + pipe->buf = NULL; + return NULL != buf; + } + regs->RXCSRL = USB_RXCSRL1_REQPKT; + return false; +} + +static bool edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *buffer, uint16_t buflen) +{ + (void)rhport; + unsigned const pipenum = find_pipe(dev_addr, ep_addr); + unsigned const dir_tx = tu_edpt_dir(ep_addr) ? 0: 1; + pipe_state_t *pipe = &_hcd.pipe[pipenum - 1][dir_tx]; + pipe->buf = buffer; + pipe->length = buflen; + pipe->remaining = buflen; + if (dir_tx) { + pipe_xfer_out(pipenum); + } else { + volatile hw_endpoint_t *regs = edpt_regs(pipenum - 1); + regs->RXCSRL = USB_RXCSRL1_REQPKT; + } + return true; +} + +static void process_ep0(uint8_t rhport) +{ + (void)rhport; + + uint_fast8_t csrl = USB0->CSRL0; + // TU_LOG1(" EP0 CSRL = %x\n", csrl); + + unsigned const dev_addr = USB0->TXFUNCADDR0; + unsigned const req = _hcd.bmRequestType; + if (csrl & (USB_CSRL0_ERROR | USB_CSRL0_NAKTO | USB_CSRL0_STALLED)) { + /* No response / NAK timed out / Stall received */ + if (csrl & (USB_CSRL0_RXRDY | USB_CSRL0_TXRDY)) + USB0->CSRH0 = USB_CSRH0_FLUSH; + USB0->CSRL0 = 0; + _hcd.bmRequestType = REQUEST_TYPE_INVALID; + uint8_t result = (csrl & USB_CSRL0_STALLED) ? XFER_RESULT_STALLED: XFER_RESULT_FAILED; + if (REQUEST_TYPE_INVALID == req) { /* SETUP */ + uint8_t const ep_addr = tu_edpt_addr(0, TUSB_DIR_OUT); + hcd_event_xfer_complete(dev_addr, ep_addr, + _hcd.pipe0.length - _hcd.pipe0.remaining, + result, true); + } else if (csrl & USB_CSRL0_STATUS) { /* STATUS */ + uint8_t const ep_addr = tu_edpt_dir(req) ? + tu_edpt_addr(0, TUSB_DIR_OUT): tu_edpt_addr(0, TUSB_DIR_IN); + hcd_event_xfer_complete(dev_addr, ep_addr, + _hcd.pipe0.length - _hcd.pipe0.remaining, + result, true); + } else { /* DATA */ + uint8_t const ep_addr = tu_edpt_dir(req) ? + tu_edpt_addr(0, TUSB_DIR_IN): tu_edpt_addr(0, TUSB_DIR_OUT); + hcd_event_xfer_complete(dev_addr, ep_addr, + _hcd.pipe0.length - _hcd.pipe0.remaining, + result, true); + } + return; + } + if (csrl & USB_CSRL0_STATUS) { + /* STATUS IN */ + TU_ASSERT(USB_CSRL0_RXRDY == (csrl & USB_CSRL0_RXRDY),); + TU_ASSERT(0 == USB0->COUNT0,); + USB0->CSRH0 = USB_CSRH0_FLUSH; + USB0->CSRL0 = 0; + _hcd.bmRequestType = REQUEST_TYPE_INVALID; + hcd_event_xfer_complete(dev_addr, tu_edpt_addr(0, TUSB_DIR_IN), + 0, XFER_RESULT_SUCCESS, true); + return; + } + if (csrl & USB_CSRL0_RXRDY) { + /* DATA IN */ + TU_ASSERT(REQUEST_TYPE_INVALID != req,); + TU_ASSERT(_hcd.pipe0.buf,); + if (edpt0_xfer_in()) { + hcd_event_xfer_complete(dev_addr, tu_edpt_addr(0, TUSB_DIR_IN), + _hcd.pipe0.length - _hcd.pipe0.remaining, + XFER_RESULT_SUCCESS, true); + } + return; + } + + /* When CSRL0 is zero, it means that completion of sending a any length packet. */ + if (!_hcd.pipe0.buf) { + /* STATUS OUT */ + TU_ASSERT(REQUEST_TYPE_INVALID != req,); + _hcd.bmRequestType = REQUEST_TYPE_INVALID; + /* EP address is the reverse direction of DATA stage */ + uint8_t const ep_addr = tu_edpt_dir(req) ? + tu_edpt_addr(0, TUSB_DIR_OUT): tu_edpt_addr(0, TUSB_DIR_IN); + hcd_event_xfer_complete(dev_addr, ep_addr, 0, XFER_RESULT_SUCCESS, true); + return; + } + if (REQUEST_TYPE_INVALID == req) { + /* SETUP */ + _hcd.bmRequestType = *(uint8_t*)_hcd.pipe0.buf; + _hcd.pipe0.buf = NULL; + hcd_event_xfer_complete(dev_addr, tu_edpt_addr(0, TUSB_DIR_OUT), + 8, XFER_RESULT_SUCCESS, true); + return; + } + + /* DATA OUT */ + if (edpt0_xfer_out()) { + hcd_event_xfer_complete(dev_addr, tu_edpt_addr(0, TUSB_DIR_OUT), + _hcd.pipe0.length - _hcd.pipe0.remaining, + XFER_RESULT_SUCCESS, true); + } +} + +static void process_pipe_tx(uint8_t rhport, uint_fast8_t pipenum) +{ + (void)rhport; + bool completed; + uint8_t result; + + volatile hw_endpoint_t *regs = edpt_regs(pipenum - 1); + unsigned const csrl = regs->TXCSRL; + // TU_LOG1(" TXCSRL%d = %x\n", pipenum, csrl); + if (csrl & (USB_TXCSRL1_STALLED | USB_TXCSRL1_ERROR)) { + if (csrl & USB_TXCSRL1_TXRDY) + regs->TXCSRL = (csrl & ~(USB_TXCSRL1_STALLED | USB_TXCSRL1_ERROR)) | USB_TXCSRL1_FLUSH; + else + regs->TXCSRL = csrl & ~(USB_TXCSRL1_STALLED | USB_TXCSRL1_ERROR); + completed = true; + result = (csrl & USB_TXCSRL1_STALLED) ? XFER_RESULT_STALLED: XFER_RESULT_FAILED; + } else { + completed = pipe_xfer_out(pipenum); + result = XFER_RESULT_SUCCESS; + } + if (completed) { + pipe_addr_t *addr = &_hcd.addr[pipenum - 1][1]; + pipe_state_t *pipe = &_hcd.pipe[pipenum - 1][1]; + hcd_event_xfer_complete(addr->dev, addr->ep, + pipe->length - pipe->remaining, + result, true); + } +} + +static void process_pipe_rx(uint8_t rhport, uint_fast8_t pipenum) +{ + (void)rhport; + bool completed; + uint8_t result; + + volatile hw_endpoint_t *regs = edpt_regs(pipenum - 1); + unsigned const csrl = regs->RXCSRL; + // TU_LOG1(" RXCSRL%d = %x\n", pipenum, csrl); + if (csrl & (USB_RXCSRL1_STALLED | USB_RXCSRL1_ERROR)) { + if (csrl & USB_RXCSRL1_RXRDY) + regs->RXCSRL = (csrl & ~(USB_RXCSRL1_STALLED | USB_RXCSRL1_ERROR)) | USB_RXCSRL1_FLUSH; + else + regs->RXCSRL = csrl & ~(USB_RXCSRL1_STALLED | USB_RXCSRL1_ERROR); + completed = true; + result = (csrl & USB_RXCSRL1_STALLED) ? XFER_RESULT_STALLED: XFER_RESULT_FAILED; + } else { + completed = pipe_xfer_in(pipenum); + result = XFER_RESULT_SUCCESS; + } + if (completed) { + pipe_addr_t *addr = &_hcd.addr[pipenum - 1][0]; + pipe_state_t *pipe = &_hcd.pipe[pipenum - 1][0]; + hcd_event_xfer_complete(addr->dev, addr->ep, + pipe->length - pipe->remaining, + result, true); + } +} + +/*------------------------------------------------------------------ + * Host API + *------------------------------------------------------------------*/ + +bool hcd_init(uint8_t rhport) +{ + (void)rhport; + + NVIC_ClearPendingIRQ(USB0_IRQn); + _hcd.bmRequestType = REQUEST_TYPE_INVALID; + USB0->DEVCTL |= USB_DEVCTL_SESSION; + USB0->IE = USB_IE_DISCON | USB_IE_CONN | USB_IE_BABBLE | USB_IE_RESUME; + return true; +} + +void hcd_int_enable(uint8_t rhport) +{ + (void)rhport; + NVIC_EnableIRQ(USB0_IRQn); +} + +void hcd_int_disable(uint8_t rhport) +{ + (void)rhport; + NVIC_DisableIRQ(USB0_IRQn); +} + +uint32_t hcd_frame_number(uint8_t rhport) +{ + (void)rhport; + /* The device must be reset at least once after connection + * in order to start the frame counter. */ + if (_hcd.need_reset) hcd_port_reset(rhport); + return USB0->FRAME; +} + +//--------------------------------------------------------------------+ +// Port API +//--------------------------------------------------------------------+ + +bool hcd_port_connect_status(uint8_t rhport) +{ + (void)rhport; + unsigned devctl = USB0->DEVCTL; + if (!(devctl & USB_DEVCTL_HOST)) return false; + if (devctl & (USB_DEVCTL_LSDEV | USB_DEVCTL_FSDEV)) return true; + return false; +} + +void hcd_port_reset(uint8_t rhport) +{ + (void)rhport; + USB0->POWER |= USB_POWER_HSENAB | USB_POWER_RESET; + unsigned cnt = SystemCoreClock / 1000 * 20; + while (cnt--) __NOP(); + USB0->POWER &= ~USB_POWER_RESET; + _hcd.need_reset = false; +} + +tusb_speed_t hcd_port_speed_get(uint8_t rhport) +{ + (void)rhport; + unsigned devctl = USB0->DEVCTL; + if (devctl & USB_DEVCTL_LSDEV) return TUSB_SPEED_LOW; + if (!(devctl & USB_DEVCTL_FSDEV)) return TUSB_SPEED_INVALID; + if (USB0->POWER & USB_POWER_HSMODE) return TUSB_SPEED_HIGH; + return TUSB_SPEED_FULL; +} + +void hcd_device_close(uint8_t rhport, uint8_t dev_addr) +{ + (void)rhport; + if (sizeof(_hcd.ctl_mps) <= dev_addr) return; + + unsigned const ie = NVIC_GetEnableIRQ(USB0_IRQn); + NVIC_DisableIRQ(USB0_IRQn); + _hcd.ctl_mps[dev_addr] = 0; + if (!dev_addr) return; + + pipe_addr_t *p = &_hcd.addr[0][0]; + for (unsigned i = 0; i < sizeof(_hcd.addr)/sizeof(_hcd.addr[0]); ++i) { + for (unsigned j = 0; j < 2; ++j, ++p) { + if (dev_addr != p->dev) continue; + hw_addr_t volatile *fadr = (hw_addr_t volatile*)&USB0->TXFUNCADDR0 + i + 1; + hw_endpoint_t volatile *regs = edpt_regs(i); + USB0->EPIDX = i + 1; + if (j) { + USB0->TXIE &= ~TU_BIT(i + 1); + if (regs->TXCSRL & USB_TXCSRL1_TXRDY) + regs->TXCSRL = USB_TXCSRL1_CLRDT | USB_TXCSRL1_FLUSH; + else + regs->TXCSRL = USB_TXCSRL1_CLRDT; + regs->TXMAXP = 0; + regs->TXTYPE = 0; + regs->TXINTERVAL = 0; + fadr->TXFUNCADDR = 0; + fadr->TXHUBADDR = 0; + fadr->TXHUBPORT = 0; + USB0->TXFIFOADD = 0; + USB0->TXFIFOSZ = 0; + } else { + USB0->RXIE &= ~TU_BIT(i + 1); + if (regs->RXCSRL & USB_RXCSRL1_RXRDY) + regs->RXCSRL = USB_RXCSRL1_CLRDT | USB_RXCSRL1_FLUSH; + else + regs->RXCSRL = USB_RXCSRL1_CLRDT; + regs->RXMAXP = 0; + regs->RXTYPE = 0; + regs->RXINTERVAL = 0; + fadr->RXFUNCADDR = 0; + fadr->RXHUBADDR = 0; + fadr->RXHUBPORT = 0; + USB0->RXFIFOADD = 0; + USB0->RXFIFOSZ = 0; + } + p->dev = 0; + p->ep = 0; + pipe_state_t *pipe = &_hcd.pipe[i][j]; + pipe->buf = NULL; + pipe->length = 0; + pipe->remaining = 0; + } + } + if (ie) NVIC_EnableIRQ(USB0_IRQn); +} + +//--------------------------------------------------------------------+ +// Endpoints API +//--------------------------------------------------------------------+ + +bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8]) +{ + (void)rhport; + pipe_write_packet((void*)(uintptr_t)setup_packet, &USB0->FIFO0_WORD, 8); + _hcd.pipe0.buf = (void*)(uintptr_t)setup_packet; + _hcd.pipe0.length = 8; + _hcd.pipe0.remaining = 0; + + hcd_devtree_info_t devtree; + hcd_devtree_get_info(dev_addr, &devtree); + switch (devtree.speed) { + default: return false; + case TUSB_SPEED_LOW: USB0->TYPE0 = USB_TYPE0_SPEED_LOW; break; + case TUSB_SPEED_FULL: USB0->TYPE0 = USB_TYPE0_SPEED_FULL; break; + case TUSB_SPEED_HIGH: USB0->TYPE0 = USB_TYPE0_SPEED_HIGH; break; + } + USB0->TXHUBADDR0 = devtree.hub_addr; + USB0->TXHUBPORT0 = devtree.hub_port; + USB0->TXFUNCADDR0 = dev_addr; + USB0->CSRL0 = USB_CSRL0_TXRDY | USB_CSRL0_SETUP; + return true; +} + +bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc) +{ + (void)rhport; + if (sizeof(_hcd.ctl_mps) <= dev_addr) return false; + unsigned const ep_addr = ep_desc->bEndpointAddress; + unsigned const epn = tu_edpt_number(ep_addr); + if (0 == epn) { + _hcd.ctl_mps[dev_addr] = ep_desc->wMaxPacketSize; + return true; + } + + unsigned const dir_tx = tu_edpt_dir(ep_addr) ? 0: 1; + /* Find a free pipe */ + unsigned pipenum = 0; + pipe_addr_t *p = &_hcd.addr[0][dir_tx]; + for (unsigned i = 0; i < sizeof(_hcd.addr)/sizeof(_hcd.addr[0]); ++i, p += 2) { + if (0 == p->ep) { + p->dev = dev_addr; + p->ep = ep_addr; + pipenum = i + 1; + break; + } + } + if (!pipenum) return false; + + unsigned const xfer = ep_desc->bmAttributes.xfer; + unsigned const mps = tu_edpt_packet_size(ep_desc); + + pipe_state_t *pipe = &_hcd.pipe[pipenum - 1][dir_tx]; + pipe->buf = NULL; + pipe->length = 0; + pipe->remaining = 0; + + uint8_t pipe_type = 0; + hcd_devtree_info_t devtree; + hcd_devtree_get_info(dev_addr, &devtree); + switch (devtree.speed) { + default: return false; + case TUSB_SPEED_LOW: pipe_type |= USB_TXTYPE1_SPEED_LOW; break; + case TUSB_SPEED_FULL: pipe_type |= USB_TXTYPE1_SPEED_FULL; break; + case TUSB_SPEED_HIGH: pipe_type |= USB_TXTYPE1_SPEED_HIGH; break; + } + switch (xfer) { + default: return false; + case TUSB_XFER_BULK: pipe_type |= USB_TXTYPE1_PROTO_BULK; break; + case TUSB_XFER_INTERRUPT: pipe_type |= USB_TXTYPE1_PROTO_INT; break; + case TUSB_XFER_ISOCHRONOUS: pipe_type |= USB_TXTYPE1_PROTO_ISOC; break; + } + + hw_addr_t volatile *fadr = (hw_addr_t volatile*)&USB0->TXFUNCADDR0 + pipenum; + hw_endpoint_t volatile *regs = edpt_regs(pipenum - 1); + if (dir_tx) { + fadr->TXFUNCADDR = dev_addr; + fadr->TXHUBADDR = devtree.hub_addr; + fadr->TXHUBPORT = devtree.hub_port; + regs->TXMAXP = mps; + regs->TXTYPE = pipe_type | epn; + regs->TXINTERVAL = ep_desc->bInterval; + if (regs->TXCSRL & USB_TXCSRL1_TXRDY) + regs->TXCSRL = USB_TXCSRL1_CLRDT | USB_TXCSRL1_FLUSH; + else + regs->TXCSRL = USB_TXCSRL1_CLRDT; + USB0->TXIE |= TU_BIT(pipenum); + } else { + fadr->RXFUNCADDR = dev_addr; + fadr->RXHUBADDR = devtree.hub_addr; + fadr->RXHUBPORT = devtree.hub_port; + regs->RXMAXP = mps; + regs->RXTYPE = pipe_type | epn; + regs->RXINTERVAL = ep_desc->bInterval; + if (regs->RXCSRL & USB_RXCSRL1_RXRDY) + regs->RXCSRL = USB_RXCSRL1_CLRDT | USB_RXCSRL1_FLUSH; + else + regs->RXCSRL = USB_RXCSRL1_CLRDT; + USB0->RXIE |= TU_BIT(pipenum); + } + + /* Setup FIFO */ + int size_in_log2_minus3 = 28 - TU_MIN(28, __CLZ((uint32_t)mps)); + if ((8u << size_in_log2_minus3) < mps) ++size_in_log2_minus3; + unsigned addr = find_free_memory(size_in_log2_minus3); + TU_ASSERT(addr); + + USB0->EPIDX = pipenum; + if (dir_tx) { + USB0->TXFIFOADD = addr; + USB0->TXFIFOSZ = size_in_log2_minus3; + } else { + USB0->RXFIFOADD = addr; + USB0->RXFIFOSZ = size_in_log2_minus3; + } + return true; +} + +bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *buffer, uint16_t buflen) +{ + (void)rhport; + bool ret = false; + if (0 == tu_edpt_number(ep_addr)) { + ret = edpt0_xfer(rhport, dev_addr, ep_addr, buffer, buflen); + } else { + ret = edpt_xfer(rhport, dev_addr, ep_addr, buffer, buflen); + } + return ret; +} + +// clear stall, data toggle is also reset to DATA0 +bool hcd_edpt_clear_stall(uint8_t dev_addr, uint8_t ep_addr) +{ + unsigned const pipenum = find_pipe(dev_addr, ep_addr); + if (!pipenum) return false; + hw_endpoint_t volatile *regs = edpt_regs(pipenum - 1); + unsigned const dir_tx = tu_edpt_dir(ep_addr) ? 0: 1; + if (dir_tx) + regs->TXCSRL = USB_TXCSRL1_CLRDT; + else + regs->RXCSRL = USB_RXCSRL1_CLRDT; + return true; +} + +/*------------------------------------------------------------------- + * ISR + *-------------------------------------------------------------------*/ +void hcd_int_handler(uint8_t rhport) +{ + uint_fast8_t is, txis, rxis; + + is = USB0->IS; /* read and clear interrupt status */ + txis = USB0->TXIS; /* read and clear interrupt status */ + rxis = USB0->RXIS; /* read and clear interrupt status */ + // TU_LOG1("D%2x T%2x R%2x\n", is, txis, rxis); + + is &= USB0->IE; /* Clear disabled interrupts */ + if (is & USB_IS_RESUME) { + } + if (is & USB_IS_CONN) { + _hcd.need_reset = true; + hcd_event_device_attach(rhport, true); + } + if (is & USB_IS_DISCON) { + hcd_event_device_remove(rhport, true); + } + if (is & USB_IS_BABBLE) { + } + txis &= USB0->TXIE; /* Clear disabled interrupts */ + if (txis & USB_TXIE_EP0) { + process_ep0(rhport); + txis &= ~TU_BIT(0); + } + while (txis) { + unsigned const num = __builtin_ctz(txis); + process_pipe_tx(rhport, num); + txis &= ~TU_BIT(num); + } + rxis &= USB0->RXIE; /* Clear disabled interrupts */ + while (rxis) { + unsigned const num = __builtin_ctz(rxis); + process_pipe_rx(rhport, num); + rxis &= ~TU_BIT(num); + } +} + +#endif diff --git a/src/portable/nordic/nrf5x/dcd_nrf5x.c b/src/portable/nordic/nrf5x/dcd_nrf5x.c index 2bcd56b8a..ed597a34f 100644 --- a/src/portable/nordic/nrf5x/dcd_nrf5x.c +++ b/src/portable/nordic/nrf5x/dcd_nrf5x.c @@ -1059,7 +1059,13 @@ void tusb_hal_nrf_power_event (uint32_t event) // Enable interrupt, priorities should be set by application NVIC_ClearPendingIRQ(USBD_IRQn); - NVIC_EnableIRQ(USBD_IRQn); + // Don't enable USBD interrupt yet, if dcd_init() did not finish yet + // Interrupt will be enabled by tud_init(), when USB stack is ready + // to handle interrupts. + if (tud_inited()) + { + NVIC_EnableIRQ(USBD_IRQn); + } // Wait for HFCLK while ( !hfclk_running() ) { } diff --git a/src/portable/raspberrypi/rp2040/dcd_rp2040.c b/src/portable/raspberrypi/rp2040/dcd_rp2040.c index e084478e0..42add3167 100644 --- a/src/portable/raspberrypi/rp2040/dcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/dcd_rp2040.c @@ -83,7 +83,7 @@ static void _hw_endpoint_alloc(struct hw_endpoint *ep, uint8_t transfer_type) assert(((uintptr_t )next_buffer_ptr & 0b111111u) == 0); uint dpram_offset = hw_data_offset(ep->hw_data_buf); - assert(hw_data_offset(next_buffer_ptr) <= USB_DPRAM_MAX); + hard_assert(hw_data_offset(next_buffer_ptr) <= USB_DPRAM_MAX); pico_info(" Alloced %d bytes at offset 0x%x (0x%p)\r\n", size, dpram_offset, ep->hw_data_buf); @@ -93,7 +93,6 @@ static void _hw_endpoint_alloc(struct hw_endpoint *ep, uint8_t transfer_type) *ep->endpoint_control = reg; } -#if 0 // todo unused static void _hw_endpoint_close(struct hw_endpoint *ep) { // Clear hardware registers and then zero the struct @@ -103,6 +102,21 @@ static void _hw_endpoint_close(struct hw_endpoint *ep) *ep->buffer_control = 0; // Clear any endpoint state memset(ep, 0, sizeof(struct hw_endpoint)); + + // Reclaim buffer space if all endpoints are closed + bool reclaim_buffers = true; + for ( uint8_t i = 1; i < USB_MAX_ENDPOINTS; i++ ) + { + if (hw_endpoint_get_by_num(i, TUSB_DIR_OUT)->hw_data_buf != NULL || hw_endpoint_get_by_num(i, TUSB_DIR_IN)->hw_data_buf != NULL) + { + reclaim_buffers = false; + break; + } + } + if (reclaim_buffers) + { + next_buffer_ptr = &usb_dpram->epx_data[0]; + } } static void hw_endpoint_close(uint8_t ep_addr) @@ -110,7 +124,6 @@ static void hw_endpoint_close(uint8_t ep_addr) struct hw_endpoint *ep = hw_endpoint_get_by_addr(ep_addr); _hw_endpoint_close(ep); } -#endif static void hw_endpoint_init(uint8_t ep_addr, uint16_t wMaxPacketSize, uint8_t transfer_type) { @@ -224,6 +237,8 @@ static void reset_non_control_endpoints(void) // clear non-control hw endpoints tu_memclr(hw_endpoints[1], sizeof(hw_endpoints) - 2*sizeof(hw_endpoint_t)); + + // reclaim buffer space next_buffer_ptr = &usb_dpram->epx_data[0]; } @@ -232,6 +247,14 @@ static void dcd_rp2040_irq(void) uint32_t const status = usb_hw->ints; uint32_t handled = 0; + // xfer events are handled before setup req. So if a transfer completes immediately + // before closing the EP, the events will be delivered in same order. + if (status & USB_INTS_BUFF_STATUS_BITS) + { + handled |= USB_INTS_BUFF_STATUS_BITS; + hw_handle_buff_status(); + } + if (status & USB_INTS_SETUP_REQ_BITS) { handled |= USB_INTS_SETUP_REQ_BITS; @@ -245,12 +268,6 @@ static void dcd_rp2040_irq(void) usb_hw_clear->sie_status = USB_SIE_STATUS_SETUP_REC_BITS; } - if (status & USB_INTS_BUFF_STATUS_BITS) - { - handled |= USB_INTS_BUFF_STATUS_BITS; - hw_handle_buff_status(); - } - #if FORCE_VBUS_DETECT == 0 // Since we force VBUS detect On, device will always think it is connected and // couldn't distinguish between disconnect and suspend @@ -479,10 +496,9 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr) { (void) rhport; - (void) ep_addr; - // usbd.c says: In progress transfers on this EP may be delivered after this call pico_trace("dcd_edpt_close %02x\n", ep_addr); + hw_endpoint_close(ep_addr); } void dcd_int_handler(uint8_t rhport) diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.c b/src/portable/raspberrypi/rp2040/rp2040_usb.c index c9e2f6b26..9d833e65f 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.c +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.c @@ -294,7 +294,7 @@ bool hw_endpoint_xfer_continue(struct hw_endpoint *ep) // Part way through a transfer if (!ep->active) { - panic("Can't continue xfer on inactive ep %d %s", tu_edpt_number(ep->ep_addr), ep_dir_string); + panic("Can't continue xfer on inactive ep %d %s", tu_edpt_number(ep->ep_addr), ep_dir_string[tu_edpt_dir(ep->ep_addr)]); } // Update EP struct from hardware state diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index bb21b3dcd..188611743 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -33,7 +33,8 @@ #if TUSB_OPT_DEVICE_ENABLED && \ ( defined(DCD_ATTR_DWC2_STM32) || \ TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3, OPT_MCU_GD32VF103) || \ - TU_CHECK_MCU(OPT_MCU_EFM32GG, OPT_MCU_BCM2711, OPT_MCU_XMC4000) ) + TU_CHECK_MCU(OPT_MCU_EFM32GG, OPT_MCU_BCM2711, OPT_MCU_BCM2835) || \ + TU_CHECK_MCU(OPT_MCU_BCM2837, OPT_MCU_XMC4000) ) #include "device/dcd.h" #include "dwc2_type.h" @@ -44,7 +45,7 @@ #include "dwc2_esp32.h" #elif TU_CHECK_MCU(OPT_MCU_GD32VF103) #include "dwc2_gd32.h" -#elif TU_CHECK_MCU(OPT_MCU_BCM2711) +#elif TU_CHECK_MCU(OPT_MCU_BCM2711, OPT_MCU_BCM2835, OPT_MCU_BCM2837) #include "dwc2_bcm.h" #elif TU_CHECK_MCU(OPT_MCU_EFM32GG) #include "dwc2_efm32.h" diff --git a/src/portable/synopsys/dwc2/dwc2_bcm.h b/src/portable/synopsys/dwc2/dwc2_bcm.h index 353bc21ee..14194e754 100644 --- a/src/portable/synopsys/dwc2/dwc2_bcm.h +++ b/src/portable/synopsys/dwc2/dwc2_bcm.h @@ -31,6 +31,7 @@ extern "C" { #endif +#include "broadcom/defines.h" #include "broadcom/interrupts.h" #include "broadcom/caches.h" @@ -47,7 +48,6 @@ static inline void dwc2_dcd_int_enable(uint8_t rhport) { (void) rhport; BP_EnableIRQ(USB_IRQn); - __asm__ volatile("isb"); // needed if TIMER1 IRQ is not enabled !? } TU_ATTR_ALWAYS_INLINE @@ -55,7 +55,6 @@ static inline void dwc2_dcd_int_disable (uint8_t rhport) { (void) rhport; BP_DisableIRQ(USB_IRQn); - __asm__ volatile("isb"); // needed if TIMER1 IRQ is not enabled !? } static inline void dwc2_remote_wakeup_delay(void) diff --git a/src/portable/valentyusb/eptri/dcd_eptri.c b/src/portable/valentyusb/eptri/dcd_eptri.c index 837d0c0ce..51fb8b401 100644 --- a/src/portable/valentyusb/eptri/dcd_eptri.c +++ b/src/portable/valentyusb/eptri/dcd_eptri.c @@ -24,6 +24,10 @@ * This file is part of the TinyUSB stack. */ +#include "tusb_option.h" + +#if TUSB_OPT_DEVICE_ENABLED && (CFG_TUSB_MCU == OPT_MCU_VALENTYUSB_EPTRI) + #ifndef DEBUG #define DEBUG 0 #endif @@ -32,10 +36,6 @@ #define LOG_USB 0 #endif -#include "tusb_option.h" - -#if TUSB_OPT_DEVICE_ENABLED && (CFG_TUSB_MCU == OPT_MCU_VALENTYUSB_EPTRI) - #include "device/dcd.h" #include "dcd_eptri.h" #include "csr.h" diff --git a/src/tusb_option.h b/src/tusb_option.h index 2edd310fa..c7c7b2454 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -132,6 +132,8 @@ // Broadcom #define OPT_MCU_BCM2711 1700 ///< Broadcom BCM2711 +#define OPT_MCU_BCM2835 1701 ///< Broadcom BCM2835 +#define OPT_MCU_BCM2837 1702 ///< Broadcom BCM2837 // Infineon #define OPT_MCU_XMC4000 1800 ///< Infineon XMC4000 |
