Changed USB queue head and transfer descriptor attributes to be explicitly aligned, instead of targeting a section.

Added miscellaneous internal USB functions.
Improved disabling of endpoints -- now clearing pending interrupts and flushing as well.
This commit is contained in:
Jared Boone
2012-10-10 14:39:03 -07:00
parent 5989465eb9
commit 165997d09b

View File

@ -33,8 +33,8 @@
usb_device_t* usb_device_usb0 = 0; usb_device_t* usb_device_usb0 = 0;
usb_queue_head_t usb_qh[12] ATTR_SECTION(".usb_qh"); usb_queue_head_t usb_qh[12] ATTR_ALIGNED(2048);
usb_transfer_descriptor_t usb_td[12] ATTR_SECTION(".usb_td"); 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_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)) #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; 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) { static void usb_wait_for_endpoint_priming_to_finish(const uint32_t mask) {
// Wait until controller has parsed new transfer descriptors and prepared // Wait until controller has parsed new transfer descriptors and prepared
// receive buffers. // 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( void usb_endpoint_disable(
const usb_endpoint_t* const endpoint const usb_endpoint_t* const endpoint
) { ) {
@ -148,6 +171,8 @@ void usb_endpoint_disable(
} else { } else {
USB0_ENDPTCTRL(endpoint_number) &= ~(USB0_ENDPTCTRL_RXE); USB0_ENDPTCTRL(endpoint_number) &= ~(USB0_ENDPTCTRL_RXE);
} }
usb_endpoint_clear_pending_interrupts(endpoint);
usb_endpoint_flush(endpoint);
} }
void usb_endpoint_prime( 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( void usb_endpoint_stall(
const usb_endpoint_t* const endpoint const usb_endpoint_t* const endpoint
) { ) {
@ -312,14 +348,6 @@ static void usb_disable_all_endpoints() {
USB0_ENDPTCTRL5 &= ~(USB0_ENDPTCTRL5_RXE | USB0_ENDPTCTRL5_TXE); 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( void usb_set_address_immediate(
const usb_device_t* const device, const usb_device_t* const device,
const uint_fast8_t address const uint_fast8_t address
@ -489,7 +517,7 @@ void usb_endpoint_schedule(
) { ) {
usb_transfer_descriptor_t* const td = usb_transfer_descriptor(endpoint->address); 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. // It may have been flushed due to an aborted transaction.
// TODO: This should be preceded by a flush? // TODO: This should be preceded by a flush?
while( usb_endpoint_is_ready(endpoint) ); while( usb_endpoint_is_ready(endpoint) );