ATMEL: usb_task.c Source File

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

# usb_task.c

Go to the documentation of this file.

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