Merge branch 'master' into port-ft90x

This commit is contained in:
Ha Thach
2022-01-17 12:36:39 +07:00
committed by GitHub
140 changed files with 4180 additions and 230 deletions

View File

@@ -0,0 +1,737 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2022 Jerzy Kasenberg
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* This file is part of the TinyUSB stack.
*/
#include "tusb_option.h"
#if TUSB_OPT_DEVICE_ENABLED && CFG_TUSB_MCU == OPT_MCU_PIC32MZ
#include <common/tusb_common.h>
#include <device/dcd.h>
#include <xc.h>
#include "usbhs_registers.h"
#define USB_REGS ((usbhs_registers_t *) (_USB_BASE_ADDRESS))
// Maximum number of endpoints, could be trimmed down in tusb_config to reduce RAM usage.
#ifndef EP_MAX
#define EP_MAX 8
#endif
typedef enum {
EP0_STAGE_NONE,
EP0_STAGE_SETUP_IN_DATA,
EP0_STAGE_SETUP_OUT_NO_DATA,
EP0_STAGE_SETUP_OUT_DATA,
EP0_STAGE_DATA_IN,
EP0_STAGE_DATA_IN_LAST_PACKET_FILLED,
EP0_STAGE_DATA_IN_SENT,
EP0_STAGE_DATA_OUT,
EP0_STAGE_DATA_OUT_COMPLETE,
EP0_STAGE_STATUS_IN,
EP0_STAGE_ADDRESS_CHANGE,
} ep0_stage_t;
typedef struct {
uint8_t * buffer;
// Total length of current transfer
uint16_t total_len;
// Bytes transferred so far
uint16_t transferred;
uint16_t max_packet_size;
uint16_t fifo_size;
// Packet size sent or received so far. It is used to modify transferred field
// after ACK is received or when filling ISO endpoint with size larger then
// FIFO size.
uint16_t last_packet_size;
uint8_t ep_addr;
} xfer_ctl_t;
static struct
{
// Current FIFO RAM address used for FIFO allocation
uint16_t fifo_addr_top;
// EP0 transfer stage
ep0_stage_t ep0_stage;
// Device address
uint8_t dev_addr;
xfer_ctl_t xfer_status[EP_MAX][2];
} _dcd;
// Two endpoint 0 descriptor definition for unified dcd_edpt_open()
static tusb_desc_endpoint_t const ep0OUT_desc =
{
.bLength = sizeof(tusb_desc_endpoint_t),
.bDescriptorType = TUSB_DESC_ENDPOINT,
.bEndpointAddress = 0x00,
.bmAttributes = { .xfer = TUSB_XFER_CONTROL },
.wMaxPacketSize = CFG_TUD_ENDPOINT0_SIZE,
.bInterval = 0
};
static tusb_desc_endpoint_t const ep0IN_desc =
{
.bLength = sizeof(tusb_desc_endpoint_t),
.bDescriptorType = TUSB_DESC_ENDPOINT,
.bEndpointAddress = 0x80,
.bmAttributes = { .xfer = TUSB_XFER_CONTROL },
.wMaxPacketSize = CFG_TUD_ENDPOINT0_SIZE,
.bInterval = 0
};
#define XFER_CTL_BASE(_ep, _dir) &_dcd.xfer_status[_ep][_dir]
static void ep0_set_stage(ep0_stage_t stage)
{
_dcd.ep0_stage = stage;
}
static ep0_stage_t ep0_get_stage(void)
{
return _dcd.ep0_stage;
}
/*------------------------------------------------------------------*/
/* Controller API
*------------------------------------------------------------------*/
void dcd_init(uint8_t rhport)
{
// Disable endpoint interrupts for now
USB_REGS->INTRRXEbits.w = 0;
USB_REGS->INTRTXEbits.w = 0;
// Enable Reset/Suspend/Resume interrupts only
USB_REGS->INTRUSBEbits.w = 7;
dcd_connect(rhport);
}
void dcd_int_enable(uint8_t rhport)
{
(void) rhport;
USBCRCONbits.USBIE = 1;
}
void dcd_int_disable(uint8_t rhport)
{
(void) rhport;
USBCRCONbits.USBIE = 0;
}
void dcd_set_address(uint8_t rhport, uint8_t dev_addr)
{
(void) rhport;
ep0_set_stage(EP0_STAGE_ADDRESS_CHANGE);
// Store address it will be used later after status stage is done
_dcd.dev_addr = dev_addr;
// Confirm packet now, address will be set when status stage is detected
USB_REGS->EPCSR[0].CSR0L_DEVICEbits.w = (USBHS_EP0_DEVICE_SERVICED_RXPKTRDY | USBHS_EP0_DEVICE_DATAEND);
}
void dcd_remote_wakeup(uint8_t rhport)
{
(void) rhport;
USB_REGS->POWERbits.RESUME = 1;
#if CFG_TUSB_OS != OPT_OS_NONE
osal_task_delay(10);
#endif
USB_REGS->POWERbits.RESUME = 0;
}
void dcd_connect(uint8_t rhport)
{
(void) rhport;
USB_REGS->POWERbits.HSEN = TUD_OPT_HIGH_SPEED ? 1 : 0;
USB_REGS->POWERbits.SOFTCONN = 1;
}
void dcd_disconnect(uint8_t rhport)
{
(void) rhport;
USB_REGS->POWERbits.SOFTCONN = 1;
}
TU_ATTR_ALWAYS_INLINE static inline bool is_in_isr(void)
{
return (_CP0_GET_STATUS() & (_CP0_STATUS_EXL_MASK | _CP0_STATUS_IPL_MASK)) != 0;
}
static void epn_rx_configure(uint8_t endpoint, uint16_t endpointSize,
uint16_t fifoAddress, uint8_t fifoSize,
uint32_t transferType)
{
uint8_t old_index = USB_REGS->INDEXbits.ENDPOINT;
// Select endpoint register set (same register address is used for all endpoints.
USB_REGS->INDEXbits.ENDPOINT = endpoint;
// Configure the Endpoint size
USB_REGS->INDEXED_EPCSR.RXMAXPbits.RXMAXP = endpointSize;
// Set up the fifo address.
USB_REGS->RXFIFOADDbits.RXFIFOAD = fifoAddress;
// Resets the endpoint data toggle to 0
USB_REGS->INDEXED_EPCSR.RXCSRL_DEVICEbits.CLRDT = 1;
// Set up the FIFO size
USB_REGS->RXFIFOSZbits.RXFIFOSZ = fifoSize;
USB_REGS->INDEXED_EPCSR.RXCSRH_DEVICEbits.ISO = transferType == 1 ? 1 : 0;
// Disable NYET Handshakes for interrupt endpoints
USB_REGS->INDEXED_EPCSR.RXCSRH_DEVICEbits.DISNYET = transferType == 3 ? 1 : 0;
// Restore the index register.
USB_REGS->INDEXbits.ENDPOINT = old_index;
// Enable the endpoint interrupt.
USB_REGS->INTRRXEbits.w |= (1 << endpoint);
}
static void epn_tx_configure(uint8_t endpoint, uint16_t endpointSize,
uint16_t fifoAddress, uint8_t fifoSize,
uint32_t transferType)
{
uint8_t old_index = USB_REGS->INDEXbits.ENDPOINT;
// Select endpoint register set (same register address is used for all endpoints.
USB_REGS->INDEXbits.ENDPOINT = endpoint;
// Configure the Endpoint size
USB_REGS->INDEXED_EPCSR.TXMAXPbits.TXMAXP = endpointSize;
// Set up the fifo address
USB_REGS->TXFIFOADDbits.TXFIFOAD = fifoAddress;
// Resets the endpoint data toggle to 0
USB_REGS->INDEXED_EPCSR.TXCSRL_DEVICEbits.CLRDT = 1;
// Set up the FIFO size
USB_REGS->TXFIFOSZbits.TXFIFOSZ = fifoSize;
USB_REGS->INDEXED_EPCSR.TXCSRH_DEVICEbits.ISO = 1 == transferType ? 1 : 0;
// Restore the index register
USB_REGS->INDEXbits.ENDPOINT = old_index;
// Enable the interrupt
USB_REGS->INTRTXEbits.w |= (1 << endpoint);
}
static void tx_fifo_write(uint8_t endpoint, uint8_t const * buffer, size_t count)
{
size_t i;
volatile uint8_t * fifo_reg;
fifo_reg = (volatile uint8_t *) (&USB_REGS->FIFO[endpoint]);
for (i = 0; i < count; i++)
{
*fifo_reg = buffer[i];
}
}
static int rx_fifo_read(uint8_t epnum, uint8_t * buffer)
{
uint32_t i;
uint32_t count;
volatile uint8_t * fifo_reg;
fifo_reg = (volatile uint8_t *) (&USB_REGS->FIFO[epnum]);
count = USB_REGS->EPCSR[epnum].RXCOUNTbits.RXCNT;
for (i = 0; i < count; i++)
{
buffer[i] = fifo_reg[i & 3];
}
return count;
}
static void xfer_complete(xfer_ctl_t * xfer, uint8_t result, bool in_isr)
{
dcd_event_xfer_complete(0, xfer->ep_addr, xfer->transferred, result, in_isr);
}
static void ep0_fill_tx(xfer_ctl_t * xfer_in)
{
uint16_t left = xfer_in->total_len - xfer_in->transferred;
if (left)
{
xfer_in->last_packet_size = tu_min16(xfer_in->max_packet_size, left);
tx_fifo_write(0, xfer_in->buffer + xfer_in->transferred, xfer_in->last_packet_size);
xfer_in->transferred += xfer_in->last_packet_size;
left = xfer_in->total_len - xfer_in->transferred;
}
if (xfer_in->last_packet_size < xfer_in->max_packet_size || left == 0)
{
switch (ep0_get_stage())
{
case EP0_STAGE_SETUP_IN_DATA:
case EP0_STAGE_DATA_IN:
case EP0_STAGE_DATA_IN_SENT:
ep0_set_stage(EP0_STAGE_DATA_IN_LAST_PACKET_FILLED);
USB_REGS->EPCSR[0].CSR0L_DEVICEbits.TXPKTRDY = 1;
break;
case EP0_STAGE_SETUP_OUT_NO_DATA:
ep0_set_stage(EP0_STAGE_STATUS_IN);
USB_REGS->EPCSR[0].CSR0L_DEVICEbits.w = (USBHS_EP0_DEVICE_SERVICED_RXPKTRDY | USBHS_EP0_DEVICE_DATAEND);
break;
case EP0_STAGE_DATA_OUT_COMPLETE:
ep0_set_stage(EP0_STAGE_STATUS_IN);
USB_REGS->EPCSR[0].CSR0L_DEVICEbits.w = (USBHS_EP0_DEVICE_SERVICED_RXPKTRDY | USBHS_EP0_DEVICE_DATAEND);
break;
default:
break;
}
}
else
{
switch (ep0_get_stage())
{
case EP0_STAGE_SETUP_IN_DATA:
ep0_set_stage(EP0_STAGE_DATA_IN);
// fall through
case EP0_STAGE_DATA_IN:
USB_REGS->EPCSR[0].CSR0L_DEVICEbits.TXPKTRDY = 1;
break;
default:
break;
}
}
}
static void epn_fill_tx(xfer_ctl_t * xfer_in, uint8_t epnum)
{
uint16_t left = xfer_in->total_len - xfer_in->transferred;
if (left)
{
xfer_in->last_packet_size = tu_min16(xfer_in->max_packet_size, left);
tx_fifo_write(epnum, xfer_in->buffer + xfer_in->transferred, xfer_in->last_packet_size);
}
USB_REGS->EPCSR[epnum].TXCSRL_DEVICEbits.TXPKTRDY = 1;
}
static bool ep0_xfer(xfer_ctl_t * xfer, int dir)
{
if (dir == TUSB_DIR_OUT)
{
if (xfer->total_len)
{
switch (_dcd.ep0_stage)
{
case EP0_STAGE_DATA_OUT_COMPLETE:
case EP0_STAGE_SETUP_OUT_DATA:
ep0_set_stage(EP0_STAGE_DATA_OUT);
USB_REGS->EPCSR[0].CSR0L_DEVICEbits.SVCRPR = 1;
break;
default:
TU_ASSERT(0);
}
}
else
{
switch (_dcd.ep0_stage)
{
case EP0_STAGE_DATA_IN_SENT:
ep0_set_stage(EP0_STAGE_NONE);
// fall through
case EP0_STAGE_NONE:
xfer_complete(xfer, XFER_RESULT_SUCCESS, true);
break;
default:
break;
}
}
}
else // IN
{
ep0_fill_tx(xfer);
}
return true;
}
/*------------------------------------------------------------------*/
/* DCD Endpoint port
*------------------------------------------------------------------*/
bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt)
{
(void) rhport;
uint8_t const epnum = tu_edpt_number(desc_edpt->bEndpointAddress);
uint8_t const dir = tu_edpt_dir(desc_edpt->bEndpointAddress);
xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir);
TU_ASSERT(epnum < EP_MAX);
xfer->max_packet_size = tu_edpt_packet_size(desc_edpt);
xfer->fifo_size = xfer->max_packet_size;
xfer->ep_addr = desc_edpt->bEndpointAddress;
if (epnum != 0)
{
if (dir == TUSB_DIR_OUT)
{
epn_rx_configure(epnum, xfer->max_packet_size, _dcd.fifo_addr_top, __builtin_ctz(xfer->fifo_size) - 3, desc_edpt->bmAttributes.xfer);
_dcd.fifo_addr_top += (xfer->fifo_size + 7) >> 3;
}
else
{
epn_tx_configure(epnum, xfer->max_packet_size, _dcd.fifo_addr_top, __builtin_ctz(xfer->fifo_size) - 3, desc_edpt->bmAttributes.xfer);
_dcd.fifo_addr_top += (xfer->fifo_size + 7) >> 3;
}
}
return true;
}
void dcd_edpt_close_all (uint8_t rhport)
{
(void) rhport;
// Reserve EP0 FIFO address
_dcd.fifo_addr_top = 64 >> 3;
for (int i = 1; i < EP_MAX; ++i)
{
tu_memclr(&_dcd.xfer_status[i], sizeof(_dcd.xfer_status[i]));
}
}
void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr)
{
(void) rhport;
(void) ep_addr;
}
bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes)
{
uint8_t const epnum = tu_edpt_number(ep_addr);
uint8_t const dir = tu_edpt_dir(ep_addr);
xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir);
(void) rhport;
xfer->buffer = buffer;
xfer->total_len = total_bytes;
xfer->last_packet_size = 0;
xfer->transferred = 0;
if (epnum == 0)
{
return ep0_xfer(xfer, dir);
}
if (dir == TUSB_DIR_OUT)
{
USB_REGS->INTRRXEbits.w |= (1u << epnum);
}
else // IN
{
epn_fill_tx(xfer, epnum);
}
return true;
}
void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr)
{
uint8_t const epnum = tu_edpt_number(ep_addr);
uint8_t const dir = tu_edpt_dir(ep_addr);
(void) rhport;
if (epnum == 0)
{
USB_REGS->EPCSR[0].CSR0L_DEVICEbits.SENDSTALL = 1;
}
else
{
if (dir == TUSB_DIR_OUT)
{
USB_REGS->EPCSR[epnum].RXCSRL_DEVICEbits.SENDSTALL = 1;
}
else
{
USB_REGS->EPCSR[epnum].TXCSRL_DEVICEbits.SENDSTALL = 1;
}
}
}
void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr)
{
uint8_t const epnum = tu_edpt_number(ep_addr);
uint8_t const dir = tu_edpt_dir(ep_addr);
(void) rhport;
if (epnum == 0)
{
USB_REGS->EPCSR[0].CSR0L_DEVICEbits.SENDSTALL = 0;
}
else
{
if (dir == TUSB_DIR_OUT)
{
USB_REGS->EPCSR[epnum].RXCSRL_DEVICEbits.w &= ~(USBHS_EP_DEVICE_RX_SENT_STALL | USBHS_EP_DEVICE_RX_SEND_STALL);
USB_REGS->EPCSR[epnum].RXCSRL_DEVICEbits.CLRDT = 1;
}
else
{
USB_REGS->EPCSR[epnum].TXCSRL_DEVICEbits.w &= ~(USBHS_EP_DEVICE_TX_SENT_STALL | USBHS_EP_DEVICE_TX_SEND_STALL);
USB_REGS->EPCSR[epnum].TXCSRL_DEVICEbits.CLRDT = 1;
}
}
}
/*------------------------------------------------------------------*/
/* Interrupt Handler
*------------------------------------------------------------------*/
static void ep0_handle_rx(void)
{
int transferred;
xfer_ctl_t * xfer = XFER_CTL_BASE(0, TUSB_DIR_OUT);
TU_ASSERT(xfer->buffer,);
transferred = rx_fifo_read(0, xfer->buffer + xfer->transferred);
xfer->transferred += transferred;
if (transferred < xfer->max_packet_size || xfer->transferred == xfer->total_len)
{
ep0_set_stage(EP0_STAGE_DATA_OUT_COMPLETE);
xfer_complete(xfer, XFER_RESULT_SUCCESS, true);
}
else
{
USB_REGS->EPCSR[0].CSR0L_DEVICEbits.SVCRPR = 1;
}
}
static void epn_handle_rx_int(uint8_t epnum)
{
uint8_t ep_status;
int transferred;
xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, TUSB_DIR_OUT);
ep_status = USB_REGS->EPCSR[epnum].RXCSRL_DEVICEbits.w;
if (ep_status & USBHS_EP_DEVICE_RX_SENT_STALL)
{
USB_REGS->EPCSR[epnum].RXCSRL_DEVICEbits.w &= ~USBHS_EP_DEVICE_RX_SENT_STALL;
}
if (ep_status & USBHS_EP0_HOST_RXPKTRDY)
{
TU_ASSERT(xfer->buffer != NULL,);
transferred = rx_fifo_read(epnum, xfer->buffer + xfer->transferred);
USB_REGS->EPCSR[epnum].RXCSRL_HOSTbits.RXPKTRDY = 0;
xfer->transferred += transferred;
if (transferred < xfer->max_packet_size || xfer->transferred == xfer->total_len)
{
xfer_complete(xfer, XFER_RESULT_SUCCESS, true);
}
}
}
static void epn_handle_tx_int(uint8_t epnum)
{
uint8_t ep_status = USB_REGS->EPCSR[epnum].TXCSRL_DEVICEbits.w;
xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, TUSB_DIR_IN);
if (ep_status & USBHS_EP_DEVICE_TX_SENT_STALL)
{
USB_REGS->EPCSR[epnum].TXCSRL_DEVICEbits.w &= ~USBHS_EP_DEVICE_TX_SENT_STALL;
}
else
{
xfer->transferred += xfer->last_packet_size;
if (xfer->last_packet_size < xfer->max_packet_size || xfer->transferred == xfer->total_len)
{
xfer->last_packet_size = 0;
xfer_complete(xfer, XFER_RESULT_SUCCESS, true);
}
else
{
epn_fill_tx(xfer, epnum);
}
}
}
static void ep0_handle_int(void)
{
__USBHS_CSR0L_DEVICE_t ep0_status;
union {
tusb_control_request_t request;
uint32_t setup_buffer[2];
} setup_packet;
xfer_ctl_t * xfer_in = XFER_CTL_BASE(0, TUSB_DIR_IN);
uint8_t old_index = USB_REGS->INDEXbits.ENDPOINT;
// Select EP0 registers
USB_REGS->INDEXbits.ENDPOINT = 0;
ep0_status = USB_REGS->EPCSR[0].CSR0L_DEVICEbits;
if (ep0_status.SENTSTALL)
{
// Stall was sent. Reset the endpoint 0 state.
// Clear the sent stall bit.
ep0_set_stage(EP0_STAGE_NONE);
USB_REGS->EPCSR[0].CSR0L_DEVICEbits.SENTSTALL = 0;
}
if (ep0_status.SETUPEND)
{
// This means the current control transfer end prematurely. We don't
// need to end any transfers. The device layer will manage the
// premature transfer end. We clear the SetupEnd bit and reset the
// driver control transfer state machine to waiting for next setup
// packet from host.
USB_REGS->EPCSR[0].CSR0L_DEVICEbits.SVSSETEND = 1;
ep0_set_stage(EP0_STAGE_NONE);
}
if (ep0_status.RXPKTRDY)
{
switch (ep0_get_stage())
{
default:
// Data arrived at unexpected state, this must be setup stage packet after all.
// Fall through
case EP0_STAGE_NONE:
// This means we were expecting a SETUP packet and we got one.
setup_packet.setup_buffer[0] = USB_REGS->FIFO[0];
setup_packet.setup_buffer[1] = USB_REGS->FIFO[0];
if (setup_packet.request.bmRequestType_bit.direction == TUSB_DIR_OUT)
{
// SVCRPR is not set yet, it will be set later when out xfer is started
// Till then NAKs will hold incommint data
ep0_set_stage(setup_packet.request.wLength == 0 ? EP0_STAGE_SETUP_OUT_NO_DATA : EP0_STAGE_SETUP_OUT_DATA);
}
else
{
USB_REGS->EPCSR[0].CSR0L_DEVICEbits.SVCRPR = 1;
ep0_set_stage(EP0_STAGE_SETUP_IN_DATA);
}
dcd_event_setup_received(0, &setup_packet.request.bmRequestType, true);
break;
case EP0_STAGE_DATA_OUT:
ep0_handle_rx();
break;
}
}
else
{
switch (ep0_get_stage())
{
case EP0_STAGE_STATUS_IN:
// Status was just sent, this concludes request, notify client
ep0_set_stage(EP0_STAGE_NONE);
xfer_complete(xfer_in, XFER_RESULT_SUCCESS, true);
break;
case EP0_STAGE_DATA_IN:
// Packet sent, fill more data
ep0_fill_tx(xfer_in);
break;
case EP0_STAGE_DATA_IN_LAST_PACKET_FILLED:
ep0_set_stage(EP0_STAGE_DATA_IN_SENT);
xfer_complete(xfer_in, XFER_RESULT_SUCCESS, true);
break;
case EP0_STAGE_ADDRESS_CHANGE:
// Status stage after set address request finished, address can be changed
USB_REGS->FADDRbits.FUNC = _dcd.dev_addr;
ep0_set_stage(EP0_STAGE_NONE);
break;
default:
break;
}
}
// Restore register index
USB_REGS->INDEXbits.ENDPOINT = old_index;
}
void dcd_int_handler(uint8_t rhport)
{
int i;
uint8_t mask;
__USBCSR2bits_t csr2_bits;
uint16_t rxints = USB_REGS->INTRRX;
uint16_t txints = USB_REGS->INTRTX;
csr2_bits = USBCSR2bits;
(void) rhport;
IFS4CLR = _IFS4_USBIF_MASK;
if (csr2_bits.SOFIF && csr2_bits.SOFIE)
{
dcd_event_bus_signal(0, DCD_EVENT_SOF, true);
}
if (csr2_bits.RESETIF)
{
dcd_edpt_open(0, &ep0OUT_desc);
dcd_edpt_open(0, &ep0IN_desc);
dcd_event_bus_reset(0, USB_REGS->POWERbits.HSMODE ? TUSB_SPEED_HIGH : TUSB_SPEED_FULL, true);
}
if (csr2_bits.SUSPIF)
{
dcd_event_bus_signal(0, DCD_EVENT_SUSPEND, true);
}
if (csr2_bits.RESUMEIF)
{
dcd_event_bus_signal(0, DCD_EVENT_RESUME, true);
}
// INTRTX has bit for EP0
if (txints & 1)
{
txints ^= 1;
ep0_handle_int();
}
for (mask = 0x02, i = 1; rxints != 0 && mask != 0; mask <<= 1, ++i)
{
if (rxints & mask)
{
rxints ^= mask;
epn_handle_rx_int(i);
}
}
for (mask = 0x02, i = 1; txints != 0 && mask != 0; mask <<= 1, ++i)
{
if (txints & mask)
{
txints ^= mask;
epn_handle_tx_int(i);
}
}
}
#endif

