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);
}
示例#2
0
/**
 * 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_otg_vbus_high();
	if (b_vbus_high) {
		udd_vbus_monitor_sleep_mode(false);
		udd_attach();
	} else {
		udd_vbus_monitor_sleep_mode(true);
		udd_detach();
	}
	UDC_VBUS_EVENT(b_vbus_high);
}
示例#3
0
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
}
示例#4
0
void udd_enable(void)
{
	uint8_t i;
	irqflags_t flags;

	// Sanity check Silicon revision
#if AVR8_PART_IS_DEFINED(ATxmega128A1U)
	// The part ATxmega128A1U Rev. J is not supported, please use new silicon revision.
	Assert(!(MCU_REVID < 0x0A));
#endif

#ifdef CONFIG_OSC_AUTOCAL_RC32MHZ_REF_OSC
# if CONFIG_OSC_AUTOCAL_RC32MHZ_REF_OSC == OSC_ID_USBSOF
	// RC oscillator calibration via USB Start Of Frame is not available
	// in low speed mode.
	// Thus, the calibration is disabled
	// when USB interface start in low speed mode
	DFLLRC32M.CTRL = 0;
# endif
#endif

#ifdef USB_DEVICE_LOW_SPEED
	// The USB hardware need of 6MHz in low speed mode
	sysclk_enable_usb(6);
	udd_set_low_speed();
#else
	// The USB hardware need of 48MHz in full speed mode
	sysclk_enable_usb(48);
	udd_set_full_speed();
#endif

// The XMEGA_A1U does not support the RC calibration through Keepalive (Low speed).
#if (!defined USB_DEVICE_LOW_SPEED) || (!XMEGA_A1U)
# ifdef CONFIG_OSC_AUTOCAL_RC32MHZ_REF_OSC
#   if CONFIG_OSC_AUTOCAL_RC32MHZ_REF_OSC == OSC_ID_USBSOF
	// The SOF calibration can be enabled
	DFLLRC32M.CTRL = DFLL_ENABLE_bm;
#   endif
# endif
#endif

	flags = cpu_irq_save();

	// Reset endpoints table
	for (i = 0; i < ((USB_DEVICE_MAX_EP + 1) * 2); i++) {
		udd_sram.ep_ctrl[i].CTRL = 0;
	}
#if (0!=USB_DEVICE_MAX_EP)
	// Reset internal variables
	for (i = 0; i < (USB_DEVICE_MAX_EP * 2); i++) {
		udd_ep_job[i].busy = false;
	}
#endif

	//** Enable USB hardware
	usb_pad_init();
	udd_set_nb_max_ep(USB_DEVICE_MAX_EP);
	udd_enable_interface();
	udd_enable_store_frame_number();
#if XMEGA_A1U
	Assert(((uint16_t)(&udd_sram) & 0x0F) == 0); /* check align on 16bit */
#else
	Assert(((uint16_t)(&udd_sram) & 0x01) == 0); /* check align on WORD */
#endif
	udd_set_ep_table_addr(udd_sram.ep_ctrl);
	// Enable TC fifo management
	udd_enable_fifo();
	udd_reset_fifo();
	// Enable Interrupt USB Device
	udd_enable_interrupt(UDD_USB_INT_LEVEL);

#ifndef UDD_NO_SLEEP_MGR
	// Initialize the sleep mode authorized for the USB suspend mode
	udd_b_idle = false;
	sleepmgr_lock_mode(USBC_SLEEP_MODE_USB_SUSPEND);
#endif

#ifndef USB_DEVICE_ATTACH_AUTO_DISABLE
	udd_attach();
