- Main Page
- Modules
- Data Structures
- Files
- Related Pages

# usb_task.c

Go to the documentation of this file.

    00001 /*This file has been prepared for Doxygen automatic documentation generation.*/
    00025
    00026 /* Copyright (c) 2007, Atmel Corporation All rights reserved.
    00027  *
    00028  * Redistribution and use in source and binary forms, with or without
    00029  * modification, are permitted provided that the following conditions are met:
    00030  *
    00031  * 1. Redistributions of source code must retain the above copyright notice,
    00032  * this list of conditions and the following disclaimer.
    00033  *
    00034  * 2. Redistributions in binary form must reproduce the above copyright notice,
    00035  * this list of conditions and the following disclaimer in the documentation
    00036  * and/or other materials provided with the distribution.
    00037  *
    00038  * 3. The name of ATMEL may not be used to endorse or promote products derived
    00039  * from this software without specific prior written permission.
    00040  *
    00041  * THIS SOFTWARE IS PROVIDED BY ATMEL ``AS IS'' AND ANY EXPRESS OR IMPLIED
    00042  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
    00043  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE EXPRESSLY AND
    00044  * SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT,
    00045  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
    00046  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
    00047  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
    00048  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    00049  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
    00050  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    00051  */
    00052
    00053 //_____  I N C L U D E S ___________________________________________________
    00054
    00055 #include "config.h"
    00056 #include "conf_usb.h"
    00057 #include "usb_task.h"
    00058 #include "lib_mcu/usb/usb_drv.h"
    00059 #if ((USB_DEVICE_FEATURE == ENABLED))
    00060 #include "usb_descriptors.h"
    00061 #endif
    00062 #include "lib_mcu/power/power_drv.h"
    00063 #include "lib_mcu/wdt/wdt_drv.h"
    00064 #include "lib_mcu/pll/pll_drv.h"
    00065
    00066 #if ((USB_HOST_FEATURE == ENABLED))
    00067    #include "modules/usb/host_chap9/usb_host_task.h"
    00068    #include "modules/usb/host_chap9/usb_host_enum.h"
    00069    #if (USB_HOST_PIPE_INTERRUPT_TRANSFER == ENABLE)
    00070       extern U8 g_sav_int_sof_enable;
    00071    #endif
    00072 #endif
    00073
    00074 #if ((USB_DEVICE_FEATURE == ENABLED))
    00075    #include "modules/usb/device_chap9/usb_device_task.h"
    00076 #endif
    00077
    00078 #ifndef  USE_USB_PADS_REGULATOR
    00079    #error "USE_USB_PADS_REGULATOR" should be defined as ENABLE or DISABLE in conf_usb.h file
    00080 #endif
    00081
    00082 //_____ M A C R O S ________________________________________________________
    00083
    00084 #ifndef LOG_STR_CODE
    00085 #define LOG_STR_CODE(str)
    00086 #else
    00087 U8 code log_device_disconnect[]="Device Disconnected";
    00088 U8 code log_id_change[]="Pin Id Change";
    00089 #endif
    00090
    00091 //_____ D E F I N I T I O N S ______________________________________________
    00092
    00103 volatile U16 g_usb_event=0;
    00104
    00105
    00106 #if (USB_DEVICE_FEATURE == ENABLED)
    00113 extern bit   usb_connected;
    00114
    00121 extern U8    usb_configuration_nb;
    00122
    00127 extern U8 remote_wakeup_feature;
    00128
    00129 #ifdef WA_USB_SUSPEND_PERTUBATION
    00130 volatile U16 delay_usb;
    00131 void usb_delay_ms(U8 ms);
    00132 #endif
    00133 #endif
    00134
    00135
    00136 #if (USB_HOST_FEATURE == ENABLED)
    00143 volatile U8 private_sof_counter=0;
    00144
    00145    #if (USB_HOST_PIPE_INTERRUPT_TRANSFER == ENABLE)
    00146 extern volatile S_pipe_int   it_pipe_str[MAX_EP_NB];
    00147    #endif
    00148
    00149    #if (USB_HUB_SUPPORT==ENABLE)
    00150 extern volatile U8 hub_interrupt_sof;
    00151    #endif
    00152
    00153 #endif
    00154
    00155 #if ((USB_DEVICE_FEATURE == ENABLED)&& (USB_HOST_FEATURE == ENABLED))
    00161    U8 g_usb_mode=USB_MODE_UNDEFINED;
    00162    U8 g_old_usb_mode;
    00163 #endif
    00164
    00165 //_____ D E C L A R A T I O N S ____________________________________________
    00166
    00177 void usb_task_init(void)
    00178 {
    00179    #if (USB_HOST_FEATURE == ENABLED && USB_DEVICE_FEATURE == ENABLED)
    00180    U8 delay;
    00181    #endif
    00182
    00183    #if (USE_USB_PADS_REGULATOR==ENABLE)  // Otherwise assume USB PADs regulator is not used
    00184    Usb_enable_regulator();
    00185    #endif
    00186
    00187 // ---- DUAL ROLE DEVICE USB MODE ---------------------------------------------
    00188 #if ((USB_DEVICE_FEATURE == ENABLED)&& (USB_HOST_FEATURE == ENABLED))
    00189    Usb_enable_uid_pin();
    00190    delay=PORTA;
    00191    g_usb_mode=USB_MODE_UNDEFINED;
    00192    if(Is_usb_id_device())
    00193    {
    00194      g_usb_mode=USB_MODE_DEVICE;
    00195      usb_device_task_init();
    00196    }
    00197    else
    00198    {
    00199      g_usb_mode=USB_MODE_HOST;
    00200      Usb_ack_id_transition(); // REQUIRED !!! Startup with ID=0, Ack ID pin transistion (default hwd start up is device mode)
    00201 #if ( ID_PIN_CHANGE_GENERATE_RESET == ENABLE)
    00202      Usb_enable_id_interrupt();
    00203 #endif
    00204      Enable_interrupt();
    00205      usb_host_task_init();
    00206    }
    00207    g_old_usb_mode=g_usb_mode;   // Store current usb mode, for mode change detection
    00208 // -----------------------------------------------------------------------------
    00209
    00210 // ---- DEVICE ONLY USB MODE ---------------------------------------------------
    00211 #elif ((USB_DEVICE_FEATURE == ENABLED)&& (USB_HOST_FEATURE == DISABLE))
    00212    Usb_force_device_mode();
    00213    usb_device_task_init();
    00214 // -----------------------------------------------------------------------------
    00215
    00216 // ---- REDUCED HOST ONLY USB MODE ---------------------------------------------
    00217 #elif ((USB_DEVICE_FEATURE == DISABLE)&& (USB_HOST_FEATURE == ENABLED))
    00218    Usb_force_host_mode();
    00219    usb_host_task_init();
    00220 #elif ((USB_DEVICE_FEATURE == DISABLE)&& (USB_HOST_FEATURE == DISABLE))
    00221    #error  at least one of USB_DEVICE_FEATURE or USB_HOST_FEATURE should be enabled
    00222 #endif
    00223 // -----------------------------------------------------------------------------
    00224
    00225
    00226 }
    00227
    00238 void usb_task(void)
    00239 {
    00240 // ---- DUAL ROLE DEVICE USB MODE ---------------------------------------------
    00241 #if ((USB_DEVICE_FEATURE == ENABLED)&& (USB_HOST_FEATURE == ENABLED))
    00242    if(Is_usb_id_device())
    00243    { g_usb_mode=USB_MODE_DEVICE;}
    00244    else
    00245    { g_usb_mode=USB_MODE_HOST;}
    00246
    00247    if( g_old_usb_mode != g_usb_mode )
    00248    {
    00249       // ID pin hot state change
    00250 #if ( ID_PIN_CHANGE_GENERATE_RESET == ENABLE)
    00251       // Hot ID transition generates wdt reset
    00252       wdtdrv_enable(WDTO_16MS);
    00253       while(1);
    00254 #else
    00255       // Hot ID transition reset USB mode
    00256       Usb_ack_id_transition(); // REQUIRED
    00257       if (Is_usb_id_host())
    00258       {
    00259          Usb_disable_resume_interrupt();
    00260          Usb_disable_wake_up_interrupt();
    00261          Usb_disable_suspend_interrupt();
    00262          Usb_disable_reset_interrupt();
    00263          Usb_detach();
    00264          Usb_disable();
    00265          usb_host_task_init();
    00266       }
    00267       else
    00268       {
    00269          Host_disable_device_disconnection_interrupt();
    00270          Host_disable_sof_interrupt();
    00271          Host_disable_sof();
    00272          Usb_disable_vbus();
    00273          Usb_disable_manual_vbus();
    00274          Usb_freeze_clock();
    00275          Usb_disable();
    00276          usb_device_task_init();
    00277       }
    00278 #endif
    00279    }
    00280
    00281    // Store current usb mode, for mode change detection
    00282    g_old_usb_mode=g_usb_mode;
    00283
    00284    // Depending on current usb mode, launch the correct usb task (device or host)
    00285    switch(g_usb_mode)
    00286    {
    00287       case USB_MODE_DEVICE:
    00288       usb_device_task();
    00289       break;
    00290
    00291       case USB_MODE_HOST:
    00292       usb_host_task();
    00293       break;
    00294
    00295       case USB_MODE_UNDEFINED:  // No break !
    00296       default:
    00297       break;
    00298   }
    00299 // -----------------------------------------------------------------------------
    00300
    00301 // ---- DEVICE ONLY USB MODE ---------------------------------------------------
    00302 #elif ((USB_DEVICE_FEATURE == ENABLED)&& (USB_HOST_FEATURE == DISABLE))
    00303    usb_device_task();
    00304 // -----------------------------------------------------------------------------
    00305
    00306 // ---- REDUCED HOST ONLY USB MODE ---------------------------------------------
    00307 #elif ((USB_DEVICE_FEATURE == DISABLE)&& (USB_HOST_FEATURE == ENABLED))
    00308    usb_host_task();
    00309 // -----------------------------------------------------------------------------
    00310
    00312 #elif ((USB_DEVICE_FEATURE == DISABLE)&& (USB_HOST_FEATURE == DISABLE))
    00313    #error  at least one of USB_DEVICE_FEATURE or USB_HOST_FEATURE should be enabled
    00314    #error  otherwise the usb task has nothing to do ...
    00315 #endif
    00316 // -----------------------------------------------------------------------------
    00317
    00318 }
    00319
    00348 #ifdef __GNUC__
    00349  ISR(USB_GEN_vect)
    00350 #else
    00351 #pragma vector = USB_General_vect
    00352 __interrupt void usb_general_interrupt()
    00353 #endif
    00354 {
    00355    #if (USB_HOST_PIPE_INTERRUPT_TRANSFER == ENABLE)
    00356    U8 i;
    00357    U8 save_pipe_nb;
    00358    #endif
    00359 // ---------- DEVICE events management -----------------------------------
    00360 #if (USB_DEVICE_FEATURE == ENABLED)
    00361
    00362    // - Device start of frame received
    00363    if (Is_usb_sof() && Is_sof_interrupt_enabled())
    00364    {
    00365       Usb_ack_sof();
    00366       Usb_sof_action();
    00367    }
    00368 #ifdef WA_USB_SUSPEND_PERTUBATION
    00369   // - Device Suspend event (no more USB activity detected)
    00370    if (Is_usb_suspend() && Is_suspend_interrupt_enabled())
    00371    {
    00372       usb_suspended=TRUE;
    00373       Usb_ack_wake_up();                 // clear wake up to detect next event
    00374       Usb_send_event(EVT_USB_SUSPEND);
    00375       Usb_ack_suspend();
    00376       Usb_enable_wake_up_interrupt();
    00377       Usb_disable_resume_interrupt();
    00378       Usb_freeze_clock();
    00379       Stop_pll();
    00380       Usb_suspend_action();
    00381    }
    00382   // - Wake up event (USB activity detected): Used to resume
    00383    if (Is_usb_wake_up() && Is_wake_up_interrupt_enabled())
    00384    {
    00385       if(Is_pll_ready()==FALSE)
    00386       {
    00387          Pll_start_auto();
    00388          Wait_pll_ready();
    00389       }
    00390       Usb_unfreeze_clock();
    00391       Usb_ack_wake_up();
    00392       if(usb_suspended)
    00393       {
    00394          Usb_enable_resume_interrupt();
    00395          Usb_enable_reset_interrupt();
    00396          while(Is_usb_wake_up())
    00397          {
    00398             Usb_ack_wake_up();
    00399          }
    00400          usb_delay_ms(2);
    00401          if(Is_usb_sof() || Is_usb_resume() || Is_usb_reset() )
    00402          {
    00403             Usb_disable_wake_up_interrupt();
    00404             Usb_wake_up_action();
    00405             Usb_send_event(EVT_USB_WAKE_UP);
    00406             Usb_enable_suspend_interrupt();
    00407             Usb_enable_resume_interrupt();
    00408             Usb_enable_reset_interrupt();
    00409
    00410          }
    00411          else // Workarround to make the USB enter power down mode again (spurious transcient detected on the USB lines)
    00412          {
    00413             Usb_ack_wake_up();                 // clear wake up to detect next event
    00414             Usb_send_event(EVT_USB_SUSPEND);
    00415             Usb_enable_wake_up_interrupt();
    00416             Usb_disable_resume_interrupt();
    00417             Usb_freeze_clock();
    00418             Stop_pll();
    00419             Usb_suspend_action();
    00420          }
    00421       }
    00422    }
    00423   // - Resume state bus detection
    00424    if (Is_usb_resume() && Is_resume_interrupt_enabled())
    00425    {
    00426       usb_suspended = FALSE;
    00427       Usb_disable_wake_up_interrupt();
    00428       Usb_ack_resume();
    00429       Usb_disable_resume_interrupt();
    00430       Usb_resume_action();
    00431       Usb_send_event(EVT_USB_RESUME);
    00432    }
    00433 #else
    00434   // - Device Suspend event (no more USB activity detected)
    00435    if (Is_usb_suspend() && Is_suspend_interrupt_enabled())
    00436    {
    00437       // Remote wake-up handler
    00438       if ((remote_wakeup_feature == ENABLED) && (usb_configuration_nb != 0))
    00439       {
    00440         Usb_disable_suspend_interrupt();
    00441         Usb_ack_wake_up();
    00442         Usb_enable_wake_up_interrupt();
    00443         Stop_pll();
    00444         Usb_freeze_clock();
    00445         Usb_suspend_action();
    00446
    00447         // After that user can execute "Usb_initiate_remote_wake_up()" to initiate a remote wake-up
    00448         // Note that the suspend interrupt flag SUSPI must still be set to enable upstream resume
    00449         // So the SUSPE enable bit must be cleared to avoid redundant interrupt
    00450         // ****************
    00451         // Please note also that is Vbus is lost during an upstream resume (Host disconnection),
    00452         // the RMWKUP bit (used to initiate remote wake up and that is normally cleared by hardware when sent)
    00453         // remains set after the event, so that a good way to handle this feature is :
    00454         //            Usb_unfreeze_clock();
    00455         //            Usb_initiate_remote_wake_up();
    00456         //            while (Is_usb_pending_remote_wake_up())
    00457         //            {
    00458         //              if (Is_usb_vbus_low())
    00459         //              {
    00460         //                // Emergency action (reset macro, etc.) if Vbus lost during resuming
    00461         //                break;
    00462         //              }
    00463         //            }
    00464         //            Usb_ack_remote_wake_up_start();
    00465         // ****************
    00466       }
    00467       else
    00468       {
    00469         // No remote wake-up supported
    00470          Usb_ack_wake_up();                 // clear wake up to detect next event
    00471          Usb_send_event(EVT_USB_SUSPEND);
    00472          Usb_ack_suspend();  // must be executed last (after Usb_suspend_action()) to allow upstream resume
    00473          Usb_enable_wake_up_interrupt();
    00474          Usb_freeze_clock();
    00475          Stop_pll();
    00476          Usb_suspend_action();
    00477       }
    00478    }
    00479   // - Wake up event (USB activity detected): Used to resume
    00480    if (Is_usb_wake_up() && Is_wake_up_interrupt_enabled())
    00481    {
    00482       if(Is_pll_ready()==FALSE)
    00483       {
    00484          Pll_start_auto();
    00485          Wait_pll_ready();
    00486       }
    00487       Usb_unfreeze_clock();
    00488       Usb_ack_wake_up();
    00489       Usb_disable_wake_up_interrupt();
    00490       Usb_wake_up_action();
    00491       Usb_send_event(EVT_USB_WAKE_UP);
    00492       Usb_enable_suspend_interrupt();
    00493    }
    00494   // - Resume state bus detection
    00495    if (Is_usb_resume() && Is_resume_interrupt_enabled())
    00496    {
    00497       Usb_disable_wake_up_interrupt();
    00498       Usb_ack_resume();
    00499       Usb_disable_resume_interrupt();
    00500       Usb_resume_action();
    00501       Usb_send_event(EVT_USB_RESUME);
    00502    }
    00503 #endif
    00504   // - USB bus reset detection
    00505    if (Is_usb_reset()&& Is_reset_interrupt_enabled())
    00506    {
    00507       Usb_ack_reset();
    00508       usb_init_device();
    00509       Usb_reset_action();
    00510       Usb_send_event(EVT_USB_RESET);
    00511    }
    00512 #endif// End DEVICE FEATURE MODE
    00513
    00514 // ---------- HOST events management -----------------------------------
    00515 #if (USB_HOST_FEATURE == ENABLED && USB_DEVICE_FEATURE == ENABLED)
    00516   // - ID pin change detection
    00517    if(Is_usb_id_transition()&&Is_usb_id_interrupt_enabled())
    00518    {
    00519       if(Is_usb_id_device())
    00520       { g_usb_mode=USB_MODE_DEVICE;}
    00521       else
    00522       { g_usb_mode=USB_MODE_HOST;}
    00523       Usb_ack_id_transition();
    00524       if( g_usb_mode != g_old_usb_mode) // Basic Debounce
    00525       {
    00526          if(Is_usb_id_device()) // Going to device mode
    00527          {
    00528             Usb_send_event(EVT_USB_DEVICE_FUNCTION);
    00529          }
    00530          else                   // Going to host mode
    00531          {
    00532             Usb_send_event(EVT_USB_HOST_FUNCTION);
    00533          }
    00534          Usb_id_transition_action();
    00535          LOG_STR_CODE(log_id_change);
    00536          #if ( ID_PIN_CHANGE_GENERATE_RESET == ENABLE)
    00537          // Hot ID transition generates wdt reset
    00538          wdtdrv_enable(WDTO_16MS);
    00539          while(1);
    00540          #endif
    00541       }
    00542    }
    00543 #endif
    00544 #if (USB_HOST_FEATURE == ENABLED)
    00545   // - The device has been disconnected
    00546    if(Is_device_disconnection() && Is_host_device_disconnection_interrupt_enabled())
    00547    {
    00548       host_disable_all_pipe();
    00549       Host_ack_device_disconnection();
    00550       device_state=DEVICE_DISCONNECTED;
    00551       Usb_send_event(EVT_HOST_DISCONNECTION);
    00552       init_usb_tree();
    00553       LOG_STR_CODE(log_device_disconnect);
    00554       Host_device_disconnection_action();
    00555    }
    00556   // - Device connection
    00557    if(Is_device_connection() && Is_host_device_connection_interrupt_enabled())
    00558    {
    00559       Host_ack_device_connection();
    00560       host_disable_all_pipe();
    00561       Host_device_connection_action();
    00562    }
    00563   // - Host Start of frame has been sent
    00564    if (Is_host_sof() && Is_host_sof_interrupt_enabled())
    00565    {
    00566       Host_ack_sof();
    00567       Usb_send_event(EVT_HOST_SOF);
    00568       private_sof_counter++;
    00569 #if (USB_HUB_SUPPORT==ENABLE)
    00570       hub_interrupt_sof++;
    00571 #endif
    00572
    00573       // delay timeout management for interrupt tranfer mode in host mode
    00574       #if ((USB_HOST_PIPE_INTERRUPT_TRANSFER==ENABLE) && (TIMEOUT_DELAY_ENABLE==ENABLE))
    00575       if (private_sof_counter>=250)   // Count 1/4 sec
    00576       {
    00577          private_sof_counter=0;
    00578          for(i=0;i<MAX_EP_NB;i++)
    00579          {
    00580             if(it_pipe_str[i].enable==ENABLE)
    00581             {
    00582                save_pipe_nb=Host_get_selected_pipe();
    00583                Host_select_pipe(i);
    00584                if((++it_pipe_str[i].timeout>TIMEOUT_DELAY) && (Host_get_pipe_type()!=TYPE_INTERRUPT))
    00585                {
    00586                   it_pipe_str[i].enable=DISABLE;
    00587                   it_pipe_str[i].status=PIPE_DELAY_TIMEOUT;
    00588                   Host_stop_pipe_interrupt(i);
    00589                   if (is_any_interrupt_pipe_active()==FALSE)    // If no more transfer is armed
    00590                   {
    00591                      if (g_sav_int_sof_enable==FALSE)
    00592                      {
    00593                         Host_disable_sof_interrupt();
    00594                      }
    00595                   }
    00596                   it_pipe_str[i].handle(PIPE_DELAY_TIMEOUT,it_pipe_str[i].nb_byte_processed);
    00597                }
    00598                Host_select_pipe(save_pipe_nb);
    00599             }
    00600          }
    00601       }
    00602       #endif  // (USB_HOST_PIPE_INTERRUPT_TRANSFER==ENABLE) && (TIMEOUT_DELAY_ENABLE==ENABLE))
    00603       Host_sof_action();
    00604    }
    00605   // - Host Wake-up has been received
    00606    if (Is_host_hwup() && Is_host_hwup_interrupt_enabled())
    00607    {
    00608       Host_disable_hwup_interrupt();  // Wake up interrupt should be disable host is now wake up !
    00609       // CAUTION HWUP can be cleared only when USB clock is active (not frozen)!
    00610       Pll_start_auto();               // First Restart the PLL for USB operation
    00611       Wait_pll_ready();               // Get sure pll is lock
    00612       Usb_unfreeze_clock();           // Enable clock on USB interface
    00613       Host_ack_hwup();                // Clear HWUP interrupt flag
    00614       Usb_send_event(EVT_HOST_HWUP);  // Send software event
    00615       Host_hwup_action();             // Map custom action
    00616    }
    00617 #endif // End HOST FEATURE MODE
    00618 }
    00619
    00620
    00621 #if (USB_DEVICE_FEATURE == ENABLED)
    00622 #ifdef WA_USB_SUSPEND_PERTUBATION
    00623 void usb_delay_ms(U8 ms)
    00624 {
    00625    for(;ms;ms--)
    00626    {
    00627       for(delay_usb=0;delay_usb<FOSC/16;delay_usb++);
    00628    }
    00629 }
    00630 #endif
    00631 #endif // USB_DEVICE_FEATURE == ENABLED
    00632
    00633
    00634
    00635
    00636