View File

@@ -0,0 +1,931 @@
/*******************************************************************************
* Copyright (C) 2019 Microchip Technology Inc. and its subsidiaries.
*
* Subject to your compliance with these terms, you may use Microchip software
* and any derivatives exclusively with Microchip products. It is your
* responsibility to comply with third party license terms applicable to your
* use of third party software (including open source software) that may
* accompany Microchip software.
*
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
* PARTICULAR PURPOSE.
*
* IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE,
* INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND
* WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS
* BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE
* FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN
* ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
* THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
*******************************************************************************/
/*******************************************************************************
USBHS Peripheral Library Register Defintions
File Name:
usbhs_registers.h
Summary:
USBHS PLIB Register Defintions
Description:
This file contains the constants and defintions which are required by the
the USBHS library.
*******************************************************************************/
#ifndef __USBHS_REGISTERS_H__
#define __USBHS_REGISTERS_H__
#include <p32xxxx.h>
#include <stdint.h>
/*****************************************
* Module Register Offsets.
*****************************************/
#define USBHS_REG_FADDR 0x000
#define USBHS_REG_POWER 0x001
#define USBHS_REG_INTRTX 0x002
#define USBHS_REG_INTRRX 0x004
#define USBHS_REG_INTRTXE 0x006
#define USBHS_REG_INTRRXE 0x008
#define USBHS_REG_INTRUSB 0x00A
#define USBHS_REG_INTRUSBE 0x00B
#define USBHS_REG_FRAME 0x00C
#define USBHS_REG_INDEX 0x00E
#define USBHS_REG_TESTMODE 0x00F
/*******************************************************
* Endpoint Control Status Registers (CSR). These values
* should be added to either the 0x10 to access the
* register through Indexed CSR. To access the actual
* CSR, see ahead in this header file.
******************************************************/
#define USBHS_REG_EP_TXMAXP 0x000
#define USBHS_REG_EP_CSR0L 0x002
#define USBHS_REG_EP_CSR0H 0x003
#define USBHS_REG_EP_TXCSRL 0x002
#define USBHS_REG_EP_TXCSRH 0x003
#define USBHS_REG_EP_RXMAXP 0x004
#define USBHS_REG_EP_RXCSRL 0x006
#define USBHS_REG_EP_RXCSRH 0x007
#define USBHS_REG_EP_COUNT0 0x008
#define USBHS_REG_EP_RXCOUNT 0x008
#define USBHS_REG_EP_TYPE0 0x01A
#define USBHS_REG_EP_TXTYPE 0x01A
#define USBHS_REG_EP_NAKLIMIT0 0x01B
#define USBHS_REG_EP_TXINTERVAL 0x01B
#define USBHS_REG_EP_RXTYPE 0x01C
#define USBHS_REG_EP_RXINTERVAL 0x01D
#define USBHS_REG_EP_CONFIGDATA 0x01F
#define USBHS_REG_EP_FIFOSIZE 0x01F
#define USBHS_HOST_EP0_SETUPKT_SET 0x8
#define USBHS_HOST_EP0_TXPKTRDY_SET 0x2
#define USBHS_SOFT_RST_NRST_SET 0x1
#define USBHS_SOFT_RST_NRSTX_SET 0x2
#define USBHS_EP0_DEVICE_SERVICED_RXPKTRDY 0x40
#define USBHS_EP0_DEVICE_DATAEND 0x08
#define USBHS_EP0_DEVICE_TXPKTRDY 0x02
#define USBHS_EP0_HOST_STATUS_STAGE_START 0x40
#define USBHS_EP0_HOST_REQPKT 0x20
#define USBHS_EP0_HOST_TXPKTRDY 0x02
#define USBHS_EP0_HOST_RXPKTRDY 0x01
#define USBHS_EP_DEVICE_TX_SENT_STALL 0x20
#define USBHS_EP_DEVICE_TX_SEND_STALL 0x10
#define USBHS_EP_DEVICE_RX_SENT_STALL 0x40
#define USBHS_EP_DEVICE_RX_SEND_STALL 0x20
/* FADDR - Device Function Address */
typedef union
{
struct __attribute__((packed))
{
unsigned FUNC:7;
unsigned :1;
};
uint8_t w;
} __USBHS_FADDR_t;
/* POWER - Control Resume and Suspend signalling */
typedef union
{
struct __attribute__((packed))
{
unsigned SUSPEN:1;
unsigned SUSPMODE:1;
unsigned RESUME:1;
unsigned RESET:1;
unsigned HSMODE:1;
unsigned HSEN:1;
unsigned SOFTCONN:1;
unsigned ISOUPD:1;
};
struct
{
uint8_t w;
};
} __USBHS_POWER_t;
/* INTRTXE - Transmit endpoint interrupt enable */
typedef union
{
struct __attribute__((packed))
{
unsigned EP0IE:1;
unsigned EP1TXIE:1;
unsigned EP2TXIE:1;
unsigned EP3TXIE:1;
unsigned EP4TXIE:1;
unsigned EP5TXIE:1;
unsigned EP6TXIE:1;
unsigned EP7TXIE:1;
unsigned :8;
};
struct
{
uint16_t w;
};
} __USBHS_INTRTXE_t;
/* INTRRXE - Receive endpoint interrupt enable */
typedef union
{
struct __attribute__((packed))
{
unsigned :1;
unsigned EP1RXIE:1;
unsigned EP2RXIE:1;
unsigned EP3RXIE:1;
unsigned EP4RXIE:1;
unsigned EP5RXIE:1;
unsigned EP6RXIE:1;
unsigned EP7RXIE:1;
unsigned :8;
};
struct
{
uint16_t w;
};
} __USBHS_INTRRXE_t;
/* INTRUSBE - General USB Interrupt enable */
typedef union
{
struct __attribute__((packed))
{
unsigned SUSPIE:1;
unsigned RESUMEIE:1;
unsigned RESETIE:1;
unsigned SOFIE:1;
unsigned CONNIE:1;
unsigned DISCONIE:1;
unsigned SESSRQIE:1;
unsigned VBUSERRIE:1;
};
struct
{
uint8_t w;
};
} __USBHS_INTRUSBE_t;
/* FRAME - Frame number */
typedef union
{
struct __attribute__((packed))
{
unsigned RFRMNUM:11;
unsigned :5;
};
struct
{
uint16_t w;
};
} __USBHS_FRAME_t;
/* INDEX - Endpoint index */
typedef union
{
struct __attribute__((packed))
{
unsigned ENDPOINT:4;
unsigned :4;
};
struct
{
uint8_t w;
};
} __USBHS_INDEX_t;
/* TESTMODE - Test mode register */
typedef union
{
struct __attribute__((packed))
{
unsigned NAK:1;
unsigned TESTJ:1;
unsigned TESTK:1;
unsigned PACKET:1;
unsigned FORCEHS:1;
unsigned FORCEFS:1;
unsigned FIFOACC:1;
unsigned FORCEHST:1;
};
struct
{
uint8_t w;
};
} __USBHS_TESTMODE_t;
/* COUNT0 - Indicates the amount of data received in endpoint 0 */
typedef union
{
struct __attribute__((packed))
{
unsigned RXCNT:7;
unsigned :1;
};
struct
{
uint8_t w;
};
} __USBHS_COUNT0_t;
/* TYPE0 - Operating speed of target device */
typedef union
{
struct __attribute__((packed))
{
unsigned :6;
unsigned SPEED:2;
};
struct
{
uint8_t w;
};
} __USBHS_TYPE0_t;
/* DEVCTL - Module control register */
typedef union
{
struct __attribute__((packed))
{
unsigned SESSION:1;
unsigned HOSTREQ:1;
unsigned HOSTMODE:1;
unsigned VBUS:2;
unsigned LSDEV:1;
unsigned FSDEV:1;
unsigned BDEV:1;
};
struct
{
uint8_t w;
};
} __USBHS_DEVCTL_t;
/* CSR0L Device - Endpoint Device Mode Control Status Register */
typedef union
{
struct __attribute__((packed))
{
unsigned RXPKTRDY:1;
unsigned TXPKTRDY:1;
unsigned SENTSTALL:1;
unsigned DATAEND:1;
unsigned SETUPEND:1;
unsigned SENDSTALL:1;
unsigned SVCRPR:1;
unsigned SVSSETEND:1;
};
struct
{
uint8_t w;
};
} __USBHS_CSR0L_DEVICE_t;
/* CSR0L Host - Endpoint Host Mode Control Status Register */
typedef union
{
struct __attribute__((packed))
{
unsigned RXPKTRDY:1;
unsigned TXPKTRDY:1;
unsigned RXSTALL:1;
unsigned SETUPPKT:1;
unsigned ERROR:1;
unsigned REQPKT:1;
unsigned STATPKT:1;
unsigned NAKTMOUT:1;
};
struct
{
uint8_t w;
};
} __USBHS_CSR0L_HOST_t;
/* TXCSRL Device - Endpoint Transmit Control Status Register Low */
typedef union
{
struct __attribute__((packed))
{
unsigned TXPKTRDY:1;
unsigned FIFOONE:1;
unsigned UNDERRUN:1;
unsigned FLUSH:1;
unsigned SENDSTALL:1;
unsigned SENTSTALL:1;
unsigned CLRDT:1;
unsigned INCOMPTX:1;
};
struct
{
uint8_t w;
};
} __USBHS_TXCSRL_DEVICE_t;
/* TXCSRL Host - Endpoint Transmit Control Status Register Low */
typedef union
{
struct __attribute__((packed))
{
unsigned TXPKTRDY:1;
unsigned FIFONE:1;
unsigned ERROR:1;
unsigned FLUSH:1;
unsigned SETUPPKT:1;
unsigned RXSTALL:1;
unsigned CLRDT:1;
unsigned INCOMPTX:1;
};
struct
{
uint8_t w;
};
} __USBHS_TXCSRL_HOST_t;
/* TXCSRH Device - Endpoint Transmit Control Status Register High */
typedef union
{
struct __attribute__((packed))
{
unsigned :2;
unsigned DMAREQMD:1;
unsigned FRCDATTG:1;
unsigned DMAREQENL:1;
unsigned MODE:1;
unsigned ISO:1;
unsigned AUTOSET:1;
};
struct
{
uint8_t w;
};
} __USBHS_TXCSRH_DEVICE_t;
/* TXCSRH Host - Endpoint Transmit Control Status Register High */
typedef union
{
struct __attribute__((packed))
{
unsigned DATATGGL:1;
unsigned DTWREN:1;
unsigned DMAREQMD:1;
unsigned FRCDATTG:1;
unsigned DMAREQEN:1;
unsigned MODE:1;
unsigned :1;
unsigned AUOTSET:1;
};
struct
{
uint8_t w;
};
} __USBHS_TXCSRH_HOST_t;
/* CSR0H Device - Endpoint 0 Control Status Register High */
typedef union
{
struct __attribute__((packed))
{
unsigned FLSHFIFO:1;
unsigned :7;
};
struct
{
uint8_t w;
};
} __USBHS_CSR0H_DEVICE_t;
/* CSR0H Host - Endpoint 0 Control Status Register High */
typedef union
{
struct __attribute__((packed))
{
unsigned FLSHFIFO:1;
unsigned DATATGGL:1;
unsigned DTWREN:1;
unsigned DISPING:1;
unsigned :4;
};
struct
{
uint8_t w;
};
} __USBHS_CSR0H_HOST_t;
/* RXMAXP - Receive Endpoint Max packet size. */
typedef union
{
struct __attribute__((packed))
{
unsigned RXMAXP:11;
unsigned MULT:5;
};
struct
{
uint16_t w;
};
} __USBHS_RXMAXP_t;
/* RXCSRL Device - Receive endpoint Control Status Register */
typedef union
{
struct __attribute__((packed))
{
unsigned RXPKTRDY:1;
unsigned FIFOFULL:1;
unsigned OVERRUN:1;
unsigned DATAERR:1;
unsigned FLUSH:1;
unsigned SENDSTALL:1;
unsigned SENTSTALL:1;
unsigned CLRDT:1;
};
struct
{
uint8_t w;
};
} __USBHS_RXCSRL_DEVICE_t;
/* RXCSRL Host - Receive endpoint Control Status Register */
typedef union
{
struct __attribute__((packed))
{
unsigned RXPKTRDY:1;
unsigned FIFOFULL:1;
unsigned ERROR:1;
unsigned DERRNAKT:1;
unsigned FLUSH:1;
unsigned REQPKT:1;
unsigned RXSTALL:1;
unsigned CLRDT:1;
};
struct
{
uint8_t w;
};
} __USBHS_RXCSRL_HOST_t;
/* RXCSRH Device - Receive endpoint Control Status Register */
typedef union
{
struct __attribute__((packed))
{
unsigned INCOMPRX:1;
unsigned :2;
unsigned DMAREQMODE:1;
unsigned DISNYET:1;
unsigned DMAREQEN:1;
unsigned ISO:1;
unsigned AUTOCLR:1;
};
struct
{
uint8_t w;
};
} __USBHS_RXCSRH_DEVICE_t;
/* RXCSRH Host - Receive endpoint Control Status Register */
typedef union
{
struct __attribute__((packed))
{
unsigned INCOMPRX:1;
unsigned DATATGGL:1;
unsigned DATATWEN:1;
unsigned DMAREQMD:1;
unsigned PIDERR:1;
unsigned DMAREQEN:1;
unsigned AUTORQ:1;
unsigned AUOTCLR:1;
};
struct
{
uint8_t w;
};
} __USBHS_RXCSRH_HOST_t;
/* RXCOUNT - Amount of data pending in RX FIFO */
typedef union
{
struct __attribute__((packed))
{
unsigned RXCNT:14;
unsigned :2;
};
struct
{
uint16_t w;
};
} __USBHS_RXCOUNT_t;
/* TXTYPE - Specifies the target transmit endpoint */
typedef union
{
struct __attribute__((packed))
{
unsigned TEP:4;
unsigned PROTOCOL:2;
unsigned SPEED:2;
};
struct
{
uint8_t w;
};
} __USBHS_TXTYPE_t;
/* RXTYPE - Specifies the target receive endpoint */
typedef union
{
struct __attribute__((packed))
{
unsigned TEP:4;
unsigned PROTOCOL:2;
unsigned SPEED:2;
};
struct
{
uint8_t w;
};
} __USBHS_RXTYPE_t;
/* TXINTERVAL - Defines the polling interval */
typedef struct
{
uint8_t TXINTERV;
} __USBHS_TXINTERVAL_t;
/* RXINTERVAL - Defines the polling interval */
typedef struct
{
uint8_t RXINTERV;
} __USBHS_RXINTERVAL_t;
/* TXMAXP - Maximum amount of data that can be transferred through a TX endpoint
* */
typedef union
{
struct __attribute__((packed))
{
unsigned TXMAXP:11;
unsigned MULT:5;
};
uint16_t w;
} __USBHS_TXMAXP_t;
/* TXFIFOSZ - Size of the transmit endpoint FIFO */
typedef struct __attribute__((packed))
{
unsigned TXFIFOSZ:4;
unsigned TXDPB:1;
unsigned :3;
} __USBHS_TXFIFOSZ_t;
/* RXFIFOSZ - Size of the receive endpoint FIFO */
typedef struct __attribute__((packed))
{
unsigned RXFIFOSZ:4;
unsigned RXDPB:1;
unsigned :3;
} __USBHS_RXFIFOSZ_t;
/* TXFIFOADD - Start address of the transmit endpoint FIFO */
typedef union
{
struct __attribute__((packed))
{
unsigned TXFIFOAD:13;
unsigned :3;
};
uint16_t w;
} __USBHS_TXFIFOADD_t;
/* RXFIFOADD - Start address of the receive endpoint FIFO */
typedef union
{
struct __attribute__((packed))
{
unsigned RXFIFOAD:13;
unsigned :3;
};
uint16_t w;
} __USBHS_RXFIFOADD_t;
/* SOFTRST - Asserts NRSTO and NRSTOX */
typedef union
{
struct __attribute__((packed))
{
unsigned NRST:1;
unsigned NRSTX:1;
unsigned :6;
};
uint8_t w;
} __USBHS_SOFTRST_t;
/* TXFUNCADDR - Target address of transmit endpoint */
typedef union
{
struct __attribute__((packed))
{
unsigned TXFADDR:7;
unsigned :1;
};
uint8_t w;
} __USBHS_TXFUNCADDR_t;
/* RXFUNCADDR - Target address of receive endpoint */
typedef union
{
struct __attribute__((packed))
{
unsigned RXFADDR:7;
unsigned :1;
};
uint8_t w;
} __USBHS_RXFUNCADDR_t;
/* TXHUBADDR - Address of the hub to which the target transmit device endpoint
* is connected */
typedef union
{
struct __attribute__((packed))
{
unsigned TXHUBADDR:7;
unsigned MULTTRAN:1;
};
uint8_t w;
} __USBHS_TXHUBADDR_t;
/* RXHUBADDR - Address of the hub to which the target receive device endpoint is
* connected */
typedef union
{
struct __attribute__((packed))
{
unsigned RXHUBADDR:7;
unsigned MULTTRAN:1;
};
uint8_t w;
} __USBHS_RXHUBADDR_t;
/* TXHUBPORT - Address of the hub to which the target transmit device endpoint
* is connected. */
typedef union
{
struct __attribute__((packed))
{
unsigned TXHUBPRT:7;
unsigned :1;
};
uint8_t w;
} __USBHS_TXHUBPORT_t;
/* RXHUBPORT - Address of the hub to which the target receive device endpoint
* is connected. */
typedef union
{
struct __attribute__((packed))
{
unsigned RXHUBPRT:7;
unsigned :1;
};
uint8_t w;
} __USBHS_RXHUBPORT_t;
/* DMACONTROL - Configures a DMA channel */
typedef union
{
struct __attribute__((packed))
{
unsigned DMAEN:1;
unsigned DMADIR:1;
unsigned DMAMODE:1;
unsigned DMAIE:1;
unsigned DMAEP:4;
unsigned DMAERR:1;
unsigned DMABRSTM:2;
unsigned:21;
};
uint32_t w;
} __USBHS_DMACNTL_t;
/* Endpoint Control and Status Register Set */
typedef struct __attribute__((packed))
{
volatile __USBHS_TXMAXP_t TXMAXPbits;
union
{
struct
{
union
{
volatile __USBHS_CSR0L_DEVICE_t CSR0L_DEVICEbits;
volatile __USBHS_CSR0L_HOST_t CSR0L_HOSTbits;
};
union
{
volatile __USBHS_CSR0H_DEVICE_t CSR0H_DEVICEbits;
volatile __USBHS_CSR0H_HOST_t CSR0H_HOSTbits;
};
};
struct
{
union
{
volatile __USBHS_TXCSRL_DEVICE_t TXCSRL_DEVICEbits;
volatile __USBHS_TXCSRL_HOST_t TXCSRL_HOSTbits;
};
union
{
volatile __USBHS_TXCSRH_DEVICE_t TXCSRH_DEVICEbits;
volatile __USBHS_TXCSRH_HOST_t TXCSRH_HOSTbits;
};
};
};
volatile __USBHS_RXMAXP_t RXMAXPbits;
union
{
volatile __USBHS_RXCSRL_DEVICE_t RXCSRL_DEVICEbits;
volatile __USBHS_RXCSRL_HOST_t RXCSRL_HOSTbits;
};
union
{
volatile __USBHS_RXCSRH_DEVICE_t RXCSRH_DEVICEbits;
volatile __USBHS_RXCSRH_HOST_t RXCSRH_HOSTbits;
};
union
{
volatile __USBHS_COUNT0_t COUNT0bits;
volatile __USBHS_RXCOUNT_t RXCOUNTbits;
};
union
{
volatile __USBHS_TYPE0_t TYPE0bits;
volatile __USBHS_TXTYPE_t TXTYPEbits;
};
union
{
volatile uint8_t NAKLIMIT0;
volatile __USBHS_TXINTERVAL_t TXINTERVALbits;
};
volatile __USBHS_RXTYPE_t RXTYPEbits;
volatile __USBHS_RXINTERVAL_t RXINTERVALbits;
unsigned :8;
union
{
volatile uint8_t CONFIGDATA;
volatile uint8_t FIFOSIZE;
};
} __USBHS_EPCSR_t;
/* Set of registers that configure the multi-point option */
typedef struct __attribute__((packed))
{
volatile __USBHS_TXFUNCADDR_t TXFUNCADDRbits;
unsigned :8;
volatile __USBHS_TXHUBADDR_t TXHUBADDRbits;
volatile __USBHS_TXHUBPORT_t TXHUBPORTbits;
volatile __USBHS_RXFUNCADDR_t RXFUNCADDRbits;
unsigned :8;
volatile __USBHS_RXHUBADDR_t RXHUBADDRbits;
volatile __USBHS_RXHUBPORT_t RXHUBPORTbits;
} __USBHS_TARGET_ADDR_t;
/* Set of registers that configure the DMA channel */
typedef struct __attribute__((packed))
{
volatile __USBHS_DMACNTL_t DMACNTLbits;
volatile uint32_t DMAADDR;
volatile uint32_t DMACOUNT;
volatile uint32_t pad;
} __USBHS_DMA_CHANNEL_t;
/* USBHS module register set */
typedef struct __attribute__((aligned(4),packed))
{
volatile __USBHS_FADDR_t FADDRbits;
volatile __USBHS_POWER_t POWERbits;
volatile uint16_t INTRTX;
volatile uint16_t INTRRX;
volatile __USBHS_INTRTXE_t INTRTXEbits;
volatile __USBHS_INTRRXE_t INTRRXEbits;
volatile uint8_t INTRUSB;
volatile __USBHS_INTRUSBE_t INTRUSBEbits;
volatile __USBHS_FRAME_t FRAMEbits;
volatile __USBHS_INDEX_t INDEXbits;
volatile __USBHS_TESTMODE_t TESTMODEbits;
volatile __USBHS_EPCSR_t INDEXED_EPCSR;
volatile uint32_t FIFO[16];
volatile __USBHS_DEVCTL_t DEVCTLbits;
volatile uint8_t MISC;
volatile __USBHS_TXFIFOSZ_t TXFIFOSZbits;
volatile __USBHS_RXFIFOSZ_t RXFIFOSZbits;
volatile __USBHS_TXFIFOADD_t TXFIFOADDbits;
volatile __USBHS_RXFIFOADD_t RXFIFOADDbits;
volatile uint32_t VCONTROL;
volatile uint16_t HWVERS;
volatile uint8_t padding1[10];
volatile uint8_t EPINFO;
volatile uint8_t RAMINFO;
volatile uint8_t LINKINFO;
volatile uint8_t VPLEN;
volatile uint8_t HS_EOF1;
volatile uint8_t FS_EOF1;
volatile uint8_t LS_EOF1;
volatile __USBHS_SOFTRST_t SOFTRSTbits;
volatile __USBHS_TARGET_ADDR_t TADDR[16];
volatile __USBHS_EPCSR_t EPCSR[16];
volatile uint32_t DMA_INTR;
volatile __USBHS_DMA_CHANNEL_t DMA_CHANNEL[8];
volatile uint32_t RQPKTXOUNT[16];
} usbhs_registers_t;
#endif

