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 AND FITNESS FOR A PARTICULAR PURPOSE 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