#endif
	cpu_irq_restore(flags);
}
示例#5
0
void udd_enable(void)
{
	irqflags_t flags;

	flags = cpu_irq_save();

#ifdef UHD_ENABLE
	//* DUAL ROLE INITIALIZATION
	if (otg_dual_enable()) {
		// The current mode has been started by otg_dual_enable()
		cpu_irq_restore(flags);
		return;
	}
#else
	//* SINGLE DEVICE MODE INITIALIZATION
	sysclk_enable_usb();

	// Here, only the device mode is possible,
	// USBC interrupt is linked to UDD interrupt
	irq_register_handler(
#   ifdef FREERTOS_USED
			(__int_handler)
#   endif
			udd_interrupt, AVR32_USBC_IRQ, UDD_USB_INT_LEVEL);

	// Always authorize asynchronous USB interrupts to exit of sleep mode
	pm_asyn_wake_up_enable(AVR32_PM_AWEN_USBCWEN_MASK);
#endif

#if (defined USB_ID) && (defined UHD_ENABLE)
	// Check that the device mode is selected by ID pin
	if (!Is_otg_id_device()) {
		cpu_irq_restore(flags);
		return; // Device is not the current mode
	}
#else
	// ID pin not used then force device mode
	otg_disable_id_pin();
	otg_force_device_mode();
#endif

	// Enable USB hardware
	otg_enable_pad();
	otg_enable();
	otg_unfreeze_clock();
	(void)Is_otg_clock_frozen();

	memset((uint8_t *) udd_g_ep_table, 0, sizeof(udd_g_ep_table));
	otg_register_desc_tab(udd_g_ep_table);

	// Reset internal variables
#if (0!=USB_DEVICE_MAX_EP)
	{
		uint8_t i;
		for (i = 0; i < USB_DEVICE_MAX_EP; i++) {
			udd_ep_job[i].busy = false;
		}
	}
#endif

	// Set the USB speed requested by configuration file
#ifdef USB_DEVICE_LOW_SPEED
	udd_low_speed_enable();
#else
	udd_low_speed_disable();
#   ifdef USB_DEVICE_HS_SUPPORT
	udd_high_speed_enable();
#   else
	udd_high_speed_disable();
#   endif
#endif
	otg_ack_vbus_transition();
	// Force Vbus interrupt in case of Vbus always with a high level
	// This is possible with a short timing between a Host mode stop/start.
	if (Is_otg_vbus_high()) {
		otg_raise_vbus_transition();
	}
	otg_enable_vbus_interrupt();
	otg_freeze_clock();

#ifndef UDD_NO_SLEEP_MGR
	// Initialize the sleep mode authorized for the USB suspend mode
	udd_b_idle = false;
	sleepmgr_lock_mode(USBC_SLEEP_MODE_USB_SUSPEND);
#endif

#if UC3L3_L4
#  ifndef USB_DEVICE_ATTACH_AUTO_DISABLE
	udd_attach();
#  endif	
#endif	

	cpu_irq_restore(flags);
}
示例#6
0
void udd_enable(void)
{
	irqflags_t flags;

	flags = cpu_irq_save();

#ifdef UHD_ENABLE
	// DUAL ROLE INITIALIZATION
	if (otg_dual_enable()) {
		// The current mode has been started by otg_dual_enable()
		cpu_irq_restore(flags);
		return;
	}
#else
	// SINGLE DEVICE MODE INITIALIZATION
	sysclk_enable_usb();
	pmc_enable_periph_clk(ID_UOTGHS);

	// Here, only the device mode is possible, then link UHDP interrupt to UDD interrupt
	NVIC_SetPriority((IRQn_Type) ID_UOTGHS, USB_INT_LEVEL);
	NVIC_EnableIRQ((IRQn_Type) ID_UOTGHS);

	// Always authorize asynchrony USB interrupts to exit of sleep mode
	// For SAM USB wake up device except BACKUP mode
	pmc_set_fast_startup_input(PMC_FSMR_USBAL);
#endif

#if (OTG_ID_IO) && (defined UHD_ENABLE)
	// Check that the device mode is selected by ID pin
	if (!Is_otg_id_device()) {
		cpu_irq_restore(flags);
		return; // Device is not the current mode
	}
#else
	// ID pin not used and force device mode
	otg_force_device_mode();
#endif
	// Enable USB hardware
	otg_enable();

	// Reset internal variables
#if (0!=USB_DEVICE_MAX_EP)
	udd_ep_job_table_reset();
#endif

#ifndef UDD_NO_SLEEP_MGR
	if (!udd_b_sleep_initialized) {
		udd_b_sleep_initialized = true;
		// Initialize the sleep mode authorized for the USB suspend mode
		udd_b_idle = false;
		sleepmgr_lock_mode(UHDP_SLEEP_MODE_USB_SUSPEND);
	} else {
		udd_sleep_mode(false); // Enter idle mode
	}
#endif

#if OTG_VBUS_IO
	/* Initialize VBus monitor */
	otg_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_otg_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);
}
示例#7
0
void udd_enable(void)
{
	uint8_t i;
	irqflags_t flags;

	// Sanity check Silicon revision
#if AVR8_PART_IS_DEFINED(ATxmega128A1U)
	// The part ATxmega128A1U Rev. J is not supported, please use new silicon revision.
	Assert(!(MCU_REVID < 0x0A));
#endif

    uint8_t dfll_save = DFLLRC32M.CTRL;
    DFLLRC32M.CTRL = 0;

#ifdef USB_DEVICE_LOW_SPEED
	// The USB hardware need of 6MHz in low speed mode
	//sysclk_enable_usb(6);
	udd_set_low_speed();
#else
	// The USB hardware need of 48MHz in full speed mode
	//sysclk_enable_usb(48);
	udd_set_full_speed();
#endif

    DFLLRC32M.CTRL = dfll_save;

	flags = cpu_irq_save();

	// Reset endpoints table
	for (i = 0; i < ((USB_DEVICE_MAX_EP + 1) * 2); i++) {
		udd_sram.ep_ctrl[i].CTRL = 0;
	}
#if (0!=USB_DEVICE_MAX_EP)
	// Reset internal variables
	for (i = 0; i < (USB_DEVICE_MAX_EP * 2); i++) {
		udd_ep_job[i].busy = false;
	}
#endif

	//** Enable USB hardware
	usb_pad_init();
	udd_set_nb_max_ep(USB_DEVICE_MAX_EP);
	udd_enable_interface();
	udd_enable_store_frame_number();
#if XMEGA_A1U
	Assert(((uint16_t)(&udd_sram) & 0x0F) == 0); /* check align on 16bit */
#else
	Assert(((uint16_t)(&udd_sram) & 0x01) == 0); /* check align on WORD */
#endif
	udd_set_ep_table_addr(udd_sram.ep_ctrl);
	// Enable TC fifo management
	udd_enable_fifo();
	udd_reset_fifo();
	// Enable Interrupt USB Device
	udd_enable_interrupt(UDD_USB_INT_LEVEL);

#ifndef UDD_NO_SLEEP_MGR
	// Initialize the sleep mode authorized for the USB suspend mode
	udd_b_idle = false;
	sleepmgr_lock_mode(USBC_SLEEP_MODE_USB_SUSPEND);
#endif

#ifndef USB_DEVICE_ATTACH_AUTO_DISABLE
	udd_attach();
#endif
	cpu_irq_restore(flags);
}