Пример #1
0
/**
 *  @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
// -----------------------------------------------------------------------------

}
Пример #2
0
//------------------------------------------------------------------------------
/// 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();
    }
}