summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBrent Kowal <[email protected]>2024-07-25 09:08:37 -0400
committerBrent Kowal <[email protected]>2024-07-25 09:08:37 -0400
commit5122d6d109f8c4b31b6cbe29c685fad30a8961fe (patch)
treef45efc716882a885d776a30f79c11fef9e41735f /src
parent13f5f20c981cc54baa8438e275524db03fb79e94 (diff)
Combined DCD MUSB implementations
Combined the new MAX32 MUSB implementation with the existing (TI) implementation to provide generic code base for working the MUSB DCD peripheral. - Added abstraction calls for FIFO setup, EP registers, Ctrl registers and interrupt setup. - Combined TM4C and MSP432E into a single header file. - Created musb_max32.h, and removed the MAX32 specific C implementation. - Updated MAX32 build system to use dcd_musb.c. - Added MAX32 conditions for cdc_dual_ports example descriptors missed during first testing.
Diffstat (limited to 'src')
-rw-r--r--src/portable/analog/max32/dcd_max32.c811
-rw-r--r--src/portable/mentor/musb/dcd_musb.c436
-rw-r--r--src/portable/mentor/musb/hcd_musb.c12
-rw-r--r--src/portable/mentor/musb/musb_max32.h221
-rw-r--r--src/portable/mentor/musb/musb_msp432e.h40
-rw-r--r--src/portable/mentor/musb/musb_ti.h285
-rw-r--r--src/portable/mentor/musb/musb_tm4c.h45
-rw-r--r--src/portable/mentor/musb/musb_type.h33
8 files changed, 691 insertions, 1192 deletions
diff --git a/src/portable/analog/max32/dcd_max32.c b/src/portable/analog/max32/dcd_max32.c
deleted file mode 100644
index df616120a..000000000
--- a/src/portable/analog/max32/dcd_max32.c
+++ /dev/null
@@ -1,811 +0,0 @@
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2021 Koji KITAYAMA
- * Copyright (c) 2024 Brent Kowal (Analog Devices, Inc)
- *
- * 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_TUD_ENABLED && \
- TU_CHECK_MCU(OPT_MCU_MAX32690, OPT_MCU_MAX32650, OPT_MCU_MAX32666, OPT_MCU_MAX78002)
-
- #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 "device/dcd.h"
-
- #include "mxc_delay.h"
- #include "mxc_device.h"
- #include "mxc_sys.h"
- #include "nvic_table.h"
- #include "usbhs_regs.h"
-
- #define USBHS_M31_CLOCK_RECOVERY
-
- /*------------------------------------------------------------------
- * MACRO TYPEDEF CONSTANT ENUM DECLARATION
- *------------------------------------------------------------------*/
- #define REQUEST_TYPE_INVALID (0xFFu)
-
-
-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
-{
- tusb_control_request_t setup_packet;
- uint16_t remaining_ctrl; /* The number of bytes remaining in data stage of control transfer. */
- int8_t status_out;
- pipe_state_t pipe0;
- pipe_state_t pipe[2][TUP_DCD_ENDPOINT_MAX - 1]; /* pipe[direction][endpoint number - 1] */
- uint16_t pipe_buf_is_fifo[2]; /* Bitmap. Each bit means whether 1:TU_FIFO or 0:POD. */
-} dcd_data_t;
-
-/*------------------------------------------------------------------
- * INTERNAL OBJECT & FUNCTION DECLARATION
- *------------------------------------------------------------------*/
-static dcd_data_t _dcd;
-
-
-static volatile void *edpt_get_fifo_ptr(unsigned epnum) {
- volatile uint32_t *ptr;
-
- ptr = &MXC_USBHS->fifo0;
- ptr += epnum; /* Pointer math: multiplies ep by sizeof(uint32_t) */
-
- return (volatile void *) ptr;
-}
-
-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 void pipe_read_write_packet_ff(tu_fifo_t *f, volatile void *fifo, unsigned len, unsigned dir) {
- static const struct {
- void (*tu_fifo_get_info)(tu_fifo_t *f, tu_fifo_buffer_info_t *info);
- void (*tu_fifo_advance)(tu_fifo_t *f, uint16_t n);
- void (*pipe_read_write)(void *buf, volatile void *fifo, unsigned len);
- } ops[] = {
- /* OUT */ {tu_fifo_get_write_info, tu_fifo_advance_write_pointer, pipe_read_packet},
- /* IN */ {tu_fifo_get_read_info, tu_fifo_advance_read_pointer, pipe_write_packet},
- };
- tu_fifo_buffer_info_t info;
- ops[dir].tu_fifo_get_info(f, &info);
- unsigned total_len = len;
- len = TU_MIN(total_len, info.len_lin);
- ops[dir].pipe_read_write(info.ptr_lin, fifo, len);
- unsigned rem = total_len - len;
- if (rem) {
- len = TU_MIN(rem, info.len_wrap);
- ops[dir].pipe_read_write(info.ptr_wrap, fifo, len);
- rem -= len;
- }
- ops[dir].tu_fifo_advance(f, total_len - rem);
-}
-
-static void process_setup_packet(uint8_t rhport) {
- uint32_t *p = (void *) &_dcd.setup_packet;
- p[0] = MXC_USBHS->fifo0;
- p[1] = MXC_USBHS->fifo0;
-
- _dcd.pipe0.buf = NULL;
- _dcd.pipe0.length = 0;
- _dcd.pipe0.remaining = 0;
- dcd_event_setup_received(rhport, (const uint8_t *) (uintptr_t) &_dcd.setup_packet, true);
-
- const unsigned len = _dcd.setup_packet.wLength;
- _dcd.remaining_ctrl = len;
- const unsigned dir_in = tu_edpt_dir(_dcd.setup_packet.bmRequestType);
- /* Clear RX FIFO and reverse the transaction direction */
- if (len && dir_in) {
- MXC_USBHS->index = 0;
- MXC_USBHS->csr0 = MXC_F_USBHS_CSR0_SERV_OUTPKTRDY;
- }
-}
-
-static bool handle_xfer_in(uint_fast8_t ep_addr) {
- unsigned epnum = tu_edpt_number(ep_addr);
- unsigned epnum_minus1 = epnum - 1;
- pipe_state_t *pipe = &_dcd.pipe[tu_edpt_dir(ep_addr)][epnum_minus1];
- const unsigned rem = pipe->remaining;
-
- //This function should not be for ep0
- TU_ASSERT(epnum);
-
- if (!rem) {
- pipe->buf = NULL;
- return true;
- }
-
- MXC_USBHS->index = epnum;
- const unsigned mps = MXC_USBHS->inmaxp;
- const unsigned len = TU_MIN(mps, rem);
- void *buf = pipe->buf;
- volatile void *fifo_ptr = edpt_get_fifo_ptr(epnum);
- if (len) {
- if (_dcd.pipe_buf_is_fifo[TUSB_DIR_IN] & TU_BIT(epnum_minus1)) {
- pipe_read_write_packet_ff(buf, fifo_ptr, len, TUSB_DIR_IN);
- } else {
- pipe_write_packet(buf, fifo_ptr, len);
- pipe->buf = buf + len;
- }
- pipe->remaining = rem - len;
- }
- MXC_USBHS->incsrl = MXC_F_USBHS_INCSRL_INPKTRDY;//TODO: Verify a | isn't needed
-
- return false;
-}
-
-static bool handle_xfer_out(uint_fast8_t ep_addr) {
- unsigned epnum = tu_edpt_number(ep_addr);
- unsigned epnum_minus1 = epnum - 1;
- pipe_state_t *pipe = &_dcd.pipe[tu_edpt_dir(ep_addr)][epnum_minus1];
-
- //This function should not be for ep0
- TU_ASSERT(epnum);
-
- MXC_USBHS->index = epnum;
-
- TU_ASSERT(MXC_USBHS->outcsrl & MXC_F_USBHS_OUTCSRL_OUTPKTRDY);
-
- const unsigned mps = MXC_USBHS->outmaxp;
- const unsigned rem = pipe->remaining;
- const unsigned vld = MXC_USBHS->outcount;
- const unsigned len = TU_MIN(TU_MIN(rem, mps), vld);
- void *buf = pipe->buf;
- volatile void *fifo_ptr = edpt_get_fifo_ptr(epnum);
- if (len) {
- if (_dcd.pipe_buf_is_fifo[TUSB_DIR_OUT] & TU_BIT(epnum_minus1)) {
- pipe_read_write_packet_ff(buf, fifo_ptr, len, TUSB_DIR_OUT);
- } else {
- pipe_read_packet(buf, fifo_ptr, len);
- pipe->buf = buf + len;
- }
- pipe->remaining = rem - len;
- }
- if ((len < mps) || (rem == len)) {
- pipe->buf = NULL;
- return NULL != buf;
- }
- MXC_USBHS->outcsrl = 0; /* Clear RXRDY bit *///TODO: Verify just setting to 0 is ok
- return false;
-}
-
-static bool edpt_n_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes) {
- (void) rhport;
-
- unsigned epnum = tu_edpt_number(ep_addr);
- unsigned epnum_minus1 = epnum - 1;
- unsigned dir_in = tu_edpt_dir(ep_addr);
-
- pipe_state_t *pipe = &_dcd.pipe[dir_in][epnum_minus1];
- pipe->buf = buffer;
- pipe->length = total_bytes;
- pipe->remaining = total_bytes;
-
- if (dir_in) {
- handle_xfer_in(ep_addr);
- } else {
- MXC_USBHS->index = epnum;
- if (MXC_USBHS->outcsrl & MXC_F_USBHS_OUTCSRL_OUTPKTRDY) {
- MXC_USBHS->outcsrl = 0;//TODO: Verify just setting to 0 is ok
- }
- }
- return true;
-}
-
-static bool edpt0_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes) {
- (void) rhport;
- TU_ASSERT(total_bytes <= 64); /* Current implementation supports for only up to 64 bytes. */
-
- const unsigned req = _dcd.setup_packet.bmRequestType;
- TU_ASSERT(req != REQUEST_TYPE_INVALID || total_bytes == 0);
-
- if (req == REQUEST_TYPE_INVALID || _dcd.status_out) {
- /* STATUS OUT stage.
- * MUSB controller automatically handles STATUS OUT packets without
- * software helps. We do not have to do anything. And STATUS stage
- * may have already finished and received the next setup packet
- * without calling this function, so we have no choice but to
- * invoke the callback function of status packet here. */
- _dcd.status_out = 0;
- if (req == REQUEST_TYPE_INVALID) {
- dcd_event_xfer_complete(rhport, ep_addr, total_bytes, XFER_RESULT_SUCCESS, false);
- } else {
- /* The next setup packet has already been received, it aborts
- * invoking callback function to avoid confusing TUSB stack. */
- TU_LOG1("Drop CONTROL_STAGE_ACK\r\n");
- }
- return true;
- }
- const unsigned dir_in = tu_edpt_dir(ep_addr);
- MXC_USBHS->index = 0;
- if (tu_edpt_dir(req) == dir_in) { /* DATA stage */
- TU_ASSERT(total_bytes <= _dcd.remaining_ctrl);
- const unsigned rem = _dcd.remaining_ctrl;
- const unsigned len = TU_MIN(TU_MIN(rem, 64), total_bytes);
- volatile void *fifo_ptr = edpt_get_fifo_ptr(0);
- if (dir_in) {
- pipe_write_packet(buffer, fifo_ptr, len);
-
- _dcd.pipe0.buf = buffer + len;
- _dcd.pipe0.length = len;
- _dcd.pipe0.remaining = 0;
-
- _dcd.remaining_ctrl = rem - len;
- if ((len < 64) || (rem == len)) {
- _dcd.setup_packet.bmRequestType = REQUEST_TYPE_INVALID; /* Change to STATUS/SETUP stage */
- _dcd.status_out = 1;
- /* Flush TX FIFO and reverse the transaction direction. */
- MXC_USBHS->csr0 = MXC_F_USBHS_CSR0_INPKTRDY | MXC_F_USBHS_CSR0_DATA_END;
- } else {
- MXC_USBHS->csr0 = MXC_F_USBHS_CSR0_INPKTRDY; /* Flush TX FIFO to return ACK. */
- }
- } else {
- _dcd.pipe0.buf = buffer;
- _dcd.pipe0.length = len;
- _dcd.pipe0.remaining = len;
- MXC_USBHS->csr0 = MXC_F_USBHS_CSR0_SERV_OUTPKTRDY; /* Clear RX FIFO to return ACK. */
- }
- } else if (dir_in) {
- _dcd.pipe0.buf = NULL;
- _dcd.pipe0.length = 0;
- _dcd.pipe0.remaining = 0;
- /* Clear RX FIFO and reverse the transaction direction */
- MXC_USBHS->csr0 = MXC_F_USBHS_CSR0_SERV_OUTPKTRDY | MXC_F_USBHS_CSR0_DATA_END;
- }
- return true;
-}
-
-static void process_ep0(uint8_t rhport) {
- MXC_USBHS->index = 0;
- uint_fast8_t csrl = MXC_USBHS->csr0;
-
- if (csrl & MXC_F_USBHS_CSR0_SENT_STALL) {
- /* Returned STALL packet to HOST. */
- MXC_USBHS->csr0 = 0; /* Clear STALL */
- return;
- }
-
- unsigned req = _dcd.setup_packet.bmRequestType;
- if (csrl & MXC_F_USBHS_CSR0_SETUP_END) {
- TU_LOG1(" ABORT by the next packets\r\n");
- MXC_USBHS->csr0 = MXC_F_USBHS_CSR0_SERV_SETUP_END;
- if (req != REQUEST_TYPE_INVALID && _dcd.pipe0.buf) {
- /* DATA stage was aborted by receiving STATUS or SETUP packet. */
- _dcd.pipe0.buf = NULL;
- _dcd.setup_packet.bmRequestType = REQUEST_TYPE_INVALID;
- dcd_event_xfer_complete(rhport,
- req & TUSB_DIR_IN_MASK,
- _dcd.pipe0.length - _dcd.pipe0.remaining,
- XFER_RESULT_SUCCESS, true);
- }
- req = REQUEST_TYPE_INVALID;
- if (!(csrl & MXC_F_USBHS_CSR0_OUTPKTRDY)) return; /* Received SETUP packet */
- }
-
- if (csrl & MXC_F_USBHS_CSR0_OUTPKTRDY) {
- /* Received SETUP or DATA OUT packet */
- if (req == REQUEST_TYPE_INVALID) {
- /* SETUP */
- TU_ASSERT(sizeof(tusb_control_request_t) == MXC_USBHS->count0, );
- process_setup_packet(rhport);
- return;
- }
- if (_dcd.pipe0.buf) {
- /* DATA OUT */
- const unsigned vld = MXC_USBHS->count0;
- const unsigned rem = _dcd.pipe0.remaining;
- const unsigned len = TU_MIN(TU_MIN(rem, 64), vld);
- volatile void *fifo_ptr = edpt_get_fifo_ptr(0);
- pipe_read_packet(_dcd.pipe0.buf, fifo_ptr, len);
-
- _dcd.pipe0.remaining = rem - len;
- _dcd.remaining_ctrl -= len;
-
- _dcd.pipe0.buf = NULL;
- dcd_event_xfer_complete(rhport,
- tu_edpt_addr(0, TUSB_DIR_OUT),
- _dcd.pipe0.length - _dcd.pipe0.remaining,
- XFER_RESULT_SUCCESS, true);
- }
- return;
- }
-
- /* When CSRL0 is zero, it means that completion of sending a any length packet
- * or receiving a zero length packet. */
- if (req != REQUEST_TYPE_INVALID && !tu_edpt_dir(req)) {
- /* STATUS IN */
- if (*(const uint16_t *) (uintptr_t) &_dcd.setup_packet == 0x0500) {
- /* The address must be changed on completion of the control transfer. */
- MXC_USBHS->faddr = (uint8_t) _dcd.setup_packet.wValue;
- }
- _dcd.setup_packet.bmRequestType = REQUEST_TYPE_INVALID;
- dcd_event_xfer_complete(rhport,
- tu_edpt_addr(0, TUSB_DIR_IN),
- _dcd.pipe0.length - _dcd.pipe0.remaining,
- XFER_RESULT_SUCCESS, true);
- return;
- }
- if (_dcd.pipe0.buf) {
- /* DATA IN */
- _dcd.pipe0.buf = NULL;
- dcd_event_xfer_complete(rhport,
- tu_edpt_addr(0, TUSB_DIR_IN),
- _dcd.pipe0.length - _dcd.pipe0.remaining,
- XFER_RESULT_SUCCESS, true);
- }
-}
-
-static void process_edpt_n(uint8_t rhport, uint_fast8_t ep_addr) {
- bool completed;
- const unsigned dir_in = tu_edpt_dir(ep_addr);
- const unsigned epnum = tu_edpt_number(ep_addr);
-
- MXC_USBHS->index = epnum;
-
- if (dir_in) {
- if (MXC_USBHS->incsrl & MXC_F_USBHS_INCSRL_SENTSTALL) {
- MXC_USBHS->incsrl &= ~(MXC_F_USBHS_INCSRL_SENTSTALL | MXC_F_USBHS_INCSRL_UNDERRUN);
- return;
- }
- completed = handle_xfer_in(ep_addr);
- } else {
- if (MXC_USBHS->outcsrl & MXC_F_USBHS_OUTCSRL_SENTSTALL) {
- MXC_USBHS->outcsrl &= ~(MXC_F_USBHS_OUTCSRL_SENTSTALL | MXC_F_USBHS_OUTCSRL_OVERRUN);
- return;
- }
- completed = handle_xfer_out(ep_addr);
- }
-
- if (completed) {
- pipe_state_t *pipe = &_dcd.pipe[dir_in][tu_edpt_number(ep_addr) - 1];
- dcd_event_xfer_complete(rhport, ep_addr,
- pipe->length - pipe->remaining,
- XFER_RESULT_SUCCESS, true);
- }
-}
-
-static void process_bus_reset(uint8_t rhport) {
- (void) rhport;
- /* When bmRequestType is REQUEST_TYPE_INVALID(0xFF),
- * a control transfer state is SETUP or STATUS stage. */
- _dcd.setup_packet.bmRequestType = REQUEST_TYPE_INVALID;
- _dcd.status_out = 0;
- /* When pipe0.buf has not NULL, DATA stage works in progress. */
- _dcd.pipe0.buf = NULL;
-
- MXC_USBHS->intrinen = 1; /* Enable only EP0 */
- MXC_USBHS->introuten = 0;
-
-
- /* Clear FIFO settings */
- for (unsigned i = 1; i < TUP_DCD_ENDPOINT_MAX; ++i) {
- MXC_USBHS->index = i;
- if (MXC_USBHS->incsrl & MXC_F_USBHS_INCSRL_INPKTRDY) {
- /* Per musbhsfc_pg, only flush FIFO if IN packet loaded */
- MXC_USBHS->incsrl = MXC_F_USBHS_INCSRL_FLUSHFIFO;
- }
-
- if (MXC_USBHS->outcsrl & MXC_F_USBHS_OUTCSRL_OUTPKTRDY) {
- /* Per musbhsfc_pg, only flush FIFO if OUT packet is ready */
- MXC_USBHS->outcsrl = MXC_F_USBHS_OUTCSRL_FLUSHFIFO;
- }
- }
- dcd_event_bus_reset(0, (MXC_USBHS->power & MXC_F_USBHS_POWER_HS_MODE) ? TUSB_SPEED_HIGH : TUSB_SPEED_FULL, true);
-}
-
-/*------------------------------------------------------------------
- * Device API
- *------------------------------------------------------------------*/
-
-void dcd_init(uint8_t rhport) {
- (void) rhport;
- MXC_USBHS->intrusben |= MXC_F_USBHS_INTRUSBEN_SUSPEND_INT_EN;
-
- //Interrupt for VBUS disconnect
- MXC_USBHS->mxm_int_en |= MXC_F_USBHS_MXM_INT_EN_NOVBUS;
-
- NVIC_ClearPendingIRQ(USB_IRQn);
- dcd_edpt_close_all(rhport);
-
- //Unsuspend the MAC
- MXC_USBHS->mxm_suspend = 0;
-
- /* Configure PHY */
- MXC_USBHS->m31_phy_xcfgi_31_0 = (0x1 << 3) | (0x1 << 11);
- MXC_USBHS->m31_phy_xcfgi_63_32 = 0;
- MXC_USBHS->m31_phy_xcfgi_95_64 = 0x1 << (72 - 64);
- MXC_USBHS->m31_phy_xcfgi_127_96 = 0;
-
-
- #ifdef USBHS_M31_CLOCK_RECOVERY
- MXC_USBHS->m31_phy_noncry_rstb = 1;
- MXC_USBHS->m31_phy_noncry_en = 1;
- MXC_USBHS->m31_phy_outclksel = 0;
- MXC_USBHS->m31_phy_coreclkin = 0;
- MXC_USBHS->m31_phy_xtlsel = 2; /* Select 25 MHz clock */
- #else
- /* Use this option to feed the PHY a 30 MHz clock, which is them used as a PLL reference */
- /* As it depends on the system core clock, this should probably be done at the SYS level */
- MXC_USBHS->m31_phy_noncry_rstb = 0;
- MXC_USBHS->m31_phy_noncry_en = 0;
- MXC_USBHS->m31_phy_outclksel = 1;
- MXC_USBHS->m31_phy_coreclkin = 1;
- MXC_USBHS->m31_phy_xtlsel = 3; /* Select 30 MHz clock */
- #endif
- MXC_USBHS->m31_phy_pll_en = 1;
- MXC_USBHS->m31_phy_oscouten = 1;
-
- /* Reset PHY */
- MXC_USBHS->m31_phy_ponrst = 0;
- MXC_USBHS->m31_phy_ponrst = 1;
-
- dcd_connect(rhport);
-}
-
-void dcd_int_enable(uint8_t rhport) {
- (void) rhport;
- NVIC_EnableIRQ(USB_IRQn);
-}
-
-void dcd_int_disable(uint8_t rhport) {
- (void) rhport;
- NVIC_DisableIRQ(USB_IRQn);
-}
-
-// 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;
- (void) dev_addr;
- _dcd.pipe0.buf = NULL;
- _dcd.pipe0.length = 0;
- _dcd.pipe0.remaining = 0;
- /* Clear RX FIFO to return ACK. */
- MXC_USBHS->index = 0;
- MXC_USBHS->csr0 = MXC_F_USBHS_CSR0_SERV_OUTPKTRDY | MXC_F_USBHS_CSR0_DATA_END;
-}
-
-// Wake up host
-void dcd_remote_wakeup(uint8_t rhport) {
- (void) rhport;
- MXC_USBHS->power |= MXC_F_USBHS_POWER_RESUME;
-
- #if CFG_TUSB_OS != OPT_OS_NONE
- osal_task_delay(10);
- #else
- MXC_Delay(MXC_DELAY_MSEC(10));
- #endif
-
- MXC_USBHS->power &= ~MXC_F_USBHS_POWER_RESUME;
-}
-
-// Connect by enabling internal pull-up resistor on D+/D-
-void dcd_connect(uint8_t rhport) {
- (void) rhport;
- MXC_USBHS->power |= TUD_OPT_HIGH_SPEED ? MXC_F_USBHS_POWER_HS_ENABLE : 0;
- MXC_USBHS->power |= MXC_F_USBHS_POWER_SOFTCONN;
-}
-
-// Disconnect by disabling internal pull-up resistor on D+/D-
-void dcd_disconnect(uint8_t rhport) {
- (void) rhport;
- MXC_USBHS->power &= ~MXC_F_USBHS_POWER_SOFTCONN;
-}
-
-void dcd_sof_enable(uint8_t rhport, bool en) {
- (void) rhport;
- (void) en;
-
- // TODO implement later
-}
-
-//--------------------------------------------------------------------+
-// 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;
-
- const unsigned ep_addr = ep_desc->bEndpointAddress;
- const unsigned epn = tu_edpt_number(ep_addr);
- const unsigned dir_in = tu_edpt_dir(ep_addr);
- const unsigned xfer = ep_desc->bmAttributes.xfer;
- const unsigned mps = tu_edpt_packet_size(ep_desc);
-
- TU_ASSERT(epn < TUP_DCD_ENDPOINT_MAX);
-
- pipe_state_t *pipe = &_dcd.pipe[dir_in][epn - 1];
- pipe->buf = NULL;
- pipe->length = 0;
- pipe->remaining = 0;
-
- MXC_USBHS->index = epn;
-
- if (dir_in) {
- MXC_USBHS->inmaxp = mps;
- MXC_USBHS->incsru = (MXC_F_USBHS_INCSRU_DPKTBUFDIS | MXC_F_USBHS_INCSRU_MODE) | ((xfer == TUSB_XFER_ISOCHRONOUS) ? MXC_F_USBHS_INCSRU_ISO : 0);
- if (MXC_USBHS->incsrl & MXC_F_USBHS_INCSRL_INPKTRDY) {
- MXC_USBHS->incsrl = MXC_F_USBHS_INCSRL_CLRDATATOG | MXC_F_USBHS_INCSRL_FLUSHFIFO;
- } else {
- MXC_USBHS->incsrl = MXC_F_USBHS_INCSRL_CLRDATATOG;
- }
- MXC_USBHS->intrinen |= TU_BIT(epn);
- } else {
- MXC_USBHS->outmaxp = mps;
- MXC_USBHS->outcsru = (MXC_F_USBHS_OUTCSRU_DPKTBUFDIS) | ((xfer == TUSB_XFER_ISOCHRONOUS) ? MXC_F_USBHS_OUTCSRU_ISO : 0);
- if (MXC_USBHS->outcsrl & MXC_F_USBHS_OUTCSRL_OUTPKTRDY) {
- MXC_USBHS->outcsrl = MXC_F_USBHS_OUTCSRL_CLRDATATOG | MXC_F_USBHS_OUTCSRL_FLUSHFIFO;
- } else {
- MXC_USBHS->outcsrl = MXC_F_USBHS_OUTCSRL_CLRDATATOG;
- }
- MXC_USBHS->introuten |= TU_BIT(epn);
- }
-
- return true;
-}
-
-void dcd_edpt_close_all(uint8_t rhport) {
- (void) rhport;
-
- MXC_SYS_Crit_Enter();
- MXC_USBHS->intrinen = 1; /* Enable only EP0 */
- MXC_USBHS->introuten = 0;
-
- for (unsigned i = 1; i < TUP_DCD_ENDPOINT_MAX; ++i) {
- MXC_USBHS->index = i;
- MXC_USBHS->inmaxp = 0;
- MXC_USBHS->incsru = MXC_F_USBHS_INCSRU_DPKTBUFDIS;
-
- if (MXC_USBHS->incsrl & MXC_F_USBHS_INCSRL_INPKTRDY) {
- MXC_USBHS->incsrl = MXC_F_USBHS_INCSRL_CLRDATATOG | MXC_F_USBHS_INCSRL_FLUSHFIFO;
- } else {
- MXC_USBHS->incsrl = MXC_F_USBHS_INCSRL_CLRDATATOG;
- }
-
- MXC_USBHS->outmaxp = 0;
- MXC_USBHS->outcsru = MXC_F_USBHS_OUTCSRU_DPKTBUFDIS;
-
- if (MXC_USBHS->outcsrl & MXC_F_USBHS_OUTCSRL_OUTPKTRDY) {
- MXC_USBHS->outcsrl = MXC_F_USBHS_OUTCSRL_CLRDATATOG | MXC_F_USBHS_OUTCSRL_FLUSHFIFO;
- } else {
- MXC_USBHS->outcsrl = MXC_F_USBHS_OUTCSRL_CLRDATATOG;
- }
- }
- MXC_SYS_Crit_Exit();
-}
-
-void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) {
- (void) rhport;
- unsigned const epn = tu_edpt_number(ep_addr);
- unsigned const dir_in = tu_edpt_dir(ep_addr);
-
- MXC_SYS_Crit_Enter();
- MXC_USBHS->index = epn;
- if (dir_in) {
- MXC_USBHS->intrinen &= ~TU_BIT(epn);
- MXC_USBHS->inmaxp = 0;
- MXC_USBHS->incsru = MXC_F_USBHS_INCSRU_DPKTBUFDIS;
- if (MXC_USBHS->incsrl & MXC_F_USBHS_INCSRL_INPKTRDY) {
- MXC_USBHS->incsrl = MXC_F_USBHS_INCSRL_CLRDATATOG | MXC_F_USBHS_INCSRL_FLUSHFIFO;
- } else {
- MXC_USBHS->incsrl = MXC_F_USBHS_INCSRL_CLRDATATOG;
- }
- } else {
- MXC_USBHS->introuten &= ~TU_BIT(epn);
- MXC_USBHS->outmaxp = 0;
- MXC_USBHS->outcsru = MXC_F_USBHS_OUTCSRU_DPKTBUFDIS;
- if (MXC_USBHS->outcsrl & MXC_F_USBHS_OUTCSRL_OUTPKTRDY) {
- MXC_USBHS->outcsrl = MXC_F_USBHS_OUTCSRL_CLRDATATOG | MXC_F_USBHS_OUTCSRL_FLUSHFIFO;
- } else {
- MXC_USBHS->outcsrl = MXC_F_USBHS_OUTCSRL_CLRDATATOG;
- }
- }
- MXC_SYS_Crit_Exit();
-}
-
-// 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;
- bool ret;
- unsigned const epnum = tu_edpt_number(ep_addr);
- MXC_SYS_Crit_Enter();
- if (epnum) {
- _dcd.pipe_buf_is_fifo[tu_edpt_dir(ep_addr)] &= ~TU_BIT(epnum - 1);
- ret = edpt_n_xfer(rhport, ep_addr, buffer, total_bytes);
- } else
- ret = edpt0_xfer(rhport, ep_addr, buffer, total_bytes);
- MXC_SYS_Crit_Exit();
- return ret;
-}
-
-// Submit a transfer where is managed by FIFO, When complete dcd_event_xfer_complete() is invoked to notify the stack - optional, however, must be listed in usbd.c
-bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t *ff, uint16_t total_bytes) {
- (void) rhport;
- bool ret;
- unsigned const epnum = tu_edpt_number(ep_addr);
- TU_ASSERT(epnum);
- MXC_SYS_Crit_Enter();
- _dcd.pipe_buf_is_fifo[tu_edpt_dir(ep_addr)] |= TU_BIT(epnum - 1);
- ret = edpt_n_xfer(rhport, ep_addr, (uint8_t *) ff, total_bytes);
- MXC_SYS_Crit_Exit();
- return ret;
-}
-
-// Stall endpoint
-void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) {
- (void) rhport;
- unsigned const epn = tu_edpt_number(ep_addr);
- MXC_SYS_Crit_Enter();
- MXC_USBHS->index = epn;
- if (0 == epn) {
- if (!ep_addr) { /* Ignore EP80 */
- _dcd.setup_packet.bmRequestType = REQUEST_TYPE_INVALID;
- _dcd.pipe0.buf = NULL;
- MXC_USBHS->csr0 = MXC_F_USBHS_CSR0_SEND_STALL;
- }
- } else {
- if (tu_edpt_dir(ep_addr)) { /* IN */
- MXC_USBHS->incsrl = MXC_F_USBHS_INCSRL_SENDSTALL;
- } else { /* OUT */
- TU_ASSERT(!(MXC_USBHS->outcsrl & MXC_F_USBHS_OUTCSRL_OUTPKTRDY), );
- MXC_USBHS->outcsrl = MXC_F_USBHS_OUTCSRL_SENDSTALL;
- }
- }
- MXC_SYS_Crit_Exit();
-}
-
-// clear stall, data toggle is also reset to DATA0
-void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) {
- (void) rhport;
- unsigned const epn = tu_edpt_number(ep_addr);
- MXC_SYS_Crit_Enter();
- MXC_USBHS->index = epn;
- if (tu_edpt_dir(ep_addr)) { /* IN */
- /* IN endpoint */
- if (MXC_USBHS->incsrl & MXC_F_USBHS_INCSRL_INPKTRDY) {
- /* Per musbhsfc_pg, only flush FIFO if IN packet loaded */
- MXC_USBHS->incsrl = MXC_F_USBHS_INCSRL_CLRDATATOG | MXC_F_USBHS_INCSRL_FLUSHFIFO;
- } else {
- MXC_USBHS->incsrl = MXC_F_USBHS_INCSRL_CLRDATATOG;
- }
- } else { /* OUT */
- /* Otherwise, must be OUT endpoint */
- if (MXC_USBHS->outcsrl & MXC_F_USBHS_OUTCSRL_OUTPKTRDY) {
- /* Per musbhsfc_pg, only flush FIFO if OUT packet is ready */
- MXC_USBHS->outcsrl = MXC_F_USBHS_OUTCSRL_CLRDATATOG | MXC_F_USBHS_OUTCSRL_FLUSHFIFO;
- } else {
- MXC_USBHS->outcsrl = MXC_F_USBHS_OUTCSRL_CLRDATATOG;
- }
- }
- MXC_SYS_Crit_Exit();
-}
-
-/*-------------------------------------------------------------------
- * ISR
- *-------------------------------------------------------------------*/
-void dcd_int_handler(uint8_t rhport) {
- uint_fast8_t is, txis, rxis;
- uint32_t mxm_int, mxm_int_en, mxm_is;
- uint32_t saved_index;
-
- /* Save current index register */
- saved_index = MXC_USBHS->index;
-
- is = MXC_USBHS->intrusb; /* read and clear interrupt status */
- txis = MXC_USBHS->intrin; /* read and clear interrupt status */
- rxis = MXC_USBHS->introut; /* read and clear interrupt status */
-
- /* These USB interrupt flags are W1C. */
- /* Order of volatile accesses must be separated for IAR */
- mxm_int = MXC_USBHS->mxm_int;
- mxm_int_en = MXC_USBHS->mxm_int_en;
- mxm_is = mxm_int & mxm_int_en;
- MXC_USBHS->mxm_int = mxm_is;
-
- is &= MXC_USBHS->intrusben; /* Clear disabled interrupts */
-
- if (mxm_is & MXC_F_USBHS_MXM_INT_NOVBUS) {
- dcd_event_bus_signal(rhport, DCD_EVENT_UNPLUGGED, true);
- }
- if (is & MXC_F_USBHS_INTRUSB_SOF_INT) {
- dcd_event_bus_signal(rhport, DCD_EVENT_SOF, true);
- }
- if (is & MXC_F_USBHS_INTRUSB_RESET_INT) {
- process_bus_reset(rhport);
- }
- if (is & MXC_F_USBHS_INTRUSB_RESUME_INT) {
- dcd_event_bus_signal(rhport, DCD_EVENT_RESUME, true);
- }
- if (is & MXC_F_USBHS_INTRUSB_SUSPEND_INT) {
- dcd_event_bus_signal(rhport, DCD_EVENT_SUSPEND, true);
- }
-
- txis &= MXC_USBHS->intrinen; /* Clear disabled interrupts */
- if (txis & MXC_F_USBHS_INTRIN_EP0_IN_INT) {
- process_ep0(rhport);
- txis &= ~TU_BIT(0);
- }
- while (txis) {
- unsigned const num = __builtin_ctz(txis);
- process_edpt_n(rhport, tu_edpt_addr(num, TUSB_DIR_IN));
- txis &= ~TU_BIT(num);
- }
- rxis &= MXC_USBHS->introuten; /* Clear disabled interrupts */
- while (rxis) {
- unsigned const num = __builtin_ctz(rxis);
- process_edpt_n(rhport, tu_edpt_addr(num, TUSB_DIR_OUT));
- rxis &= ~TU_BIT(num);
- }
-
- /* Restore register index before exiting ISR */
- MXC_USBHS->index = saved_index;
-}
-
-#endif
diff --git a/src/portable/mentor/musb/dcd_musb.c b/src/portable/mentor/musb/dcd_musb.c
index a817c5d6e..ee36656fd 100644
--- a/src/portable/mentor/musb/dcd_musb.c
+++ b/src/portable/mentor/musb/dcd_musb.c
@@ -2,6 +2,7 @@
* The MIT License (MIT)
*
* Copyright (c) 2021 Koji KITAYAMA
+ * Copyright (c) 2024, Brent Kowal (Analog Devices, Inc)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -26,8 +27,7 @@
#include "tusb_option.h"
-#if CFG_TUD_ENABLED && \
- TU_CHECK_MCU(OPT_MCU_MSP432E4, OPT_MCU_TM4C123, OPT_MCU_TM4C129)
+#if CFG_TUD_ENABLED
#if __GNUC__ > 8 && defined(__ARM_FEATURE_UNALIGNED)
/* GCC warns that an address may be unaligned, even though
@@ -35,43 +35,30 @@
_Pragma("GCC diagnostic ignored \"-Waddress-of-packed-member\"");
#endif
+#include "musb_type.h"
#include "device/dcd.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
- #define FIFO1_WORD FIFO1
-
+// Following symbols must be defined by port header
+// - musb_dcd_int_enable/disable/clear/get_enable
+// - musb_dcd_int_handler_enter/exit
+// - musb_dcd_epn_regs: Get memory mapped struct of end point registers
+// - musb_dcd_ep0_regs: Get memory mapped struct of EP0 registers
+// - musb_dcd_ctl_regs: Get memory mapped struct of control registers
+// - musb_dcd_ep_get_fifo_ptr: Gets the address of the provided EP's FIFO
+// - musb_dcd_setup_fifo/reset_fifo: Configuration of the EP's FIFO
+#if TU_CHECK_MCU(OPT_MCU_MSP432E4, OPT_MCU_TM4C123, OPT_MCU_TM4C129)
+ #include "musb_ti.h"
+#elif TU_CHECK_MCU(OPT_MCU_MAX32690, OPT_MCU_MAX32650, OPT_MCU_MAX32666, OPT_MCU_MAX78002)
+ #include "musb_max32.h"
#else
- #error "Unsupported MCUs"
+ #error "Unsupported MCU"
#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 {
- uint16_t TXMAXP;
- uint8_t TXCSRL;
- uint8_t TXCSRH;
- uint16_t RXMAXP;
- uint8_t RXCSRL;
- uint8_t RXCSRH;
- uint16_t RXCOUNT;
- uint16_t RESERVED[3];
-} hw_endpoint_t;
+#define REQUEST_TYPE_INVALID (0xFFu)
typedef union {
uint8_t u8;
@@ -92,7 +79,7 @@ typedef struct
uint16_t remaining_ctrl; /* The number of bytes remaining in data stage of control transfer. */
int8_t status_out;
pipe_state_t pipe0;
- pipe_state_t pipe[2][7]; /* pipe[direction][endpoint number - 1] */
+ pipe_state_t pipe[2][TUP_DCD_ENDPOINT_MAX-1]; /* pipe[direction][endpoint number - 1] */
uint16_t pipe_buf_is_fifo[2]; /* Bitmap. Each bit means whether 1:TU_FIFO or 0:POD. */
} dcd_data_t;
@@ -102,126 +89,6 @@ typedef struct
static dcd_data_t _dcd;
-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;
-}
-
-#if 0
-static inline void print_block_list(free_block_t const *blk, unsigned num)
-{
- TU_LOG1("*************\r\n");
- for (unsigned i = 0; i < num; ++i) {
- TU_LOG1(" Blk%u %u %u\r\n", i, blk->beg, blk->end);
- ++blk;
- }
-}
-#else
-#define print_block_list(a,b)
-#endif
-
-static unsigned find_free_memory(uint_fast16_t size_in_log2_minus3)
-{
- free_block_t free_blocks[2 * (TUP_DCD_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 < TUP_DCD_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;
- print_block_list(free_blocks, num_blocks);
- }
- 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;
- print_block_list(free_blocks, num_blocks);
- }
- }
- print_block_list(free_blocks, num_blocks);
-
- /* 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 void pipe_write_packet(void *buf, volatile void *fifo, unsigned len)
{
volatile hw_fifo_t *reg = (volatile hw_fifo_t*)fifo;
@@ -287,8 +154,10 @@ static void pipe_read_write_packet_ff(tu_fifo_t *f, volatile void *fifo, unsigne
static void process_setup_packet(uint8_t rhport)
{
uint32_t *p = (void*)&_dcd.setup_packet;
- p[0] = USB0->FIFO0_WORD;
- p[1] = USB0->FIFO0_WORD;
+ volatile uint32_t *fifo_ptr = musb_dcd_ep_get_fifo_ptr(rhport, 0);
+ volatile musb_dcd_ep0_regs_t* ep0_regs = musb_dcd_ep0_regs(rhport);
+ p[0] = *fifo_ptr;
+ p[1] = *fifo_ptr;
_dcd.pipe0.buf = NULL;
_dcd.pipe0.length = 0;
@@ -299,12 +168,13 @@ static void process_setup_packet(uint8_t rhport)
_dcd.remaining_ctrl = len;
const unsigned dir_in = tu_edpt_dir(_dcd.setup_packet.bmRequestType);
/* Clear RX FIFO and reverse the transaction direction */
- if (len && dir_in) USB0->CSRL0 = USB_CSRL0_RXRDYC;
+ if (len && dir_in) ep0_regs->CSRL0 = USB_CSRL0_RXRDYC;
}
-static bool handle_xfer_in(uint_fast8_t ep_addr)
+static bool handle_xfer_in(uint8_t rhport, uint_fast8_t ep_addr)
{
- unsigned epnum_minus1 = tu_edpt_number(ep_addr) - 1;
+ unsigned epnum = tu_edpt_number(ep_addr);
+ unsigned epnum_minus1 = epnum - 1;
pipe_state_t *pipe = &_dcd.pipe[tu_edpt_dir(ep_addr)][epnum_minus1];
const unsigned rem = pipe->remaining;
@@ -313,30 +183,32 @@ static bool handle_xfer_in(uint_fast8_t ep_addr)
return true;
}
- volatile hw_endpoint_t *regs = edpt_regs(epnum_minus1);
+ volatile musb_dcd_epn_regs_t *regs = musb_dcd_epn_regs(rhport, epnum);
const unsigned mps = regs->TXMAXP;
const unsigned len = TU_MIN(mps, rem);
void *buf = pipe->buf;
+ volatile void *fifo_ptr = musb_dcd_ep_get_fifo_ptr(rhport, epnum);
// TU_LOG1(" %p mps %d len %d rem %d\r\n", buf, mps, len, rem);
if (len) {
if (_dcd.pipe_buf_is_fifo[TUSB_DIR_IN] & TU_BIT(epnum_minus1)) {
- pipe_read_write_packet_ff(buf, &USB0->FIFO1_WORD + epnum_minus1, len, TUSB_DIR_IN);
+ pipe_read_write_packet_ff(buf, fifo_ptr, len, TUSB_DIR_IN);
} else {
- pipe_write_packet(buf, &USB0->FIFO1_WORD + epnum_minus1, len);
+ pipe_write_packet(buf, fifo_ptr, len);
pipe->buf = buf + len;
}
pipe->remaining = rem - len;
}
regs->TXCSRL = USB_TXCSRL1_TXRDY;
- // TU_LOG1(" TXCSRL%d = %x %d\r\n", epnum_minus1 + 1, regs->TXCSRL, rem - len);
+ // TU_LOG1(" TXCSRL%d = %x %d\r\n", epnum, regs->TXCSRL, rem - len);
return false;
}
-static bool handle_xfer_out(uint_fast8_t ep_addr)
+static bool handle_xfer_out(uint8_t rhport, uint_fast8_t ep_addr)
{
- unsigned epnum_minus1 = tu_edpt_number(ep_addr) - 1;
+ unsigned epnum = tu_edpt_number(ep_addr);
+ unsigned epnum_minus1 = epnum - 1;
pipe_state_t *pipe = &_dcd.pipe[tu_edpt_dir(ep_addr)][epnum_minus1];
- volatile hw_endpoint_t *regs = edpt_regs(epnum_minus1);
+ volatile musb_dcd_epn_regs_t *regs = musb_dcd_epn_regs(rhport, epnum);
// TU_LOG1(" RXCSRL%d = %x\r\n", epnum_minus1 + 1, regs->RXCSRL);
TU_ASSERT(regs->RXCSRL & USB_RXCSRL1_RXRDY);
@@ -346,11 +218,12 @@ static bool handle_xfer_out(uint_fast8_t ep_addr)
const unsigned vld = regs->RXCOUNT;
const unsigned len = TU_MIN(TU_MIN(rem, mps), vld);
void *buf = pipe->buf;
+ volatile void *fifo_ptr = musb_dcd_ep_get_fifo_ptr(rhport, epnum);
if (len) {
if (_dcd.pipe_buf_is_fifo[TUSB_DIR_OUT] & TU_BIT(epnum_minus1)) {
- pipe_read_write_packet_ff(buf, &USB0->FIFO1_WORD + epnum_minus1, len, TUSB_DIR_OUT);
+ pipe_read_write_packet_ff(buf, fifo_ptr, len, TUSB_DIR_OUT);
} else {
- pipe_read_packet(buf, &USB0->FIFO1_WORD + epnum_minus1, len);
+ pipe_read_packet(buf, fifo_ptr, len);
pipe->buf = buf + len;
}
pipe->remaining = rem - len;
@@ -365,9 +238,8 @@ static bool handle_xfer_out(uint_fast8_t ep_addr)
static bool edpt_n_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes)
{
- (void)rhport;
-
- unsigned epnum_minus1 = tu_edpt_number(ep_addr) - 1;
+ unsigned epnum = tu_edpt_number(ep_addr);
+ unsigned epnum_minus1 = epnum - 1;
unsigned dir_in = tu_edpt_dir(ep_addr);
pipe_state_t *pipe = &_dcd.pipe[dir_in][epnum_minus1];
@@ -376,9 +248,9 @@ static bool edpt_n_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16
pipe->remaining = total_bytes;
if (dir_in) {
- handle_xfer_in(ep_addr);
+ handle_xfer_in(rhport, ep_addr);
} else {
- volatile hw_endpoint_t *regs = edpt_regs(epnum_minus1);
+ volatile musb_dcd_epn_regs_t *regs = musb_dcd_epn_regs(rhport, epnum);
if (regs->RXCSRL & USB_RXCSRL1_RXRDY) regs->RXCSRL = 0;
}
return true;
@@ -388,7 +260,7 @@ static bool edpt0_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_
{
(void)rhport;
TU_ASSERT(total_bytes <= 64); /* Current implementation supports for only up to 64 bytes. */
-
+ volatile musb_dcd_ep0_regs_t* ep0_regs = musb_dcd_ep0_regs(rhport);
const unsigned req = _dcd.setup_packet.bmRequestType;
TU_ASSERT(req != REQUEST_TYPE_INVALID || total_bytes == 0);
@@ -399,7 +271,7 @@ static bool edpt0_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_
* may have already finished and received the next setup packet
* without calling this function, so we have no choice but to
* invoke the callback function of status packet here. */
- // TU_LOG1(" STATUS OUT USB0->CSRL0 = %x\r\n", USB0->CSRL0);
+ // TU_LOG1(" STATUS OUT ep0_regs->CSRL0 = %x\r\n", ep0_regs->CSRL0);
_dcd.status_out = 0;
if (req == REQUEST_TYPE_INVALID) {
dcd_event_xfer_complete(rhport, ep_addr, total_bytes, XFER_RESULT_SUCCESS, false);
@@ -415,8 +287,9 @@ static bool edpt0_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_
TU_ASSERT(total_bytes <= _dcd.remaining_ctrl);
const unsigned rem = _dcd.remaining_ctrl;
const unsigned len = TU_MIN(TU_MIN(rem, 64), total_bytes);
+ volatile void *fifo_ptr = musb_dcd_ep_get_fifo_ptr(rhport, 0);
if (dir_in) {
- pipe_write_packet(buffer, &USB0->FIFO0_WORD, len);
+ pipe_write_packet(buffer, fifo_ptr, len);
_dcd.pipe0.buf = buffer + len;
_dcd.pipe0.length = len;
@@ -427,45 +300,46 @@ static bool edpt0_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_
_dcd.setup_packet.bmRequestType = REQUEST_TYPE_INVALID; /* Change to STATUS/SETUP stage */
_dcd.status_out = 1;
/* Flush TX FIFO and reverse the transaction direction. */
- USB0->CSRL0 = USB_CSRL0_TXRDY | USB_CSRL0_DATAEND;
+ ep0_regs->CSRL0 = USB_CSRL0_TXRDY | USB_CSRL0_DATAEND;
} else {
- USB0->CSRL0 = USB_CSRL0_TXRDY; /* Flush TX FIFO to return ACK. */
+ ep0_regs->CSRL0 = USB_CSRL0_TXRDY; /* Flush TX FIFO to return ACK. */
}
- // TU_LOG1(" IN USB0->CSRL0 = %x\r\n", USB0->CSRL0);
+ // TU_LOG1(" IN ep0_regs->CSRL0 = %x\r\n", ep0_regs->CSRL0);
} else {
- // TU_LOG1(" OUT USB0->CSRL0 = %x\r\n", USB0->CSRL0);
+ // TU_LOG1(" OUT ep0_regs->CSRL0 = %x\r\n", ep0_regs->CSRL0);
_dcd.pipe0.buf = buffer;
_dcd.pipe0.length = len;
_dcd.pipe0.remaining = len;
- USB0->CSRL0 = USB_CSRL0_RXRDYC; /* Clear RX FIFO to return ACK. */
+ ep0_regs->CSRL0 = USB_CSRL0_RXRDYC; /* Clear RX FIFO to return ACK. */
}
} else if (dir_in) {
- // TU_LOG1(" STATUS IN USB0->CSRL0 = %x\r\n", USB0->CSRL0);
+ // TU_LOG1(" STATUS IN ep0_regs->CSRL0 = %x\r\n", ep0_regs->CSRL0);
_dcd.pipe0.buf = NULL;
_dcd.pipe0.length = 0;
_dcd.pipe0.remaining = 0;
/* Clear RX FIFO and reverse the transaction direction */
- USB0->CSRL0 = USB_CSRL0_RXRDYC | USB_CSRL0_DATAEND;
+ ep0_regs->CSRL0 = USB_CSRL0_RXRDYC | USB_CSRL0_DATAEND;
}
return true;
}
static void process_ep0(uint8_t rhport)
{
- uint_fast8_t csrl = USB0->CSRL0;
+ volatile musb_dcd_ep0_regs_t* ep0_regs = musb_dcd_ep0_regs(rhport);
+ uint_fast8_t csrl = ep0_regs->CSRL0;
- // TU_LOG1(" EP0 USB0->CSRL0 = %x\r\n", csrl);
+ // TU_LOG1(" EP0 ep0_regs->CSRL0 = %x\r\n", csrl);
if (csrl & USB_CSRL0_STALLED) {
/* Returned STALL packet to HOST. */
- USB0->CSRL0 = 0; /* Clear STALL */
+ ep0_regs->CSRL0 = 0; /* Clear STALL */
return;
}
unsigned req = _dcd.setup_packet.bmRequestType;
if (csrl & USB_CSRL0_SETEND) {
TU_LOG1(" ABORT by the next packets\r\n");
- USB0->CSRL0 = USB_CSRL0_SETENDC;
+ ep0_regs->CSRL0 = USB_CSRL0_SETENDC;
if (req != REQUEST_TYPE_INVALID && _dcd.pipe0.buf) {
/* DATA stage was aborted by receiving STATUS or SETUP packet. */
_dcd.pipe0.buf = NULL;
@@ -483,16 +357,17 @@ static void process_ep0(uint8_t rhport)
/* Received SETUP or DATA OUT packet */
if (req == REQUEST_TYPE_INVALID) {
/* SETUP */
- TU_ASSERT(sizeof(tusb_control_request_t) == USB0->COUNT0,);
+ TU_ASSERT(sizeof(tusb_control_request_t) == ep0_regs->COUNT0,);
process_setup_packet(rhport);
return;
}
if (_dcd.pipe0.buf) {
/* DATA OUT */
- const unsigned vld = USB0->COUNT0;
+ const unsigned vld = ep0_regs->COUNT0;
const unsigned rem = _dcd.pipe0.remaining;
const unsigned len = TU_MIN(TU_MIN(rem, 64), vld);
- pipe_read_packet(_dcd.pipe0.buf, &USB0->FIFO0_WORD, len);
+ volatile void *fifo_ptr = musb_dcd_ep_get_fifo_ptr(rhport, 0);
+ pipe_read_packet(_dcd.pipe0.buf, fifo_ptr, len);
_dcd.pipe0.remaining = rem - len;
_dcd.remaining_ctrl -= len;
@@ -506,13 +381,15 @@ static void process_ep0(uint8_t rhport)
return;
}
+ volatile musb_dcd_ctl_regs_t *ctrl_regs = musb_dcd_ctl_regs(rhport);
+
/* When CSRL0 is zero, it means that completion of sending a any length packet
* or receiving a zero length packet. */
if (req != REQUEST_TYPE_INVALID && !tu_edpt_dir(req)) {
/* STATUS IN */
if (*(const uint16_t*)(uintptr_t)&_dcd.setup_packet == 0x0500) {
/* The address must be changed on completion of the control transfer. */
- USB0->FADDR = (uint8_t)_dcd.setup_packet.wValue;
+ ctrl_regs->FADDR = (uint8_t)_dcd.setup_packet.wValue;
}
_dcd.setup_packet.bmRequestType = REQUEST_TYPE_INVALID;
dcd_event_xfer_complete(rhport,
@@ -535,27 +412,28 @@ static void process_edpt_n(uint8_t rhport, uint_fast8_t ep_addr)
{
bool completed;
const unsigned dir_in = tu_edpt_dir(ep_addr);
- const unsigned epn_minus1 = tu_edpt_number(ep_addr) - 1;
+ const unsigned epn = tu_edpt_number(ep_addr);
+ const unsigned epn_minus1 = epn - 1;
- volatile hw_endpoint_t *regs = edpt_regs(epn_minus1);
+ volatile musb_dcd_epn_regs_t *regs = musb_dcd_epn_regs(rhport, epn);
if (dir_in) {
- // TU_LOG1(" TXCSRL%d = %x\r\n", epn_minus1 + 1, regs->TXCSRL);
+ // TU_LOG1(" TXCSRL%d = %x\r\n", epn, regs->TXCSRL);
if (regs->TXCSRL & USB_TXCSRL1_STALLED) {
regs->TXCSRL &= ~(USB_TXCSRL1_STALLED | USB_TXCSRL1_UNDRN);
return;
}
- completed = handle_xfer_in(ep_addr);
+ completed = handle_xfer_in(rhport, ep_addr);
} else {
- // TU_LOG1(" RXCSRL%d = %x\r\n", epn_minus1 + 1, regs->RXCSRL);
+ // TU_LOG1(" RXCSRL%d = %x\r\n", epn, regs->RXCSRL);
if (regs->RXCSRL & USB_RXCSRL1_STALLED) {
regs->RXCSRL &= ~(USB_RXCSRL1_STALLED | USB_RXCSRL1_OVER);
return;
}
- completed = handle_xfer_out(ep_addr);
+ completed = handle_xfer_out(rhport, ep_addr);
}
if (completed) {
- pipe_state_t *pipe = &_dcd.pipe[dir_in][tu_edpt_number(ep_addr) - 1];
+ pipe_state_t *pipe = &_dcd.pipe[dir_in][epn_minus1];
dcd_event_xfer_complete(rhport, ep_addr,
pipe->length - pipe->remaining,
XFER_RESULT_SUCCESS, true);
@@ -564,6 +442,7 @@ static void process_edpt_n(uint8_t rhport, uint_fast8_t ep_addr)
static void process_bus_reset(uint8_t rhport)
{
+ volatile musb_dcd_ctl_regs_t *ctrl_regs = musb_dcd_ctl_regs(rhport);
/* When bmRequestType is REQUEST_TYPE_INVALID(0xFF),
* a control transfer state is SETUP or STATUS stage. */
_dcd.setup_packet.bmRequestType = REQUEST_TYPE_INVALID;
@@ -571,18 +450,15 @@ static void process_bus_reset(uint8_t rhport)
/* When pipe0.buf has not NULL, DATA stage works in progress. */
_dcd.pipe0.buf = NULL;
- USB0->TXIE = 1; /* Enable only EP0 */
- USB0->RXIE = 0;
+ ctrl_regs->TXIE = 1; /* Enable only EP0 */
+ ctrl_regs->RXIE = 0;
/* Clear FIFO settings */
for (unsigned i = 1; i < TUP_DCD_ENDPOINT_MAX; ++i) {
- USB0->EPIDX = i;
- USB0->TXFIFOSZ = 0;
- USB0->TXFIFOADD = 0;
- USB0->RXFIFOSZ = 0;
- USB0->RXFIFOADD = 0;
+ musb_dcd_reset_fifo(rhport, i, 0);
+ musb_dcd_reset_fifo(rhport, i, 1);
}
- dcd_event_bus_reset(rhport, TUSB_SPEED_FULL, true);
+ dcd_event_bus_reset(rhport, (ctrl_regs->POWER & USB_POWER_HSMODE) ? TUSB_SPEED_HIGH : TUSB_SPEED_FULL, true);
}
/*------------------------------------------------------------------
@@ -591,61 +467,60 @@ static void process_bus_reset(uint8_t rhport)
void dcd_init(uint8_t rhport)
{
- (void)rhport;
- USB0->IE |= USB_IE_SUSPND;
- NVIC_ClearPendingIRQ(USB0_IRQn);
-
+ volatile musb_dcd_ctl_regs_t *ctrl_regs = musb_dcd_ctl_regs(rhport);
+ ctrl_regs->IE |= USB_IE_SUSPND;
+ musb_dcd_int_clear(rhport);
+ musb_dcd_phy_init(rhport);
dcd_connect(rhport);
}
void dcd_int_enable(uint8_t rhport)
{
- (void)rhport;
- NVIC_EnableIRQ(USB0_IRQn);
+ musb_dcd_int_enable(rhport);
}
void dcd_int_disable(uint8_t rhport)
{
- (void)rhport;
- NVIC_DisableIRQ(USB0_IRQn);
+ musb_dcd_int_disable(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)rhport;
(void)dev_addr;
+ volatile musb_dcd_ep0_regs_t* ep0_regs = musb_dcd_ep0_regs(rhport);
_dcd.pipe0.buf = NULL;
_dcd.pipe0.length = 0;
_dcd.pipe0.remaining = 0;
/* Clear RX FIFO to return ACK. */
- USB0->CSRL0 = USB_CSRL0_RXRDYC | USB_CSRL0_DATAEND;
+ ep0_regs->CSRL0 = USB_CSRL0_RXRDYC | USB_CSRL0_DATAEND;
}
// Wake up host
void dcd_remote_wakeup(uint8_t rhport)
{
- (void)rhport;
- USB0->POWER |= USB_POWER_RESUME;
+ volatile musb_dcd_ctl_regs_t *ctrl_regs = musb_dcd_ctl_regs(rhport);
+ ctrl_regs->POWER |= USB_POWER_RESUME;
unsigned cnt = SystemCoreClock / 1000;
while (cnt--) __NOP();
- USB0->POWER &= ~USB_POWER_RESUME;
+ ctrl_regs->POWER &= ~USB_POWER_RESUME;
}
// Connect by enabling internal pull-up resistor on D+/D-
void dcd_connect(uint8_t rhport)
{
- (void)rhport;
- USB0->POWER |= USB_POWER_SOFTCONN;
+ volatile musb_dcd_ctl_regs_t *ctrl_regs = musb_dcd_ctl_regs(rhport);
+ ctrl_regs->POWER |= TUD_OPT_HIGH_SPEED ? USB_POWER_HSENAB : 0;
+ ctrl_regs->POWER |= USB_POWER_SOFTCONN;
}
// Disconnect by disabling internal pull-up resistor on D+/D-
void dcd_disconnect(uint8_t rhport)
{
- (void)rhport;
- USB0->POWER &= ~USB_POWER_SOFTCONN;
+ volatile musb_dcd_ctl_regs_t *ctrl_regs = musb_dcd_ctl_regs(rhport);
+ ctrl_regs->POWER &= ~USB_POWER_SOFTCONN;
}
void dcd_sof_enable(uint8_t rhport, bool en)
@@ -663,8 +538,6 @@ void dcd_sof_enable(uint8_t rhport, bool en)
// Configure endpoint's registers according to descriptor
bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * ep_desc)
{
- (void) rhport;
-
const unsigned ep_addr = ep_desc->bEndpointAddress;
const unsigned epn = tu_edpt_number(ep_addr);
const unsigned dir_in = tu_edpt_dir(ep_addr);
@@ -678,7 +551,8 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * ep_desc)
pipe->length = 0;
pipe->remaining = 0;
- volatile hw_endpoint_t *regs = edpt_regs(epn - 1);
+ volatile musb_dcd_epn_regs_t *regs = musb_dcd_epn_regs(rhport, epn);
+ volatile musb_dcd_ctl_regs_t *ctrl_regs = musb_dcd_ctl_regs(rhport);
if (dir_in) {
regs->TXMAXP = mps;
regs->TXCSRH = (xfer == TUSB_XFER_ISOCHRONOUS) ? USB_TXCSRH1_ISO : 0;
@@ -686,7 +560,7 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * ep_desc)
regs->TXCSRL = USB_TXCSRL1_CLRDT | USB_TXCSRL1_FLUSH;
else
regs->TXCSRL = USB_TXCSRL1_CLRDT;
- USB0->TXIE |= TU_BIT(epn);
+ ctrl_regs->TXIE |= TU_BIT(epn);
} else {
regs->RXMAXP = mps;
regs->RXCSRH = (xfer == TUSB_XFER_ISOCHRONOUS) ? USB_RXCSRH1_ISO : 0;
@@ -694,36 +568,25 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * ep_desc)
regs->RXCSRL = USB_RXCSRL1_CLRDT | USB_RXCSRL1_FLUSH;
else
regs->RXCSRL = USB_RXCSRL1_CLRDT;
- USB0->RXIE |= TU_BIT(epn);
+ ctrl_regs->RXIE |= TU_BIT(epn);
}
/* 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 = epn;
- if (dir_in) {
- USB0->TXFIFOADD = addr;
- USB0->TXFIFOSZ = size_in_log2_minus3;
- } else {
- USB0->RXFIFOADD = addr;
- USB0->RXFIFOSZ = size_in_log2_minus3;
- }
+ musb_dcd_setup_fifo(rhport, epn, dir_in, mps);
return true;
}
void dcd_edpt_close_all(uint8_t rhport)
{
- (void) rhport;
- volatile hw_endpoint_t *regs = (volatile hw_endpoint_t *)(uintptr_t)&USB0->TXMAXP1;
- unsigned const ie = NVIC_GetEnableIRQ(USB0_IRQn);
- NVIC_DisableIRQ(USB0_IRQn);
- USB0->TXIE = 1; /* Enable only EP0 */
- USB0->RXIE = 0;
+ volatile musb_dcd_epn_regs_t *regs;
+ volatile musb_dcd_ctl_regs_t *ctrl_regs = musb_dcd_ctl_regs(rhport);
+ unsigned const ie = musb_dcd_get_int_enable(rhport);
+ musb_dcd_int_disable(rhport);
+ ctrl_regs->TXIE = 1; /* Enable only EP0 */
+ ctrl_regs->RXIE = 0;
for (unsigned i = 1; i < TUP_DCD_ENDPOINT_MAX; ++i) {
+ regs = musb_dcd_epn_regs(rhport, i);
regs->TXMAXP = 0;
regs->TXCSRH = 0;
if (regs->TXCSRL & USB_TXCSRL1_TXRDY)
@@ -738,50 +601,41 @@ void dcd_edpt_close_all(uint8_t rhport)
else
regs->RXCSRL = USB_RXCSRL1_CLRDT;
- USB0->EPIDX = i;
- USB0->TXFIFOSZ = 0;
- USB0->TXFIFOADD = 0;
- USB0->RXFIFOSZ = 0;
- USB0->RXFIFOADD = 0;
+ musb_dcd_reset_fifo(rhport, i, 0);
+ musb_dcd_reset_fifo(rhport, i, 1);
+
}
- if (ie) NVIC_EnableIRQ(USB0_IRQn);
+ if (ie) musb_dcd_int_enable(rhport);
}
void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr)
{
- (void)rhport;
unsigned const epn = tu_edpt_number(ep_addr);
unsigned const dir_in = tu_edpt_dir(ep_addr);
- hw_endpoint_t volatile *regs = edpt_regs(epn - 1);
- unsigned const ie = NVIC_GetEnableIRQ(USB0_IRQn);
- NVIC_DisableIRQ(USB0_IRQn);
+ volatile musb_dcd_epn_regs_t *regs = musb_dcd_epn_regs(rhport, epn);
+ volatile musb_dcd_ctl_regs_t *ctrl_regs = musb_dcd_ctl_regs(rhport);
+ unsigned const ie = musb_dcd_get_int_enable(rhport);
+ musb_dcd_int_disable(rhport);
if (dir_in) {
- USB0->TXIE &= ~TU_BIT(epn);
+ ctrl_regs->TXIE &= ~TU_BIT(epn);
regs->TXMAXP = 0;
regs->TXCSRH = 0;
if (regs->TXCSRL & USB_TXCSRL1_TXRDY)
regs->TXCSRL = USB_TXCSRL1_CLRDT | USB_TXCSRL1_FLUSH;
else
regs->TXCSRL = USB_TXCSRL1_CLRDT;
-
- USB0->EPIDX = epn;
- USB0->TXFIFOSZ = 0;
- USB0->TXFIFOADD = 0;
} else {
- USB0->RXIE &= ~TU_BIT(epn);
+ ctrl_regs->RXIE &= ~TU_BIT(epn);
regs->RXMAXP = 0;
regs->RXCSRH = 0;
if (regs->RXCSRL & USB_RXCSRL1_RXRDY)
regs->RXCSRL = USB_RXCSRL1_CLRDT | USB_RXCSRL1_FLUSH;
else
regs->RXCSRL = USB_RXCSRL1_CLRDT;
-
- USB0->EPIDX = epn;
- USB0->RXFIFOSZ = 0;
- USB0->RXFIFOADD = 0;
}
- if (ie) NVIC_EnableIRQ(USB0_IRQn);
+ musb_dcd_reset_fifo(rhport, epn, dir_in);
+ if (ie) musb_dcd_int_enable(rhport);
}
// Submit a transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack
@@ -791,14 +645,14 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t t
bool ret;
// TU_LOG1("X %x %d\r\n", ep_addr, total_bytes);
unsigned const epnum = tu_edpt_number(ep_addr);
- unsigned const ie = NVIC_GetEnableIRQ(USB0_IRQn);
- NVIC_DisableIRQ(USB0_IRQn);
+ unsigned const ie = musb_dcd_get_int_enable(rhport);
+ musb_dcd_int_disable(rhport);
if (epnum) {
_dcd.pipe_buf_is_fifo[tu_edpt_dir(ep_addr)] &= ~TU_BIT(epnum - 1);
ret = edpt_n_xfer(rhport, ep_addr, buffer, total_bytes);
} else
ret = edpt0_xfer(rhport, ep_addr, buffer, total_bytes);
- if (ie) NVIC_EnableIRQ(USB0_IRQn);
+ if (ie) musb_dcd_int_enable(rhport);
return ret;
}
@@ -810,29 +664,29 @@ bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_
// TU_LOG1("X %x %d\r\n", ep_addr, total_bytes);
unsigned const epnum = tu_edpt_number(ep_addr);
TU_ASSERT(epnum);
- unsigned const ie = NVIC_GetEnableIRQ(USB0_IRQn);
- NVIC_DisableIRQ(USB0_IRQn);
+ unsigned const ie = musb_dcd_get_int_enable(rhport);
+ musb_dcd_int_disable(rhport);
_dcd.pipe_buf_is_fifo[tu_edpt_dir(ep_addr)] |= TU_BIT(epnum - 1);
ret = edpt_n_xfer(rhport, ep_addr, (uint8_t*)ff, total_bytes);
- if (ie) NVIC_EnableIRQ(USB0_IRQn);
+ if (ie) musb_dcd_int_enable(rhport);
return ret;
}
// Stall endpoint
void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr)
{
- (void)rhport;
unsigned const epn = tu_edpt_number(ep_addr);
- unsigned const ie = NVIC_GetEnableIRQ(USB0_IRQn);
- NVIC_DisableIRQ(USB0_IRQn);
+ unsigned const ie = musb_dcd_get_int_enable(rhport);
+ musb_dcd_int_disable(rhport);
if (0 == epn) {
+ volatile musb_dcd_ep0_regs_t* ep0_regs = musb_dcd_ep0_regs(rhport);
if (!ep_addr) { /* Ignore EP80 */
_dcd.setup_packet.bmRequestType = REQUEST_TYPE_INVALID;
_dcd.pipe0.buf = NULL;
- USB0->CSRL0 = USB_CSRL0_STALL;
+ ep0_regs->CSRL0 = USB_CSRL0_STALL;
}
} else {
- volatile hw_endpoint_t *regs = edpt_regs(epn - 1);
+ volatile musb_dcd_epn_regs_t *regs = musb_dcd_epn_regs(rhport, epn);
if (tu_edpt_dir(ep_addr)) { /* IN */
regs->TXCSRL = USB_TXCSRL1_STALL;
} else { /* OUT */
@@ -840,7 +694,7 @@ void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr)
regs->RXCSRL = USB_RXCSRL1_STALL;
}
}
- if (ie) NVIC_EnableIRQ(USB0_IRQn);
+ if (ie) musb_dcd_int_enable(rhport);
}
// clear stall, data toggle is also reset to DATA0
@@ -848,15 +702,15 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr)
{
(void)rhport;
unsigned const epn = tu_edpt_number(ep_addr);
- hw_endpoint_t volatile *regs = edpt_regs(epn - 1);
- unsigned const ie = NVIC_GetEnableIRQ(USB0_IRQn);
- NVIC_DisableIRQ(USB0_IRQn);
+ musb_dcd_epn_regs_t volatile *regs = musb_dcd_epn_regs(rhport, epn);
+ unsigned const ie = musb_dcd_get_int_enable(rhport);
+ musb_dcd_int_disable(rhport);
if (tu_edpt_dir(ep_addr)) { /* IN */
regs->TXCSRL = USB_TXCSRL1_CLRDT;
} else { /* OUT */
regs->RXCSRL = USB_RXCSRL1_CLRDT;
}
- if (ie) NVIC_EnableIRQ(USB0_IRQn);
+ if (ie) musb_dcd_int_enable(rhport);
}
/*-------------------------------------------------------------------
@@ -865,13 +719,18 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr)
void dcd_int_handler(uint8_t rhport)
{
uint_fast8_t is, txis, rxis;
+ volatile musb_dcd_ctl_regs_t *ctrl_regs;
- is = USB0->IS; /* read and clear interrupt status */
- txis = USB0->TXIS; /* read and clear interrupt status */
- rxis = USB0->RXIS; /* read and clear interrupt status */
+ //Part specific ISR setup/entry
+ musb_dcd_int_handler_enter(rhport);
+
+ ctrl_regs = musb_dcd_ctl_regs(rhport);
+ is = ctrl_regs->IS; /* read and clear interrupt status */
+ txis = ctrl_regs->TXIS; /* read and clear interrupt status */
+ rxis = ctrl_regs->RXIS; /* read and clear interrupt status */
// TU_LOG1("D%2x T%2x R%2x\r\n", is, txis, rxis);
- is &= USB0->IE; /* Clear disabled interrupts */
+ is &= ctrl_regs->IE; /* Clear disabled interrupts */
if (is & USB_IS_DISCON) {
}
if (is & USB_IS_SOF) {
@@ -887,7 +746,7 @@ void dcd_int_handler(uint8_t rhport)
dcd_event_bus_signal(rhport, DCD_EVENT_SUSPEND, true);
}
- txis &= USB0->TXIE; /* Clear disabled interrupts */
+ txis &= ctrl_regs->TXIE; /* Clear disabled interrupts */
if (txis & USB_TXIE_EP0) {
process_ep0(rhport);
txis &= ~TU_BIT(0);
@@ -897,12 +756,15 @@ void dcd_int_handler(uint8_t rhport)
process_edpt_n(rhport, tu_edpt_addr(num, TUSB_DIR_IN));
txis &= ~TU_BIT(num);
}
- rxis &= USB0->RXIE; /* Clear disabled interrupts */
+ rxis &= ctrl_regs->RXIE; /* Clear disabled interrupts */
while (rxis) {
unsigned const num = __builtin_ctz(rxis);
process_edpt_n(rhport, tu_edpt_addr(num, TUSB_DIR_OUT));
rxis &= ~TU_BIT(num);
}
+
+ //Part specific ISR exit
+ musb_dcd_int_handler_exit(rhport);
}
#endif
diff --git a/src/portable/mentor/musb/hcd_musb.c b/src/portable/mentor/musb/hcd_musb.c
index 5312c2812..8fc225676 100644
--- a/src/portable/mentor/musb/hcd_musb.c
+++ b/src/portable/mentor/musb/hcd_musb.c
@@ -37,16 +37,10 @@ _Pragma("GCC diagnostic ignored \"-Waddress-of-packed-member\"");
#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
+#include "musb_type.h"
+#if TU_CHECK_MCU(OPT_MCU_MSP432E4, OPT_MCU_TM4C123, OPT_MCU_TM4C129)
+ #include "musb_ti.h"
#else
#error "Unsupported MCUs"
#endif
diff --git a/src/portable/mentor/musb/musb_max32.h b/src/portable/mentor/musb/musb_max32.h
new file mode 100644
index 000000000..297a695f8
--- /dev/null
+++ b/src/portable/mentor/musb/musb_max32.h
@@ -0,0 +1,221 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2024, Brent Kowal (Analog Devices, Inc)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * This file is part of the TinyUSB stack.
+ */
+
+#ifndef _TUSB_MUSB_MAX32_H_
+#define _TUSB_MUSB_MAX32_H_
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+#if TU_CHECK_MCU(OPT_MCU_MAX32690, OPT_MCU_MAX32650, OPT_MCU_MAX32666, OPT_MCU_MAX78002)
+ #include "mxc_device.h"
+ #include "usbhs_regs.h"
+#else
+ #error "Unsupported MCUs"
+#endif
+
+
+#if CFG_TUD_ENABLED
+#define USBHS_M31_CLOCK_RECOVERY
+
+// Mapping of peripheral instances to port. Currently just 1.
+static mxc_usbhs_regs_t* const musb_periph_inst[] = {
+ MXC_USBHS
+};
+
+// Mapping of IRQ numbers to port. Currently just 1.
+static const IRQn_Type musb_irqs[] = {
+ USB_IRQn
+};
+
+TU_ATTR_ALWAYS_INLINE
+static inline void musb_dcd_int_enable(uint8_t rhport)
+{
+ NVIC_EnableIRQ(musb_irqs[rhport]);
+}
+
+TU_ATTR_ALWAYS_INLINE
+static inline void musb_dcd_int_disable(uint8_t rhport)
+{
+ NVIC_DisableIRQ(musb_irqs[rhport]);
+}
+
+TU_ATTR_ALWAYS_INLINE
+static inline unsigned musb_dcd_get_int_enable(uint8_t rhport)
+{
+ return NVIC_GetEnableIRQ(musb_irqs[rhport]);
+}
+
+TU_ATTR_ALWAYS_INLINE
+static inline void musb_dcd_int_clear(uint8_t rhport)
+{
+ NVIC_ClearPendingIRQ(musb_irqs[rhport]);
+}
+
+//Used to save and restore user's register map when interrupt occurs
+static volatile unsigned isr_saved_index = 0;
+
+static inline void musb_dcd_int_handler_enter(uint8_t rhport)
+{
+ uint32_t mxm_int, mxm_int_en, mxm_is;
+
+ //save current register index
+ isr_saved_index = musb_periph_inst[rhport]->index;
+
+ //Handle PHY specific events
+ mxm_int = musb_periph_inst[rhport]->mxm_int;
+ mxm_int_en = musb_periph_inst[rhport]->mxm_int_en;
+ mxm_is = mxm_int & mxm_int_en;
+ musb_periph_inst[rhport]->mxm_int = mxm_is;
+
+ if (mxm_is & MXC_F_USBHS_MXM_INT_NOVBUS) {
+ dcd_event_bus_signal(rhport, DCD_EVENT_UNPLUGGED, true);
+ }
+}
+
+static inline void musb_dcd_int_handler_exit(uint8_t rhport)
+{
+ //restore register index
+ musb_periph_inst[rhport]->index = isr_saved_index;
+}
+
+static inline void musb_dcd_phy_init(uint8_t rhport)
+{
+ //Interrupt for VBUS disconnect
+ musb_periph_inst[rhport]->mxm_int_en |= MXC_F_USBHS_MXM_INT_EN_NOVBUS;
+
+ musb_dcd_int_clear(rhport);
+
+ //Unsuspend the MAC
+ musb_periph_inst[rhport]->mxm_suspend = 0;
+
+ // Configure PHY
+ musb_periph_inst[rhport]->m31_phy_xcfgi_31_0 = (0x1 << 3) | (0x1 << 11);
+ musb_periph_inst[rhport]->m31_phy_xcfgi_63_32 = 0;
+ musb_periph_inst[rhport]->m31_phy_xcfgi_95_64 = 0x1 << (72 - 64);
+ musb_periph_inst[rhport]->m31_phy_xcfgi_127_96 = 0;
+
+
+ #ifdef USBHS_M31_CLOCK_RECOVERY
+ musb_periph_inst[rhport]->m31_phy_noncry_rstb = 1;
+ musb_periph_inst[rhport]->m31_phy_noncry_en = 1;
+ musb_periph_inst[rhport]->m31_phy_outclksel = 0;
+ musb_periph_inst[rhport]->m31_phy_coreclkin = 0;
+ musb_periph_inst[rhport]->m31_phy_xtlsel = 2; /* Select 25 MHz clock */
+ #else
+ musb_periph_inst[rhport]->m31_phy_noncry_rstb = 0;
+ musb_periph_inst[rhport]->m31_phy_noncry_en = 0;
+ musb_periph_inst[rhport]->m31_phy_outclksel = 1;
+ musb_periph_inst[rhport]->m31_phy_coreclkin = 1;
+ musb_periph_inst[rhport]->m31_phy_xtlsel = 3; /* Select 30 MHz clock */
+ #endif
+ musb_periph_inst[rhport]->m31_phy_pll_en = 1;
+ musb_periph_inst[rhport]->m31_phy_oscouten = 1;
+
+ /* Reset PHY */
+ musb_periph_inst[rhport]->m31_phy_ponrst = 0;
+ musb_periph_inst[rhport]->m31_phy_ponrst = 1;
+}
+
+static inline volatile musb_dcd_ctl_regs_t* musb_dcd_ctl_regs(uint8_t rhport)
+{
+ volatile musb_dcd_ctl_regs_t *regs = (volatile musb_dcd_ctl_regs_t*)((uintptr_t)&(musb_periph_inst[rhport]->faddr));
+ return regs;
+}
+
+static inline volatile musb_dcd_epn_regs_t* musb_dcd_epn_regs(uint8_t rhport, unsigned epnum)
+{
+ //Need to set index to map EP registers
+ musb_periph_inst[rhport]->index = epnum;
+ volatile musb_dcd_epn_regs_t *regs = (volatile musb_dcd_epn_regs_t*)((uintptr_t)&(musb_periph_inst[rhport]->inmaxp));
+ return regs;
+}
+
+static inline volatile musb_dcd_ep0_regs_t* musb_dcd_ep0_regs(uint8_t rhport)
+{
+ //Need to set index to map EP0 registers
+ musb_periph_inst[rhport]->index = 0;
+ volatile musb_dcd_ep0_regs_t *regs = (volatile musb_dcd_ep0_regs_t*)((uintptr_t)&(musb_periph_inst[rhport]->csr0));
+ return regs;
+}
+
+static volatile void *musb_dcd_ep_get_fifo_ptr(uint8_t rhport, unsigned epnum)
+{
+ volatile uint32_t *ptr;
+
+ ptr = &(musb_periph_inst[rhport]->fifo0);
+ ptr += epnum;
+
+ return (volatile void *) ptr;
+}
+
+
+static inline void musb_dcd_setup_fifo(uint8_t rhport, unsigned epnum, unsigned dir_in, unsigned mps)
+{
+ (void)mps;
+
+ //Most likely the caller has already grabbed the right register block. But
+ //as a precaution save and restore the register bank anyways
+ unsigned saved_index = musb_periph_inst[rhport]->index;
+
+ musb_periph_inst[rhport]->index = epnum;
+
+ //Disable double buffering
+ if(dir_in) {
+ musb_periph_inst[rhport]->incsru |= (MXC_F_USBHS_INCSRU_DPKTBUFDIS | MXC_F_USBHS_INCSRU_MODE);
+ } else {
+ musb_periph_inst[rhport]->outcsru |= (MXC_F_USBHS_OUTCSRU_DPKTBUFDIS);
+ }
+
+ musb_periph_inst[rhport]->index = saved_index;
+}
+
+static inline void musb_dcd_reset_fifo(uint8_t rhport, unsigned epnum, unsigned dir_in)
+{
+ //Most likely the caller has already grabbed the right register block. But
+ //as a precaution save and restore the register bank anyways
+ unsigned saved_index = musb_periph_inst[rhport]->index;
+
+ musb_periph_inst[rhport]->index = epnum;
+
+ //Disable double buffering
+ if(dir_in) {
+ musb_periph_inst[rhport]->incsru |= (MXC_F_USBHS_INCSRU_DPKTBUFDIS);
+ } else {
+ musb_periph_inst[rhport]->outcsru |= (MXC_F_USBHS_OUTCSRU_DPKTBUFDIS);
+ }
+
+ musb_periph_inst[rhport]->index = saved_index;
+}
+
+#endif // CFG_TUD_ENABLED
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif // _TUSB_MUSB_MAX32_H_
diff --git a/src/portable/mentor/musb/musb_msp432e.h b/src/portable/mentor/musb/musb_msp432e.h
deleted file mode 100644
index fce21de88..000000000
--- a/src/portable/mentor/musb/musb_msp432e.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2021, Ha Thach (tinyusb.org)
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- *
- * This file is part of the TinyUSB stack.
- */
-
-#ifndef _TUSB_MUSB_MSP432E_H_
-#define _TUSB_MUSB_MSP432E_H_
-
-#ifdef __cplusplus
- extern "C" {
-#endif
-
-#include "msp.h"
-
-#ifdef __cplusplus
- }
-#endif
-
-#endif
diff --git a/src/portable/mentor/musb/musb_ti.h b/src/portable/mentor/musb/musb_ti.h
new file mode 100644
index 000000000..dbf82f391
--- /dev/null
+++ b/src/portable/mentor/musb/musb_ti.h
@@ -0,0 +1,285 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2024, Brent Kowal (Analog Devices, Inc)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * This file is part of the TinyUSB stack.
+ */
+
+#ifndef _TUSB_MUSB_TI_H_
+#define _TUSB_MUSB_TI_H_
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+#if CFG_TUSB_MCU == OPT_MCU_TM4C123
+ #include "TM4C123.h"
+ #define FIFO0_WORD FIFO0
+ #define FIFO1_WORD FIFO1
+//#elif CFG_TUSB_MCU == OPT_MCU_TM4C129
+#elif CFG_TUSB_MCU == OPT_MCU_MSP432E4
+ #include "msp.h"
+#else
+ #error "Unsupported MCUs"
+#endif
+
+
+// Header supports both device and host modes. Only include whats necessary
+#if CFG_TUD_ENABLED
+
+// Mapping of peripheral instances to port. Currently just 1.
+static USB0_Type* const musb_periph_inst[] = {
+ USB0
+};
+
+// Mapping of IRQ numbers to port. Currently just 1.
+static const IRQn_Type musb_irqs[] = {
+ USB0_IRQn
+};
+
+static inline void musb_dcd_phy_init(uint8_t rhport){
+ (void)rhport;
+ //Nothing to do for this part
+}
+
+TU_ATTR_ALWAYS_INLINE
+static inline void musb_dcd_int_enable(uint8_t rhport)
+{
+ NVIC_EnableIRQ(musb_irqs[rhport]);
+}
+
+TU_ATTR_ALWAYS_INLINE
+static inline void musb_dcd_int_disable(uint8_t rhport)
+{
+ NVIC_DisableIRQ(musb_irqs[rhport]);
+}
+
+TU_ATTR_ALWAYS_INLINE
+static inline unsigned musb_dcd_get_int_enable(uint8_t rhport)
+{
+ return NVIC_GetEnableIRQ(musb_irqs[rhport]);
+}
+
+TU_ATTR_ALWAYS_INLINE
+static inline void musb_dcd_int_clear(uint8_t rhport)
+{
+ NVIC_ClearPendingIRQ(musb_irqs[rhport]);
+}
+
+static inline void musb_dcd_int_handler_enter(uint8_t rhport){
+ (void)rhport;
+ //Nothing to do for this part
+}
+
+static inline void musb_dcd_int_handler_exit(uint8_t rhport){
+ (void)rhport;
+ //Nothing to do for this part
+}
+
+static inline volatile musb_dcd_ctl_regs_t* musb_dcd_ctl_regs(uint8_t rhport)
+{
+ volatile musb_dcd_ctl_regs_t *regs = (volatile musb_dcd_ctl_regs_t*)((uintptr_t)&(musb_periph_inst[rhport]->FADDR));
+ return regs;
+}
+
+static inline volatile musb_dcd_epn_regs_t* musb_dcd_epn_regs(uint8_t rhport, unsigned epnum)
+{
+ uintptr_t baseptr = (uintptr_t)&(musb_periph_inst[rhport]->TXMAXP1);
+
+ //On the TI parts, the epn registers are 16-bytes apart. The core regs defined
+ //by musb_dcd_epn_regs and 6 reserved/other use bytes
+ volatile musb_dcd_epn_regs_t *regs = (volatile musb_dcd_epn_regs_t*)(baseptr + ((epnum - 1)*16));
+ return regs;
+}
+
+static inline volatile musb_dcd_ep0_regs_t* musb_dcd_ep0_regs(uint8_t rhport)
+{
+ volatile musb_dcd_ep0_regs_t *regs = (volatile musb_dcd_ep0_regs_t*)((uintptr_t)&(musb_periph_inst[rhport]->CSRL0));
+ return regs;
+}
+
+static volatile void *musb_dcd_ep_get_fifo_ptr(uint8_t rhport, unsigned epnum)
+{
+ if(epnum){
+ return (volatile void *)(&(musb_periph_inst[rhport]->FIFO1_WORD) + (epnum - 1));
+ } else {
+ return (volatile void *)&(musb_periph_inst[rhport]->FIFO0_WORD);
+ }
+}
+
+
+typedef struct {
+ uint_fast16_t beg; /* offset of including first element */
+ uint_fast16_t end; /* offset of excluding the last element */
+} free_block_t;
+
+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;
+}
+
+#if 0
+static inline void print_block_list(free_block_t const *blk, unsigned num)
+{
+ TU_LOG1("*************\r\n");
+ for (unsigned i = 0; i < num; ++i) {
+ TU_LOG1(" Blk%u %u %u\r\n", i, blk->beg, blk->end);
+ ++blk;
+ }
+}
+#else
+#define print_block_list(a,b)
+#endif
+
+static unsigned find_free_memory(uint8_t rhport, uint_fast16_t size_in_log2_minus3)
+{
+ free_block_t free_blocks[2 * (TUP_DCD_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 < TUP_DCD_ENDPOINT_MAX; ++i) {
+ uint_fast16_t addr;
+ int num;
+ musb_periph_inst[rhport]->EPIDX = i;
+ addr = musb_periph_inst[rhport]->TXFIFOADD;
+ if (addr) {
+ unsigned sz = musb_periph_inst[rhport]->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;
+ print_block_list(free_blocks, num_blocks);
+ }
+ addr = musb_periph_inst[rhport]->RXFIFOADD;
+ if (addr) {
+ unsigned sz = musb_periph_inst[rhport]->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;
+ print_block_list(free_blocks, num_blocks);
+ }
+ }
+ print_block_list(free_blocks, num_blocks);
+
+ /* 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 void musb_dcd_setup_fifo(uint8_t rhport, unsigned epnum, unsigned dir_in, unsigned mps)
+{
+ 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(rhport, size_in_log2_minus3);
+ TU_ASSERT(addr,);
+
+ musb_periph_inst[rhport]->EPIDX = epnum;
+ if (dir_in) {
+ musb_periph_inst[rhport]->TXFIFOADD = addr;
+ musb_periph_inst[rhport]->TXFIFOSZ = size_in_log2_minus3;
+ } else {
+ musb_periph_inst[rhport]->RXFIFOADD = addr;
+ musb_periph_inst[rhport]->RXFIFOSZ = size_in_log2_minus3;
+ }
+}
+
+static inline void musb_dcd_reset_fifo(uint8_t rhport, unsigned epnum, unsigned dir_in)
+{
+ musb_periph_inst[rhport]->EPIDX = epnum;
+ if (dir_in) {
+ musb_periph_inst[rhport]->TXFIFOADD = 0;
+ musb_periph_inst[rhport]->TXFIFOSZ = 0;
+ } else {
+ musb_periph_inst[rhport]->RXFIFOADD = 0;
+ musb_periph_inst[rhport]->RXFIFOSZ = 0;
+ }
+}
+
+#endif // CFG_TUD_ENABLED
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif // _TUSB_MUSB_TI_H_
diff --git a/src/portable/mentor/musb/musb_tm4c.h b/src/portable/mentor/musb/musb_tm4c.h
deleted file mode 100644
index 65a1751b0..000000000
--- a/src/portable/mentor/musb/musb_tm4c.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2021, Ha Thach (tinyusb.org)
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- *
- * This file is part of the TinyUSB stack.
- */
-
-#ifndef _TUSB_MUSB_TM4C_H_
-#define _TUSB_MUSB_TM4C_H_
-
-#ifdef __cplusplus
- extern "C" {
-#endif
-
-#if CFG_TUSB_MCU == OPT_MCU_TM4C123
- #include "TM4C123.h"
-//#elif CFG_TUSB_MCU == OPT_MCU_TM4C129
-#else
- #error "Unsupported MCUs"
-#endif
-
-#ifdef __cplusplus
- }
-#endif
-
-#endif
diff --git a/src/portable/mentor/musb/musb_type.h b/src/portable/mentor/musb/musb_type.h
index 8f83305a5..e8af8f19b 100644
--- a/src/portable/mentor/musb/musb_type.h
+++ b/src/portable/mentor/musb/musb_type.h
@@ -35,10 +35,43 @@
#ifndef _TUSB_MUSB_TYPE_H_
#define _TUSB_MUSB_TYPE_H_
+#include "stdint.h"
+
#ifdef __cplusplus
extern "C" {
#endif
+// Endpoint register mapping. Non-zero end points.
+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;
+} musb_dcd_epn_regs_t;
+
+// Endpoint 0 register mapping.
+typedef struct TU_ATTR_PACKED {
+ uint8_t CSRL0;
+ uint8_t CSRH0;
+ uint32_t RESERVED;
+ uint8_t COUNT0;
+} musb_dcd_ep0_regs_t;
+
+// Control register mapping
+typedef struct TU_ATTR_PACKED {
+ uint8_t FADDR;
+ uint8_t POWER;
+ uint16_t TXIS;
+ uint16_t RXIS;
+ uint16_t TXIE;
+ uint16_t RXIE;
+ uint8_t IS;
+ uint8_t IE;
+} musb_dcd_ctl_regs_t;
+
//*****************************************************************************
//
// The following are defines for the bit fields in the USB_O_FADDR register.