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