//! usb_init_device. //! //! This function initializes the USB device controller and //! configures the Default Control Endpoint. //! //! //! @param none //! //! @return status //! U8 usb_init_device (void) { Usb_select_device(); if(Is_usb_id_device()) { Usb_select_endpoint(EP_CONTROL); if(!Is_usb_endpoint_enabled()) { #if (USB_LOW_SPEED_DEVICE==DISABLE) return usb_configure_endpoint(EP_CONTROL, \ TYPE_CONTROL, \ DIRECTION_OUT, \ SIZE_64, \ ONE_BANK, \ NYET_DISABLED); #else return usb_configure_endpoint(EP_CONTROL, \ TYPE_CONTROL, \ DIRECTION_OUT, \ SIZE_8, \ ONE_BANK, \ NYET_DISABLED); #endif } } return FALSE; }
//------------------------------------------------------------------------------ /// Initializes the USB process /// Depending on the mode supported (HOST/DEVICE/DUAL_ROLE) the function calls /// the coresponding USB mode initialization function //------------------------------------------------------------------------------ void usb_task_init(void) { // DUAL ROLE DEVICE USB MODE Otg_message_task_init(); // OTG program needs to display event messages to the user b_uut_device_state = B_IDLE; // init state machines variables device_state = DEVICE_UNATTACHED; otg_device_nb_hnp_retry = BDEV_HNP_NB_RETRY; Clear_all_user_request(); Usb_enable_uid_pin(); g_usb_mode=USB_MODE_UNDEFINED; if(Is_usb_id_device()) { g_usb_mode=USB_MODE_DEVICE; #ifdef MSD_PROJECT MSDDriver_Initialize(luns, numMedias); #else // HID HIDDMouseDriver_Initialize(); #endif id_changed_to_host_event = DISABLE; } else { Usb_send_event(EVT_USB_HOST_FUNCTION); g_usb_mode=USB_MODE_HOST; // Startup with ID=0, Ack ID pin transistion (default hwd start up is device mode) Usb_ack_id_transition(); Usb_enable_id_interrupt(); usb_host_task_init(); id_changed_to_host_event = ENABLE; } // Store current usb mode, for mode change detection g_old_usb_mode = g_usb_mode; }
//! usb_init_device //! //! This function initializes the USB device controller and //! configures the Default Control Endpoint. //! //! @return Status //! Status_bool_t usb_init_device(void) { return Is_usb_id_device() && !Is_usb_endpoint_enabled(EP_CONTROL) && Usb_configure_endpoint(EP_CONTROL, TYPE_CONTROL, DIRECTION_OUT, EP_CONTROL_LENGTH, SINGLE_BANK); }
/** * @brief Entry point of the USB mamnagement * * Depending on the USB mode supported (HOST/DEVICE/DUAL_ROLE) the function * calls the coresponding usb management function. * * @param none * * @return none */ void usb_task(void) { // ---- DUAL ROLE DEVICE USB MODE --------------------------------------------- #if ((USB_DEVICE_FEATURE == ENABLED)&& (USB_HOST_FEATURE == ENABLED)) if(Is_usb_id_device()) { g_usb_mode=USB_MODE_DEVICE;} else { g_usb_mode=USB_MODE_HOST;} // TODO !!! ID pin hot state change // Preliminary management: HARDWARE RESET !!! #if ( ID_PIN_CHANGE_GENERATE_RESET == ENABLE) // Hot ID transition generates wdt reset if((g_old_usb_mode!=g_usb_mode)) #ifndef AVRGCC {Wdt_change_16ms(); while(1); LOG_STR_CODE(log_id_change);} #else {Wdt_change_enable(); while(1); LOG_STR_CODE(log_id_change);} #endif #endif g_old_usb_mode=g_usb_mode; // Store current usb mode, for mode change detection // Depending on current usb mode, launch the correct usb task (device or host) switch(g_usb_mode) { case USB_MODE_DEVICE: usb_device_task(); break; case USB_MODE_HOST: usb_host_task(); break; case USB_MODE_UNDEFINED: // No break ! default: break; } // ----------------------------------------------------------------------------- // ---- DEVICE ONLY USB MODE --------------------------------------------------- #elif ((USB_DEVICE_FEATURE == ENABLED)&& (USB_HOST_FEATURE == DISABLE)) usb_device_task(); // ----------------------------------------------------------------------------- // ---- REDUCED HOST ONLY USB MODE --------------------------------------------- #elif ((USB_DEVICE_FEATURE == DISABLE)&& (USB_HOST_FEATURE == ENABLED)) usb_host_task(); // ----------------------------------------------------------------------------- //! ---- ERROR, NO MODE ENABLED ------------------------------------------------- #elif ((USB_DEVICE_FEATURE == DISABLE)&& (USB_HOST_FEATURE == DISABLE)) #error at least one of USB_DEVICE_FEATURE or USB_HOST_FEATURE should be enabled #error otherwise the usb task has nothing to do ... #endif // ----------------------------------------------------------------------------- }
/** * @brief This function initializes the USB process. * * Depending on the mode supported (HOST/DEVICE/DUAL_ROLE) the function * calls the coresponding usb mode initialization function * * @param none * * @return none */ void usb_task_init(void) { #if (USB_HOST_FEATURE == ENABLED && USB_DEVICE_FEATURE == ENABLED) U8 delay; #endif #if (USE_USB_PADS_REGULATOR==ENABLE) // Otherwise assume USB PADs regulator is not used Usb_enable_regulator(); #endif // ---- DUAL ROLE DEVICE USB MODE --------------------------------------------- #if ((USB_DEVICE_FEATURE == ENABLED)&& (USB_HOST_FEATURE == ENABLED)) Usb_enable_uid_pin(); delay=PORTA; g_usb_mode=USB_MODE_UNDEFINED; if(Is_usb_id_device()) { g_usb_mode=USB_MODE_DEVICE; usb_device_task_init(); } else { g_usb_mode=USB_MODE_HOST; Usb_ack_id_transition(); // REQUIRED !!! Startup with ID=0, Ack ID pin transistion (default hwd start up is device mode) #if ( ID_PIN_CHANGE_GENERATE_RESET == ENABLE) Usb_enable_id_interrupt(); #endif Enable_interrupt(); usb_host_task_init(); } g_old_usb_mode=g_usb_mode; // Store current usb mode, for mode change detection // ----------------------------------------------------------------------------- // ---- DEVICE ONLY USB MODE --------------------------------------------------- #elif ((USB_DEVICE_FEATURE == ENABLED)&& (USB_HOST_FEATURE == DISABLE)) Usb_force_device_mode(); usb_device_task_init(); // ----------------------------------------------------------------------------- // ---- REDUCED HOST ONLY USB MODE --------------------------------------------- #elif ((USB_DEVICE_FEATURE == DISABLE)&& (USB_HOST_FEATURE == ENABLED)) Usb_force_host_mode(); usb_host_task_init(); #elif ((USB_DEVICE_FEATURE == DISABLE)&& (USB_HOST_FEATURE == DISABLE)) #error at least one of USB_DEVICE_FEATURE or USB_HOST_FEATURE should be enabled #endif // ----------------------------------------------------------------------------- }
void usb_task(void) { // ---- DUAL-ROLE DEVICE/HOST USB MODE ----------------------------------------- #if USB_DEVICE_FEATURE == true && USB_HOST_FEATURE == true if (g_old_usb_mode != g_usb_mode) { if (Is_usb_id_device()) { usb_device_task_init(); }else{ private_sof_counter = 0; usb_host_task_init(); } g_old_usb_mode = g_usb_mode; // Store current USB mode, for mode change detection Usb_enable_id_interrupt(); Enable_global_interrupt(); } // Depending on current USB mode, launch the correct USB task (device or host) switch (g_old_usb_mode) { case USB_MODE_DEVICE: usb_device_task(); break; case USB_MODE_HOST: usb_host_task(); break; case USB_MODE_UNDEFINED: default: break; } // ----------------------------------------------------------------------------- // ---- DEVICE-ONLY USB MODE --------------------------------------------------- #elif USB_DEVICE_FEATURE == true usb_device_task(); // ----------------------------------------------------------------------------- // ---- REDUCED-HOST-ONLY USB MODE --------------------------------------------- #elif USB_HOST_FEATURE == true usb_host_task(); // ----------------------------------------------------------------------------- // ---- ERROR, NO MODE true ------------------------------------------------- #else #error At least one of USB_DEVICE_FEATURE and USB_HOST_FEATURE must be enabled #endif // ----------------------------------------------------------------------------- }
//------------------------------------------------------------------------------ /// Entry point of the USB mamnagement /// Depending on the USB mode supported (HOST/DEVICE/DUAL_ROLE) the function /// calls the coresponding USB management function //------------------------------------------------------------------------------ void usb_task(void) { // DUAL ROLE DEVICE USB MODE if(Is_usb_id_device()) { g_usb_mode = USB_MODE_DEVICE; } else { g_usb_mode = USB_MODE_HOST; } g_old_usb_mode = g_usb_mode; // Store current usb mode, for mode change detection // Depending on current usb mode, launch the correct usb task (device or host) // Configure OTG timers Set_otg_custom_timer(VBUSRISE_70MS); Set_otg_custom_timer(VBUSPULSE_40MS); Set_otg_custom_timer(VFALLTMOUT_131MS); Set_otg_custom_timer(SRPMINDET_100US); switch(g_usb_mode) { case USB_MODE_DEVICE: //usb_device_task(); //MSDDriver_StateMachine(); Scheduler_task_3(); break; case USB_MODE_HOST: if( pOTGDescriptor->bOTGADevSRPReaction == VBUS_PULSE) { Usb_select_vbus_srp_method(); } else { Usb_select_data_srp_method(); } usb_host_task(); // Handle Vbus overcurrent error (auto-disabled if not supported or not defined in board driver file) if (Is_vbus_overcurrent()) { Otg_print_new_event_message(OTGMSG_VBUS_SURCHARGE,OTG_TEMPO_3SEC); } break; case USB_MODE_UNDEFINED: // No break ! default: break; } Otg_message_task(); }
//! usb_init_device. //! //! This function initializes the USB device controller and //! configures the Default Control Endpoint. //! //! @returns Zero is returned if the device could not be initialized. A non-zero, //! positive number is returned if the initialization was successful. uint8_t usb_init_device (void) { Usb_select_device(); if(Is_usb_id_device()) { Usb_select_endpoint(EP_CONTROL); if(!Is_usb_endpoint_enabled()) { return usb_configure_endpoint(EP_CONTROL, \ TYPE_CONTROL, \ DIRECTION_OUT, \ SIZE_64, \ ONE_BANK, \ NYET_DISABLED); } } return false; }
void usb_task(void *pvParameters) { #endif // FREERTOS_USED // Register the USB interrupt handler to the interrupt controller and enable // the USB interrupt. Disable_global_interrupt(); INTC_register_interrupt((__int_handler)&usb_general_interrupt, AVR32_USBB_IRQ, USB_INT_LEV); Enable_global_interrupt(); #ifdef FREERTOS_USED while (true) { // Wait for the semaphore while (!xSemaphoreTake(usb_tsk_semphr, portMAX_DELAY)); #endif // FREERTOS_USED // ---- DUAL-ROLE DEVICE/HOST USB MODE ----------------------------------------- #if USB_DEVICE_FEATURE == true && USB_HOST_FEATURE == true #ifdef FREERTOS_USED if (usb_device_tsk) vTaskDelete(usb_device_tsk), usb_device_tsk = NULL; if (usb_host_tsk) vTaskDelete(usb_host_tsk), usb_host_tsk = NULL; #endif Usb_input_id_pin(); Usb_enable_id_pin(); if (Is_usb_id_device()) { g_usb_mode = USB_MODE_DEVICE; usb_device_task_init(); } else { private_sof_counter = 0; g_usb_mode = USB_MODE_HOST; usb_host_task_init(); } g_old_usb_mode = g_usb_mode; // Store current USB mode, for mode change detection Usb_raise_id_transition(); // Check no ID transition has been missed during initialization Usb_enable_id_interrupt(); Enable_global_interrupt(); // ----------------------------------------------------------------------------- // ---- DEVICE-ONLY USB MODE --------------------------------------------------- #elif USB_DEVICE_FEATURE == true #ifdef FREERTOS_USED if (usb_device_tsk) vTaskDelete(usb_device_tsk), usb_device_tsk = NULL; #endif Usb_force_device_mode(); usb_device_task_init(); // ----------------------------------------------------------------------------- // ---- REDUCED-HOST-ONLY USB MODE --------------------------------------------- #elif USB_HOST_FEATURE == true #ifdef FREERTOS_USED if (usb_host_tsk) vTaskDelete(usb_host_tsk), usb_host_tsk = NULL; #endif private_sof_counter = 0; Usb_force_host_mode(); usb_host_task_init(); // ----------------------------------------------------------------------------- // ---- ERROR, NO MODE true ------------------------------------------------- #else #error At least one of USB_DEVICE_FEATURE and USB_HOST_FEATURE must be enabled #endif // ----------------------------------------------------------------------------- #ifdef FREERTOS_USED } #endif }
ISR(usb_general_interrupt, AVR32_USBB_IRQ_GROUP, USB_INT_LEVEL) #endif { #ifdef FREERTOS_USED portBASE_TYPE task_woken = pdFALSE; #endif uint8_t i; /* avoid Cppcheck Warning */ UNUSED(i); // ---------- DEVICE/HOST events management ------------------------------------ #if USB_DEVICE_FEATURE == true && USB_HOST_FEATURE == true // ID pin change detection if (Is_usb_id_transition() && Is_usb_id_interrupt_enabled()) { g_usb_mode = (Is_usb_id_device()) ? USB_MODE_DEVICE : USB_MODE_HOST; Usb_ack_id_transition(); if (g_usb_mode != g_old_usb_mode) // Basic debounce { // Previously in device mode, check if disconnection was detected if (g_old_usb_mode == USB_MODE_DEVICE) { if (usb_connected) { // Device mode diconnection actions usb_connected = false; usb_configuration_nb = 0; Usb_vbus_off_action(); } } // Previously in host mode, check if disconnection was detected else if (Is_host_attached()) { // Host mode diconnection actions device_state = DEVICE_UNATTACHED; Host_device_disconnection_action(); } LOG_STR(log_pin_id_changed); Usb_send_event((Is_usb_device()) ? EVT_USB_DEVICE_FUNCTION : EVT_USB_HOST_FUNCTION); Usb_id_transition_action(); //! @todo ID pin hot state change!!! // Preliminary management: HARDWARE RESET!!! #if ID_PIN_CHANGE_GENERATE_RESET == ENABLE // Hot ID transition generates CPU reset Usb_disable(); Usb_disable_otg_pad(); #ifdef FREERTOS_USED // Release the semaphore in order to start a new device/host task taskENTER_CRITICAL(); xSemaphoreGiveFromISR(usb_tsk_semphr, &task_woken); taskEXIT_CRITICAL(); #else #if defined(CPU_RESET_CALLBACK) CPU_RESET_CALLBACK(); #endif Reset_CPU(); #endif #endif g_old_usb_mode = g_usb_mode; // Store current USB mode, for mode change detection } } #endif // End DEVICE/HOST FEATURE MODE // ---------- DEVICE events management ----------------------------------------- #if USB_DEVICE_FEATURE == true #if USB_HOST_FEATURE == true // If both device and host features are enabled, check if device mode is engaged // (accessing the USB registers of a non-engaged mode, even with load operations, // may corrupt USB FIFO data). if (Is_usb_device()) #endif { // VBus state detection if (Is_usb_vbus_transition() && Is_usb_vbus_interrupt_enabled()) { Usb_ack_vbus_transition(); if (Is_usb_vbus_high()) { usb_start_device(); Usb_send_event(EVT_USB_POWERED); Usb_vbus_on_action(); } else { Usb_unfreeze_clock(); Usb_detach(); usb_connected = false; usb_configuration_nb = 0; Usb_send_event(EVT_USB_UNPOWERED); Usb_vbus_off_action(); #ifdef FREERTOS_USED // Release the semaphore in order to start a new device/host task taskENTER_CRITICAL(); xSemaphoreGiveFromISR(usb_tsk_semphr, &task_woken); taskEXIT_CRITICAL(); #endif } } // Device Start-of-Frame received if (Is_usb_sof() && Is_usb_sof_interrupt_enabled()) { Usb_ack_sof(); Usb_sof_action(); } // Device Suspend event (no more USB activity detected) if (Is_usb_suspend() && Is_usb_suspend_interrupt_enabled()) { Usb_ack_suspend(); Usb_enable_wake_up_interrupt(); (void)Is_usb_wake_up_interrupt_enabled(); Usb_freeze_clock(); Usb_send_event(EVT_USB_SUSPEND); Usb_suspend_action(); } // Wake-up event (USB activity detected): Used to resume if (Is_usb_wake_up() && Is_usb_wake_up_interrupt_enabled()) { Usb_unfreeze_clock(); (void)Is_usb_clock_frozen(); Usb_ack_wake_up(); Usb_disable_wake_up_interrupt(); Usb_wake_up_action(); Usb_send_event(EVT_USB_WAKE_UP); } // Resume state bus detection if (Is_usb_resume() && Is_usb_resume_interrupt_enabled()) { Usb_disable_wake_up_interrupt(); Usb_ack_resume(); Usb_disable_resume_interrupt(); Usb_resume_action(); Usb_send_event(EVT_USB_RESUME); } // USB bus reset detection if (Is_usb_reset() && Is_usb_reset_interrupt_enabled()) { Usb_ack_reset(); usb_init_device(); Usb_reset_action(); Usb_send_event(EVT_USB_RESET); } } #endif // End DEVICE FEATURE MODE // ---------- HOST events management ------------------------------------------- #if USB_HOST_FEATURE == true #if USB_DEVICE_FEATURE == true // If both device and host features are enabled, check if host mode is engaged // (accessing the USB registers of a non-engaged mode, even with load operations, // may corrupt USB FIFO data). else #endif { // The device has been disconnected if (Is_host_device_disconnection() && Is_host_device_disconnection_interrupt_enabled()) { host_disable_all_pipes(); Host_ack_device_disconnection(); #if USB_HOST_PIPE_INTERRUPT_TRANSFER == ENABLE reset_it_pipe_str(); #endif #ifdef HOST_VBUS_LOW_TIMEOUT cpu_set_timeout(HOST_VBUS_LOW_TIMEOUT, &timer_vbus_low); device_state = DEVICE_VBUS_LOW; #else device_state = DEVICE_UNATTACHED; #endif LOG_STR(log_device_disconnected); Usb_send_event(EVT_HOST_DISCONNECTION); Host_device_disconnection_action(); #ifdef FREERTOS_USED // Release the semaphore in order to start a new device/host task taskENTER_CRITICAL(); xSemaphoreGiveFromISR(usb_tsk_semphr, &task_woken); taskEXIT_CRITICAL(); #endif } // Device connection if (Is_host_device_connection() && Is_host_device_connection_interrupt_enabled()) { Host_ack_device_connection(); host_disable_all_pipes(); Usb_send_event(EVT_HOST_CONNECTION); Host_device_connection_action(); } // Host Start-of-Frame has been sent if (Is_host_sof() && Is_host_sof_interrupt_enabled()) { Host_ack_sof(); Usb_send_event(EVT_HOST_SOF); private_sof_counter++; // Delay time-out management for interrupt tranfer mode in host mode #if USB_HOST_PIPE_INTERRUPT_TRANSFER == ENABLE && TIMEOUT_DELAY_ENABLE == ENABLE if (private_sof_counter >= 250) // Count 250 ms (SOF @ 1 ms) { private_sof_counter = 0; for (i = 0; i < MAX_PEP_NB; i++) { if (it_pipe_str[i].enable && ++it_pipe_str[i].timeout > TIMEOUT_DELAY && Host_get_pipe_type(i) != TYPE_INTERRUPT) { it_pipe_str[i].enable = false; it_pipe_str[i].status = PIPE_DELAY_TIMEOUT; Host_reset_pipe(i); if (!is_any_interrupt_pipe_active() && !g_sav_int_sof_enable) // If no more transfer is armed { Host_disable_sof_interrupt(); } it_pipe_str[i].handler(PIPE_DELAY_TIMEOUT, it_pipe_str[i].nb_byte_processed); } } } #endif Host_sof_action(); } // Host Wake-up has been received if (Is_host_hwup() && Is_host_hwup_interrupt_enabled()) { // CAUTION: HWUP can be cleared only when USB clock is active (not frozen)! //! @todo Implement this on the silicon version //Pll_start_auto(); // First Restart the PLL for USB operation //Wait_pll_ready(); // Make sure PLL is locked Usb_unfreeze_clock(); // Enable clock on USB interface (void)Is_usb_clock_frozen(); // Make sure USB interface clock is enabled Host_disable_hwup_interrupt(); // Wake-up interrupt should be disabled as host is now awoken! Host_ack_hwup(); // Clear HWUP interrupt flag Usb_send_event(EVT_HOST_HWUP); // Send software event Host_hwup_action(); // Map custom action } Host_int_action(); while ((i = Host_get_interrupt_pipe_number()) < MAX_PEP_NB) { if (Is_host_in_received(i) && Is_host_in_received_interrupt_enabled(i)) { Host_freeze_pipe(i); Host_disable_in_received_interrupt(i); } } #if defined(USB_HIGH_SPEED_SUPPORT) && USB_HIGH_SPEED_SUPPORT == true && \ defined(PIPE_AUDIO_IN) // Workaround - freeze the IN audio pipe if (Is_host_in_received(PIPE_AUDIO_IN)) { extern void workaround_freeze_iso_in(void); workaround_freeze_iso_in(); } #endif // USB_HIGH_SPEED_SUPPORT == true #if USB_HOST_PIPE_INTERRUPT_TRANSFER == ENABLE // Host pipe interrupts while ((i = Host_get_interrupt_pipe_number()) < MAX_PEP_NB) usb_pipe_interrupt(i); #endif } #endif // End HOST FEATURE MODE #ifdef FREERTOS_USED return task_woken; #endif }
__interrupt void usb_general_interrupt() #endif { #if (USB_HOST_PIPE_INTERRUPT_TRANSFER == ENABLE) U8 i; U8 save_pipe_nb; #endif // ---------- DEVICE events management ----------------------------------- #if (USB_DEVICE_FEATURE == ENABLED) // - Device start of frame received if (Is_usb_sof() && Is_sof_interrupt_enabled()) { Usb_ack_sof(); Usb_sof_action(); } #ifdef WA_USB_SUSPEND_PERTUBATION // - Device Suspend event (no more USB activity detected) if (Is_usb_suspend() && Is_suspend_interrupt_enabled()) { usb_suspended=TRUE; Usb_ack_wake_up(); // clear wake up to detect next event Usb_send_event(EVT_USB_SUSPEND); Usb_ack_suspend(); Usb_enable_wake_up_interrupt(); Usb_disable_resume_interrupt(); Usb_freeze_clock(); Stop_pll(); Usb_suspend_action(); } // - Wake up event (USB activity detected): Used to resume if (Is_usb_wake_up() && Is_wake_up_interrupt_enabled()) { if(Is_pll_ready()==FALSE) { Pll_start_auto(); Wait_pll_ready(); } Usb_unfreeze_clock(); Usb_ack_wake_up(); if(usb_suspended) { Usb_enable_resume_interrupt(); Usb_enable_reset_interrupt(); while(Is_usb_wake_up()) { Usb_ack_wake_up(); } usb_delay_ms(2); if(Is_usb_sof() || Is_usb_resume() || Is_usb_reset() ) { Usb_disable_wake_up_interrupt(); Usb_wake_up_action(); Usb_send_event(EVT_USB_WAKE_UP); Usb_enable_suspend_interrupt(); Usb_enable_resume_interrupt(); Usb_enable_reset_interrupt(); } else // Workarround to make the USB enter power down mode again (spurious transcient detected on the USB lines) { Usb_ack_wake_up(); // clear wake up to detect next event Usb_send_event(EVT_USB_SUSPEND); Usb_enable_wake_up_interrupt(); Usb_disable_resume_interrupt(); Usb_freeze_clock(); Stop_pll(); Usb_suspend_action(); } } } // - Resume state bus detection if (Is_usb_resume() && Is_resume_interrupt_enabled()) { usb_suspended = FALSE; Usb_disable_wake_up_interrupt(); Usb_ack_resume(); Usb_disable_resume_interrupt(); Usb_resume_action(); Usb_send_event(EVT_USB_RESUME); } #else // - Device Suspend event (no more USB activity detected) if (Is_usb_suspend() && Is_suspend_interrupt_enabled()) { // Remote wake-up handler if ((remote_wakeup_feature == ENABLED) && (usb_configuration_nb != 0)) { Usb_disable_suspend_interrupt(); Usb_ack_wake_up(); Usb_enable_wake_up_interrupt(); Stop_pll(); Usb_freeze_clock(); Usb_suspend_action(); // After that user can execute "Usb_initiate_remote_wake_up()" to initiate a remote wake-up // Note that the suspend interrupt flag SUSPI must still be set to enable upstream resume // So the SUSPE enable bit must be cleared to avoid redundant interrupt // **************** // Please note also that is Vbus is lost during an upstream resume (Host disconnection), // the RMWKUP bit (used to initiate remote wake up and that is normally cleared by hardware when sent) // remains set after the event, so that a good way to handle this feature is : // Usb_unfreeze_clock(); // Usb_initiate_remote_wake_up(); // while (Is_usb_pending_remote_wake_up()) // { // if (Is_usb_vbus_low()) // { // // Emergency action (reset macro, etc.) if Vbus lost during resuming // break; // } // } // Usb_ack_remote_wake_up_start(); // **************** } else { // No remote wake-up supported Usb_ack_wake_up(); // clear wake up to detect next event Usb_send_event(EVT_USB_SUSPEND); Usb_ack_suspend(); // must be executed last (after Usb_suspend_action()) to allow upstream resume Usb_enable_wake_up_interrupt(); Usb_freeze_clock(); Stop_pll(); Usb_suspend_action(); } } // - Wake up event (USB activity detected): Used to resume if (Is_usb_wake_up() && Is_wake_up_interrupt_enabled()) { if(Is_pll_ready()==FALSE) { Pll_start_auto(); Wait_pll_ready(); } Usb_unfreeze_clock(); Usb_ack_wake_up(); Usb_disable_wake_up_interrupt(); Usb_wake_up_action(); Usb_send_event(EVT_USB_WAKE_UP); Usb_enable_suspend_interrupt(); } // - Resume state bus detection if (Is_usb_resume() && Is_resume_interrupt_enabled()) { Usb_disable_wake_up_interrupt(); Usb_ack_resume(); Usb_disable_resume_interrupt(); Usb_resume_action(); Usb_send_event(EVT_USB_RESUME); } #endif // - USB bus reset detection if (Is_usb_reset()&& Is_reset_interrupt_enabled()) { Usb_ack_reset(); usb_init_device(); Usb_reset_action(); Usb_send_event(EVT_USB_RESET); } #endif// End DEVICE FEATURE MODE // ---------- HOST events management ----------------------------------- #if (USB_HOST_FEATURE == ENABLED && USB_DEVICE_FEATURE == ENABLED) // - ID pin change detection if(Is_usb_id_transition()&&Is_usb_id_interrupt_enabled()) { if(Is_usb_id_device()) { g_usb_mode=USB_MODE_DEVICE;} else { g_usb_mode=USB_MODE_HOST;} Usb_ack_id_transition(); if( g_usb_mode != g_old_usb_mode) // Basic Debounce { if(Is_usb_id_device()) // Going to device mode { Usb_send_event(EVT_USB_DEVICE_FUNCTION); } else // Going to host mode { Usb_send_event(EVT_USB_HOST_FUNCTION); } Usb_id_transition_action(); LOG_STR_CODE(log_id_change); #if ( ID_PIN_CHANGE_GENERATE_RESET == ENABLE) // Hot ID transition generates wdt reset wdtdrv_enable(WDTO_16MS); while(1); #endif } } #endif #if (USB_HOST_FEATURE == ENABLED) // - The device has been disconnected if(Is_device_disconnection() && Is_host_device_disconnection_interrupt_enabled()) { host_disable_all_pipe(); Host_ack_device_disconnection(); device_state=DEVICE_DISCONNECTED; Usb_send_event(EVT_HOST_DISCONNECTION); init_usb_tree(); LOG_STR_CODE(log_device_disconnect); Host_device_disconnection_action(); } // - Device connection if(Is_device_connection() && Is_host_device_connection_interrupt_enabled()) { Host_ack_device_connection(); host_disable_all_pipe(); Host_device_connection_action(); } // - Host Start of frame has been sent if (Is_host_sof() && Is_host_sof_interrupt_enabled()) { Host_ack_sof(); Usb_send_event(EVT_HOST_SOF); private_sof_counter++; #if (USB_HUB_SUPPORT==ENABLE) hub_interrupt_sof++; #endif // delay timeout management for interrupt tranfer mode in host mode #if ((USB_HOST_PIPE_INTERRUPT_TRANSFER==ENABLE) && (TIMEOUT_DELAY_ENABLE==ENABLE)) if (private_sof_counter>=250) // Count 1/4 sec { private_sof_counter=0; for(i=0;i<MAX_EP_NB;i++) { if(it_pipe_str[i].enable==ENABLE) { save_pipe_nb=Host_get_selected_pipe(); Host_select_pipe(i); if((++it_pipe_str[i].timeout>TIMEOUT_DELAY) && (Host_get_pipe_type()!=TYPE_INTERRUPT)) { it_pipe_str[i].enable=DISABLE; it_pipe_str[i].status=PIPE_DELAY_TIMEOUT; Host_stop_pipe_interrupt(i); if (is_any_interrupt_pipe_active()==FALSE) // If no more transfer is armed { if (g_sav_int_sof_enable==FALSE) { Host_disable_sof_interrupt(); } } it_pipe_str[i].handle(PIPE_DELAY_TIMEOUT,it_pipe_str[i].nb_byte_processed); } Host_select_pipe(save_pipe_nb); } } } #endif // (USB_HOST_PIPE_INTERRUPT_TRANSFER==ENABLE) && (TIMEOUT_DELAY_ENABLE==ENABLE)) Host_sof_action(); } // - Host Wake-up has been received if (Is_host_hwup() && Is_host_hwup_interrupt_enabled()) { Host_disable_hwup_interrupt(); // Wake up interrupt should be disable host is now wake up ! // CAUTION HWUP can be cleared only when USB clock is active (not frozen)! Pll_start_auto(); // First Restart the PLL for USB operation Wait_pll_ready(); // Get sure pll is lock Usb_unfreeze_clock(); // Enable clock on USB interface Host_ack_hwup(); // Clear HWUP interrupt flag Usb_send_event(EVT_HOST_HWUP); // Send software event Host_hwup_action(); // Map custom action } #endif // End HOST FEATURE MODE }
/** * @brief Entry point of the USB mamnagement * * Depending on the USB mode supported (HOST/DEVICE/DUAL_ROLE) the function * calls the coresponding usb management function. * * @param none * * @return none */ void usb_task(void) { // ---- DUAL ROLE DEVICE USB MODE --------------------------------------------- #if ((USB_DEVICE_FEATURE == ENABLED)&& (USB_HOST_FEATURE == ENABLED)) if(Is_usb_id_device()) { g_usb_mode=USB_MODE_DEVICE;} else { g_usb_mode=USB_MODE_HOST;} if( g_old_usb_mode != g_usb_mode ) { // ID pin hot state change #if ( ID_PIN_CHANGE_GENERATE_RESET == ENABLE) // Hot ID transition generates wdt reset wdtdrv_enable(WDTO_16MS); while(1); #else // Hot ID transition reset USB mode Usb_ack_id_transition(); // REQUIRED if (Is_usb_id_host()) { Usb_disable_resume_interrupt(); Usb_disable_wake_up_interrupt(); Usb_disable_suspend_interrupt(); Usb_disable_reset_interrupt(); Usb_detach(); Usb_disable(); usb_host_task_init(); } else { Host_disable_device_disconnection_interrupt(); Host_disable_sof_interrupt(); Host_disable_sof(); Usb_disable_vbus(); Usb_disable_manual_vbus(); Usb_freeze_clock(); Usb_disable(); usb_device_task_init(); } #endif } // Store current usb mode, for mode change detection g_old_usb_mode=g_usb_mode; // Depending on current usb mode, launch the correct usb task (device or host) switch(g_usb_mode) { case USB_MODE_DEVICE: usb_device_task(); break; case USB_MODE_HOST: usb_host_task(); break; case USB_MODE_UNDEFINED: // No break ! default: break; } // ----------------------------------------------------------------------------- // ---- DEVICE ONLY USB MODE --------------------------------------------------- #elif ((USB_DEVICE_FEATURE == ENABLED)&& (USB_HOST_FEATURE == DISABLE)) usb_device_task(); // ----------------------------------------------------------------------------- // ---- REDUCED HOST ONLY USB MODE --------------------------------------------- #elif ((USB_DEVICE_FEATURE == DISABLE)&& (USB_HOST_FEATURE == ENABLED)) usb_host_task(); // ----------------------------------------------------------------------------- //! ---- ERROR, NO MODE ENABLED ------------------------------------------------- #elif ((USB_DEVICE_FEATURE == DISABLE)&& (USB_HOST_FEATURE == DISABLE)) #error at least one of USB_DEVICE_FEATURE or USB_HOST_FEATURE should be enabled #error otherwise the usb task has nothing to do ... #endif // ----------------------------------------------------------------------------- }
__interrupt void usb_general_interrupt() #endif { #if (USB_HOST_PIPE_INTERRUPT_TRANSFER == ENABLE) U8 i; U8 save_pipe_nb; #endif // ---------- DEVICE events management ----------------------------------- #if (USB_DEVICE_FEATURE == ENABLED) //- VBUS state detection if (Is_usb_vbus_transition() && Is_usb_vbus_interrupt_enabled()) { Usb_ack_vbus_transition(); if (Is_usb_vbus_high()) { usb_connected = TRUE; Usb_vbus_on_action(); Usb_send_event(EVT_USB_POWERED); Usb_enable_reset_interrupt(); usb_start_device(); Usb_attach(); } else { Usb_vbus_off_action(); usb_connected = FALSE; usb_configuration_nb = 0; Usb_send_event(EVT_USB_UNPOWERED); } } // - Device start of frame received if (Is_usb_sof() && Is_sof_interrupt_enabled()) { Usb_ack_sof(); Usb_sof_action(); } // - Device Suspend event (no more USB activity detected) if (Is_usb_suspend() && Is_suspend_interrupt_enabled()) { Usb_ack_suspend(); Usb_enable_wake_up_interrupt(); Usb_ack_wake_up(); // clear wake up to detect next event Usb_freeze_clock(); Usb_send_event(EVT_USB_SUSPEND); Usb_suspend_action(); } // - Wake up event (USB activity detected): Used to resume if (Is_usb_wake_up() && Is_swake_up_interrupt_enabled()) { Usb_unfreeze_clock(); Usb_ack_wake_up(); Usb_disable_wake_up_interrupt(); Usb_wake_up_action(); Usb_send_event(EVT_USB_WAKE_UP); } // - Resume state bus detection if (Is_usb_resume() && Is_resume_interrupt_enabled()) { Usb_disable_wake_up_interrupt(); Usb_ack_resume(); Usb_disable_resume_interrupt(); Usb_resume_action(); Usb_send_event(EVT_USB_RESUME); } // - USB bus reset detection if (Is_usb_reset()&& Is_reset_interrupt_enabled()) { Usb_ack_reset(); usb_init_device(); Usb_reset_action(); Usb_send_event(EVT_USB_RESET); } #endif// End DEVICE FEATURE MODE // ---------- HOST events management ----------------------------------- #if (USB_HOST_FEATURE == ENABLED && USB_DEVICE_FEATURE == ENABLED) // - ID pin change detection if(Is_usb_id_transition()&&Is_usb_id_interrupt_enabled()) { if(Is_usb_id_device()) { g_usb_mode=USB_MODE_DEVICE;} else { g_usb_mode=USB_MODE_HOST;} Usb_ack_id_transition(); if( g_usb_mode != g_old_usb_mode) // Basic Debounce { if(Is_usb_id_device()) // Going to device mode { Usb_send_event(EVT_USB_DEVICE_FUNCTION); } else // Going to host mode { Usb_send_event(EVT_USB_HOST_FUNCTION); } Usb_id_transition_action(); LOG_STR_CODE(log_id_change); #if ( ID_PIN_CHANGE_GENERATE_RESET == ENABLE) // Hot ID transition generates wdt reset #ifndef AVRGCC Wdt_change_16ms(); while(1); #else Wdt_change_enable(); while(1); #endif #endif } } #endif #if (USB_HOST_FEATURE == ENABLED) // - The device has been disconnected if(Is_device_disconnection() && Is_host_device_disconnection_interrupt_enabled()) { host_disable_all_pipe(); Host_ack_device_disconnection(); device_state=DEVICE_DISCONNECTED; Usb_send_event(EVT_HOST_DISCONNECTION); LOG_STR_CODE(log_device_disconnect); Host_device_disconnection_action(); } // - Device connection if(Is_device_connection() && Is_host_device_connection_interrupt_enabled()) { Host_ack_device_connection(); host_disable_all_pipe(); Host_device_connection_action(); } // - Host Start of frame has been sent if (Is_host_sof() && Is_host_sof_interrupt_enabled()) { Host_ack_sof(); Usb_send_event(EVT_HOST_SOF); private_sof_counter++; // delay timeout management for interrupt tranfer mode in host mode #if ((USB_HOST_PIPE_INTERRUPT_TRANSFER==ENABLE) && (TIMEOUT_DELAY_ENABLE==ENABLE)) if (private_sof_counter>=250) // Count 1/4 sec { private_sof_counter=0; for(i=0;i<MAX_EP_NB;i++) { if(it_pipe_str[i].enable==ENABLE) { save_pipe_nb=Host_get_selected_pipe(); Host_select_pipe(i); if((++it_pipe_str[i].timeout>TIMEOUT_DELAY) && (Host_get_pipe_type()!=TYPE_INTERRUPT)) { it_pipe_str[i].enable=DISABLE; it_pipe_str[i].status=PIPE_DELAY_TIMEOUT; Host_stop_pipe_interrupt(i); if (is_any_interrupt_pipe_active()==FALSE) // If no more transfer is armed { if (g_sav_int_sof_enable==FALSE) { Host_disable_sof_interrupt(); } } it_pipe_str[i].handle(PIPE_DELAY_TIMEOUT,it_pipe_str[i].nb_byte_processed); } Host_select_pipe(save_pipe_nb); } } } #endif // (USB_HOST_PIPE_INTERRUPT_TRANSFER==ENABLE) && (TIMEOUT_DELAY_ENABLE==ENABLE)) Host_sof_action(); } // - Host Wake-up has been received if (Is_host_hwup() && Is_host_hwup_interrupt_enabled()) { Host_disable_hwup_interrupt(); // Wake up interrupt should be disable host is now wake up ! // CAUTION HWUP can be cleared only when USB clock is active (not frozen)! Pll_start_auto(); // First Restart the PLL for USB operation Wait_pll_ready(); // Get sure pll is lock Usb_unfreeze_clock(); // Enable clock on USB interface Host_ack_hwup(); // Clear HWUP interrupt flag Usb_send_event(EVT_HOST_HWUP); // Send software event Host_hwup_action(); // Map custom action } #endif // End HOST FEATURE MODE }
//------------------------------------------------------------------------------ /// USB interrupt subroutine /// /// This function is called each time a USB interrupt occurs. /// The following USB DEVICE events are taken in charge: /// - VBus On / Off /// - Start Of Frame /// - Suspend /// - Wake-Up /// - Resume /// - Reset /// - Start of frame /// /// The following USB HOST events are taken in charge: /// - Device connection /// - Device Disconnection /// - Start Of Frame /// - ID pin change /// - SOF (or Keep alive in low speed) sent /// - Wake up on USB line detected /// /// The following USB HOST events are taken in charge: /// - HNP success (Role Exchange) /// - HNP failure (HNP Error) /// /// For each event, the user can launch an action by completing /// the associate define (See conf_usb.h file to add action upon events) /// /// Note: Only interrupts events that are enabled are processed //------------------------------------------------------------------------------ void usb_general_interrupt(void) { //TRACE_DEBUG("usb_general_interrupt\n\r"); // ---------- DEVICE events management ----------------------------------- // ----------------------------------------------------------------------- //- VBUS state detection // ----------------------------------------------------------------------- /// Arbitrer // ----------------------------------------------------------------------- if (Is_usb_vbus_transition() && Is_usb_vbus_interrupt_enabled() && Is_usb_id_device()) { Usb_ack_vbus_transition(); if (Is_usb_vbus_high()) { usb_connected = TRUE; Usb_vbus_on_action(); Usb_send_event(EVT_USB_POWERED); //jcb Usb_enable_reset_interrupt(); //usb_start_device(); USBD_Connect();//Usb_attach(); } else { TRACE_DEBUG("VBUS low\n\r"); USBD_Disconnect(); Usb_device_stop_hnp(); TRACE_DEBUG("Usb_select_device4\n\r"); Usb_select_device(); Clear_all_user_request(); Usb_vbus_off_action(); usb_connected = FALSE; usb_configuration_nb = 0; Usb_send_event(EVT_USB_UNPOWERED); } } // ----------------------------------------------------------------------- /// Device // ----------------------------------------------------------------------- // - Device start of frame received if (Is_usb_sof() && Is_sof_interrupt_enabled()) { // TRACE_DEBUG_WP("F"); // device Usb_ack_sof(); Usb_sof_action(); //sof_seen_in_session = TRUE; otg_last_sof_received = UDFNUML; // store last frame number received } // ----------------------------------------------------------------------- /// Device // ----------------------------------------------------------------------- // - Device Suspend event (no more USB activity detected) if (Is_usb_suspend()) { //&& Is_suspend_interrupt_enabled()) { //TRACE_DEBUG_WP("D\n\r"); // 1st : B-PERIPH mode ? if (Is_usb_id_device()) { // HNP Handler TRACE_DEBUG("HNP Handler\n\r"); //TRACE_DEBUG("device_state = %d\n\r", device_state); //TRACE_DEBUG("b_uut_device_state = %d\n\r", b_uut_device_state); if (Is_host_requested_hnp() // "b_hnp_enable" feature received && (Is_session_started_with_srp() || Is_user_requested_hnp() )) { if (otg_device_nb_hnp_retry == 0) { otg_features_supported &= ~USBFeatureRequest_OTG_B_HNP_ENABLE; } else { Ack_user_request_hnp(); Usb_ack_hnp_error_interrupt(); Usb_ack_role_exchange_interrupt(); Usb_enable_role_exchange_interrupt(); Usb_enable_hnp_error_interrupt(); Usb_device_initiate_hnp(); otg_device_nb_hnp_retry--; } } else { // Remote wake-up handler //TRACE_DEBUG("Remote wake-up handler\n\r"); //TRACE_DEBUG("device_state = %d\n\r", device_state); //TRACE_DEBUG("b_uut_device_state = %d\n\r", b_uut_device_state); if ((remote_wakeup_feature == ENABLE) && (usb_configuration_nb != 0)) { //TRACE_DEBUG("enabled\n\r"); // After that user can execute "Usb_initiate_remote_wake_up()" to initiate a remote wake-up // Note that the suspend interrupt flag SUSPI must still be set to enable upstream resume // So the SUSPE enable bit must be cleared to avoid redundant interrupt // **************** // Please note also that is Vbus is lost during an upstream resume (Host disconnection), // the RMWKUP bit (used to initiate remote wake up and that is normally cleared by hardware when sent) // remains set after the event, so that a good way to handle this feature is : // Usb_initiate_remote_wake_up(); // while (Is_usb_pending_remote_wake_up()) // { // if (Is_usb_vbus_low()) // { // // Emergency action (reset macro, etc.) if Vbus lost during resuming // break; // } // } // Usb_ack_remote_wake_up_start(); // **************** } else { //TRACE_DEBUG("disabled: %d %d\n\r", usb_configuration_nb, remote_wakeup_feature); // No remote wake-up supported Usb_send_event(EVT_USB_SUSPEND); } } } else { //TRACE_DEBUG("ici\n\r"); // A-PERIPH mode (will cause a session end, handled in usb_host_task.c) Usb_send_event(EVT_USB_SUSPEND); Usb_suspend_action(); //jcb Usb_ack_suspend(); } } // ----------------------------------------------------------------------- /// Device // ----------------------------------------------------------------------- // - Wake up event (USB activity detected): Used to resume if (Is_usb_wake_up() && Is_swake_up_interrupt_enabled()) { TRACE_DEBUG("W\n\r"); Usb_unfreeze_clock(); Usb_send_event(EVT_USB_WAKE_UP); } // ----------------------------------------------------------------------- /// Device // ----------------------------------------------------------------------- // - Resume state bus detection if (Is_usb_resume() && Is_resume_interrupt_enabled()) { TRACE_DEBUG("Resume state bus detect\n\r"); Usb_send_event(EVT_USB_RESUME); } // ----------------------------------------------------------------------- /// Device // ----------------------------------------------------------------------- // - USB bus reset detection if (Is_usb_reset()&& Is_reset_interrupt_enabled()) { TRACE_DEBUG_WP("B\n\r"); if (Is_usb_id_host()) { //TRACE_DEBUG_WP("id_host\n\r"); dev_configure_endpoint(EP_CONTROL, TYPE_CONTROL, DIRECTION_OUT, SIZE_64, ONE_BANK, NYET_DISABLED); } // First initialization is important to be synchronized // A reset must first have been received if (device_state == A_PERIPHERAL) { //TRACE_DEBUG_WP("r A_PERIPHERAL\n\r"); otg_last_sof_received = UDFNUML; otg_last_sof_stored = UDFNUML; Usb_ack_sof(); Usb_enable_sof_interrupt(); reset_received = TRUE; Timer16_set_counter(0); } Usb_reset_action(); Usb_send_event(EVT_USB_RESET); } // ---------- OTG events management ------------------------------------ // --------------------------------------------------------------------- // ----------------------------------------------------------------------- /// Arbitrer // ----------------------------------------------------------------------- // - OTG HNP Success detection if (Is_usb_role_exchange_interrupt() && Is_role_exchange_interrupt_enabled()) { // TRACE_DEBUG("OTG HNP detect\n\r"); Usb_ack_role_exchange_interrupt(); Host_ack_device_connection(); Host_ack_device_disconnection(); Otg_send_event(EVT_OTG_HNP_SUCCESS); End_session_with_srp(); Clear_otg_features_from_host(); if (Is_usb_id_host()) { // HOST (A- or B-) mode if ((device_state != A_PERIPHERAL) && (device_state != A_END_HNP_WAIT_VFALL)) { static volatile unsigned int jcb; // Current mode is A-HOST, device will take the A-PERIPHERAL role b_uut_device_state = B_PERIPHERAL; device_state = A_PERIPHERAL; usb_connected = FALSE; usb_configuration_nb = 0; Usb_select_device(); USBD_Connect();//Usb_attach(); Usb_unfreeze_clock(); Usb_disable_role_exchange_interrupt(); Usb_disable_hnp_error_interrupt(); Usb_device_stop_hnp(); Usb_ack_reset(); Timer16_set_counter(0); Usb_freeze_clock(); // USB clock can be freezed to slow down events and condition detection //jcb while (Timer16_get_counter_low() != 20); jcb=0; while( jcb <100000){ jcb++; } Usb_unfreeze_clock(); reset_received = FALSE; Usb_disable_sof_interrupt(); // will be set in the next OTG Timer IT (mandatory) Usb_enable_suspend_interrupt(); Usb_enable_reset_interrupt(); dev_configure_endpoint(EP_CONTROL, TYPE_CONTROL, DIRECTION_OUT, SIZE_64, ONE_BANK, NYET_DISABLED); } } else { // In B_HOST mode, the HNPREQ bit must not be cleared because it releases the bus in suspend mode (and sof can't start) if ((b_uut_device_state != B_HOST) && (b_uut_device_state != B_END_HNP_SUSPEND)) { static volatile unsigned int jcb2; // Current mode is B-PERIPHERAL, device will go into B-HOST role End_session_with_srp(); Clear_otg_features_from_host(); b_uut_device_state = B_HOST; device_state = DEVICE_ATTACHED; usb_connected = FALSE; usb_configuration_nb = 0; TRACE_DEBUG("Select host 3\n\r"); Usb_select_host(); TRACE_DEBUG("Send reset\n\r"); Host_send_reset(); // send the first RESET while (Host_is_reset()); TRACE_DEBUG("Reset passed\n\r"); jcb2=0; while( jcb2 <1000000){ jcb2++; } Host_enable_sof(); // start Host (sof) Usb_disable_role_exchange_interrupt(); Usb_disable_hnp_error_interrupt(); Clear_all_user_request(); TRACE_DEBUG("Select host 3\n\r"); } } } // ----------------------------------------------------------------------- /// Arbitrer // ----------------------------------------------------------------------- // - OTG HNP Failure detection if (Is_usb_hnp() && Is_usb_hnp_error_interrupt()&& Is_hnp_error_interrupt_enabled()) { TRACE_DEBUG("OTG HNP failure\n\r"); Usb_device_stop_hnp(); Usb_disable_role_exchange_interrupt(); Usb_disable_hnp_error_interrupt(); Usb_ack_hnp_error_interrupt(); if (Is_usb_id_device()) { Otg_send_event(EVT_OTG_HNP_ERROR); Clear_all_user_request(); } } // ---------- HOST events management ----------------------------------- // --------------------------------------------------------------------- // ----------------------------------------------------------------------- /// Arbitrer // ----------------------------------------------------------------------- // - ID pin change detection if(Is_usb_id_transition()&&Is_usb_id_interrupt_enabled()) { TRACE_DEBUG("ID pin change\n\r"); TRACE_DEBUG("device_state = %d\n\r", device_state); TRACE_DEBUG("b_uut_device_state = %d\n\r", b_uut_device_state); Usb_device_stop_hnp(); Clear_all_user_request(); if(Is_usb_id_device()) { g_usb_mode = USB_MODE_DEVICE; } else { g_usb_mode = USB_MODE_HOST; } Usb_ack_id_transition(); if( g_usb_mode != g_old_usb_mode) { // Basic Debounce if(Is_usb_id_device()) { // Going into device mode Usb_send_event(EVT_USB_DEVICE_FUNCTION); b_uut_device_state = B_IDLE; device_state = DEVICE_UNATTACHED; id_changed_to_host_event = DISABLE; } else { // Going into host mode b_uut_device_state = B_IDLE; device_state = DEVICE_UNATTACHED; Usb_send_event(EVT_USB_HOST_FUNCTION); id_changed_to_host_event = ENABLE; } Usb_id_transition_action(); TRACE_INFO("Pin Id changed\n\r"); } } // ----------------------------------------------------------------------- /// Host // ----------------------------------------------------------------------- // - The device has been disconnected // JCB to be fix if(Is_device_disconnection() && Is_host_device_disconnection_interrupt_enabled()) { TRACE_DEBUG("device disconnect\n\r"); host_disable_all_pipe(); Host_ack_device_disconnection(); device_state=DEVICE_DISCONNECTED; Usb_send_event(EVT_HOST_DISCONNECTION); TRACE_INFO("Device disconnected\n\r"); Host_device_disconnection_action(); Clear_all_user_request(); } // ----------------------------------------------------------------------- /// Host // ----------------------------------------------------------------------- // - Device connection if(Is_device_connection() && Is_host_device_connection_interrupt_enabled()) { TRACE_DEBUG("device connect\n\r"); Host_ack_device_connection(); host_disable_all_pipe(); Host_device_connection_action(); } // ----------------------------------------------------------------------- /// Host // ----------------------------------------------------------------------- // - Host Start of frame has been sent if (Is_host_sof() && Is_host_sof_interrupt_enabled()) { //TRACE_DEBUG_WP("_"); // host Host_ack_sof(); Usb_send_event(EVT_HOST_SOF); private_sof_counter++; // delay timeout management for interrupt tranfer mode in host mode #if ((USB_HOST_PIPE_INTERRUPT_TRANSFER==ENABLE) && (TIMEOUT_DELAY_ENABLE==ENABLE)) if (private_sof_counter>=250) { // Count 1/4 sec private_sof_counter=0; for(i=0;i<MAX_EP_NB;i++) { if(it_pipe_str[i].enable==ENABLE) { save_pipe_nb=Host_get_selected_pipe(); Host_select_pipe(i); if((++it_pipe_str[i].timeout>TIMEOUT_DELAY) && (Host_get_pipe_type()!=TYPE_INTERRUPT)) { it_pipe_str[i].enable=DISABLE; it_pipe_str[i].status=PIPE_DELAY_TIMEOUT; Host_stop_pipe_interrupt(i); if (is_any_interrupt_pipe_active()==FALSE) { // If no more transfer is armed if (g_sav_int_sof_enable==FALSE) { Host_disable_sof_interrupt(); } } it_pipe_str[i].handle(PIPE_DELAY_TIMEOUT,it_pipe_str[i].nb_byte_processed); } Host_select_pipe(save_pipe_nb); } } } #endif // (USB_HOST_PIPE_INTERRUPT_TRANSFER==ENABLE) && (TIMEOUT_DELAY_ENABLE==ENABLE)) Host_sof_action(); } // ----------------------------------------------------------------------- /// Host // ----------------------------------------------------------------------- // - Host Wake-up has been received if (Is_host_hwup() && Is_host_hwup_interrupt_enabled()) { TRACE_DEBUG("Host wake up\n\r"); Host_disable_hwup_interrupt(); // Wake up interrupt should be disable host is now wake up ! Host_disable_remote_wakeup_interrupt(); // CAUTION HWUP can be cleared only when USB clock is active (not frozen)! Usb_unfreeze_clock(); // Enable clock on USB interface Host_enable_sof(); // start sending SOF Host_ack_hwup(); // Clear HWUP interrupt flag Host_ack_remote_wakeup(); Usb_send_event(EVT_HOST_HWUP); // Send software event Usb_send_event(EVT_HOST_REMOTE_WAKEUP); Host_hwup_action(); // Map custom action if (Is_usb_hnp()) { Usb_host_reject_hnp(); Usb_disable_hnp_error_interrupt(); Usb_disable_role_exchange_interrupt(); } Host_send_resume(); } // ----------------------------------------------------------------------- /// Host // ----------------------------------------------------------------------- // Remote Wake Up has been received if (Is_host_remote_wakeup_interrupt_enabled() && Is_host_remote_wakeup()) { TRACE_DEBUG("Remote wake up\n\r"); Host_disable_remote_wakeup_interrupt(); Host_disable_hwup_interrupt(); Host_ack_remote_wakeup(); Host_ack_hwup(); // Clear HWUP interrupt flag Usb_unfreeze_clock(); // Enable clock on USB interface Host_enable_sof(); // start sending SOF Usb_send_event(EVT_HOST_REMOTE_WAKEUP); Usb_send_event(EVT_HOST_HWUP); // Send software event if (Is_usb_hnp()) { Usb_host_reject_hnp(); Usb_disable_hnp_error_interrupt(); Usb_disable_role_exchange_interrupt(); } Host_send_resume(); } }
__interrupt #endif static void usb_general_interrupt(void) #endif { #ifdef FREERTOS_USED portBASE_TYPE task_woken = pdFALSE; #endif #if USB_HOST_FEATURE == true && USB_HOST_PIPE_INTERRUPT_TRANSFER == ENABLE U8 i; #endif // ---------- DEVICE/HOST events management ------------------------------------ #if USB_DEVICE_FEATURE == true && USB_HOST_FEATURE == true // ID pin change detection if (Is_usb_id_transition() && Is_usb_id_interrupt_enabled()) { g_usb_mode = (Is_usb_id_device()) ? USB_MODE_DEVICE : USB_MODE_HOST; Usb_ack_id_transition(); if (g_usb_mode != g_old_usb_mode) // Basic debounce { // Previously in device mode, check if disconnection was detected if (g_old_usb_mode == USB_MODE_DEVICE) { if (usb_connected) { // Device mode disconnection actions usb_connected = false; usb_configuration_nb = 0; Usb_vbus_off_action(); } } // Previously in host mode, check if disconnection was detected else if (Is_host_attached()) { // Host mode disconnection actions device_state = DEVICE_UNATTACHED; Host_device_disconnection_action(); } //LOG_STR(log_pin_id_changed); if (Is_usb_id_device() == USB_MODE_DEVICE) { LOG_STR(log_pin_id_changed_to_device); } else { LOG_STR(log_pin_id_changed_to_host); } Usb_send_event((Is_usb_device()) ? EVT_USB_DEVICE_FUNCTION : EVT_USB_HOST_FUNCTION); Usb_id_transition_action(); // Easier to recover from ID signal de-bounce and ID pin transitions by shutting down the USB and resetting state machine to re-init #if ID_PIN_CHANGE_SHUTDOWN_USB == ENABLE Usb_disable(); Usb_disable_otg_pad(); extern void UsbResetStateMachine(void); UsbResetStateMachine(); #ifdef FREERTOS_USED // Release the semaphore in order to start a new device/host task taskENTER_CRITICAL(); xSemaphoreGiveFromISR(usb_tsk_semphr, &task_woken); taskEXIT_CRITICAL(); #endif #endif #if ID_PIN_CHANGE_GENERATE_RESET == ENABLE Reset_CPU(); #endif } } #endif // End DEVICE/HOST FEATURE MODE // ---------- DEVICE events management ----------------------------------------- #if USB_DEVICE_FEATURE == true #if USB_HOST_FEATURE == true // If both device and host features are enabled, check if device mode is engaged // (accessing the USB registers of a non-engaged mode, even with load operations, // may corrupt USB FIFO data). if (Is_usb_device()) #endif { // VBus state detection if (Is_usb_vbus_transition() && Is_usb_vbus_interrupt_enabled()) { Usb_ack_vbus_transition(); if (Is_usb_vbus_high()) { usb_start_device(); Usb_send_event(EVT_USB_POWERED); Usb_vbus_on_action(); } else { Usb_unfreeze_clock(); Usb_detach(); usb_connected = false; usb_configuration_nb = 0; Usb_send_event(EVT_USB_UNPOWERED); Usb_vbus_off_action(); #ifdef FREERTOS_USED // Release the semaphore in order to start a new device/host task taskENTER_CRITICAL(); xSemaphoreGiveFromISR(usb_tsk_semphr, &task_woken); taskEXIT_CRITICAL(); #endif } } // Device Start-of-Frame received if (Is_usb_sof() && Is_usb_sof_interrupt_enabled()) { Usb_ack_sof(); Usb_sof_action(); } // Device Suspend event (no more USB activity detected) if (Is_usb_suspend() && Is_usb_suspend_interrupt_enabled()) { Usb_ack_suspend(); Usb_enable_wake_up_interrupt(); (void)Is_usb_wake_up_interrupt_enabled(); Usb_freeze_clock(); Usb_send_event(EVT_USB_SUSPEND); Usb_suspend_action(); } // Wake-up event (USB activity detected): Used to resume if (Is_usb_wake_up() && Is_usb_wake_up_interrupt_enabled()) { Usb_unfreeze_clock(); (void)Is_usb_clock_frozen(); Usb_ack_wake_up(); Usb_disable_wake_up_interrupt(); Usb_wake_up_action(); Usb_send_event(EVT_USB_WAKE_UP); } // Resume state bus detection if (Is_usb_resume() && Is_usb_resume_interrupt_enabled()) { Usb_disable_wake_up_interrupt(); Usb_ack_resume(); Usb_disable_resume_interrupt(); Usb_resume_action(); Usb_send_event(EVT_USB_RESUME); } // USB bus reset detection if (Is_usb_reset() && Is_usb_reset_interrupt_enabled()) { Usb_ack_reset(); usb_init_device(); Usb_reset_action(); Usb_send_event(EVT_USB_RESET); } } #endif // End DEVICE FEATURE MODE // ---------- HOST events management ------------------------------------------- #if USB_HOST_FEATURE == true #if USB_DEVICE_FEATURE == true // If both device and host features are enabled, check if host mode is engaged // (accessing the USB registers of a non-engaged mode, even with load operations, // may corrupt USB FIFO data). else #endif { // The device has been disconnected if (Is_host_device_disconnection() && Is_host_device_disconnection_interrupt_enabled()) { host_disable_all_pipes(); Host_ack_device_disconnection(); #if USB_HOST_PIPE_INTERRUPT_TRANSFER == ENABLE reset_it_pipe_str(); #endif device_state = DEVICE_UNATTACHED; LOG_STR(log_device_disconnected); Usb_send_event(EVT_HOST_DISCONNECTION); Host_device_disconnection_action(); #ifdef FREERTOS_USED // Release the semaphore in order to start a new device/host task taskENTER_CRITICAL(); xSemaphoreGiveFromISR(usb_tsk_semphr, &task_woken); taskEXIT_CRITICAL(); #endif } // Device connection if (Is_host_device_connection() && Is_host_device_connection_interrupt_enabled()) { Host_ack_device_connection(); host_disable_all_pipes(); Host_device_connection_action(); } // Host Start-of-Frame has been sent if (Is_host_sof() && Is_host_sof_interrupt_enabled()) { Host_ack_sof(); Usb_send_event(EVT_HOST_SOF); #if (USB_HIGH_SPEED_SUPPORT==true) if( Is_usb_full_speed_mode() ) { private_sof_counter++; }else{ private_sof_counter_HS++; if( 0 == (private_sof_counter_HS%8) ) { private_sof_counter++; } } #else private_sof_counter++; #endif // Delay time-out management for interrupt transfer mode in host mode #if USB_HOST_PIPE_INTERRUPT_TRANSFER == ENABLE && TIMEOUT_DELAY_ENABLE == ENABLE if (private_sof_counter >= 250) // Count 250 ms (SOF @ 1 ms) { private_sof_counter = 0; for (i = 0; i < MAX_PEP_NB; i++) { if (it_pipe_str[i].enable && ++it_pipe_str[i].timeout > TIMEOUT_DELAY && Host_get_pipe_type(i) != TYPE_INTERRUPT) { it_pipe_str[i].enable = false; it_pipe_str[i].status = PIPE_DELAY_TIMEOUT; Host_reset_pipe(i); if (!is_any_interrupt_pipe_active() && !g_sav_int_sof_enable) // If no more transfer is armed { Host_disable_sof_interrupt(); } it_pipe_str[i].handler(PIPE_DELAY_TIMEOUT, it_pipe_str[i].nb_byte_processed); } } } #endif Host_sof_action(); } // Host Wake-up has been received if (Is_host_hwup() && Is_host_hwup_interrupt_enabled()) { // CAUTION: HWUP can be cleared only when USB clock is active (not frozen)! //! @todo Implement this on the silicon version //Pll_start_auto(); // First Restart the PLL for USB operation //Wait_pll_ready(); // Make sure PLL is locked Usb_unfreeze_clock(); // Enable clock on USB interface (void)Is_usb_clock_frozen(); // Make sure USB interface clock is enabled Host_disable_hwup_interrupt(); // Wake-up interrupt should be disabled as host is now awoken! Host_ack_hwup(); // Clear HWUP interrupt flag Usb_send_event(EVT_HOST_HWUP); // Send software event Host_hwup_action(); // Map custom action } #if USB_HOST_PIPE_INTERRUPT_TRANSFER == ENABLE // Host pipe interrupts while ((i = Host_get_interrupt_pipe_number()) < MAX_PEP_NB) usb_pipe_interrupt(i); #endif } #endif // End HOST FEATURE MODE #ifdef FREERTOS_USED return task_woken; #endif }
//! @brief This function initializes the hardware/software resources required for ushell task. //! void ushell_task_init(uint32_t pba_hz) { uint8_t u8_i; //** Initialize the USART used by uShell with the configured parameters static const gpio_map_t SHL_USART_GPIO_MAP = { {SHL_USART_RX_PIN, SHL_USART_RX_FUNCTION}, {SHL_USART_TX_PIN, SHL_USART_TX_FUNCTION} }; #if (defined __GNUC__) set_usart_base((void *)SHL_USART); gpio_enable_module(SHL_USART_GPIO_MAP, sizeof(SHL_USART_GPIO_MAP) / sizeof(SHL_USART_GPIO_MAP[0])); usart_init(SHL_USART_BAUDRATE); #elif (defined __ICCAVR32__) static const usart_options_t SHL_USART_OPTIONS = { .baudrate = SHL_USART_BAUDRATE, .charlength = 8, .paritytype = USART_NO_PARITY, .stopbits = USART_1_STOPBIT, .channelmode = USART_NORMAL_CHMODE }; extern volatile avr32_usart_t *volatile stdio_usart_base; stdio_usart_base = SHL_USART; gpio_enable_module(SHL_USART_GPIO_MAP, sizeof(SHL_USART_GPIO_MAP) / sizeof(SHL_USART_GPIO_MAP[0])); usart_init_rs232(SHL_USART, &SHL_USART_OPTIONS, pba_hz); #endif //** Configure standard I/O streams as unbuffered. #if (defined __GNUC__) setbuf(stdin, NULL); #endif setbuf(stdout, NULL); // Set default state of ushell g_b_ushell_task_run = false; for( u8_i=0; u8_i<USHELL_HISTORY; u8_i++ ) { g_s_cmd_his[u8_i][0] = 0; // Set end of line for all cmd line history } fputs(MSG_EXIT, stdout ); g_u32_ushell_pba_hz = pba_hz; // Save value to manage a time counter during perform command #ifdef FREERTOS_USED xTaskCreate(ushell_task, configTSK_USHELL_NAME, configTSK_USHELL_STACK_SIZE, NULL, configTSK_USHELL_PRIORITY, NULL); #endif // FREERTOS_USED } #ifdef FREERTOS_USED /*! \brief Entry point of the explorer task management. * * This function performs uShell decoding to access file-system functions. * * \param pvParameters Unused. */ void ushell_task(void *pvParameters) #else /*! \brief Entry point of the explorer task management. * * This function performs uShell decoding to access file-system functions. */ void ushell_task(void) #endif { #ifdef FREERTOS_USED //** Inifinite loop for RTOS because it is a RTOS task portTickType xLastWakeTime; xLastWakeTime = xTaskGetTickCount(); while (true) { vTaskDelayUntil(&xLastWakeTime, configTSK_USHELL_PERIOD); #else //** No loop with the basic scheduler { #endif // FREERTOS_USED //** Check the USB mode and authorize/unauthorize ushell if(!g_b_ushell_task_run) { if( Is_usb_id_device() ) #ifdef FREERTOS_USED continue; // Continue in the RTOS task #else return; // Exit of the task scheduled #endif g_b_ushell_task_run = true; // Display shell startup fputs(MSG_WELCOME, stdout); ushell_cmd_nb_drive(); fputs(MSG_PROMPT, stdout); // Reset the embedded FS on ushell navigator and on first drive nav_reset(); nav_select( FS_NAV_ID_USHELL_CMD ); nav_drive_set( 0 ); }else{ if( Is_usb_id_device() ) { g_b_ushell_task_run = false; fputs(MSG_EXIT, stdout ); nav_exit(); #ifdef FREERTOS_USED continue; // Continue in the RTOS task #else return; // Exit of the task scheduled #endif } } //** Scan shell command if( !ushell_cmd_scan() ) #ifdef FREERTOS_USED continue; // Continue in the RTOS task #else return; // Exit of the task scheduled #endif //** Command ready then decode and execute this one switch( ushell_cmd_decode() ) { // Displays number of drives case CMD_NB_DRIVE: ushell_cmd_nb_drive(); break; // Displays free space information for all connected drives case CMD_DF: ushell_cmd_free_space(); break; // Formats disk case CMD_FORMAT: ushell_cmd_format(); break; // Mounts a drive (e.g. "b:") case CMD_MOUNT: ushell_cmd_mount(); break; // Displays the space information for current drive case CMD_SPACE: ushell_cmd_space(); break; // Lists the files present in current directory (e.g. "ls") case CMD_LS: ushell_cmd_ls(false); break; case CMD_LS_MORE: ushell_cmd_ls(true); break; // Enters in a directory (e.g. "cd folder_toto") case CMD_CD: ushell_cmd_cd(); break; // Enters in parent directory ("cd..") case CMD_UP: ushell_cmd_gotoparent(); break; // Displays a text file case CMD_CAT: ushell_cmd_cat(false); break; case CMD_CAT_MORE: ushell_cmd_cat(true); break; // Displays the help case CMD_HELP: ushell_cmd_help(); break; // Creates directory case CMD_MKDIR: ushell_cmd_mkdir(); break; // Creates file case CMD_TOUCH: ushell_cmd_touch(); break; // Deletes files or directories case CMD_RM: ushell_cmd_rm(); break; // Appends char to selected file case CMD_APPEND: ushell_cmd_append_file(); break; // Index routines (= specific shortcut from ATMEL FileSystem) case CMD_SET_ID: g_mark_index = nav_getindex(); break; case CMD_GOTO_ID: nav_gotoindex( &g_mark_index ); break; // Copies file to other location case CMD_CP: ushell_cmd_copy(); break; // Renames file case CMD_MV: ushell_cmd_rename(); break; // Synchronize folders case CMD_SYNC: ushell_cmd_sync(); break; case CMD_PERFORM: ushell_cmd_perform(); break; // USB commands #if USB_HOST_FEATURE == true case CMD_LS_USB: ushell_cmdusb_ls(); break; case CMD_USB_SUSPEND: ushell_cmdusb_suspend(); break; case CMD_USB_RESUME: ushell_cmdusb_resume(); break; #endif case CMD_NONE: break; // Unknown command default: fputs(MSG_ER_CMD_NOT_FOUND, stdout); break; } fputs(MSG_PROMPT, stdout); } } //! @brief Get the full command line to be interpreted. //! //! @return true, if a command is ready //! bool ushell_cmd_scan(void) { int c_key; // Something new of the UART ? if (usart_read_char(SHL_USART, &c_key) != USART_SUCCESS) { usart_reset_status(SHL_USART); return false; } if( 0 != g_u8_escape_sequence ) { //** Decode escape sequence if( 1 == g_u8_escape_sequence ) { if( 0x5B != c_key ) { g_u8_escape_sequence=0; return false; // Escape sequence cancel } g_u8_escape_sequence=2; } else { // Decode value of the sequence switch (c_key) { /* Note: OVERRUN error on USART with an RTOS and USART without interrupt management If you want support "Escape sequence", then you have to implement USART interrupt management case 0x41: // UP command ushell_clean_cmd_line(); ushell_history_up(); ushell_history_display(); break; case 0x42: // DOWN command ushell_clean_cmd_line(); ushell_history_down(); ushell_history_display(); break; */ default: // Ignore other command break; } g_u8_escape_sequence=0; // End of Escape sequence } return false; } //** Normal sequence switch (c_key) { //** Command validation case ASCII_CR: putchar(ASCII_CR); // Echo putchar(ASCII_LF); // Add new line flag g_s_cmd_his[g_u8_history_pos][g_u8_cmd_size]=0; // Add NULL terminator at the end of command line return true; //** Enter in escape sequence case ASCII_ESCAPE: g_u8_escape_sequence=1; break; //** backspace case ASCII_BKSPACE: if(g_u8_cmd_size>0) // Beginning of line ? { // Remove the last character on terminal putchar(ASCII_BKSPACE); // Send a backspace to go in previous character putchar(' '); // Send a space to erase previous character putchar(ASCII_BKSPACE); // Send a backspace to go in new end position (=previous character position) // Remove the last character on cmd line buffer g_u8_cmd_size--; } break; // History management case '!': ushell_clean_cmd_line(); ushell_history_up(); ushell_history_display(); break; case '$': ushell_clean_cmd_line(); ushell_history_down(); ushell_history_display(); break; //** Other char default: if( (0x1F<c_key) && (c_key<0x7F) && (USHELL_SIZE_CMD_LINE!=g_u8_cmd_size) ) { // Accept char putchar(c_key); // Echo g_s_cmd_his[g_u8_history_pos][g_u8_cmd_size++] = c_key; // append to cmd line } break; } return false; }
//! @brief Entry point of the USB device mamagement //! //! This function is the entry point of the USB management. Each USB //! event is checked here in order to launch the appropriate action. //! If a Setup request occurs on the Default Control Endpoint, //! the usb_process_request() function is call in the usb_standard_request.c file //! //! @param none //! //! @return none void usb_device_task(void) { #if (USB_OTG_FEATURE == ENABLED) // Check if a reset has been received if(Is_usb_event(EVT_USB_RESET)) { Usb_ack_event(EVT_USB_RESET); Usb_reset_endpoint(0); usb_configuration_nb=0; otg_b_device_state = B_IDLE; Clear_otg_features_from_host(); } // When OTG mode enabled, B-Device is managed thanks to its state machine switch (otg_b_device_state) { //------------------------------------------------------ // B_IDLE state // // - waits for Vbus to rise // - initiate SRP if asked by user // case B_IDLE: if (Is_usb_vbus_high()) { // Vbus rise usb_connected = TRUE; remote_wakeup_feature = DISABLED; usb_start_device(); Usb_vbus_on_action(); Usb_attach(); otg_b_device_state = B_PERIPHERAL; Ack_user_request_srp(); Clear_otg_features_from_host(); remote_wakeup_feature = DISABLED; End_session_with_srp(); if (Is_srp_sent_and_waiting_answer() && (sof_seen_in_session == TRUE)) { Ack_srp_sent_and_answer(); Otg_print_new_failure_message(OTGMSG_A_RESPONDED,OTG_TEMPO_2SEC); } Usb_enable_sof_interrupt(); } else { if (Is_user_requested_srp() && Is_usb_id_device()) { // User has requested a SRP Ack_user_request_srp(); if (!Is_srp_sent_and_waiting_answer()) { Pll_start_auto(); // reinit device mode Wait_pll_ready(); Usb_disable(); Usb_enable_uid_pin(); Usb_enable(); Usb_unfreeze_clock(); Usb_select_device(); Usb_attach(); otg_b_device_state = B_SRP_INIT; Usb_device_initiate_srp(); // hardware waits for initial condition (SE0, Session End level) sof_seen_in_session = FALSE; } } if ((Is_srp_sent_and_waiting_answer()) && (Is_tb_srp_counter_overflow())) { // SRP failed because A-Device did not respond End_session_with_srp(); Ack_srp_sent_and_answer(); Otg_print_new_failure_message(OTGMSG_SRP_A_NO_RESP,OTG_TEMPO_3SEC); } } break; //------------------------------------------------------ // B_SRP_INIT // // - a SRP has been initiated // - B-Device waits it is finished to initialize variables // case B_SRP_INIT: if (!Is_usb_device_initiating_srp()) { otg_b_device_state = B_IDLE; // SRP initiated, return to Idle state (wait for Vbus to rise) Srp_sent_and_waiting_answer(); Init_tb_srp_counter(); Start_session_with_srp(); Otg_print_new_event_message(OTGMSG_SRP_STARTED,TB_SRP_FAIL_MIN); } break; //------------------------------------------------------ // B_PERIPHERAL : the main state of OTG Peripheral // // - all events are interrupt-handled // - but they are saved and this function can execute alternate actions // - also handle user requests (disconnect) // // ====================================================================================== case B_PERIPHERAL: if (Is_otg_event(EVT_OTG_DEVICE_CONNECTED)) { Otg_ack_event(EVT_OTG_DEVICE_CONNECTED); // set on a SetConfiguration descriptor reception Otg_print_new_event_message(OTGMSG_CONNECTED_TO_A,OTG_TEMPO_4SEC); } if (Is_usb_event(EVT_USB_SUSPEND)) // SUSPEND state { // Suspend and HNP operations are handled in the interrupt functions } if (Is_srp_sent_and_waiting_answer() && (sof_seen_in_session == TRUE)) { Ack_srp_sent_and_answer(); Otg_print_new_failure_message(OTGMSG_A_RESPONDED,OTG_TEMPO_2SEC); } if ((Is_srp_sent_and_waiting_answer()) && (Is_tb_srp_counter_overflow())) { // SRP failed because A-Device did not respond End_session_with_srp(); Ack_srp_sent_and_answer(); Otg_print_new_failure_message(OTGMSG_SRP_A_NO_RESP,OTG_TEMPO_3SEC); } if (Is_usb_event(EVT_USB_RESUME) && !Is_usb_pending_remote_wake_up()) // RESUME signal detected { Usb_ack_event(EVT_USB_RESUME); Usb_ack_event(EVT_USB_SUSPEND); Usb_ack_remote_wake_up_start(); } if (Is_usb_event(EVT_USB_UNPOWERED)) { Usb_ack_event(EVT_USB_UNPOWERED); Clear_all_user_request(); otg_b_device_state = B_IDLE; } if(Is_usb_event(EVT_USB_RESET)) { Usb_ack_event(EVT_USB_RESET); Usb_reset_endpoint(0); usb_configuration_nb=0; Clear_otg_features_from_host(); } if (Is_otg_event(EVT_OTG_HNP_ERROR)) { Otg_ack_event(EVT_OTG_HNP_ERROR); Otg_print_new_failure_message(OTGMSG_DEVICE_NO_RESP,OTG_TEMPO_4SEC); PORTC &= ~0x10; } if (Is_user_requested_disc()) { Ack_user_request_disc(); if (Is_usb_id_device()) { Usb_detach(); Usb_freeze_clock(); while (Is_usb_vbus_high()); // wait for Vbus to be under Va_vbus_valid otg_b_device_state = B_IDLE; usb_configuration_nb = 0; usb_connected = FALSE; Clear_all_user_request(); } } break; //------------------------------------------------------ // B_HOST // // - state entered after an HNP success // - handle user requests (disconnection, suspend, hnp) // - call the "host_task()" for Host level handlers // // ====================================================================================== case B_HOST: if (Is_otg_event(EVT_OTG_DEV_UNSUPPORTED)) { Otg_ack_event(EVT_OTG_DEV_UNSUPPORTED); Clear_all_user_request(); otg_b_device_state = B_IDLE; device_state = DEVICE_UNATTACHED; } if (Is_user_requested_disc() || Is_user_requested_suspend() || Is_user_requested_hnp()) { Ack_user_request_disc(); // suspend and hnp requests cleared in B_END_HNP_SUSPEND stage Host_disable_sof(); // go into suspend mode Usb_host_reject_hnp(); otg_b_device_state = B_END_HNP_SUSPEND; Usb_ack_suspend(); Usb_enable_suspend_interrupt(); } if (Is_usb_event(EVT_USB_UNPOWERED)) { Usb_ack_event(EVT_USB_UNPOWERED); Usb_freeze_clock(); otg_b_device_state = B_IDLE; device_state = DEVICE_UNATTACHED; } usb_host_task(); // call the host task break; //------------------------------------------------------ // B_END_HNP_SUSPEND // // - device enters this state after being B_HOST, on a user request to stop bus activity (suspend, disconnect or hnp request) // - macro is reset to peripheral mode // // ====================================================================================== case B_END_HNP_SUSPEND: if (Is_usb_event(EVT_USB_SUSPEND)) { Usb_ack_event(EVT_USB_SUSPEND); Usb_device_stop_hnp(); Usb_select_device(); device_state = DEVICE_UNATTACHED; if (Is_user_requested_hnp() || Is_user_requested_suspend()) { otg_b_device_state = B_PERIPHERAL; Ack_user_request_suspend(); Ack_user_request_hnp(); } else { otg_b_device_state = B_IDLE; Usb_detach(); Usb_freeze_clock(); } } break; default: otg_b_device_state = B_IDLE; Clear_all_user_request(); device_state = DEVICE_UNATTACHED; break; } #else // Non-OTG exclusives Device operations // VBUS state detection if (Is_usb_vbus_high()&& (usb_connected==FALSE)) { usb_connected = TRUE; remote_wakeup_feature = DISABLED; Usb_vbus_on_action(); Usb_send_event(EVT_USB_POWERED); usb_start_device(); } if (Is_usb_vbus_low()&& (usb_connected==TRUE)) { usb_connected = FALSE; usb_configuration_nb = 0; Usb_send_event(EVT_USB_UNPOWERED); Usb_detach(); Usb_freeze_clock(); Usb_vbus_off_action(); } if(Is_usb_event(EVT_USB_RESET)) { Usb_ack_event(EVT_USB_RESET); Usb_reset_endpoint(0); usb_configuration_nb=0; } #endif // ======================================= // Common Standard Device Control Requests // ======================================= // - device enumeration process // - device control commands and features Usb_select_endpoint(EP_CONTROL); if (Is_usb_receive_setup()) { usb_process_request(); } }