View File

@@ -1059,7 +1059,13 @@ void tusb_hal_nrf_power_event (uint32_t event)
// Enable interrupt, priorities should be set by application
NVIC_ClearPendingIRQ(USBD_IRQn);
NVIC_EnableIRQ(USBD_IRQn);
// Don't enable USBD interrupt yet, if dcd_init() did not finish yet
// Interrupt will be enabled by tud_init(), when USB stack is ready
// to handle interrupts.
if (tud_inited())
{
NVIC_EnableIRQ(USBD_IRQn);
}
// Wait for HFCLK
while ( !hfclk_running() ) { }

View File

@@ -83,7 +83,7 @@ static void _hw_endpoint_alloc(struct hw_endpoint *ep, uint8_t transfer_type)
assert(((uintptr_t )next_buffer_ptr & 0b111111u) == 0);
uint dpram_offset = hw_data_offset(ep->hw_data_buf);
assert(hw_data_offset(next_buffer_ptr) <= USB_DPRAM_MAX);
hard_assert(hw_data_offset(next_buffer_ptr) <= USB_DPRAM_MAX);
pico_info(" Alloced %d bytes at offset 0x%x (0x%p)\r\n", size, dpram_offset, ep->hw_data_buf);
@@ -93,7 +93,6 @@ static void _hw_endpoint_alloc(struct hw_endpoint *ep, uint8_t transfer_type)
*ep->endpoint_control = reg;
}
#if 0 // todo unused
static void _hw_endpoint_close(struct hw_endpoint *ep)
{
// Clear hardware registers and then zero the struct
@@ -103,6 +102,21 @@ static void _hw_endpoint_close(struct hw_endpoint *ep)
*ep->buffer_control = 0;
// Clear any endpoint state
memset(ep, 0, sizeof(struct hw_endpoint));
// Reclaim buffer space if all endpoints are closed
bool reclaim_buffers = true;
for ( uint8_t i = 1; i < USB_MAX_ENDPOINTS; i++ )
{
if (hw_endpoint_get_by_num(i, TUSB_DIR_OUT)->hw_data_buf != NULL || hw_endpoint_get_by_num(i, TUSB_DIR_IN)->hw_data_buf != NULL)
{
reclaim_buffers = false;
break;
}
}
if (reclaim_buffers)
{
next_buffer_ptr = &usb_dpram->epx_data[0];
}
}
static void hw_endpoint_close(uint8_t ep_addr)
@@ -110,7 +124,6 @@ static void hw_endpoint_close(uint8_t ep_addr)
struct hw_endpoint *ep = hw_endpoint_get_by_addr(ep_addr);
_hw_endpoint_close(ep);
}
#endif
static void hw_endpoint_init(uint8_t ep_addr, uint16_t wMaxPacketSize, uint8_t transfer_type)
{
@@ -224,6 +237,8 @@ static void reset_non_control_endpoints(void)
// clear non-control hw endpoints
tu_memclr(hw_endpoints[1], sizeof(hw_endpoints) - 2*sizeof(hw_endpoint_t));
// reclaim buffer space
next_buffer_ptr = &usb_dpram->epx_data[0];
}
@@ -232,6 +247,14 @@ static void dcd_rp2040_irq(void)
uint32_t const status = usb_hw->ints;
uint32_t handled = 0;
// xfer events are handled before setup req. So if a transfer completes immediately
// before closing the EP, the events will be delivered in same order.
if (status & USB_INTS_BUFF_STATUS_BITS)
{
handled |= USB_INTS_BUFF_STATUS_BITS;
hw_handle_buff_status();
}
if (status & USB_INTS_SETUP_REQ_BITS)
{
handled |= USB_INTS_SETUP_REQ_BITS;
@@ -245,12 +268,6 @@ static void dcd_rp2040_irq(void)
usb_hw_clear->sie_status = USB_SIE_STATUS_SETUP_REC_BITS;
}
if (status & USB_INTS_BUFF_STATUS_BITS)
{
handled |= USB_INTS_BUFF_STATUS_BITS;
hw_handle_buff_status();
}
#if FORCE_VBUS_DETECT == 0
// Since we force VBUS detect On, device will always think it is connected and
// couldn't distinguish between disconnect and suspend
@@ -479,10 +496,9 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr)
void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr)
{
(void) rhport;
(void) ep_addr;
// usbd.c says: In progress transfers on this EP may be delivered after this call
pico_trace("dcd_edpt_close %02x\n", ep_addr);
hw_endpoint_close(ep_addr);
}
void dcd_int_handler(uint8_t rhport)

