diff --git a/firmware/usb_performance/usb.c b/firmware/usb_performance/usb.c index 73ed3592..5054160b 100644 --- a/firmware/usb_performance/usb.c +++ b/firmware/usb_performance/usb.c @@ -33,8 +33,8 @@ usb_device_t* usb_device_usb0 = 0; -usb_queue_head_t usb_qh[12] ATTR_SECTION(".usb_qh"); -usb_transfer_descriptor_t usb_td[12] ATTR_SECTION(".usb_td"); +usb_queue_head_t usb_qh[12] ATTR_ALIGNED(2048); +usb_transfer_descriptor_t usb_td[12] ATTR_ALIGNED(64); #define USB_QH_INDEX(endpoint_address) (((endpoint_address & 0xF) * 2) + ((endpoint_address >> 7) & 1)) #define USB_TD_INDEX(endpoint_address) (((endpoint_address & 0xF) * 2) + ((endpoint_address >> 7) & 1)) @@ -83,6 +83,18 @@ static void usb_phy_enable() { CREG_CREG0 &= ~CREG_CREG0_USB0PHY; } +static void usb_clear_pending_interrupts(const uint32_t mask) { + USB0_ENDPTNAK = mask; + USB0_ENDPTNAKEN = mask; + USB0_USBSTS_D = mask; + USB0_ENDPTSETUPSTAT = USB0_ENDPTSETUPSTAT & mask; + USB0_ENDPTCOMPLETE = USB0_ENDPTCOMPLETE & mask; +} + +static void usb_clear_all_pending_interrupts() { + usb_clear_pending_interrupts(0xFFFFFFFF); +} + static void usb_wait_for_endpoint_priming_to_finish(const uint32_t mask) { // Wait until controller has parsed new transfer descriptors and prepared // receive buffers. @@ -139,6 +151,17 @@ static void usb_endpoint_enable( } } +static void usb_endpoint_clear_pending_interrupts( + const usb_endpoint_t* const endpoint +) { + const uint_fast8_t endpoint_number = usb_endpoint_number(endpoint->address); + if( usb_endpoint_is_in(endpoint->address) ) { + usb_clear_pending_interrupts(USB0_ENDPTCOMPLETE_ETCE(1 << endpoint_number)); + } else { + usb_clear_pending_interrupts(USB0_ENDPTCOMPLETE_ERCE(1 << endpoint_number)); + } +} + void usb_endpoint_disable( const usb_endpoint_t* const endpoint ) { @@ -148,6 +171,8 @@ void usb_endpoint_disable( } else { USB0_ENDPTCTRL(endpoint_number) &= ~(USB0_ENDPTCTRL_RXE); } + usb_endpoint_clear_pending_interrupts(endpoint); + usb_endpoint_flush(endpoint); } void usb_endpoint_prime( @@ -215,6 +240,17 @@ bool usb_endpoint_is_ready( } } +bool usb_endpoint_is_complete( + const usb_endpoint_t* const endpoint +) { + const uint_fast8_t endpoint_number = usb_endpoint_number(endpoint->address); + if( usb_endpoint_is_in(endpoint->address) ) { + return USB0_ENDPTCOMPLETE & USB0_ENDPTCOMPLETE_ETCE(1 << endpoint_number); + } else { + return USB0_ENDPTCOMPLETE & USB0_ENDPTCOMPLETE_ERCE(1 << endpoint_number); + } +} + void usb_endpoint_stall( const usb_endpoint_t* const endpoint ) { @@ -312,14 +348,6 @@ static void usb_disable_all_endpoints() { USB0_ENDPTCTRL5 &= ~(USB0_ENDPTCTRL5_RXE | USB0_ENDPTCTRL5_TXE); } -static void usb_clear_all_pending_interrupts() { - USB0_ENDPTNAK = ~0; - USB0_ENDPTNAKEN = 0; - USB0_USBSTS_D = ~0; - USB0_ENDPTSETUPSTAT = USB0_ENDPTSETUPSTAT; - USB0_ENDPTCOMPLETE = USB0_ENDPTCOMPLETE; -} - void usb_set_address_immediate( const usb_device_t* const device, const uint_fast8_t address @@ -489,7 +517,7 @@ void usb_endpoint_schedule( ) { usb_transfer_descriptor_t* const td = usb_transfer_descriptor(endpoint->address); - // Ensure that OUT endpoint is ready to be primed. + // Ensure that endpoint is ready to be primed. // It may have been flushed due to an aborted transaction. // TODO: This should be preceded by a flush? while( usb_endpoint_is_ready(endpoint) );