Merge pull request #1495 from hathach/enhance-tusb-config
Better support multiple controllers configuration
This commit is contained in:
@@ -239,12 +239,12 @@ static void _dcd_ft90x_attach(void)
|
||||
|
||||
CRITICAL_SECTION_BEGIN
|
||||
// Turn off the device enable bit.
|
||||
#if BOARD_DEVICE_RHPORT_SPEED == OPT_MODE_HIGH_SPEED
|
||||
#if BOARD_TUD_MAX_SPEED == OPT_MODE_HIGH_SPEED
|
||||
USBD_REG(fctrl) = 0;
|
||||
#else // BOARD_DEVICE_RHPORT_SPEED == OPT_MODE_FULL_SPEED
|
||||
#else // BOARD_TUD_MAX_SPEED == OPT_MODE_FULL_SPEED
|
||||
//Set the full speed only bit if required.
|
||||
USBD_REG(fctrl) = MASK_USBD_FCTRL_MODE_FS_ONLY;
|
||||
#endif // BOARD_DEVICE_RHPORT_SPEED
|
||||
#endif // BOARD_TUD_MAX_SPEED
|
||||
|
||||
// Clear first reset and suspend interrupts.
|
||||
do
|
||||
@@ -291,7 +291,7 @@ static void _dcd_ft90x_detach(void)
|
||||
delayms(1);
|
||||
|
||||
// Disable USB PHY
|
||||
dcd_disconnect(BOARD_DEVICE_RHPORT_NUM);
|
||||
dcd_disconnect(BOARD_TUD_RHPORT);
|
||||
delayms(1);
|
||||
|
||||
// Disable Chip USB device clock/PM configuration.
|
||||
@@ -312,7 +312,7 @@ static void _dcd_ft90x_detach(void)
|
||||
|
||||
// Determine the speed of the USB to which we are connected.
|
||||
// Set the speed of the PHY accordingly.
|
||||
// High speed can be disabled through CFG_TUSB_RHPORT0_MODE settings.
|
||||
// High speed can be disabled through CFG_TUSB_RHPORT0_MODE or CFG_TUD_MAX_SPEED settings.
|
||||
static void _ft90x_usb_speed(void)
|
||||
{
|
||||
uint8_t fctrl_val;
|
||||
@@ -323,7 +323,7 @@ static void _ft90x_usb_speed(void)
|
||||
delayus(200);
|
||||
}
|
||||
|
||||
#if BOARD_DEVICE_RHPORT_SPEED == OPT_MODE_HIGH_SPEED
|
||||
#if BOARD_TUD_MAX_SPEED == OPT_MODE_HIGH_SPEED
|
||||
|
||||
/* Detect high or full speed */
|
||||
fctrl_val = MASK_USBD_FCTRL_USB_DEV_EN;
|
||||
@@ -347,11 +347,11 @@ static void _ft90x_usb_speed(void)
|
||||
delayus(125 + 5);
|
||||
_speed = (USBD_REG(cmif) & MASK_USBD_CMIF_SOFIRQ) ?
|
||||
TUSB_SPEED_HIGH : TUSB_SPEED_FULL;
|
||||
dcd_event_bus_reset(BOARD_DEVICE_RHPORT_NUM, _speed, true);
|
||||
dcd_event_bus_reset(BOARD_TUD_RHPORT, _speed, true);
|
||||
|
||||
#endif /* !__FT930__ */
|
||||
|
||||
#else // BOARD_DEVICE_RHPORT_SPEED == OPT_MODE_FULL_SPEED
|
||||
#else // BOARD_TUD_MAX_SPEED == OPT_MODE_FULL_SPEED
|
||||
|
||||
/* User force set to full speed */
|
||||
_speed = TUSB_SPEED_FULL;
|
||||
@@ -364,10 +364,10 @@ static void _ft90x_usb_speed(void)
|
||||
}
|
||||
#endif
|
||||
USBD_REG(fctrl) = fctrl_val;
|
||||
dcd_event_bus_reset(BOARD_DEVICE_RHPORT_NUM, _speed, true);
|
||||
dcd_event_bus_reset(BOARD_TUD_RHPORT, _speed, true);
|
||||
return;
|
||||
|
||||
#endif // BOARD_DEVICE_RHPORT_SPEED
|
||||
#endif // BOARD_TUD_MAX_SPEED
|
||||
}
|
||||
|
||||
// Send a buffer to the USB IN FIFO.
|
||||
@@ -899,7 +899,7 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr)
|
||||
|
||||
void _ft90x_usbd_ISR(void)
|
||||
{
|
||||
tud_int_handler(BOARD_DEVICE_RHPORT_NUM); // Resolves to dcd_int_handler().
|
||||
tud_int_handler(BOARD_TUD_RHPORT); // Resolves to dcd_int_handler().
|
||||
}
|
||||
|
||||
void dcd_int_handler(uint8_t rhport)
|
||||
@@ -937,19 +937,19 @@ void dcd_int_handler(uint8_t rhport)
|
||||
{
|
||||
// Reset endpoints to default state.
|
||||
_ft90x_reset_edpts();
|
||||
dcd_event_bus_reset(BOARD_DEVICE_RHPORT_NUM, _speed, true);
|
||||
dcd_event_bus_reset(BOARD_TUD_RHPORT, _speed, true);
|
||||
}
|
||||
if (cmif & MASK_USBD_CMIF_SUSIRQ) //Handle Suspend interrupt
|
||||
{
|
||||
dcd_event_bus_signal(BOARD_DEVICE_RHPORT_NUM, DCD_EVENT_SUSPEND, true);
|
||||
dcd_event_bus_signal(BOARD_TUD_RHPORT, DCD_EVENT_SUSPEND, true);
|
||||
}
|
||||
if (cmif & MASK_USBD_CMIF_RESIRQ) //Handle Resume interrupt
|
||||
{
|
||||
dcd_event_bus_signal(BOARD_DEVICE_RHPORT_NUM, DCD_EVENT_RESUME, true);
|
||||
dcd_event_bus_signal(BOARD_TUD_RHPORT, DCD_EVENT_RESUME, true);
|
||||
}
|
||||
if (cmif & MASK_USBD_CMIF_SOFIRQ) //Handle SOF interrupt
|
||||
{
|
||||
dcd_event_bus_signal(BOARD_DEVICE_RHPORT_NUM, DCD_EVENT_SOF, true);
|
||||
dcd_event_bus_signal(BOARD_TUD_RHPORT, DCD_EVENT_SOF, true);
|
||||
}
|
||||
}
|
||||
// Handle endpoint interrupts.
|
||||
@@ -980,7 +980,7 @@ void dcd_int_handler(uint8_t rhport)
|
||||
_ft90x_dusb_out(USBD_EP_0, (uint8_t *)_ft90x_setup_packet, sizeof(USB_device_request));
|
||||
|
||||
// Send the packet to tinyusb.
|
||||
dcd_event_setup_received(BOARD_DEVICE_RHPORT_NUM, _ft90x_setup_packet, true);
|
||||
dcd_event_setup_received(BOARD_TUD_RHPORT, _ft90x_setup_packet, true);
|
||||
|
||||
// Clear the interrupt that signals a SETUP packet is received.
|
||||
USBD_EP_SR_REG(USBD_EP_0) = (MASK_USBD_EP0SR_SETUP);
|
||||
@@ -1002,7 +1002,7 @@ void dcd_int_handler(uint8_t rhport)
|
||||
xfer_bytes = _ft90x_edpt_xfer_out(USBD_EP_0, (uint8_t *)ep_xfer[USBD_EP_0].buff_ptr, xfer_bytes);
|
||||
}
|
||||
// Now signal completion of data packet.
|
||||
dcd_event_xfer_complete(BOARD_DEVICE_RHPORT_NUM, (ep_xfer[USBD_EP_0].dir ? TUSB_DIR_IN_MASK : 0), xfer_bytes, XFER_RESULT_SUCCESS, true);
|
||||
dcd_event_xfer_complete(BOARD_TUD_RHPORT, (ep_xfer[USBD_EP_0].dir ? TUSB_DIR_IN_MASK : 0), xfer_bytes, XFER_RESULT_SUCCESS, true);
|
||||
|
||||
// Allow new transfers on the control endpoint.
|
||||
ep_xfer[USBD_EP_0].valid = 0;
|
||||
@@ -1059,7 +1059,7 @@ void dcd_int_handler(uint8_t rhport)
|
||||
if (ep_xfer[ep_number].remain_size == 0)
|
||||
{
|
||||
// Signal tinyUSB.
|
||||
dcd_event_xfer_complete(BOARD_DEVICE_RHPORT_NUM, ep_number | ep_dirmask, ep_xfer[ep_number].total_size, XFER_RESULT_SUCCESS, true);
|
||||
dcd_event_xfer_complete(BOARD_TUD_RHPORT, ep_number | ep_dirmask, ep_xfer[ep_number].total_size, XFER_RESULT_SUCCESS, true);
|
||||
|
||||
// Allow new transfers on this endpoint.
|
||||
ep_xfer[ep_number].valid = 0;
|
||||
@@ -1084,21 +1084,21 @@ void ft90x_usbd_pm_ISR(void)
|
||||
{
|
||||
// Signal connection interrupt
|
||||
SYS->PMCFG_H = MASK_SYS_PMCFG_PM_GPIO_IRQ_PEND;
|
||||
dcd_event_bus_signal(BOARD_DEVICE_RHPORT_NUM, DCD_EVENT_RESUME, true);
|
||||
dcd_event_bus_signal(BOARD_TUD_RHPORT, DCD_EVENT_RESUME, true);
|
||||
}
|
||||
|
||||
if (pmcfg & MASK_SYS_PMCFG_DEV_DIS_DEV)
|
||||
{
|
||||
// Signal disconnection interrupt
|
||||
SYS->PMCFG_H = MASK_SYS_PMCFG_PM_GPIO_IRQ_PEND;
|
||||
dcd_event_bus_signal(BOARD_DEVICE_RHPORT_NUM, DCD_EVENT_UNPLUGGED, true);
|
||||
dcd_event_bus_signal(BOARD_TUD_RHPORT, DCD_EVENT_UNPLUGGED, true);
|
||||
}
|
||||
|
||||
if (pmcfg & MASK_SYS_PMCFG_HOST_RST_DEV)
|
||||
{
|
||||
// Signal Host Reset interrupt
|
||||
SYS->PMCFG_H = MASK_SYS_PMCFG_PM_GPIO_IRQ_PEND;
|
||||
dcd_event_bus_signal(BOARD_DEVICE_RHPORT_NUM, DCD_EVENT_BUS_RESET, true);
|
||||
dcd_event_bus_signal(BOARD_TUD_RHPORT, DCD_EVENT_BUS_RESET, true);
|
||||
}
|
||||
|
||||
if (pmcfg & MASK_SYS_PMCFG_HOST_RESUME_DEV)
|
||||
@@ -1109,7 +1109,7 @@ void ft90x_usbd_pm_ISR(void)
|
||||
{
|
||||
// If we are driving K-state on Device USB port;
|
||||
// We must maintain the 1ms requirement before resuming the phy
|
||||
dcd_event_bus_signal(BOARD_DEVICE_RHPORT_NUM, DCD_EVENT_RESUME, true);
|
||||
dcd_event_bus_signal(BOARD_TUD_RHPORT, DCD_EVENT_RESUME, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,6 +34,13 @@
|
||||
#include "device/dcd.h"
|
||||
#include "dwc2_type.h"
|
||||
|
||||
// Following symbols must be defined by port header
|
||||
// - _dwc2_controller[]: array of controllers
|
||||
// - DWC2_EP_MAX: largest EP counts of all controllers
|
||||
// - dwc2_phy_init/dwc2_phy_update: phy init called before and after core reset
|
||||
// - dwc2_dcd_int_enable/dwc2_dcd_int_disable
|
||||
// - dwc2_remote_wakeup_delay
|
||||
|
||||
#if defined(TUP_USBIP_DWC2_STM32)
|
||||
#include "dwc2_stm32.h"
|
||||
#elif TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3)
|
||||
@@ -55,7 +62,7 @@
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
// DWC2 registers
|
||||
#define DWC2_REG(_port) ((dwc2_regs_t*) DWC2_REG_BASE)
|
||||
#define DWC2_REG(_port) ((dwc2_regs_t*) _dwc2_controller[_port].reg_base)
|
||||
|
||||
// Debug level for DWC2
|
||||
#define DWC2_DEBUG 2
|
||||
@@ -72,7 +79,6 @@
|
||||
#define dcache_clean_invalidate(_addr, _size)
|
||||
#endif
|
||||
|
||||
|
||||
static TU_ATTR_ALIGNED(4) uint32_t _setup_packet[2];
|
||||
|
||||
typedef struct {
|
||||
@@ -97,34 +103,32 @@ static bool _out_ep_closed; // Flag to check if RX FIFO si
|
||||
static bool _sof_en;
|
||||
|
||||
// Calculate the RX FIFO size according to recommendations from reference manual
|
||||
static inline uint16_t calc_rx_ff_size(uint16_t ep_size)
|
||||
static inline uint16_t calc_grxfsiz(uint16_t max_ep_size, uint8_t ep_count)
|
||||
{
|
||||
return 15 + 2*(ep_size/4) + 2*DWC2_EP_MAX;
|
||||
return 15 + 2*(max_ep_size/4) + 2*ep_count;
|
||||
}
|
||||
|
||||
static void update_grxfsiz(uint8_t rhport)
|
||||
{
|
||||
(void) rhport;
|
||||
|
||||
dwc2_regs_t * dwc2 = DWC2_REG(rhport);
|
||||
dwc2_regs_t * dwc2 = DWC2_REG(rhport);
|
||||
uint8_t const ep_count = _dwc2_controller[rhport].ep_count;
|
||||
|
||||
// Determine largest EP size for RX FIFO
|
||||
uint16_t max_epsize = 0;
|
||||
for (uint8_t epnum = 0; epnum < DWC2_EP_MAX; epnum++)
|
||||
for (uint8_t epnum = 0; epnum < ep_count; epnum++)
|
||||
{
|
||||
max_epsize = tu_max16(max_epsize, xfer_status[epnum][TUSB_DIR_OUT].max_size);
|
||||
}
|
||||
|
||||
// Update size of RX FIFO
|
||||
dwc2->grxfsiz = calc_rx_ff_size(max_epsize);
|
||||
dwc2->grxfsiz = calc_grxfsiz(max_epsize, ep_count);
|
||||
}
|
||||
|
||||
// Setup the control endpoint 0.
|
||||
// Start of Bus Reset
|
||||
static void bus_reset(uint8_t rhport)
|
||||
{
|
||||
(void) rhport;
|
||||
|
||||
dwc2_regs_t * dwc2 = DWC2_REG(rhport);
|
||||
dwc2_regs_t * dwc2 = DWC2_REG(rhport);
|
||||
uint8_t const ep_count = _dwc2_controller[rhport].ep_count;
|
||||
|
||||
tu_memclr(xfer_status, sizeof(xfer_status));
|
||||
_out_ep_closed = false;
|
||||
@@ -135,7 +139,7 @@ static void bus_reset(uint8_t rhport)
|
||||
dwc2->dcfg &= ~DCFG_DAD_Msk;
|
||||
|
||||
// 1. NAK for all OUT endpoints
|
||||
for ( uint8_t n = 0; n < DWC2_EP_MAX; n++ )
|
||||
for ( uint8_t n = 0; n < ep_count; n++ )
|
||||
{
|
||||
dwc2->epout[n].doepctl |= DOEPCTL_SNAK;
|
||||
}
|
||||
@@ -185,22 +189,24 @@ static void bus_reset(uint8_t rhport)
|
||||
// - 2 for each used OUT endpoint
|
||||
//
|
||||
// Therefore GRXFSIZ = 13 + 1 + 1 + 2 x (Largest-EPsize/4) + 2 x EPOUTnum
|
||||
// - FullSpeed (64 Bytes ): GRXFSIZ = 15 + 2 x 16 + 2 x DWC2_EP_MAX = 47 + 2 x DWC2_EP_MAX
|
||||
// - Highspeed (512 bytes): GRXFSIZ = 15 + 2 x 128 + 2 x DWC2_EP_MAX = 271 + 2 x DWC2_EP_MAX
|
||||
// - FullSpeed (64 Bytes ): GRXFSIZ = 15 + 2 x 16 + 2 x ep_count = 47 + 2 x ep_count
|
||||
// - Highspeed (512 bytes): GRXFSIZ = 15 + 2 x 128 + 2 x ep_count = 271 + 2 x ep_count
|
||||
//
|
||||
// NOTE: Largest-EPsize & EPOUTnum is actual used endpoints in configuration. Since DCD has no knowledge
|
||||
// of the overall picture yet. We will use the worst scenario: largest possible + DWC2_EP_MAX
|
||||
// of the overall picture yet. We will use the worst scenario: largest possible + ep_count
|
||||
//
|
||||
// For Isochronous, largest EP size can be 1023/1024 for FS/HS respectively. In addition if multiple ISO
|
||||
// are enabled at least "2 x (Largest-EPsize/4) + 1" are recommended. Maybe provide a macro for application to
|
||||
// overwrite this.
|
||||
|
||||
dwc2->grxfsiz = calc_rx_ff_size(TUD_OPT_HIGH_SPEED ? 512 : 64);
|
||||
// EP0 out max is 64
|
||||
dwc2->grxfsiz = calc_grxfsiz(64, ep_count);
|
||||
|
||||
// Setup the control endpoint 0
|
||||
_allocated_fifo_words_tx = 16;
|
||||
|
||||
// Control IN uses FIFO 0 with 64 bytes ( 16 32-bit word )
|
||||
dwc2->dieptxf0 = (16 << DIEPTXF0_TX0FD_Pos) | (DWC2_EP_FIFO_SIZE/4 - _allocated_fifo_words_tx);
|
||||
dwc2->dieptxf0 = (16 << DIEPTXF0_TX0FD_Pos) | (_dwc2_controller[rhport].ep_fifo_size/4 - _allocated_fifo_words_tx);
|
||||
|
||||
// Fixed control EP0 size to 64 bytes
|
||||
dwc2->epin[0].diepctl &= ~(0x03 << DIEPCTL_MPSIZ_Pos);
|
||||
@@ -363,7 +369,11 @@ static void reset_core(dwc2_regs_t * dwc2)
|
||||
static bool phy_hs_supported(dwc2_regs_t * dwc2)
|
||||
{
|
||||
// note: esp32 incorrect report its hs_phy_type as utmi
|
||||
#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3)
|
||||
return false;
|
||||
#else
|
||||
return TUD_OPT_HIGH_SPEED && dwc2->ghwcfg2_bm.hs_phy_type != HS_PHY_TYPE_NONE;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void phy_fs_init(dwc2_regs_t * dwc2)
|
||||
@@ -462,6 +472,7 @@ static bool check_dwc2(dwc2_regs_t * dwc2)
|
||||
#endif
|
||||
|
||||
// For some reasons: GD32VF103 snpsid and all hwcfg register are always zero (skip it)
|
||||
(void) dwc2;
|
||||
#if !TU_CHECK_MCU(OPT_MCU_GD32VF103)
|
||||
uint32_t const gsnpsid = dwc2->gsnpsid & GSNPSID_ID_MASK;
|
||||
TU_ASSERT(gsnpsid == DWC2_OTG_ID || gsnpsid == DWC2_FS_IOT_ID || gsnpsid == DWC2_HS_IOT_ID);
|
||||
@@ -620,12 +631,13 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt)
|
||||
{
|
||||
(void) rhport;
|
||||
|
||||
dwc2_regs_t * dwc2 = DWC2_REG(rhport);
|
||||
dwc2_regs_t * dwc2 = DWC2_REG(rhport);
|
||||
uint8_t const ep_count = _dwc2_controller[rhport].ep_count;
|
||||
|
||||
uint8_t const epnum = tu_edpt_number(desc_edpt->bEndpointAddress);
|
||||
uint8_t const dir = tu_edpt_dir(desc_edpt->bEndpointAddress);
|
||||
|
||||
TU_ASSERT(epnum < DWC2_EP_MAX);
|
||||
TU_ASSERT(epnum < ep_count);
|
||||
|
||||
xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir);
|
||||
xfer->max_size = tu_edpt_packet_size(desc_edpt);
|
||||
@@ -636,12 +648,12 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt)
|
||||
if(dir == TUSB_DIR_OUT)
|
||||
{
|
||||
// Calculate required size of RX FIFO
|
||||
uint16_t const sz = calc_rx_ff_size(4*fifo_size);
|
||||
uint16_t const sz = calc_grxfsiz(4*fifo_size, ep_count);
|
||||
|
||||
// If size_rx needs to be extended check if possible and if so enlarge it
|
||||
if (dwc2->grxfsiz < sz)
|
||||
{
|
||||
TU_ASSERT(sz + _allocated_fifo_words_tx <= DWC2_EP_FIFO_SIZE/4);
|
||||
TU_ASSERT(sz + _allocated_fifo_words_tx <= _dwc2_controller[rhport].ep_fifo_size/4);
|
||||
|
||||
// Enlarge RX FIFO
|
||||
dwc2->grxfsiz = sz;
|
||||
@@ -678,15 +690,15 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt)
|
||||
// - IN EP 1 gets FIFO 1, IN EP "n" gets FIFO "n".
|
||||
|
||||
// Check if free space is available
|
||||
TU_ASSERT(_allocated_fifo_words_tx + fifo_size + dwc2->grxfsiz <= DWC2_EP_FIFO_SIZE/4);
|
||||
TU_ASSERT(_allocated_fifo_words_tx + fifo_size + dwc2->grxfsiz <= _dwc2_controller[rhport].ep_fifo_size/4);
|
||||
|
||||
_allocated_fifo_words_tx += fifo_size;
|
||||
|
||||
TU_LOG(DWC2_DEBUG, " Allocated %u bytes at offset %u", fifo_size*4, DWC2_EP_FIFO_SIZE-_allocated_fifo_words_tx*4);
|
||||
TU_LOG(DWC2_DEBUG, " Allocated %u bytes at offset %lu", fifo_size*4, _dwc2_controller[rhport].ep_fifo_size-_allocated_fifo_words_tx*4);
|
||||
|
||||
// DIEPTXF starts at FIFO #1.
|
||||
// Both TXFD and TXSA are in unit of 32-bit words.
|
||||
dwc2->dieptxf[epnum - 1] = (fifo_size << DIEPTXF_INEPTXFD_Pos) | (DWC2_EP_FIFO_SIZE/4 - _allocated_fifo_words_tx);
|
||||
dwc2->dieptxf[epnum - 1] = (fifo_size << DIEPTXF_INEPTXFD_Pos) | (_dwc2_controller[rhport].ep_fifo_size/4 - _allocated_fifo_words_tx);
|
||||
|
||||
dwc2->epin[epnum].diepctl |= (1 << DIEPCTL_USBAEP_Pos) |
|
||||
(epnum << DIEPCTL_TXFNUM_Pos) |
|
||||
@@ -703,14 +715,13 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt)
|
||||
// Close all non-control endpoints, cancel all pending transfers if any.
|
||||
void dcd_edpt_close_all (uint8_t rhport)
|
||||
{
|
||||
(void) rhport;
|
||||
|
||||
dwc2_regs_t * dwc2 = DWC2_REG(rhport);
|
||||
dwc2_regs_t * dwc2 = DWC2_REG(rhport);
|
||||
uint8_t const ep_count = _dwc2_controller[rhport].ep_count;
|
||||
|
||||
// Disable non-control interrupt
|
||||
dwc2->daintmsk = (1 << DAINTMSK_OEPM_Pos) | (1 << DAINTMSK_IEPM_Pos);
|
||||
|
||||
for(uint8_t n = 1; n < DWC2_EP_MAX; n++)
|
||||
for(uint8_t n = 1; n < ep_count; n++)
|
||||
{
|
||||
// disable OUT endpoint
|
||||
dwc2->epout[n].doepctl = 0;
|
||||
@@ -871,8 +882,9 @@ void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr)
|
||||
{
|
||||
uint16_t const fifo_size = (dwc2->dieptxf[epnum - 1] & DIEPTXF_INEPTXFD_Msk) >> DIEPTXF_INEPTXFD_Pos;
|
||||
uint16_t const fifo_start = (dwc2->dieptxf[epnum - 1] & DIEPTXF_INEPTXSA_Msk) >> DIEPTXF_INEPTXSA_Pos;
|
||||
|
||||
// For now only the last opened endpoint can be closed without fuss.
|
||||
TU_ASSERT(fifo_start == DWC2_EP_FIFO_SIZE/4 - _allocated_fifo_words_tx,);
|
||||
TU_ASSERT(fifo_start == _dwc2_controller[rhport].ep_fifo_size/4 - _allocated_fifo_words_tx,);
|
||||
_allocated_fifo_words_tx -= fifo_size;
|
||||
}
|
||||
else
|
||||
@@ -1075,11 +1087,12 @@ static void handle_rxflvl_irq(uint8_t rhport)
|
||||
|
||||
static void handle_epout_irq (uint8_t rhport)
|
||||
{
|
||||
dwc2_regs_t *dwc2 = DWC2_REG(rhport);
|
||||
dwc2_regs_t * dwc2 = DWC2_REG(rhport);
|
||||
uint8_t const ep_count = _dwc2_controller[rhport].ep_count;
|
||||
|
||||
// DAINT for a given EP clears when DOEPINTx is cleared.
|
||||
// OEPINT will be cleared when DAINT's out bits are cleared.
|
||||
for ( uint8_t n = 0; n < DWC2_EP_MAX; n++ )
|
||||
for ( uint8_t n = 0; n < ep_count; n++ )
|
||||
{
|
||||
if ( dwc2->daint & TU_BIT(DAINT_OEPINT_Pos + n) )
|
||||
{
|
||||
@@ -1126,12 +1139,13 @@ static void handle_epout_irq (uint8_t rhport)
|
||||
|
||||
static void handle_epin_irq (uint8_t rhport)
|
||||
{
|
||||
dwc2_regs_t *dwc2 = DWC2_REG(rhport);
|
||||
dwc2_epin_t* epin = dwc2->epin;
|
||||
dwc2_regs_t * dwc2 = DWC2_REG(rhport);
|
||||
uint8_t const ep_count = _dwc2_controller[rhport].ep_count;
|
||||
dwc2_epin_t* epin = dwc2->epin;
|
||||
|
||||
// DAINT for a given EP clears when DIEPINTx is cleared.
|
||||
// IEPINT will be cleared when DAINT's out bits are cleared.
|
||||
for ( uint8_t n = 0; n < DWC2_EP_MAX; n++ )
|
||||
for ( uint8_t n = 0; n < ep_count; n++ )
|
||||
{
|
||||
if ( dwc2->daint & TU_BIT(DAINT_IEPINT_Pos + n) )
|
||||
{
|
||||
|
||||
@@ -35,9 +35,12 @@
|
||||
#include "broadcom/interrupts.h"
|
||||
#include "broadcom/caches.h"
|
||||
|
||||
#define DWC2_REG_BASE USB_OTG_GLOBAL_BASE
|
||||
#define DWC2_EP_MAX 8
|
||||
#define DWC2_EP_FIFO_SIZE 4096
|
||||
|
||||
static const dwc2_controller_t _dwc2_controller[] =
|
||||
{
|
||||
{ .reg_base = USB_OTG_GLOBAL_BASE, .irqnum = USB_IRQn, .ep_count = DWC2_EP_MAX, .ep_fifo_size = 4096 }
|
||||
};
|
||||
|
||||
#define dcache_clean(_addr, _size) data_clean(_addr, _size)
|
||||
#define dcache_invalidate(_addr, _size) data_invalidate(_addr, _size)
|
||||
@@ -46,15 +49,13 @@
|
||||
TU_ATTR_ALWAYS_INLINE
|
||||
static inline void dwc2_dcd_int_enable(uint8_t rhport)
|
||||
{
|
||||
(void) rhport;
|
||||
BP_EnableIRQ(USB_IRQn);
|
||||
BP_EnableIRQ(_dwc2_controller[rhport].irqnum);
|
||||
}
|
||||
|
||||
TU_ATTR_ALWAYS_INLINE
|
||||
static inline void dwc2_dcd_int_disable (uint8_t rhport)
|
||||
{
|
||||
(void) rhport;
|
||||
BP_DisableIRQ(USB_IRQn);
|
||||
BP_DisableIRQ(_dwc2_controller[rhport].irqnum);
|
||||
}
|
||||
|
||||
static inline void dwc2_remote_wakeup_delay(void)
|
||||
|
||||
@@ -37,20 +37,22 @@
|
||||
// EFM32 has custom control register before DWC registers
|
||||
#define DWC2_REG_BASE (USB_BASE + offsetof(USB_TypeDef, GOTGCTL))
|
||||
#define DWC2_EP_MAX 7
|
||||
#define DWC2_EP_FIFO_SIZE 2048
|
||||
|
||||
static const dwc2_controller_t _dwc2_controller[] =
|
||||
{
|
||||
{ .reg_base = DWC2_REG_BASE, .irqnum = USB_IRQn, .ep_count = DWC2_EP_MAX, .ep_fifo_size = 2048 }
|
||||
};
|
||||
|
||||
TU_ATTR_ALWAYS_INLINE
|
||||
static inline void dwc2_dcd_int_enable(uint8_t rhport)
|
||||
{
|
||||
(void) rhport;
|
||||
NVIC_EnableIRQ(USB_IRQn);
|
||||
NVIC_EnableIRQ(_dwc2_controller[rhport].irqnum);
|
||||
}
|
||||
|
||||
TU_ATTR_ALWAYS_INLINE
|
||||
static inline void dwc2_dcd_int_disable (uint8_t rhport)
|
||||
{
|
||||
(void) rhport;
|
||||
NVIC_DisableIRQ(USB_IRQn);
|
||||
NVIC_DisableIRQ(_dwc2_controller[rhport].irqnum);
|
||||
}
|
||||
|
||||
static inline void dwc2_remote_wakeup_delay(void)
|
||||
|
||||
@@ -37,10 +37,12 @@
|
||||
//#include "soc/usb_periph.h"
|
||||
|
||||
#define DWC2_REG_BASE 0x60080000UL
|
||||
#define DWC2_EP_MAX 5 // USB_OUT_EP_NUM
|
||||
#define DWC2_EP_FIFO_SIZE 1024
|
||||
#define DWC2_EP_MAX 6 // USB_OUT_EP_NUM. TODO ESP32Sx only has 5 tx fifo (5 endpoint IN)
|
||||
|
||||
// #define EP_FIFO_NUM 5
|
||||
static const dwc2_controller_t _dwc2_controller[] =
|
||||
{
|
||||
{ .reg_base = DWC2_REG_BASE, .irqnum = 0, .ep_count = DWC2_EP_MAX, .ep_fifo_size = 1024 }
|
||||
};
|
||||
|
||||
static intr_handle_t usb_ih;
|
||||
|
||||
|
||||
@@ -34,8 +34,11 @@
|
||||
|
||||
#define DWC2_REG_BASE 0x50000000UL
|
||||
#define DWC2_EP_MAX 4
|
||||
#define DWC2_EP_FIFO_SIZE 1280
|
||||
#define RHPORT_IRQn 86
|
||||
|
||||
static const dwc2_controller_t _dwc2_controller[] =
|
||||
{
|
||||
{ .reg_base = DWC2_REG_BASE, .irqnum = 86, .ep_count = DWC2_EP_MAX, .ep_fifo_size = 1280 }
|
||||
};
|
||||
|
||||
extern uint32_t SystemCoreClock;
|
||||
|
||||
@@ -57,15 +60,13 @@ static inline void __eclic_disable_interrupt (uint32_t irq){
|
||||
TU_ATTR_ALWAYS_INLINE
|
||||
static inline void dwc2_dcd_int_enable(uint8_t rhport)
|
||||
{
|
||||
(void) rhport;
|
||||
__eclic_enable_interrupt(RHPORT_IRQn);
|
||||
__eclic_enable_interrupt(_dwc2_controller[rhport].irqnum);
|
||||
}
|
||||
|
||||
TU_ATTR_ALWAYS_INLINE
|
||||
static inline void dwc2_dcd_int_disable (uint8_t rhport)
|
||||
{
|
||||
(void) rhport;
|
||||
__eclic_disable_interrupt(RHPORT_IRQn);
|
||||
__eclic_disable_interrupt(_dwc2_controller[rhport].irqnum);
|
||||
}
|
||||
|
||||
static inline void dwc2_remote_wakeup_delay(void)
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
#include "stm32f4xx.h"
|
||||
#define EP_MAX_FS USB_OTG_FS_MAX_IN_ENDPOINTS
|
||||
#define EP_FIFO_SIZE_FS USB_OTG_FS_TOTAL_FIFO_SIZE
|
||||
|
||||
#define EP_MAX_HS USB_OTG_HS_MAX_IN_ENDPOINTS
|
||||
#define EP_FIFO_SIZE_HS USB_OTG_HS_TOTAL_FIFO_SIZE
|
||||
|
||||
@@ -54,19 +55,18 @@
|
||||
#include "stm32h7xx.h"
|
||||
#define EP_MAX_FS 9
|
||||
#define EP_FIFO_SIZE_FS 4096
|
||||
|
||||
#define EP_MAX_HS 9
|
||||
#define EP_FIFO_SIZE_HS 4096
|
||||
#if (! defined USB2_OTG_FS)
|
||||
// H7 with only 1 USB port: H72x / H73x / H7Ax / H7Bx
|
||||
// USB_OTG_FS_PERIPH_BASE and OTG_FS_IRQn not defined
|
||||
#define USB_OTG_FS_PERIPH_BASE USB1_OTG_HS_PERIPH_BASE
|
||||
#define OTG_FS_IRQn OTG_HS_IRQn
|
||||
#endif
|
||||
|
||||
// NOTE: H7 with only 1 USB port: H72x / H73x / H7Ax / H7Bx
|
||||
// USB_OTG_FS_PERIPH_BASE and OTG_FS_IRQn not defined
|
||||
|
||||
#elif CFG_TUSB_MCU == OPT_MCU_STM32F7
|
||||
#include "stm32f7xx.h"
|
||||
#define EP_MAX_FS 6
|
||||
#define EP_FIFO_SIZE_FS 1280
|
||||
|
||||
#define EP_MAX_HS 9
|
||||
#define EP_FIFO_SIZE_HS 4096
|
||||
|
||||
@@ -79,35 +79,42 @@
|
||||
#error "Unsupported MCUs"
|
||||
#endif
|
||||
|
||||
// On STM32 we associate Port0 to OTG_FS, and Port1 to OTG_HS
|
||||
#if TUD_OPT_RHPORT == 0
|
||||
#define DWC2_REG_BASE USB_OTG_FS_PERIPH_BASE
|
||||
#define DWC2_EP_MAX EP_MAX_FS
|
||||
#define DWC2_EP_FIFO_SIZE EP_FIFO_SIZE_FS
|
||||
#define RHPORT_IRQn OTG_FS_IRQn
|
||||
|
||||
// OTG HS always has higher number of endpoints than FS
|
||||
#ifdef USB_OTG_HS_PERIPH_BASE
|
||||
#define DWC2_EP_MAX EP_MAX_HS
|
||||
#else
|
||||
#define DWC2_REG_BASE USB_OTG_HS_PERIPH_BASE
|
||||
#define DWC2_EP_MAX EP_MAX_HS
|
||||
#define DWC2_EP_FIFO_SIZE EP_FIFO_SIZE_HS
|
||||
#define RHPORT_IRQn OTG_HS_IRQn
|
||||
|
||||
#define DWC2_EP_MAX EP_MAX_FS
|
||||
#endif
|
||||
|
||||
// On STM32 for consistency we associate
|
||||
// - Port0 to OTG_FS, and Port1 to OTG_HS
|
||||
static const dwc2_controller_t _dwc2_controller[] =
|
||||
{
|
||||
#ifdef USB_OTG_FS_PERIPH_BASE
|
||||
{ .reg_base = USB_OTG_FS_PERIPH_BASE, .irqnum = OTG_FS_IRQn, .ep_count = EP_MAX_FS, .ep_fifo_size = EP_FIFO_SIZE_FS },
|
||||
#endif
|
||||
|
||||
#ifdef USB_OTG_HS_PERIPH_BASE
|
||||
{ .reg_base = USB_OTG_HS_PERIPH_BASE, .irqnum = OTG_HS_IRQn, .ep_count = EP_MAX_HS, .ep_fifo_size = EP_FIFO_SIZE_HS },
|
||||
#endif
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
//
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
extern uint32_t SystemCoreClock;
|
||||
|
||||
TU_ATTR_ALWAYS_INLINE
|
||||
static inline void dwc2_dcd_int_enable(uint8_t rhport)
|
||||
{
|
||||
(void) rhport;
|
||||
NVIC_EnableIRQ(RHPORT_IRQn);
|
||||
NVIC_EnableIRQ(_dwc2_controller[rhport].irqnum);
|
||||
}
|
||||
|
||||
TU_ATTR_ALWAYS_INLINE
|
||||
static inline void dwc2_dcd_int_disable (uint8_t rhport)
|
||||
{
|
||||
(void) rhport;
|
||||
NVIC_DisableIRQ(RHPORT_IRQn);
|
||||
NVIC_DisableIRQ(_dwc2_controller[rhport].irqnum);
|
||||
}
|
||||
|
||||
TU_ATTR_ALWAYS_INLINE
|
||||
|
||||
@@ -19,6 +19,19 @@
|
||||
|
||||
#include "stdint.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Controller
|
||||
typedef struct
|
||||
{
|
||||
uintptr_t reg_base;
|
||||
uint32_t irqnum;
|
||||
uint8_t ep_count;
|
||||
uint32_t ep_fifo_size;
|
||||
}dwc2_controller_t;
|
||||
|
||||
/* DWC OTG HW Release versions */
|
||||
#define DWC2_CORE_REV_2_71a 0x4f54271a
|
||||
#define DWC2_CORE_REV_2_72a 0x4f54272a
|
||||
@@ -40,10 +53,6 @@
|
||||
#define DWC2_FS_IOT_ID 0x55310000
|
||||
#define DWC2_HS_IOT_ID 0x55320000
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
// HS PHY
|
||||
typedef struct
|
||||
|
||||
@@ -34,23 +34,24 @@
|
||||
|
||||
#include "xmc_device.h"
|
||||
|
||||
// XMC has custom control register before DWC registers
|
||||
#define DWC2_REG_BASE USB0_BASE
|
||||
#define DWC2_EP_MAX 7
|
||||
#define DWC2_EP_FIFO_SIZE 2048
|
||||
|
||||
static const dwc2_controller_t _dwc2_controller[] =
|
||||
{
|
||||
// Note: XMC has some custom control registers before DWC registers
|
||||
{ .reg_base = USB0_BASE, .irqnum = USB0_0_IRQn, .ep_count = DWC2_EP_MAX, .ep_fifo_size = 2048 }
|
||||
};
|
||||
|
||||
TU_ATTR_ALWAYS_INLINE
|
||||
static inline void dwc2_dcd_int_enable(uint8_t rhport)
|
||||
{
|
||||
(void) rhport;
|
||||
NVIC_EnableIRQ(USB0_0_IRQn);
|
||||
NVIC_EnableIRQ(_dwc2_controller[rhport].irqnum);
|
||||
}
|
||||
|
||||
TU_ATTR_ALWAYS_INLINE
|
||||
static inline void dwc2_dcd_int_disable (uint8_t rhport)
|
||||
{
|
||||
(void) rhport;
|
||||
NVIC_DisableIRQ(USB0_0_IRQn);
|
||||
NVIC_DisableIRQ(_dwc2_controller[rhport].irqnum);
|
||||
}
|
||||
|
||||
static inline void dwc2_remote_wakeup_delay(void)
|
||||
|
||||
Reference in New Issue
Block a user