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);
}
Example #3
0
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;
}