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(); // Reset following interrupts flag udd_ack_reset(); udd_ack_sof(); // The first suspend interrupt must be forced udd_raise_suspend(); udd_ack_wake_up(); otg_freeze_clock(); cpu_irq_restore(flags); }
void udd_detach(void) { otg_unfreeze_clock(); // Detach device from the bus udd_detach_device(); otg_freeze_clock(); udd_sleep_mode(false); }
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(); // This section of clock check can be improved with a chek of // USB clock source via sysclk() #if UC3A3 // For parts with high speed feature, the "USABLE" clock is the UTMI clock, // and the UTMI clock is disabled in suspend mode. Thereby, the utmi clock // can't be checked when USB line is not attached or in suspend mode // But it is not a issue, because the clock source is the OSC #else // Check USB clock because the source can be a PLL while( !Is_clock_usable() ); #endif // Authorize attach if VBus is present udd_attach_device(); // (RESET_AND_WAKEUP) // After the attach and the first USB suspend, the following USB Reset time can be inferior to CPU restart clock time. // Thus, the USB Reset state is not detected and endpoint control is not allocated // In this case, a Reset is do automatically after attach. udc_reset(); // Reset USB Device Stack Core udd_reset_ep_ctrl(); // Reset endpoint control udd_ctrl_init(); // Reset endpoint control management // Enable USB line events udd_enable_reset_interrupt(); udd_enable_suspend_interrupt(); udd_enable_wake_up_interrupt(); #ifdef UDC_SOF_EVENT udd_enable_sof_interrupt(); #endif // Reset following interupts flag udd_ack_reset(); udd_ack_sof(); // 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); }
uint32_t UDD_Init(void) { uint32_t i; for (i = 0; i < MAX_ENDPOINTS; ++i) { ul_send_fifo_ptr[i] = 0; ul_recv_fifo_ptr[i] = 0; } // Enables the USB Clock pmc_enable_periph_clk(ID_UOTGHS); pmc_enable_upll_clock(); pmc_switch_udpck_to_upllck(0); // div=0+1 pmc_enable_udpck(); // Configure interrupts NVIC_SetPriority((IRQn_Type) ID_UOTGHS, 0UL); NVIC_EnableIRQ((IRQn_Type) ID_UOTGHS); // Always authorize asynchrone USB interrupts to exit from sleep mode // for SAM3 USB wake up device except BACKUP mode //pmc_set_fast_startup_input(PMC_FSMR_USBAL); // ID pin not used then force device mode otg_disable_id_pin(); otg_force_device_mode(); // Enable USB hardware otg_disable_pad(); otg_enable_pad(); otg_enable(); otg_unfreeze_clock(); // Check USB clock //while (!Is_otg_clock_usable()) // ; // Enable High Speed udd_low_speed_disable(); udd_high_speed_enable(); //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(); return 0UL ; }
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); }
void udd_disable(void) { irqflags_t flags; #ifdef UHD_ENABLE # if OTG_ID_IO if (Is_otg_id_host()) { // Freeze clock to switch mode otg_freeze_clock(); udd_detach(); otg_disable(); return; // Host mode running, ignore UDD disable } # else if (Is_otg_host_mode_forced()) { return; // Host mode running, ignore UDD disable } # endif #endif flags = cpu_irq_save(); otg_unfreeze_clock(); udd_detach(); #ifndef UDD_NO_SLEEP_MGR if (udd_b_sleep_initialized) { udd_b_sleep_initialized = false; sleepmgr_unlock_mode(UHDP_SLEEP_MODE_USB_SUSPEND); } #endif #ifndef UHD_ENABLE otg_disable(); sysclk_disable_usb(); pmc_disable_periph_clk(ID_UOTGHS); #endif cpu_irq_restore(flags); }
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, then link USBB interrupt to UDD interrupt irq_register_handler( #ifdef FREERTOS_USED (__int_handler) #endif udd_interrupt, AVR32_USBB_IRQ, UDD_USB_INT_LEVEL); // Always authorize asynchronous USB interrupts to exit of sleep mode pm_asyn_wake_up_enable(AVR32_PM_AWEN_USB_WAKEN_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(); // Reset internal variables #if (0!=USB_DEVICE_MAX_EP) udd_ep_job_table_reset(); #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(USBB_SLEEP_MODE_USB_SUSPEND); #endif 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 }
void udd_enable(void) { irqflags_t flags; sysclk_enable_usb(); flags = cpu_irq_save(); //** Enable USB hardware otg_disable(); (void)Is_otg_enabled(); #ifdef OTG // Check UID pin state before enter in USB device mode if (!Is_otg_id_device()) return FALSE; #else // Here, only the Device mode is possible, then link USBB interrupt to UDD interrupt irq_register_handler(udd_interrupt, AVR32_USBB_IRQ, UDD_USB_INT_LEVEL); otg_force_device_mode(); #endif otg_disable_pad(); otg_enable_pad(); otg_enable(); otg_unfreeze_clock(); (void)Is_otg_clock_frozen(); #if UC3A3 // For parts with high speed feature, the "USABLE" clock is the UTMI clock, // and the UTMI clock is disabled in suspend mode. Thereby, the utmi clock // can't be checked when USB line is not attached or in suspend mode #else // Check USB clock while( !Is_clock_usable() ); #endif // Reset internal variables #if (0!=USB_DEVICE_MAX_EP) udd_ep_job_table_reset(); #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 udd_enable_vbus_interrupt(); otg_freeze_clock(); // Always authorize asynchrone USB interrupts to exit of sleep mode AVR32_PM.AWEN.usb_waken = 1; #ifndef UDD_NO_SLEEP_MGR // Initialize the sleep mode authorized for the USB suspend mode udd_b_idle = false; sleepmgr_lock_mode(USBB_SLEEP_MODE_USB_SUSPEND); #endif cpu_irq_restore(flags); }
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; }
void udd_enable(void) { irqflags_t flags; sysclk_enable_usb(); flags = cpu_irq_save(); //** Enable USB hardware otg_disable(); (void)Is_otg_enabled(); #ifdef OTG // Check UID pin state before enter in USB device mode if (!Is_otg_id_device()) #warning returning bool but the function is void return FALSE; #else // Here, only the Device mode is possible, then link USBC interrupt to UDD interrupt irq_register_handler(udd_interrupt, AVR32_USBC_IRQ, UDD_USB_INT_LEVEL); otg_force_device_mode(); #endif otg_disable_pad(); otg_enable_pad(); otg_enable(); otg_unfreeze_clock(); (void)Is_otg_clock_frozen(); #if 0 // For parts with high speed feature, the "USABLE" clock is the UTMI clock, // and the UTMI clock is disabled in suspend mode. Thereby, the utmi clock // can't be checked when USB line is not attached or in suspend mode #else // Check USB clock while( !Is_clock_usable() ); #endif memset((uint8_t *) udd_g_ep_table, 0, sizeof(udd_g_ep_table)); Usb_set_desc_tab_addr_reg(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(); #endif # ifdef USB_DEVICE_HS_SUPPORT udd_high_speed_enable(); # else udd_high_speed_disable(); # endif udd_enable_vbus_interrupt(); otg_freeze_clock(); // Always authorize asynchronous USB interrupts to exit from sleep mode #if(!defined AVR32_PM_WITHOUT_AWEN) AVR32_PM.awen |= AVR32_PM_AWEN_USBCWEN_MASK; #endif #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 cpu_irq_restore(flags); }