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