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:
@ -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) );
|
||||||
|
Reference in New Issue
Block a user