void udd_enable(void) { irqflags_t flags; flags = cpu_irq_save(); #if SAMG55 matrix_set_usb_device(); #endif // Enable USB hardware udd_enable_periph_ck(); sysclk_enable_usb(); // Cortex, uses NVIC, no need to register IRQ handler NVIC_SetPriority((IRQn_Type) ID_UDP, UDD_USB_INT_LEVEL); NVIC_EnableIRQ((IRQn_Type) ID_UDP); // Reset internal variables #if (0!=USB_DEVICE_MAX_EP) udd_ep_job_table_reset(); #endif // Always authorize asynchronous USB interrupts to exit of sleep mode pmc_set_fast_startup_input(PMC_FSMR_USBAL); #ifndef UDD_NO_SLEEP_MGR // Initialize the sleep mode authorized for the USB suspend mode udd_b_idle = false; sleepmgr_lock_mode(UDP_SLEEP_MODE_USB_SUSPEND); #endif #if UDD_VBUS_IO /* Initialize VBus monitor */ udd_vbus_init(udd_vbus_handler); udd_vbus_monitor_sleep_mode(true); /* Force Vbus interrupt when Vbus is always high * This is possible due to a short timing between a Host mode stop/start. */ if (Is_udd_vbus_high()) { udd_vbus_handler(USB_VBUS_PIO_ID, USB_VBUS_PIO_MASK); } #else # ifndef USB_DEVICE_ATTACH_AUTO_DISABLE udd_attach(); # endif #endif cpu_irq_restore(flags); }
/** * USB VBus pin change handler */ static void udd_vbus_handler(uint32_t id, uint32_t mask) { if (USB_VBUS_PIO_ID != id || USB_VBUS_PIO_MASK != mask) { return; } /* PIO interrupt status has been cleared, just detect level */ bool b_vbus_high = Is_udd_vbus_high(); if (b_vbus_high) { udd_ack_vbus_interrupt(true); udd_vbus_monitor_sleep_mode(false); udd_attach(); } else { udd_ack_vbus_interrupt(false); udd_vbus_monitor_sleep_mode(true); udd_detach(); } UDC_VBUS_EVENT(b_vbus_high); }
ISR(udd_interrupt, AVR32_USBB_IRQ_GROUP, UDD_USB_INT_LEVEL) #endif { #ifdef UDC_SOF_EVENT if (Is_udd_sof()) { udd_ack_sof(); UDC_SOF_EVENT(); goto udd_interrupt_end; } #endif 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 (0!=USB_DEVICE_MAX_EP) 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_clock_usable() ) { if(Is_udd_suspend()) break; // In case of USB state change in HS }; // 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_udd_vbus_transition()) { // Ack VBus transition and send status to high level otg_unfreeze_clock(); udd_ack_vbus_transition(); otg_freeze_clock(); #ifdef UDC_VBUS_EVENT UDC_VBUS_EVENT(Is_udd_vbus_high()); #endif goto udd_interrupt_end; } udd_interrupt_end: otg_data_memory_barrier(); return; }