void udd_attach(void) { irqflags_t flags; flags = cpu_irq_save(); // At startup the USB bus state is unknown, // therefore the state is considered IDLE to not miss any USB event udd_sleep_mode(true); otg_unfreeze_clock(); while( !Is_otg_clock_usable() ); // Authorize attach if Vbus is present udd_attach_device(); // Enable USB line events udd_enable_reset_interrupt(); udd_enable_suspend_interrupt(); udd_enable_wake_up_interrupt(); udd_enable_sof_interrupt(); #ifdef USB_DEVICE_HS_SUPPORT udd_enable_msof_interrupt(); #endif // Reset following interrupts flag udd_ack_reset(); udd_ack_sof(); udd_ack_msof(); // The first suspend interrupt must be forced #if UC3A3 // With UTMI, the first suspend is detected but must be cleared to reoccur interrupt udd_ack_suspend(); #else // The first suspend interrupt is not detected else raise it udd_raise_suspend(); #endif udd_ack_wake_up(); otg_freeze_clock(); cpu_irq_restore(flags); }
ISR(udd_interrupt, AVR32_USBB_IRQ_GROUP, UDD_USB_INT_LEVEL) # endif #endif { if (Is_udd_sof()) { udd_ack_sof(); if (Is_udd_full_speed_mode()) { udc_sof_notify(); } #ifdef UDC_SOF_EVENT UDC_SOF_EVENT(); #endif goto udd_interrupt_end; } if (Is_udd_msof()) { udd_ack_msof(); udc_sof_notify(); goto udd_interrupt_end; } if (udd_ctrl_interrupt()) goto udd_interrupt_end; // Interrupt acked by control endpoint managed #if (0 != USB_DEVICE_MAX_EP) if (udd_ep_interrupt()) goto udd_interrupt_end; // Interrupt acked by bulk/interrupt/isochronous endpoint managed #endif // USB bus reset detection if (Is_udd_reset()) { udd_ack_reset(); // Abort all jobs on-going #if (USB_DEVICE_MAX_EP != 0) udd_ep_job_table_kill(); #endif // Reset USB Device Stack Core udc_reset(); // Reset endpoint control udd_reset_ep_ctrl(); // Reset endpoint control management udd_ctrl_init(); goto udd_interrupt_end; } if (Is_udd_suspend_interrupt_enabled() && Is_udd_suspend()) { otg_unfreeze_clock(); // The suspend interrupt is automatic acked when a wakeup occur udd_disable_suspend_interrupt(); udd_enable_wake_up_interrupt(); otg_freeze_clock(); // Mandatory to exit of sleep mode after a wakeup event udd_sleep_mode(false); // Enter in SUSPEND mode #ifdef UDC_SUSPEND_EVENT UDC_SUSPEND_EVENT(); #endif goto udd_interrupt_end; } if (Is_udd_wake_up_interrupt_enabled() && Is_udd_wake_up()) { // Ack wakeup interrupt and enable suspend interrupt otg_unfreeze_clock(); // Check USB clock ready after suspend and eventually sleep USB clock while( !Is_otg_clock_usable() ); // The wakeup interrupt is automatic acked when a suspend occur udd_disable_wake_up_interrupt(); udd_enable_suspend_interrupt(); udd_sleep_mode(true); // Enter in IDLE mode #ifdef UDC_RESUME_EVENT UDC_RESUME_EVENT(); #endif goto udd_interrupt_end; } if (Is_otg_vbus_transition()) { // Ack Vbus transition and send status to high level otg_unfreeze_clock(); otg_ack_vbus_transition(); otg_freeze_clock(); #ifndef USB_DEVICE_ATTACH_AUTO_DISABLE if (Is_otg_vbus_high()) { udd_attach(); } else { udd_detach(); } #endif #ifdef UDC_VBUS_EVENT UDC_VBUS_EVENT(Is_otg_vbus_high()); #endif goto udd_interrupt_end; } udd_interrupt_end: otg_data_memory_barrier(); #if (defined FREERTOS_USED) // Since we do not know if the user callbacks have used or not FreeRTOS APIs, let's // consider that exiting from the USB interrupt will require a context switch. return pdTRUE; #else return; #endif }
ISR(udd_interrupt, AVR32_USBB_IRQ_GROUP, UDD_USB_INT_LEVEL) # endif #endif { if (Is_udd_sof()) { udd_ack_sof(); if (Is_udd_full_speed_mode()) { udc_sof_notify(); } #ifdef UDC_SOF_EVENT UDC_SOF_EVENT(); #endif goto udd_interrupt_end; } if (Is_udd_msof()) { udd_ack_msof(); udc_sof_notify(); goto udd_interrupt_end; } if (udd_ctrl_interrupt()) goto udd_interrupt_end; // Interrupt acked by control endpoint managed #if (0 != USB_DEVICE_MAX_EP) if (udd_ep_interrupt()) goto udd_interrupt_end; // Interrupt acked by bulk/interrupt/isochronous endpoint managed #endif // USB bus reset detection if (Is_udd_reset()) { udd_ack_reset(); // Abort all jobs on-going #if (USB_DEVICE_MAX_EP != 0) udd_ep_job_table_kill(); #endif // Reset USB Device Stack Core udc_reset(); // Reset endpoint control udd_reset_ep_ctrl(); // Reset endpoint control management udd_ctrl_init(); goto udd_interrupt_end; } if (Is_udd_suspend_interrupt_enabled() && Is_udd_suspend()) { otg_unfreeze_clock(); // The suspend interrupt is automatic acked when a wakeup occur udd_disable_suspend_interrupt(); udd_enable_wake_up_interrupt(); otg_freeze_clock(); // Mandatory to exit of sleep mode after a wakeup event udd_sleep_mode(false); // Enter in SUSPEND mode #ifdef UDC_SUSPEND_EVENT UDC_SUSPEND_EVENT(); #endif goto udd_interrupt_end; } if (Is_udd_wake_up_interrupt_enabled() && Is_udd_wake_up()) { // Ack wakeup interrupt and enable suspend interrupt otg_unfreeze_clock(); // Check USB clock ready after suspend and eventually sleep USB clock while( !Is_otg_clock_usable() ); // The wakeup interrupt is automatic acked when a suspend occur udd_disable_wake_up_interrupt(); udd_enable_suspend_interrupt(); udd_sleep_mode(true); // Enter in IDLE mode #ifdef UDC_RESUME_EVENT UDC_RESUME_EVENT(); #endif goto udd_interrupt_end; } if (Is_otg_vbus_transition()) { // Ack Vbus transition and send status to high level otg_unfreeze_clock(); otg_ack_vbus_transition(); otg_freeze_clock(); #ifdef UDC_VBUS_EVENT UDC_VBUS_EVENT(Is_otg_vbus_high()); #endif goto udd_interrupt_end; } udd_interrupt_end: otg_data_memory_barrier(); return; }