View File

@@ -294,7 +294,7 @@ bool hw_endpoint_xfer_continue(struct hw_endpoint *ep)
// Part way through a transfer
if (!ep->active)
{
panic("Can't continue xfer on inactive ep %d %s", tu_edpt_number(ep->ep_addr), ep_dir_string);
panic("Can't continue xfer on inactive ep %d %s", tu_edpt_number(ep->ep_addr), ep_dir_string[tu_edpt_dir(ep->ep_addr)]);
}
// Update EP struct from hardware state

View File

@@ -33,7 +33,8 @@
#if TUSB_OPT_DEVICE_ENABLED && \
( defined(DCD_ATTR_DWC2_STM32) || \
TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3, OPT_MCU_GD32VF103) || \
TU_CHECK_MCU(OPT_MCU_EFM32GG, OPT_MCU_BCM2711, OPT_MCU_XMC4000) )
TU_CHECK_MCU(OPT_MCU_EFM32GG, OPT_MCU_BCM2711, OPT_MCU_BCM2835) || \
TU_CHECK_MCU(OPT_MCU_BCM2837, OPT_MCU_XMC4000) )
#include "device/dcd.h"
#include "dwc2_type.h"
@@ -44,7 +45,7 @@
#include "dwc2_esp32.h"
#elif TU_CHECK_MCU(OPT_MCU_GD32VF103)
#include "dwc2_gd32.h"
#elif TU_CHECK_MCU(OPT_MCU_BCM2711)
#elif TU_CHECK_MCU(OPT_MCU_BCM2711, OPT_MCU_BCM2835, OPT_MCU_BCM2837)
#include "dwc2_bcm.h"
#elif TU_CHECK_MCU(OPT_MCU_EFM32GG)
#include "dwc2_efm32.h"

