Merge branch 'master' into dwc2_dma

This commit is contained in:
HiFiPhile
2024-09-08 17:15:28 +02:00
committed by GitHub
231 changed files with 10553 additions and 6942 deletions

View File

@@ -168,14 +168,14 @@ enum {
};
enum {
MAX_NAK_DEFAULT = 1 // Number of NAK per endpoint per usb frame
MAX_NAK_DEFAULT = 1 // Number of NAK per endpoint per usb frame to save CPU/SPI bus usage
};
enum {
EP_STATE_IDLE = 0,
EP_STATE_COMPLETE = 1,
EP_STATE_ABORTING = 2,
EP_STATE_ATTEMPT_1 = 3, // pending 1st attempt
EP_STATE_ATTEMPT_1 = 3, // Number of attempts to transfer in a frame. Incremented after each NAK
EP_STATE_ATTEMPT_MAX = 15
};
@@ -183,17 +183,20 @@ enum {
//
//--------------------------------------------------------------------+
typedef struct TU_ATTR_PACKED {
uint8_t ep_num : 4;
uint8_t is_setup : 1;
uint8_t is_out : 1;
uint8_t is_iso : 1;
} hxfr_bm_t;
TU_VERIFY_STATIC(sizeof(hxfr_bm_t) == 1, "size is not correct");
typedef struct {
uint8_t daddr;
union { ;
struct TU_ATTR_PACKED {
uint8_t ep_num : 4;
uint8_t is_setup : 1;
uint8_t is_out : 1;
uint8_t is_iso : 1;
}hxfr_bm;
union {
hxfr_bm_t hxfr_bm;
uint8_t hxfr;
};
@@ -219,7 +222,16 @@ typedef struct {
uint8_t hien;
uint8_t mode;
uint8_t peraddr;
uint8_t hxfr;
union {
hxfr_bm_t hxfr_bm;
uint8_t hxfr;
};
// owner of data in SNDFIFO, for retrying NAKed without re-writing to FIFO
struct {
uint8_t daddr;
uint8_t hxfr;
}sndfifo_owner;
atomic_flag busy; // busy transferring
@@ -317,33 +329,9 @@ bool tuh_max3421_reg_write(uint8_t rhport, uint8_t reg, uint8_t data, bool in_is
return ret;
}
static void fifo_write(uint8_t rhport, uint8_t reg, uint8_t const * buffer, uint16_t len, bool in_isr) {
uint8_t hirq;
reg |= CMDBYTE_WRITE;
max3421_spi_lock(rhport, in_isr);
tuh_max3421_spi_xfer_api(rhport, &reg, &hirq, 1);
_hcd_data.hirq = hirq;
tuh_max3421_spi_xfer_api(rhport, buffer, NULL, len);
max3421_spi_unlock(rhport, in_isr);
}
static void fifo_read(uint8_t rhport, uint8_t * buffer, uint16_t len, bool in_isr) {
uint8_t hirq;
uint8_t const reg = RCVVFIFO_ADDR;
max3421_spi_lock(rhport, in_isr);
tuh_max3421_spi_xfer_api(rhport, &reg, &hirq, 1);
_hcd_data.hirq = hirq;
tuh_max3421_spi_xfer_api(rhport, NULL, buffer, len);
max3421_spi_unlock(rhport, in_isr);
}
//------------- register write helper -------------//
//--------------------------------------------------------------------
// Register helper
//--------------------------------------------------------------------
TU_ATTR_ALWAYS_INLINE static inline void hirq_write(uint8_t rhport, uint8_t data, bool in_isr) {
reg_write(rhport, HIRQ_ADDR, data, in_isr);
// HIRQ write 1 is clear
@@ -377,6 +365,47 @@ TU_ATTR_ALWAYS_INLINE static inline void sndbc_write(uint8_t rhport, uint8_t dat
reg_write(rhport, SNDBC_ADDR, data, in_isr);
}
//--------------------------------------------------------------------
// FIFO access (receive, send, setup)
//--------------------------------------------------------------------
static void hwfifo_write(uint8_t rhport, uint8_t reg, const uint8_t* buffer, uint8_t len, bool in_isr) {
uint8_t hirq;
reg |= CMDBYTE_WRITE;
max3421_spi_lock(rhport, in_isr);
tuh_max3421_spi_xfer_api(rhport, &reg, &hirq, 1);
_hcd_data.hirq = hirq;
tuh_max3421_spi_xfer_api(rhport, buffer, NULL, len);
max3421_spi_unlock(rhport, in_isr);
}
// Write to SNDFIFO if len > 0 and update SNDBC
TU_ATTR_ALWAYS_INLINE static inline void hwfifo_send(uint8_t rhport, const uint8_t* buffer, uint8_t len, bool in_isr) {
if (len) {
hwfifo_write(rhport, SNDFIFO_ADDR, buffer, len, in_isr);
}
sndbc_write(rhport, len, in_isr);
}
TU_ATTR_ALWAYS_INLINE static inline void hwfifo_setup(uint8_t rhport, const uint8_t* buffer, bool in_isr) {
hwfifo_write(rhport, SUDFIFO_ADDR, buffer, 8, in_isr);
}
static void hwfifo_receive(uint8_t rhport, uint8_t * buffer, uint16_t len, bool in_isr) {
uint8_t hirq;
uint8_t const reg = RCVVFIFO_ADDR;
max3421_spi_lock(rhport, in_isr);
tuh_max3421_spi_xfer_api(rhport, &reg, &hirq, 1);
_hcd_data.hirq = hirq;
tuh_max3421_spi_xfer_api(rhport, NULL, buffer, len);
max3421_spi_unlock(rhport, in_isr);
}
//--------------------------------------------------------------------+
// Endpoint helper
//--------------------------------------------------------------------+
@@ -417,7 +446,7 @@ static void free_ep(uint8_t daddr) {
}
}
// Check if endpoint has an queued transfer and not reach max NAK
// Check if endpoint has a queued transfer and not reach max NAK in this frame
TU_ATTR_ALWAYS_INLINE static inline bool is_ep_pending(max3421_ep_t const * ep) {
uint8_t const state = ep->state;
return ep->packet_size && (state >= EP_STATE_ATTEMPT_1) &&
@@ -487,6 +516,7 @@ bool hcd_init(uint8_t rhport) {
reg_write(rhport, PINCTL_ADDR, _tuh_cfg.pinctl | PINCTL_FDUPSPI, false);
// v1 is 0x01, v2 is 0x12, v3 is 0x13
// Note: v1 and v2 has host OUT errata whose workaround is not implemented in this driver
uint8_t const revision = reg_read(rhport, REVISION_ADDR, false);
TU_LOG2_HEX(revision);
TU_ASSERT(revision == 0x01 || revision == 0x12 || revision == 0x13, false);
@@ -615,22 +645,45 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t daddr, tusb_desc_endpoint_t const * e
return true;
}
/* The microcontroller repeatedly writes the SNDFIFO register R2 to load the FIFO with up to 64 data bytes.
* Then the microcontroller writes the SNDBC register, which this does three things:
* 1. Tells the MAX3421E SIE (Serial Interface Engine) how many bytes in the FIFO to send.
* 2. Connects the SNDFIFO and SNDBC register to the USB logic for USB transmission.
* 3. Clears the SNDBAVIRQ interrupt flag. If the second FIFO is available for µC loading, the SNDBAVIRQ immediately re-asserts.
+-----------+
--->| SNDBC-A |
/ | SNDFIFO-A |
/ +-----------+
+------+ +-------------+ / +----------+
| MCU |------>| R2: SNDFIFO |---- << Write R7 Flip >> ---| MAX3241E |
|(hcd) | | R7: SNDBC | / | SIE |
+------+ +-------------+ / +----------+
+-----------+ /
| SNDBC-B | /
| SNDFIFO-B |<---
+-----------+
Note: xact_out() is called when starting a new transfer, continue a transfer (isr) or retry a transfer (NAK)
For NAK retry, we do not need to write to FIFO or SNDBC register again.
*/
static void xact_out(uint8_t rhport, max3421_ep_t *ep, bool switch_ep, bool in_isr) {
// Page 12: Programming BULK-OUT Transfers
// TODO double buffered
// TODO: double buffering for ISO transfer
if (switch_ep) {
peraddr_write(rhport, ep->daddr, in_isr);
uint8_t const hctl = (ep->data_toggle ? HCTL_SNDTOG1 : HCTL_SNDTOG0);
const uint8_t hctl = (ep->data_toggle ? HCTL_SNDTOG1 : HCTL_SNDTOG0);
reg_write(rhport, HCTL_ADDR, hctl, in_isr);
}
uint8_t const xact_len = (uint8_t) tu_min16(ep->total_len - ep->xferred_len, ep->packet_size);
TU_ASSERT(_hcd_data.hirq & HIRQ_SNDBAV_IRQ,);
if (xact_len) {
fifo_write(rhport, SNDFIFO_ADDR, ep->buf, xact_len, in_isr);
// Only write to sndfifo and sdnbc register if it is not a NAKed retry
if (!(ep->daddr == _hcd_data.sndfifo_owner.daddr && ep->hxfr == _hcd_data.sndfifo_owner.hxfr)) {
// skip SNDBAV IRQ check, overwrite sndfifo if needed
const uint8_t xact_len = (uint8_t) tu_min16(ep->total_len - ep->xferred_len, ep->packet_size);
hwfifo_send(rhport, ep->buf, xact_len, in_isr);
}
sndbc_write(rhport, xact_len, in_isr);
_hcd_data.sndfifo_owner.daddr = ep->daddr;
_hcd_data.sndfifo_owner.hxfr = ep->hxfr;
hxfr_write(rhport, ep->hxfr, in_isr);
}
@@ -648,7 +701,7 @@ static void xact_in(uint8_t rhport, max3421_ep_t *ep, bool switch_ep, bool in_is
static void xact_setup(uint8_t rhport, max3421_ep_t *ep, bool in_isr) {
peraddr_write(rhport, ep->daddr, in_isr);
fifo_write(rhport, SUDFIFO_ADDR, ep->buf, 8, in_isr);
hwfifo_setup(rhport, ep->buf, in_isr);
hxfr_write(rhport, HXFR_SETUP, in_isr);
}
@@ -662,7 +715,7 @@ static void xact_generic(uint8_t rhport, max3421_ep_t *ep, bool switch_ep, bool
// status
if (ep->buf == NULL || ep->total_len == 0) {
uint8_t const hxfr = (uint8_t) (HXFR_HS | (ep->hxfr & HXFR_OUT_NIN));
const uint8_t hxfr = (uint8_t) (HXFR_HS | (ep->hxfr & HXFR_OUT_NIN));
peraddr_write(rhport, ep->daddr, in_isr);
hxfr_write(rhport, hxfr, in_isr);
return;
@@ -823,11 +876,11 @@ static void xfer_complete_isr(uint8_t rhport, max3421_ep_t *ep, xfer_result_t re
}
static void handle_xfer_done(uint8_t rhport, bool in_isr) {
uint8_t const hrsl = reg_read(rhport, HRSL_ADDR, in_isr);
uint8_t const hresult = hrsl & HRSL_RESULT_MASK;
uint8_t const ep_num = _hcd_data.hxfr & HXFR_EPNUM_MASK;
uint8_t const hxfr_type = _hcd_data.hxfr & 0xf0;
uint8_t const ep_dir = ((hxfr_type & HXFR_SETUP) || (hxfr_type & HXFR_OUT_NIN)) ? 0 : 1;
const uint8_t hrsl = reg_read(rhport, HRSL_ADDR, in_isr);
const uint8_t hresult = hrsl & HRSL_RESULT_MASK;
const uint8_t ep_num = _hcd_data.hxfr_bm.ep_num;
const uint8_t hxfr_type = _hcd_data.hxfr & 0xf0;
const uint8_t ep_dir = ((hxfr_type & HXFR_SETUP) || (hxfr_type & HXFR_OUT_NIN)) ? 0 : 1;
max3421_ep_t *ep = find_opened_ep(_hcd_data.peraddr, ep_num, ep_dir);
TU_VERIFY(ep, );
@@ -842,7 +895,8 @@ static void handle_xfer_done(uint8_t rhport, bool in_isr) {
// control endpoint -> retry immediately and return
hxfr_write(rhport, _hcd_data.hxfr, in_isr);
return;
} else if (EP_STATE_ATTEMPT_1 <= ep->state && ep->state < EP_STATE_ATTEMPT_MAX) {
}
if (EP_STATE_ATTEMPT_1 <= ep->state && ep->state < EP_STATE_ATTEMPT_MAX) {
ep->state++;
}
}
@@ -853,7 +907,6 @@ static void handle_xfer_done(uint8_t rhport, bool in_isr) {
hxfr_write(rhport, _hcd_data.hxfr, in_isr);
} else if (next_ep) {
// switch to next pending endpoint
// TODO could have issue with double buffered if not clear previously out data
xact_generic(rhport, next_ep, true, in_isr);
} else {
// no more pending in this frame -> clear busy
@@ -896,11 +949,15 @@ static void handle_xfer_done(uint8_t rhport, bool in_isr) {
if (ep->state == EP_STATE_COMPLETE) {
xfer_complete_isr(rhport, ep, xfer_result, hrsl, in_isr);
}else {
// more to transfer
hxfr_write(rhport, _hcd_data.hxfr, in_isr);
hxfr_write(rhport, _hcd_data.hxfr, in_isr); // more to transfer
}
} else {
// SETUP or OUT transfer
// clear sndfifo owner since data is sent
_hcd_data.sndfifo_owner.daddr = 0xff;
_hcd_data.sndfifo_owner.hxfr = 0xff;
uint8_t xact_len;
if (hxfr_type & HXFR_SETUP) {
@@ -917,8 +974,7 @@ static void handle_xfer_done(uint8_t rhport, bool in_isr) {
if (xact_len < ep->packet_size || ep->xferred_len >= ep->total_len) {
xfer_complete_isr(rhport, ep, xfer_result, hrsl, in_isr);
} else {
// more to transfer
xact_out(rhport, ep, false, in_isr);
xact_out(rhport, ep, false, in_isr); // more to transfer
}
}
}
@@ -978,16 +1034,16 @@ void hcd_int_handler(uint8_t rhport, bool in_isr) {
// not call this handler again. So we need to loop until all IRQ are cleared
while (hirq & (HIRQ_RCVDAV_IRQ | HIRQ_HXFRDN_IRQ)) {
if (hirq & HIRQ_RCVDAV_IRQ) {
uint8_t const ep_num = _hcd_data.hxfr & HXFR_EPNUM_MASK;
const uint8_t ep_num = _hcd_data.hxfr_bm.ep_num;
max3421_ep_t* ep = find_opened_ep(_hcd_data.peraddr, ep_num, 1);
uint8_t xact_len = 0;
// RCVDAV_IRQ can trigger 2 times (dual buffered)
while (hirq & HIRQ_RCVDAV_IRQ) {
uint8_t rcvbc = reg_read(rhport, RCVBC_ADDR, in_isr);
const uint8_t rcvbc = reg_read(rhport, RCVBC_ADDR, in_isr);
xact_len = (uint8_t) tu_min16(rcvbc, ep->total_len - ep->xferred_len);
if (xact_len) {
fifo_read(rhport, ep->buf, xact_len, in_isr);
hwfifo_receive(rhport, ep->buf, xact_len, in_isr);
ep->buf += xact_len;
ep->xferred_len += xact_len;
}

View File

@@ -207,6 +207,7 @@ void dcd_init(uint8_t rhport)
USB_USBRSTMSK_M |
USB_ENUMDONEMSK_M |
USB_RESETDETMSK_M |
USB_WKUPINT_M |
USB_DISCONNINTMSK_M; // host most only
dcd_connect(rhport);

File diff suppressed because it is too large Load Diff

View File

@@ -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

View File

@@ -0,0 +1,150 @@
/*
* 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
#include "mxc_device.h"
#include "usbhs_regs.h"
#define MUSB_CFG_SHARED_FIFO 1 // shared FIFO for TX and RX endpoints
#define MUSB_CFG_DYNAMIC_FIFO 0 // dynamic EP FIFO sizing
const uintptr_t MUSB_BASES[] = { MXC_BASE_USBHS };
#if CFG_TUD_ENABLED
#define USBHS_M31_CLOCK_RECOVERY
// 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) {
#ifdef NVIC_GetEnableIRQ // only defined in CMSIS 5
return NVIC_GetEnableIRQ(musb_irqs[rhport]);
#else
uint32_t IRQn = (uint32_t) musb_irqs[rhport];
return ((NVIC->ISER[IRQn >> 5UL] & (1UL << (IRQn & 0x1FUL))) != 0UL) ? 1UL : 0UL;
#endif
}
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) {
mxc_usbhs_regs_t* hs_phy = MXC_USBHS;
uint32_t mxm_int, mxm_int_en, mxm_is;
//Handle PHY specific events
mxm_int = hs_phy->mxm_int;
mxm_int_en = hs_phy->mxm_int_en;
mxm_is = mxm_int & mxm_int_en;
hs_phy->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_phy_init(uint8_t rhport) {
(void) rhport;
mxc_usbhs_regs_t* hs_phy = MXC_USBHS;
// Interrupt for VBUS disconnect
hs_phy->mxm_int_en |= MXC_F_USBHS_MXM_INT_EN_NOVBUS;
musb_dcd_int_clear(rhport);
// Unsuspend the MAC
hs_phy->mxm_suspend = 0;
// Configure PHY
hs_phy->m31_phy_xcfgi_31_0 = (0x1 << 3) | (0x1 << 11);
hs_phy->m31_phy_xcfgi_63_32 = 0;
hs_phy->m31_phy_xcfgi_95_64 = 0x1 << (72 - 64);
hs_phy->m31_phy_xcfgi_127_96 = 0;
#ifdef USBHS_M31_CLOCK_RECOVERY
hs_phy->m31_phy_noncry_rstb = 1;
hs_phy->m31_phy_noncry_en = 1;
hs_phy->m31_phy_outclksel = 0;
hs_phy->m31_phy_coreclkin = 0;
hs_phy->m31_phy_xtlsel = 2; /* Select 25 MHz clock */
#else
hs_phy->m31_phy_noncry_rstb = 0;
hs_phy->m31_phy_noncry_en = 0;
hs_phy->m31_phy_outclksel = 1;
hs_phy->m31_phy_coreclkin = 1;
hs_phy->m31_phy_xtlsel = 3; /* Select 30 MHz clock */
#endif
hs_phy->m31_phy_pll_en = 1;
hs_phy->m31_phy_oscouten = 1;
/* Reset PHY */
hs_phy->m31_phy_ponrst = 0;
hs_phy->m31_phy_ponrst = 1;
}
// 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;
// }
#endif // CFG_TUD_ENABLED
#ifdef __cplusplus
}
#endif
#endif // TUSB_MUSB_MAX32_H_

View File

@@ -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

View File

@@ -1,7 +1,7 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2021, Ha Thach (tinyusb.org)
* 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
@@ -24,8 +24,8 @@
* This file is part of the TinyUSB stack.
*/
#ifndef _TUSB_MUSB_TM4C_H_
#define _TUSB_MUSB_TM4C_H_
#ifndef TUSB_MUSB_TI_H_
#define TUSB_MUSB_TI_H_
#ifdef __cplusplus
extern "C" {
@@ -33,13 +33,59 @@
#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
#define MUSB_CFG_SHARED_FIFO 0
#define MUSB_CFG_DYNAMIC_FIFO 1
#define MUSB_CFG_DYNAMIC_FIFO_SIZE 4096
const uintptr_t MUSB_BASES[] = { USB0_BASE };
// Header supports both device and host modes. Only include what's necessary
#if CFG_TUD_ENABLED
// 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
}
#endif // CFG_TUD_ENABLED
#ifdef __cplusplus
}
#endif
#endif
#endif // TUSB_MUSB_TI_H_

File diff suppressed because it is too large Load Diff

View File

@@ -277,6 +277,11 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc)
return true;
}
void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) {
(void) rhport; (void) ep_addr;
// TODO implement dcd_edpt_close()
}
void dcd_edpt_close_all (uint8_t rhport)
{
(void) rhport;

View File

@@ -441,11 +441,11 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t to
bool const control_status = (epnum == 0 && total_bytes == 0 && dir != tu_edpt_dir(NRF_USBD->BMREQUESTTYPE));
if (control_status) {
// Status Phase also requires EasyDMA has to be available as well !!!!
edpt_dma_start(&NRF_USBD->TASKS_EP0STATUS);
// The nRF doesn't interrupt on status transmit so we queue up a success response.
dcd_event_xfer_complete(0, ep_addr, 0, XFER_RESULT_SUCCESS, is_in_isr());
// Status Phase also requires EasyDMA has to be available as well !!!!
edpt_dma_start(&NRF_USBD->TASKS_EP0STATUS);
} else if (dir == TUSB_DIR_OUT) {
xfer->started = true;
if (epnum == 0) {

View File

@@ -335,6 +335,11 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc)
return true;
}
void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) {
(void) rhport; (void) ep_addr;
// TODO implement dcd_edpt_close()
}
void dcd_edpt_close_all (uint8_t rhport)
{
(void) rhport;

View File

@@ -53,6 +53,14 @@ TU_ATTR_ALWAYS_INLINE static inline bool is_host_mode(void) {
//--------------------------------------------------------------------+
// Implementation
//--------------------------------------------------------------------+
// Provide own byte by byte memcpy as not all copies are aligned
static void unaligned_memcpy(void *dst, const void *src, size_t n) {
uint8_t *dst_byte = (uint8_t*)dst;
const uint8_t *src_byte = (const uint8_t*)src;
while (n--) {
*dst_byte++ = *src_byte++;
}
}
void rp2040_usb_init(void) {
// Reset usb controller
@@ -67,7 +75,6 @@ void rp2040_usb_init(void) {
#pragma GCC diagnostic ignored "-Wstringop-overflow"
#endif
#endif
memset(usb_hw, 0, sizeof(*usb_hw));
memset(usb_dpram, 0, sizeof(*usb_dpram));
#ifdef __GNUC__
#pragma GCC diagnostic pop
@@ -125,7 +132,7 @@ static uint32_t __tusb_irq_path_func(prepare_ep_buffer)(struct hw_endpoint* ep,
if (!ep->rx) {
// Copy data from user buffer to hw buffer
memcpy(ep->hw_data_buf + buf_id * 64, ep->user_buf, buflen);
unaligned_memcpy(ep->hw_data_buf + buf_id * 64, ep->user_buf, buflen);
ep->user_buf += buflen;
// Mark as full
@@ -230,7 +237,7 @@ static uint16_t __tusb_irq_path_func(sync_ep_buffer)(struct hw_endpoint* ep, uin
// we have received AFTER we have copied it to the user buffer at the appropriate offset
assert(buf_ctrl & USB_BUF_CTRL_FULL);
memcpy(ep->user_buf, ep->hw_data_buf + buf_id * 64, xferred_bytes);
unaligned_memcpy(ep->user_buf, ep->hw_data_buf + buf_id * 64, xferred_bytes);
ep->xferred_len = (uint16_t) (ep->xferred_len + xferred_bytes);
ep->user_buf += xferred_bytes;
}

File diff suppressed because it is too large Load Diff

View File

@@ -54,44 +54,8 @@
#endif
#define FSDEV_PMA_SIZE (512u)
// volatile 32-bit aligned
#define _va32 volatile TU_ATTR_ALIGNED(4)
typedef struct {
_va32 uint16_t EP0R; // 00: USB Endpoint 0 register
_va32 uint16_t EP1R; // 04: USB Endpoint 1 register
_va32 uint16_t EP2R; // 08: USB Endpoint 2 register
_va32 uint16_t EP3R; // 0C: USB Endpoint 3 register
_va32 uint16_t EP4R; // 10: USB Endpoint 4 register
_va32 uint16_t EP5R; // 14: USB Endpoint 5 register
_va32 uint16_t EP6R; // 18: USB Endpoint 6 register
_va32 uint16_t EP7R; // 1C: USB Endpoint 7 register
_va32 uint16_t RESERVED7[16]; // Reserved
_va32 uint16_t CNTR; // 40: Control register
_va32 uint16_t ISTR; // 44: Interrupt status register
_va32 uint16_t FNR; // 48: Frame number register
_va32 uint16_t DADDR; // 4C: Device address register
_va32 uint16_t BTABLE; // 50: Buffer Table address register
} USB_TypeDef;
TU_VERIFY_STATIC(sizeof(USB_TypeDef) == 0x54, "Size is not correct");
TU_VERIFY_STATIC(offsetof(USB_TypeDef, CNTR) == 0x40, "Wrong offset");
#define USB_BASE (APB1PERIPH_BASE + 0x00005C00UL) /*!< USB_IP Peripheral Registers base address */
#define USB_PMAADDR (APB1PERIPH_BASE + 0x00006000UL) /*!< USB_IP Packet Memory Area base address */
#define USB ((USB_TypeDef *)USB_BASE)
/******************************************************************************/
/* */
/* USB Device General registers */
/* */
/******************************************************************************/
#define USB_CNTR (USB_BASE + 0x40U) /*!< Control register */
#define USB_ISTR (USB_BASE + 0x44U) /*!< Interrupt status register */
#define USB_FNR (USB_BASE + 0x48U) /*!< Frame number register */
#define USB_DADDR (USB_BASE + 0x4CU) /*!< Device address register */
#define USB_BTABLE (USB_BASE + 0x50U) /*!< Buffer Table address register */
#define FSDEV_REG_BASE (APB1PERIPH_BASE + 0x00005C00UL)
#define FSDEV_PMA_BASE (APB1PERIPH_BASE + 0x00006000UL)
/**************************** ISTR interrupt events *************************/
#define USB_ISTR_CTR ((uint16_t)0x8000U) /*!< Correct TRansfer (clear-only bit) */

View File

@@ -1,371 +0,0 @@
/*
* The MIT License (MIT)
*
* Copyright(c) 2016 STMicroelectronics
* Copyright(c) N Conrad
* Copyright (c) 2024, hathach (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.
*
*/
#ifndef TUSB_FSDEV_COMMON_H
#define TUSB_FSDEV_COMMON_H
#ifdef __cplusplus
extern "C" {
#endif
#include "stdint.h"
// FSDEV_PMA_SIZE is PMA buffer size in bytes.
// On 512-byte devices, access with a stride of two words (use every other 16-bit address)
// On 1024-byte devices, access with a stride of one word (use every 16-bit address)
// For purposes of accessing the packet
#if ((FSDEV_PMA_SIZE) == 512u)
#define FSDEV_PMA_STRIDE (2u)
#elif ((FSDEV_PMA_SIZE) == 1024u)
#define FSDEV_PMA_STRIDE (1u)
#endif
// The fsdev_bus_t type can be used for both register and PMA access necessities
// For type-safety create a new macro for the volatile address of PMAADDR
// The compiler should warn us if we cast it to a non-volatile type?
#ifdef FSDEV_BUS_32BIT
typedef uint32_t fsdev_bus_t;
static volatile uint32_t * const pma32 = (volatile uint32_t*)USB_PMAADDR;
#else
typedef uint16_t fsdev_bus_t;
// Volatile is also needed to prevent the optimizer from changing access to 32-bit (as 32-bit access is forbidden)
static volatile uint16_t * const pma = (volatile uint16_t*)USB_PMAADDR;
TU_ATTR_ALWAYS_INLINE static inline volatile uint16_t * pcd_btable_word_ptr(USB_TypeDef * USBx, size_t x) {
size_t total_word_offset = (((USBx)->BTABLE)>>1) + x;
total_word_offset *= FSDEV_PMA_STRIDE;
return &(pma[total_word_offset]);
}
TU_ATTR_ALWAYS_INLINE static inline volatile uint16_t* pcd_ep_tx_cnt_ptr(USB_TypeDef * USBx, uint32_t bEpIdx) {
return pcd_btable_word_ptr(USBx,(bEpIdx)*4u + 1u);
}
TU_ATTR_ALWAYS_INLINE static inline volatile uint16_t* pcd_ep_rx_cnt_ptr(USB_TypeDef * USBx, uint32_t bEpIdx) {
return pcd_btable_word_ptr(USBx,(bEpIdx)*4u + 3u);
}
#endif
/* Aligned buffer size according to hardware */
TU_ATTR_ALWAYS_INLINE static inline uint16_t pcd_aligned_buffer_size(uint16_t size) {
/* The STM32 full speed USB peripheral supports only a limited set of
* buffer sizes given by the RX buffer entry format in the USB_BTABLE. */
uint16_t blocksize = (size > 62) ? 32 : 2;
// Round up while dividing requested size by blocksize
uint16_t numblocks = (size + blocksize - 1) / blocksize ;
return numblocks * blocksize;
}
TU_ATTR_ALWAYS_INLINE static inline void pcd_set_endpoint(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wRegValue) {
#ifdef FSDEV_BUS_32BIT
(void) USBx;
volatile uint32_t *reg = (volatile uint32_t *)(USB_DRD_BASE + bEpIdx*4);
*reg = wRegValue;
#else
volatile uint16_t *reg = (volatile uint16_t *)((&USBx->EP0R) + bEpIdx*2u);
*reg = (uint16_t)wRegValue;
#endif
}
TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_endpoint(USB_TypeDef * USBx, uint32_t bEpIdx) {
#ifdef FSDEV_BUS_32BIT
(void) USBx;
volatile const uint32_t *reg = (volatile const uint32_t *)(USB_DRD_BASE + bEpIdx*4);
#else
volatile const uint16_t *reg = (volatile const uint16_t *)((&USBx->EP0R) + bEpIdx*2u);
#endif
return *reg;
}
TU_ATTR_ALWAYS_INLINE static inline void pcd_set_eptype(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wType) {
uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx);
regVal &= (uint32_t)USB_EP_T_MASK;
regVal |= wType;
regVal |= USB_EP_CTR_RX | USB_EP_CTR_TX; // These clear on write0, so must set high
pcd_set_endpoint(USBx, bEpIdx, regVal);
}
TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_eptype(USB_TypeDef * USBx, uint32_t bEpIdx) {
uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx);
regVal &= USB_EP_T_FIELD;
return regVal;
}
/**
* @brief Clears bit CTR_RX / CTR_TX in the endpoint register.
* @param USBx USB peripheral instance register address.
* @param bEpIdx Endpoint Number.
* @retval None
*/
TU_ATTR_ALWAYS_INLINE static inline void pcd_clear_rx_ep_ctr(USB_TypeDef * USBx, uint32_t bEpIdx) {
uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx);
regVal &= USB_EPREG_MASK;
regVal &= ~USB_EP_CTR_RX;
regVal |= USB_EP_CTR_TX; // preserve CTR_TX (clears on writing 0)
pcd_set_endpoint(USBx, bEpIdx, regVal);
}
TU_ATTR_ALWAYS_INLINE static inline void pcd_clear_tx_ep_ctr(USB_TypeDef * USBx, uint32_t bEpIdx) {
uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx);
regVal &= USB_EPREG_MASK;
regVal &= ~USB_EP_CTR_TX;
regVal |= USB_EP_CTR_RX; // preserve CTR_RX (clears on writing 0)
pcd_set_endpoint(USBx, bEpIdx,regVal);
}
/**
* @brief gets counter of the tx buffer.
* @param USBx USB peripheral instance register address.
* @param bEpIdx Endpoint Number.
* @retval Counter value
*/
TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_tx_cnt(USB_TypeDef * USBx, uint32_t bEpIdx) {
#ifdef FSDEV_BUS_32BIT
(void) USBx;
return (pma32[2*bEpIdx] & 0x03FF0000) >> 16;
#else
volatile const uint16_t *regPtr = pcd_ep_tx_cnt_ptr(USBx, bEpIdx);
return *regPtr & 0x3ffU;
#endif
}
TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_rx_cnt(USB_TypeDef * USBx, uint32_t bEpIdx) {
#ifdef FSDEV_BUS_32BIT
(void) USBx;
return (pma32[2*bEpIdx + 1] & 0x03FF0000) >> 16;
#else
volatile const uint16_t *regPtr = pcd_ep_rx_cnt_ptr(USBx, bEpIdx);
return *regPtr & 0x3ffU;
#endif
}
#define pcd_get_ep_dbuf0_cnt pcd_get_ep_tx_cnt
#define pcd_get_ep_dbuf1_cnt pcd_get_ep_rx_cnt
/**
* @brief Sets address in an endpoint register.
* @param USBx USB peripheral instance register address.
* @param bEpIdx Endpoint Number.
* @param bAddr Address.
* @retval None
*/
TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_address(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t bAddr) {
uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx);
regVal &= USB_EPREG_MASK;
regVal |= bAddr;
regVal |= USB_EP_CTR_RX|USB_EP_CTR_TX;
pcd_set_endpoint(USBx, bEpIdx,regVal);
}
TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_tx_address(USB_TypeDef * USBx, uint32_t bEpIdx) {
#ifdef FSDEV_BUS_32BIT
(void) USBx;
return pma32[2*bEpIdx] & 0x0000FFFFu ;
#else
return *pcd_btable_word_ptr(USBx,(bEpIdx)*4u + 0u);
#endif
}
TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_rx_address(USB_TypeDef * USBx, uint32_t bEpIdx) {
#ifdef FSDEV_BUS_32BIT
(void) USBx;
return pma32[2*bEpIdx + 1] & 0x0000FFFFu;
#else
return *pcd_btable_word_ptr(USBx,(bEpIdx)*4u + 2u);
#endif
}
#define pcd_get_ep_dbuf0_address pcd_get_ep_tx_address
#define pcd_get_ep_dbuf1_address pcd_get_ep_rx_address
TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_tx_address(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t addr) {
#ifdef FSDEV_BUS_32BIT
(void) USBx;
pma32[2*bEpIdx] = (pma32[2*bEpIdx] & 0xFFFF0000u) | (addr & 0x0000FFFCu);
#else
*pcd_btable_word_ptr(USBx,(bEpIdx)*4u + 0u) = addr;
#endif
}
TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_rx_address(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t addr) {
#ifdef FSDEV_BUS_32BIT
(void) USBx;
pma32[2*bEpIdx + 1] = (pma32[2*bEpIdx + 1] & 0xFFFF0000u) | (addr & 0x0000FFFCu);
#else
*pcd_btable_word_ptr(USBx,(bEpIdx)*4u + 2u) = addr;
#endif
}
#define pcd_set_ep_dbuf0_address pcd_set_ep_tx_address
#define pcd_set_ep_dbuf1_address pcd_set_ep_rx_address
TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_tx_cnt(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wCount) {
#ifdef FSDEV_BUS_32BIT
(void) USBx;
pma32[2*bEpIdx] = (pma32[2*bEpIdx] & ~0x03FF0000u) | ((wCount & 0x3FFu) << 16);
#else
volatile uint16_t * reg = pcd_ep_tx_cnt_ptr(USBx, bEpIdx);
*reg = (uint16_t) (*reg & (uint16_t) ~0x3FFU) | (wCount & 0x3FFU);
#endif
}
#define pcd_set_ep_tx_dbuf0_cnt pcd_set_ep_tx_cnt
TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_tx_dbuf1_cnt(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wCount) {
#ifdef FSDEV_BUS_32BIT
(void) USBx;
pma32[2*bEpIdx + 1] = (pma32[2*bEpIdx + 1] & ~0x03FF0000u) | ((wCount & 0x3FFu) << 16);
#else
volatile uint16_t * reg = pcd_ep_rx_cnt_ptr(USBx, bEpIdx);
*reg = (uint16_t) (*reg & (uint16_t) ~0x3FFU) | (wCount & 0x3FFU);
#endif
}
TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_blsize_num_blocks(USB_TypeDef * USBx, uint32_t rxtx_idx,
uint32_t blocksize, uint32_t numblocks) {
/* Encode into register. When BLSIZE==1, we need to subtract 1 block count */
#ifdef FSDEV_BUS_32BIT
(void) USBx;
pma32[rxtx_idx] = (pma32[rxtx_idx] & 0x0000FFFFu) | (blocksize << 31) | ((numblocks - blocksize) << 26);
#else
volatile uint16_t *pdwReg = pcd_btable_word_ptr(USBx, rxtx_idx*2u + 1u);
*pdwReg = (blocksize << 15) | ((numblocks - blocksize) << 10);
#endif
}
TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_bufsize(USB_TypeDef * USBx, uint32_t rxtx_idx, uint32_t wCount) {
wCount = pcd_aligned_buffer_size(wCount);
/* We assume that the buffer size is already aligned to hardware requirements. */
uint16_t blocksize = (wCount > 62) ? 1 : 0;
uint16_t numblocks = wCount / (blocksize ? 32 : 2);
/* There should be no remainder in the above calculation */
TU_ASSERT((wCount - (numblocks * (blocksize ? 32 : 2))) == 0, /**/);
/* Encode into register. When BLSIZE==1, we need to subtract 1 block count */
pcd_set_ep_blsize_num_blocks(USBx, rxtx_idx, blocksize, numblocks);
}
TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_rx_dbuf0_cnt(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wCount) {
pcd_set_ep_bufsize(USBx, 2*bEpIdx, wCount);
}
TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_rx_cnt(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wCount) {
pcd_set_ep_bufsize(USBx, 2*bEpIdx + 1, wCount);
}
#define pcd_set_ep_rx_dbuf1_cnt pcd_set_ep_rx_cnt
/**
* @brief sets the status for tx transfer (bits STAT_TX[1:0]).
* @param USBx USB peripheral instance register address.
* @param bEpIdx Endpoint Number.
* @param wState new state
* @retval None
*/
TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_tx_status(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wState) {
uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx);
regVal &= USB_EPTX_DTOGMASK;
regVal ^= wState;
regVal |= USB_EP_CTR_RX|USB_EP_CTR_TX;
pcd_set_endpoint(USBx, bEpIdx, regVal);
}
/**
* @brief sets the status for rx transfer (bits STAT_TX[1:0])
* @param USBx USB peripheral instance register address.
* @param bEpIdx Endpoint Number.
* @param wState new state
* @retval None
*/
TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_rx_status(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wState) {
uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx);
regVal &= USB_EPRX_DTOGMASK;
regVal ^= wState;
regVal |= USB_EP_CTR_RX|USB_EP_CTR_TX;
pcd_set_endpoint(USBx, bEpIdx, regVal);
}
TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_rx_status(USB_TypeDef * USBx, uint32_t bEpIdx) {
uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx);
return (regVal & USB_EPRX_STAT) >> (12u);
}
TU_ATTR_ALWAYS_INLINE static inline void pcd_rx_dtog(USB_TypeDef * USBx, uint32_t bEpIdx) {
uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx);
regVal &= USB_EPREG_MASK;
regVal |= USB_EP_CTR_RX|USB_EP_CTR_TX|USB_EP_DTOG_RX;
pcd_set_endpoint(USBx, bEpIdx, regVal);
}
TU_ATTR_ALWAYS_INLINE static inline void pcd_tx_dtog(USB_TypeDef * USBx, uint32_t bEpIdx) {
uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx);
regVal &= USB_EPREG_MASK;
regVal |= USB_EP_CTR_RX|USB_EP_CTR_TX|USB_EP_DTOG_TX;
pcd_set_endpoint(USBx, bEpIdx, regVal);
}
TU_ATTR_ALWAYS_INLINE static inline void pcd_clear_rx_dtog(USB_TypeDef * USBx, uint32_t bEpIdx) {
uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx);
if((regVal & USB_EP_DTOG_RX) != 0) {
pcd_rx_dtog(USBx,bEpIdx);
}
}
TU_ATTR_ALWAYS_INLINE static inline void pcd_clear_tx_dtog(USB_TypeDef * USBx, uint32_t bEpIdx) {
uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx);
if((regVal & USB_EP_DTOG_TX) != 0) {
pcd_tx_dtog(USBx,bEpIdx);
}
}
TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_kind(USB_TypeDef * USBx, uint32_t bEpIdx) {
uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx);
regVal |= USB_EP_KIND;
regVal &= USB_EPREG_MASK;
regVal |= USB_EP_CTR_RX|USB_EP_CTR_TX;
pcd_set_endpoint(USBx, bEpIdx, regVal);
}
TU_ATTR_ALWAYS_INLINE static inline void pcd_clear_ep_kind(USB_TypeDef * USBx, uint32_t bEpIdx) {
uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx);
regVal &= USB_EPKIND_MASK;
regVal |= USB_EP_CTR_RX|USB_EP_CTR_TX;
pcd_set_endpoint(USBx, bEpIdx, regVal);
}
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -35,6 +35,7 @@
#if CFG_TUSB_MCU == OPT_MCU_STM32F0
#include "stm32f0xx.h"
#define FSDEV_PMA_SIZE (1024u)
#define FSDEV_REG_BASE USB_BASE
// F0x2 models are crystal-less
// All have internal D+ pull-up
// 070RB: 2 x 16 bits/word memory LPM Support, BCD Support
@@ -81,12 +82,9 @@
#elif CFG_TUSB_MCU == OPT_MCU_STM32G0
#include "stm32g0xx.h"
#define FSDEV_BUS_32BIT
#define FSDEV_PMA_SIZE (2048u)
#undef USB_PMAADDR
#define USB_PMAADDR USB_DRD_PMAADDR
#define USB_TypeDef USB_DRD_TypeDef
#define EP0R CHEP0R
#define USB USB_DRD_FS
#define USB_EP_CTR_RX USB_EP_VTRX
#define USB_EP_CTR_TX USB_EP_VTTX
#define USB_EP_T_FIELD USB_CHEP_UTYPE
@@ -99,7 +97,6 @@
#define USB_EPRX_DTOG2 USB_CHEP_RX_DTOG2
#define USB_EPRX_STAT USB_CH_RX_VALID
#define USB_EPKIND_MASK USB_EP_KIND_MASK
#define USB USB_DRD_FS
#define USB_CNTR_FRES USB_CNTR_USBRST
#define USB_CNTR_RESUME USB_CNTR_L2RES
#define USB_ISTR_EP_ID USB_ISTR_IDN
@@ -109,17 +106,9 @@
#elif CFG_TUSB_MCU == OPT_MCU_STM32H5
#include "stm32h5xx.h"
#define FSDEV_BUS_32BIT
#if !defined(USB_DRD_BASE) && defined(USB_DRD_FS_BASE)
#define USB_DRD_BASE USB_DRD_FS_BASE
#endif
#define FSDEV_PMA_SIZE (2048u)
#undef USB_PMAADDR
#define USB_PMAADDR USB_DRD_PMAADDR
#define USB_TypeDef USB_DRD_TypeDef
#define EP0R CHEP0R
#define USB USB_DRD_FS
#define USB_EP_CTR_RX USB_EP_VTRX
#define USB_EP_CTR_TX USB_EP_VTTX
#define USB_EP_T_FIELD USB_CHEP_UTYPE
@@ -132,7 +121,6 @@
#define USB_EPRX_DTOG2 USB_CHEP_RX_DTOG2
#define USB_EPRX_STAT USB_CH_RX_VALID
#define USB_EPKIND_MASK USB_EP_KIND_MASK
#define USB USB_DRD_FS
#define USB_CNTR_FRES USB_CNTR_USBRST
#define USB_CNTR_RESUME USB_CNTR_L2RES
#define USB_ISTR_EP_ID USB_ISTR_IDN
@@ -143,9 +131,8 @@
#elif CFG_TUSB_MCU == OPT_MCU_STM32WB
#include "stm32wbxx.h"
#define FSDEV_PMA_SIZE (1024u)
/* ST provided header has incorrect value */
#undef USB_PMAADDR
#define USB_PMAADDR USB1_PMAADDR
/* ST provided header has incorrect value of USB_PMAADDR */
#define FSDEV_PMA_BASE USB1_PMAADDR
#elif CFG_TUSB_MCU == OPT_MCU_STM32L4
#include "stm32l4xx.h"
@@ -161,13 +148,9 @@
#elif CFG_TUSB_MCU == OPT_MCU_STM32U5
#include "stm32u5xx.h"
#define FSDEV_BUS_32BIT
#define FSDEV_PMA_SIZE (2048u)
#undef USB_PMAADDR
#define USB_PMAADDR USB_DRD_PMAADDR
#define USB_TypeDef USB_DRD_TypeDef
#define EP0R CHEP0R
#define USB USB_DRD_FS
#define USB_EP_CTR_RX USB_EP_VTRX
#define USB_EP_CTR_TX USB_EP_VTTX
#define USB_EP_T_FIELD USB_CHEP_UTYPE
@@ -180,7 +163,6 @@
#define USB_EPRX_DTOG2 USB_CHEP_RX_DTOG2
#define USB_EPRX_STAT USB_CH_RX_VALID
#define USB_EPKIND_MASK USB_EP_KIND_MASK
#define USB USB_DRD_FS
#define USB_CNTR_FRES USB_CNTR_USBRST
#define USB_CNTR_RESUME USB_CNTR_L2RES
#define USB_ISTR_EP_ID USB_ISTR_IDN
@@ -193,6 +175,31 @@
// This includes U0
#endif
//--------------------------------------------------------------------+
// Register and PMA Base Address
//--------------------------------------------------------------------+
#ifndef FSDEV_REG_BASE
#if defined(USB_BASE)
#define FSDEV_REG_BASE USB_BASE
#elif defined(USB_DRD_BASE)
#define FSDEV_REG_BASE USB_DRD_BASE
#elif defined(USB_DRD_FS_BASE)
#define FSDEV_REG_BASE USB_DRD_FS_BASE
#else
#error "FSDEV_REG_BASE not defined"
#endif
#endif
#ifndef FSDEV_PMA_BASE
#if defined(USB_PMAADDR)
#define FSDEV_PMA_BASE USB_PMAADDR
#elif defined(USB_DRD_PMAADDR)
#define FSDEV_PMA_BASE USB_DRD_PMAADDR
#else
#error "FSDEV_PMA_BASE not defined"
#endif
#endif
// This checks if the device has "LPM"
#if defined(USB_ISTR_L1REQ)
#define USB_ISTR_L1REQ_FORCED (USB_ISTR_L1REQ)

View File

@@ -0,0 +1,307 @@
/*
* The MIT License (MIT)
*
* Copyright(c) N Conrad
* Copyright(c) 2024, hathach (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_FSDEV_TYPE_H
#define TUSB_FSDEV_TYPE_H
#ifdef __cplusplus
extern "C" {
#endif
#include "stdint.h"
// If sharing with CAN, one can set this to be non-zero to give CAN space where it wants it
// Both of these MUST be a multiple of 2, and are in byte units.
#ifndef FSDEV_BTABLE_BASE
#define FSDEV_BTABLE_BASE 0U
#endif
TU_VERIFY_STATIC(FSDEV_BTABLE_BASE % 8 == 0, "BTABLE base must be aligned to 8 bytes");
// FSDEV_PMA_SIZE is PMA buffer size in bytes.
// - 512-byte devices, access with a stride of two words (use every other 16-bit address)
// - 1024-byte devices, access with a stride of one word (use every 16-bit address)
// - 2048-byte devices, access with 32-bit address
// For purposes of accessing the packet
#if FSDEV_PMA_SIZE == 512
// 1x16 bit / word access scheme
#define FSDEV_PMA_STRIDE 2
#define pma_access_scheme TU_ATTR_ALIGNED(4)
#elif FSDEV_PMA_SIZE == 1024
// 2x16 bit / word access scheme
#define FSDEV_PMA_STRIDE 1
#define pma_access_scheme
#elif FSDEV_PMA_SIZE == 2048
// 32 bit access scheme
#define FSDEV_BUS_32BIT
#define FSDEV_PMA_STRIDE 1
#define pma_access_scheme
#endif
// The fsdev_bus_t type can be used for both register and PMA access necessities
#ifdef FSDEV_BUS_32BIT
typedef uint32_t fsdev_bus_t;
#define fsdevbus_unaligned_read(_addr) tu_unaligned_read32(_addr)
#define fsdevbus_unaligned_write(_addr, _value) tu_unaligned_write32(_addr, _value)
#else
typedef uint16_t fsdev_bus_t;
#define fsdevbus_unaligned_read(_addr) tu_unaligned_read16(_addr)
#define fsdevbus_unaligned_write(_addr, _value) tu_unaligned_write16(_addr, _value)
#endif
enum {
FSDEV_BUS_SIZE = sizeof(fsdev_bus_t),
};
//--------------------------------------------------------------------+
// BTable Typedef
//--------------------------------------------------------------------+
enum {
BTABLE_BUF_TX = 0,
BTABLE_BUF_RX = 1
};
// hardware limit endpoint
#define FSDEV_EP_COUNT 8
// Buffer Table is located in Packet Memory Area (PMA) and therefore its address access is forced to either
// 16-bit or 32-bit depending on FSDEV_BUS_32BIT.
// 0: TX (IN), 1: RX (OUT)
typedef union {
// data is strictly 16-bit access (address could be 32-bit aligned)
struct {
volatile pma_access_scheme uint16_t addr;
volatile pma_access_scheme uint16_t count;
} ep16[FSDEV_EP_COUNT][2];
// strictly 32-bit access
struct {
volatile uint32_t count_addr;
} ep32[FSDEV_EP_COUNT][2];
} fsdev_btable_t;
TU_VERIFY_STATIC(sizeof(fsdev_btable_t) == FSDEV_EP_COUNT*8*FSDEV_PMA_STRIDE, "size is not correct");
TU_VERIFY_STATIC(FSDEV_BTABLE_BASE + FSDEV_EP_COUNT*8 <= FSDEV_PMA_SIZE, "BTABLE does not fit in PMA RAM");
#define FSDEV_BTABLE ((volatile fsdev_btable_t*) (FSDEV_PMA_BASE + FSDEV_PMA_STRIDE*(FSDEV_BTABLE_BASE)))
typedef struct {
volatile pma_access_scheme fsdev_bus_t value;
} fsdev_pma_buf_t;
#define PMA_BUF_AT(_addr) ((fsdev_pma_buf_t*) (FSDEV_PMA_BASE + FSDEV_PMA_STRIDE*(_addr)))
//--------------------------------------------------------------------+
// Registers Typedef
//--------------------------------------------------------------------+
// volatile 32-bit aligned
#define _va32 volatile TU_ATTR_ALIGNED(4)
typedef struct {
struct {
_va32 fsdev_bus_t reg;
}ep[FSDEV_EP_COUNT];
_va32 uint32_t RESERVED7[8]; // Reserved
_va32 fsdev_bus_t CNTR; // 40: Control register
_va32 fsdev_bus_t ISTR; // 44: Interrupt status register
_va32 fsdev_bus_t FNR; // 48: Frame number register
_va32 fsdev_bus_t DADDR; // 4C: Device address register
_va32 fsdev_bus_t BTABLE; // 50: Buffer Table address register (16-bit only)
_va32 fsdev_bus_t LPMCSR; // 54: LPM Control and Status Register (32-bit only)
_va32 fsdev_bus_t BCDR; // 58: Battery Charging Detector Register (32-bit only)
} fsdev_regs_t;
TU_VERIFY_STATIC(offsetof(fsdev_regs_t, CNTR) == 0x40, "Wrong offset");
TU_VERIFY_STATIC(sizeof(fsdev_regs_t) == 0x5C, "Size is not correct");
#define FSDEV_REG ((fsdev_regs_t*) FSDEV_REG_BASE)
#ifndef USB_EPTX_STAT
#define USB_EPTX_STAT 0x0030U
#endif
#ifndef USB_EPRX_STAT
#define USB_EPRX_STAT 0x3000U
#endif
#ifndef USB_EPTX_STAT_Pos
#define USB_EPTX_STAT_Pos 4u
#endif
#ifndef USB_EP_DTOG_TX_Pos
#define USB_EP_DTOG_TX_Pos 6u
#endif
#ifndef USB_EP_CTR_TX_Pos
#define USB_EP_CTR_TX_Pos 7u
#endif
typedef enum {
EP_STAT_DISABLED = 0,
EP_STAT_STALL = 1,
EP_STAT_NAK = 2,
EP_STAT_VALID = 3
}ep_stat_t;
#define EP_STAT_MASK(_dir) (3u << (USB_EPTX_STAT_Pos + ((_dir) == TUSB_DIR_IN ? 0 : 8)))
#define EP_DTOG_MASK(_dir) (1u << (USB_EP_DTOG_TX_Pos + ((_dir) == TUSB_DIR_IN ? 0 : 8)))
//--------------------------------------------------------------------+
// Endpoint Helper
// - CTR is write 0 to clear
// - DTOG and STAT are write 1 to toggle
//--------------------------------------------------------------------+
TU_ATTR_ALWAYS_INLINE static inline uint32_t ep_read(uint32_t ep_id) {
return FSDEV_REG->ep[ep_id].reg;
}
TU_ATTR_ALWAYS_INLINE static inline void ep_write(uint32_t ep_id, uint32_t value, bool need_exclusive) {
if (need_exclusive) {
dcd_int_disable(0);
}
FSDEV_REG->ep[ep_id].reg = (fsdev_bus_t) value;
if (need_exclusive) {
dcd_int_enable(0);
}
}
TU_ATTR_ALWAYS_INLINE static inline void ep_write_clear_ctr(uint32_t ep_id, tusb_dir_t dir) {
uint32_t reg = FSDEV_REG->ep[ep_id].reg;
reg |= USB_EP_CTR_TX | USB_EP_CTR_RX;
reg &= USB_EPREG_MASK;
reg &= ~(1 << (USB_EP_CTR_TX_Pos + (dir == TUSB_DIR_IN ? 0 : 8)));
ep_write(ep_id, reg, false);
}
TU_ATTR_ALWAYS_INLINE static inline void ep_change_status(uint32_t* reg, tusb_dir_t dir, ep_stat_t state) {
*reg ^= (state << (USB_EPTX_STAT_Pos + (dir == TUSB_DIR_IN ? 0 : 8)));
}
TU_ATTR_ALWAYS_INLINE static inline void ep_change_dtog(uint32_t* reg, tusb_dir_t dir, uint8_t state) {
*reg ^= (state << (USB_EP_DTOG_TX_Pos + (dir == TUSB_DIR_IN ? 0 : 8)));
}
TU_ATTR_ALWAYS_INLINE static inline bool ep_is_iso(uint32_t reg) {
return (reg & USB_EP_TYPE_MASK) == USB_EP_ISOCHRONOUS;
}
//--------------------------------------------------------------------+
// BTable Helper
//--------------------------------------------------------------------+
TU_ATTR_ALWAYS_INLINE static inline uint32_t btable_get_addr(uint32_t ep_id, uint8_t buf_id) {
#ifdef FSDEV_BUS_32BIT
return FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr & 0x0000FFFFu;
#else
return FSDEV_BTABLE->ep16[ep_id][buf_id].addr;
#endif
}
TU_ATTR_ALWAYS_INLINE static inline void btable_set_addr(uint32_t ep_id, uint8_t buf_id, uint16_t addr) {
#ifdef FSDEV_BUS_32BIT
uint32_t count_addr = FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr;
count_addr = (count_addr & 0xFFFF0000u) | (addr & 0x0000FFFCu);
FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr = count_addr;
#else
FSDEV_BTABLE->ep16[ep_id][buf_id].addr = addr;
#endif
}
TU_ATTR_ALWAYS_INLINE static inline uint16_t btable_get_count(uint32_t ep_id, uint8_t buf_id) {
uint16_t count;
#ifdef FSDEV_BUS_32BIT
count = (FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr >> 16);
#else
count = FSDEV_BTABLE->ep16[ep_id][buf_id].count;
#endif
return count & 0x3FFU;
}
TU_ATTR_ALWAYS_INLINE static inline void btable_set_count(uint32_t ep_id, uint8_t buf_id, uint16_t byte_count) {
#ifdef FSDEV_BUS_32BIT
uint32_t count_addr = FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr;
count_addr = (count_addr & ~0x03FF0000u) | ((byte_count & 0x3FFu) << 16);
FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr = count_addr;
#else
uint16_t cnt = FSDEV_BTABLE->ep16[ep_id][buf_id].count;
cnt = (cnt & ~0x3FFU) | (byte_count & 0x3FFU);
FSDEV_BTABLE->ep16[ep_id][buf_id].count = cnt;
#endif
}
/* Aligned buffer size according to hardware */
TU_ATTR_ALWAYS_INLINE static inline uint16_t pma_align_buffer_size(uint16_t size, uint8_t* blsize, uint8_t* num_block) {
/* The STM32 full speed USB peripheral supports only a limited set of
* buffer sizes given by the RX buffer entry format in the USB_BTABLE. */
uint16_t block_in_bytes;
if (size > 62) {
block_in_bytes = 32;
*blsize = 1;
*num_block = tu_div_ceil(size, 32);
} else {
block_in_bytes = 2;
*blsize = 0;
*num_block = tu_div_ceil(size, 2);
}
return (*num_block) * block_in_bytes;
}
TU_ATTR_ALWAYS_INLINE static inline void btable_set_rx_bufsize(uint32_t ep_id, uint8_t buf_id, uint16_t wCount) {
uint8_t blsize, num_block;
(void) pma_align_buffer_size(wCount, &blsize, &num_block);
/* Encode into register. When BLSIZE==1, we need to subtract 1 block count */
uint16_t bl_nb = (blsize << 15) | ((num_block - blsize) << 10);
if (bl_nb == 0) {
// zlp but 0 is invalid value, set blsize to 1 (32 bytes)
// Note: lower value can cause PMAOVR on setup with ch32v203
bl_nb = 1 << 15;
}
#ifdef FSDEV_BUS_32BIT
uint32_t count_addr = FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr;
count_addr = (bl_nb << 16) | (count_addr & 0x0000FFFFu);
FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr = count_addr;
#else
FSDEV_BTABLE->ep16[ep_id][buf_id].count = bl_nb;
#endif
}
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -43,7 +43,7 @@
#if defined(TUP_USBIP_DWC2_STM32)
#include "dwc2_stm32.h"
#elif TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3)
#elif defined(TUP_USBIP_DWC2_ESP32)
#include "dwc2_esp32.h"
#elif TU_CHECK_MCU(OPT_MCU_GD32VF103)
#include "dwc2_gd32.h"
@@ -732,12 +732,34 @@ void dcd_remote_wakeup(uint8_t rhport) {
void dcd_connect(uint8_t rhport) {
(void) rhport;
dwc2_regs_t* dwc2 = DWC2_REG(rhport);
#ifdef TUP_USBIP_DWC2_ESP32
usb_wrap_otg_conf_reg_t conf = USB_WRAP.otg_conf;
conf.pad_pull_override = 0;
conf.dp_pullup = 0;
conf.dp_pulldown = 0;
conf.dm_pullup = 0;
conf.dm_pulldown = 0;
USB_WRAP.otg_conf = conf;
#endif
dwc2->dctl &= ~DCTL_SDIS;
}
void dcd_disconnect(uint8_t rhport) {
(void) rhport;
dwc2_regs_t* dwc2 = DWC2_REG(rhport);
#ifdef TUP_USBIP_DWC2_ESP32
usb_wrap_otg_conf_reg_t conf = USB_WRAP.otg_conf;
conf.pad_pull_override = 1;
conf.dp_pullup = 0;
conf.dp_pulldown = 1;
conf.dm_pullup = 0;
conf.dm_pulldown = 1;
USB_WRAP.otg_conf = conf;
#endif
dwc2->dctl |= DCTL_SDIS;
}
@@ -1299,25 +1321,13 @@ void dcd_int_handler(uint8_t rhport) {
// }
}
#if defined(TUP_USBIP_DWC2_TEST_MODE) && CFG_TUD_TEST_MODE
bool dcd_check_test_mode_support(test_mode_t test_selector) {
// Check if test mode selector is unsupported
if (TEST_FORCE_ENABLE < test_selector || TEST_J > test_selector) {
return false;
}
return true;
}
void dcd_enter_test_mode(uint8_t rhport, test_mode_t test_selector) {
// Get port address...
#if CFG_TUD_TEST_MODE
void dcd_enter_test_mode(uint8_t rhport, tusb_feature_test_mode_t test_selector) {
dwc2_regs_t* dwc2 = DWC2_REG(rhport);
// Enable the test mode
dwc2->dctl = (dwc2->dctl & ~DCTL_TCTL_Msk) | (test_selector << DCTL_TCTL_Pos);
dwc2->dctl = (dwc2->dctl & ~DCTL_TCTL_Msk) | (((uint8_t) test_selector) << DCTL_TCTL_Pos);
}
#endif /* TUP_USBIP_DWC2_TEST_MODE && CFG_TUD_TEST_MODE */
#endif
#endif

View File

@@ -32,61 +32,53 @@
extern "C" {
#endif
#include "freertos/task.h"
#include "esp_intr_alloc.h"
#include "soc/periph_defs.h"
//#include "soc/usb_periph.h"
#include "freertos/task.h"
#include "soc/usb_wrap_struct.h"
#define DWC2_REG_BASE 0x60080000UL
#define DWC2_EP_MAX 7
#define DWC2_EP_IN_MAX 5
static const dwc2_controller_t _dwc2_controller[] =
{
static const dwc2_controller_t _dwc2_controller[] = {
{ .reg_base = DWC2_REG_BASE, .irqnum = 0, .ep_count = DWC2_EP_MAX, .ep_in_count = DWC2_EP_IN_MAX, .ep_fifo_size = 1024 }
};
static intr_handle_t usb_ih;
static void dcd_int_handler_wrap(void* arg)
{
(void) arg;
static void dcd_int_handler_wrap(void* arg) {
(void)arg;
dcd_int_handler(0);
}
TU_ATTR_ALWAYS_INLINE
static inline void dwc2_dcd_int_enable (uint8_t rhport)
{
(void) rhport;
TU_ATTR_ALWAYS_INLINE static inline void dwc2_dcd_int_enable(uint8_t rhport) {
(void)rhport;
esp_intr_alloc(ETS_USB_INTR_SOURCE, ESP_INTR_FLAG_LOWMED, dcd_int_handler_wrap, NULL, &usb_ih);
}
TU_ATTR_ALWAYS_INLINE
static inline void dwc2_dcd_int_disable (uint8_t rhport)
{
(void) rhport;
TU_ATTR_ALWAYS_INLINE static inline void dwc2_dcd_int_disable(uint8_t rhport) {
(void)rhport;
esp_intr_free(usb_ih);
}
static inline void dwc2_remote_wakeup_delay(void)
{
TU_ATTR_ALWAYS_INLINE static inline void dwc2_remote_wakeup_delay(void) {
vTaskDelay(pdMS_TO_TICKS(1));
}
// MCU specific PHY init, called BEFORE core reset
static inline void dwc2_phy_init(dwc2_regs_t * dwc2, uint8_t hs_phy_type)
{
(void) dwc2;
(void) hs_phy_type;
TU_ATTR_ALWAYS_INLINE static inline void dwc2_phy_init(dwc2_regs_t* dwc2, uint8_t hs_phy_type) {
(void)dwc2;
(void)hs_phy_type;
// nothing to do
}
// MCU specific PHY update, it is called AFTER init() and core reset
static inline void dwc2_phy_update(dwc2_regs_t * dwc2, uint8_t hs_phy_type)
{
(void) dwc2;
(void) hs_phy_type;
TU_ATTR_ALWAYS_INLINE static inline void dwc2_phy_update(dwc2_regs_t* dwc2, uint8_t hs_phy_type) {
(void)dwc2;
(void)hs_phy_type;
// nothing to do
}
@@ -95,4 +87,4 @@ static inline void dwc2_phy_update(dwc2_regs_t * dwc2, uint8_t hs_phy_type)
}
#endif
#endif /* _DWC2_ESP32_H_ */
#endif

View File

@@ -102,6 +102,22 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc)
return false;
}
// Allocate packet buffer used by ISO endpoints
// Some MCU need manual packet buffer allocation, we allocate the largest size to avoid clustering
bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) {
(void) rhport;
(void) ep_addr;
(void) largest_packet_size;
return false;
}
// Configure and enable an ISO endpoint according to descriptor
bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const * desc_ep) {
(void) rhport;
(void) desc_ep;
return false;
}
void dcd_edpt_close_all (uint8_t rhport)
{
(void) rhport;

View File

@@ -332,6 +332,11 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt)
return true;
}
void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) {
(void) rhport; (void) ep_addr;
// TODO implement dcd_edpt_close()
}
void dcd_edpt_close_all (uint8_t rhport)
{
(void) rhport;

View File

@@ -436,6 +436,11 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc)
return true;
}
void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) {
(void) rhport; (void) ep_addr;
// TODO implement dcd_edpt_close()
}
void dcd_edpt_close_all (uint8_t rhport)
{
(void) rhport;