View File

@@ -31,6 +31,7 @@
extern "C" {
#endif
#include "broadcom/defines.h"
#include "broadcom/interrupts.h"
#include "broadcom/caches.h"
@@ -47,7 +48,6 @@ static inline void dwc2_dcd_int_enable(uint8_t rhport)
{
(void) rhport;
BP_EnableIRQ(USB_IRQn);
__asm__ volatile("isb"); // needed if TIMER1 IRQ is not enabled !?
}
TU_ATTR_ALWAYS_INLINE
@@ -55,7 +55,6 @@ static inline void dwc2_dcd_int_disable (uint8_t rhport)
{
(void) rhport;
BP_DisableIRQ(USB_IRQn);
__asm__ volatile("isb"); // needed if TIMER1 IRQ is not enabled !?
}
static inline void dwc2_remote_wakeup_delay(void)

View File

@@ -24,6 +24,10 @@
* This file is part of the TinyUSB stack.
*/
#include "tusb_option.h"
#if TUSB_OPT_DEVICE_ENABLED && (CFG_TUSB_MCU == OPT_MCU_VALENTYUSB_EPTRI)
#ifndef DEBUG
#define DEBUG 0
#endif
@@ -32,10 +36,6 @@
#define LOG_USB 0
#endif
#include "tusb_option.h"
#if TUSB_OPT_DEVICE_ENABLED && (CFG_TUSB_MCU == OPT_MCU_VALENTYUSB_EPTRI)
#include "device/dcd.h"
#include "dcd_eptri.h"
#include "csr.h"