usb_task.c File Reference


Detailed Description

Management of the USB task either device/host or both.

The USB task selects the correct USB task (USB device task or USB host task) to be executed depending on the current mode available.

According to the values of USB_DEVICE_FEATURE and USB_HOST_FEATURE (located in the conf_usb.h file), the USB task can be configured to support USB device mode or USB host mode or both for a dual-role device application.

This module also contains the general USB interrupt subroutine. This subroutine is used to detect asynchronous USB events.

Note:

Author:
Atmel Corporation: http://www.atmel.com
Support and FAQ: http://support.atmel.no/

Definition in file usb_task.c.

#include "compiler.h"
#include "intc.h"
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
#include "conf_usb.h"
#include "usb_drv.h"
#include "usb_task.h"
#include "usb_descriptors.h"
#include "usb_device_task.h"
#include "usb_host_task.h"
#include "pm.h"

Go to the source code of this file.

Functions

U32 host_get_timeout (void)
void host_suspend_action (void)
static void usb_general_interrupt (void)
 USB interrupt routine.
static portBASE_TYPE usb_general_interrupt_non_naked (void)
 Entry point of the USB mamnagement.
void usb_suspend_action (void)
void usb_task (void *pvParameters)
 Entry point of the USB mamnagement.
void usb_task_init (void)
 This function initializes the USB process.

Variables

static volatile U8 g_old_usb_mode
volatile Bool g_sav_int_sof_enable
volatile U16 g_usb_event = 0
 Public: U16 g_usb_event usb_connected is used to store USB events detected upon USB general interrupt subroutine Its value is managed by the following macros (See usb_task.h file) Usb_send_event(x) Usb_ack_event(x) Is_usb_event(x) Usb_clear_all_event().
volatile U8 g_usb_mode = USB_MODE_UNDEFINED
 Public: U8 g_usb_mode Used in dual-role application (both device/host) to store the current mode the USB controller is operating.
volatile S_pipe_int it_pipe_str [MAX_PEP_NB]
static const char log_device_disconnected [] = "Device disconnected\n"
static const char log_pin_id_changed [] = "Pin Id changed\n"
volatile U32 private_sof_counter
 Private: U8 private_sof_counter Incremented by host SOF interrupt subroutime This counter is used to detect time-out in host requests.
static U8 private_sof_counter_HS = 0
volatile Bool usb_connected
 Public: Bool usb_connected usb_connected is set to TRUE when VBus has been detected usb_connected is set to FALSE otherwise Used with USB_DEVICE_FEATURE == ENABLED only.
xTaskHandle usb_device_tsk
 Handle to the USB Device task.
xTaskHandle usb_host_tsk
 Handle to the USB Host task.
static xSemaphoreHandle usb_tsk_semphr = NULL
 Handle to the USB task semaphore.


Function Documentation

U32 host_get_timeout ( void   ) 

Definition at line 675 of file usb_task.c.

References private_sof_counter.

Referenced by host_transfer_control().

00676 {
00677   return private_sof_counter;
00678 }

static void usb_general_interrupt ( void   )  [static]

USB interrupt routine.

When FreeRTOS is used, the USB interrupt routine may trigger task switches, so it must use special OS prologue and epilogue. This function must be naked in order to have no stack frame. usb_general_interrupt_non_naked is therefore used for the required stack frame of the interrupt routine.

Definition at line 194 of file usb_task.c.

References usb_general_interrupt_non_naked().

Referenced by usb_task().

00195 {
00196   portENTER_SWITCHING_ISR();
00197   usb_general_interrupt_non_naked();
00198   portEXIT_SWITCHING_ISR();
00199 }

static portBASE_TYPE usb_general_interrupt_non_naked ( void   )  [static]

Entry point of the USB mamnagement.

Depending on the USB mode supported (HOST/DEVICE/DUAL_ROLE) the function calls the coresponding USB management function. USB interrupt routine 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

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
  • Pipe events

For each event, the user can launch an action by completing the associated #define (see the conf_usb.h file to add actions on events).

Note: Only interrupt events that are enabled are processed.

Warning: If device and host tasks are not tasks in an RTOS, rough events like ID transition, VBus transition, device disconnection, etc. that need to kill then restart these tasks may lead to an undefined state if they occur just before something is activated in the USB macro (e.g. pipe/endpoint transfer...).

Returns:
Nothing in the standalone configuration; a boolean indicating whether a task switch is required in the FreeRTOS configuration

Todo:
ID pin hot state change!!!

Todo:
Implement this on the silicon version

Definition at line 400 of file usb_task.c.

References device_state, DEVICE_UNATTACHED, S_pipe_int::enable, EVT_HOST_DISCONNECTION, EVT_HOST_HWUP, EVT_HOST_SOF, EVT_USB_DEVICE_FUNCTION, EVT_USB_HOST_FUNCTION, EVT_USB_POWERED, EVT_USB_RESET, EVT_USB_RESUME, EVT_USB_SUSPEND, EVT_USB_UNPOWERED, EVT_USB_WAKE_UP, g_old_usb_mode, g_sav_int_sof_enable, g_usb_mode, S_pipe_int::handler, Host_ack_device_connection, Host_ack_device_disconnection, Host_ack_hwup, Host_ack_sof, Host_device_connection_action, Host_device_disconnection_action, host_disable_all_pipes(), Host_disable_hwup_interrupt, Host_disable_sof_interrupt, Host_get_interrupt_pipe_number, Host_get_pipe_type, Host_hwup_action, Host_reset_pipe, Host_sof_action, is_any_interrupt_pipe_active(), Is_host_attached, Is_host_device_connection, Is_host_device_connection_interrupt_enabled, Is_host_device_disconnection, Is_host_device_disconnection_interrupt_enabled, Is_host_hwup, Is_host_hwup_interrupt_enabled, Is_host_sof, Is_host_sof_interrupt_enabled, Is_usb_clock_frozen, Is_usb_device, Is_usb_full_speed_mode, Is_usb_id_device, Is_usb_id_interrupt_enabled, Is_usb_id_transition, Is_usb_reset, Is_usb_reset_interrupt_enabled, Is_usb_resume, Is_usb_resume_interrupt_enabled, Is_usb_sof, Is_usb_sof_interrupt_enabled, Is_usb_suspend, Is_usb_suspend_interrupt_enabled, Is_usb_vbus_high, Is_usb_vbus_interrupt_enabled, Is_usb_vbus_transition, Is_usb_wake_up, Is_usb_wake_up_interrupt_enabled, log_device_disconnected, log_pin_id_changed, LOG_STR, MAX_PEP_NB, PIPE_DELAY_TIMEOUT, private_sof_counter, private_sof_counter_HS, reset_it_pipe_str(), S_pipe_int::status, TIMEOUT_DELAY, TYPE_INTERRUPT, Usb_ack_id_transition, Usb_ack_reset, Usb_ack_resume, Usb_ack_sof, Usb_ack_suspend, Usb_ack_vbus_transition, Usb_ack_wake_up, usb_configuration_nb, usb_connected, Usb_detach, Usb_disable, Usb_disable_otg_pad, Usb_disable_resume_interrupt, Usb_disable_wake_up_interrupt, Usb_enable_wake_up_interrupt, Usb_freeze_clock, Usb_id_transition_action, usb_init_device(), USB_MODE_DEVICE, USB_MODE_HOST, usb_pipe_interrupt(), Usb_reset_action, Usb_resume_action, Usb_send_event, Usb_sof_action, usb_start_device(), Usb_suspend_action, usb_tsk_semphr, Usb_unfreeze_clock, Usb_vbus_off_action, Usb_vbus_on_action, and Usb_wake_up_action.

Referenced by usb_general_interrupt().

00412 {
00413 #ifdef FREERTOS_USED
00414   portBASE_TYPE task_woken = pdFALSE;
00415 #endif
00416 #if USB_HOST_FEATURE == ENABLED && USB_HOST_PIPE_INTERRUPT_TRANSFER == ENABLE
00417   U8 i;
00418 #endif
00419 
00420 // ---------- DEVICE/HOST events management ------------------------------------
00421 #if USB_DEVICE_FEATURE == ENABLED && USB_HOST_FEATURE == ENABLED
00422   // ID pin change detection
00423   if (Is_usb_id_transition() && Is_usb_id_interrupt_enabled())
00424   {
00425     g_usb_mode = (Is_usb_id_device()) ? USB_MODE_DEVICE : USB_MODE_HOST;
00426     Usb_ack_id_transition();
00427     if (g_usb_mode != g_old_usb_mode) // Basic debounce
00428     {
00429       // Previously in device mode, check if disconnection was detected
00430       if (g_old_usb_mode == USB_MODE_DEVICE)
00431       {
00432         if (usb_connected)
00433         {
00434           // Device mode diconnection actions
00435           usb_connected = FALSE;
00436           usb_configuration_nb = 0;
00437           Usb_vbus_off_action();
00438         }
00439       }
00440       // Previously in host mode, check if disconnection was detected
00441       else if (Is_host_attached())
00442       {
00443         // Host mode diconnection actions
00444         device_state = DEVICE_UNATTACHED;
00445         Host_device_disconnection_action();
00446       }
00447       LOG_STR(log_pin_id_changed);
00448       Usb_send_event((Is_usb_device()) ? EVT_USB_DEVICE_FUNCTION :
00449                                          EVT_USB_HOST_FUNCTION);
00450       Usb_id_transition_action();
00452       // Preliminary management: HARDWARE RESET!!!
00453   #if ID_PIN_CHANGE_GENERATE_RESET == ENABLE
00454       // Hot ID transition generates CPU reset
00455       Usb_disable();
00456       Usb_disable_otg_pad();
00457     #ifdef FREERTOS_USED
00458       // Release the semaphore in order to start a new device/host task
00459       taskENTER_CRITICAL();
00460       xSemaphoreGiveFromISR(usb_tsk_semphr, &task_woken);
00461       taskEXIT_CRITICAL();
00462     #else
00463 //      Reset_CPU();
00464     #endif
00465   #endif
00466     }
00467   }
00468 #endif  // End DEVICE/HOST FEATURE MODE
00469 
00470 // ---------- DEVICE events management -----------------------------------------
00471 #if USB_DEVICE_FEATURE == ENABLED
00472   #if USB_HOST_FEATURE == ENABLED
00473   // If both device and host features are enabled, check if device mode is engaged
00474   // (accessing the USB registers of a non-engaged mode, even with load operations,
00475   // may corrupt USB FIFO data).
00476   if (Is_usb_device())
00477   #endif
00478   {
00479     // VBus state detection
00480     if (Is_usb_vbus_transition() && Is_usb_vbus_interrupt_enabled())
00481     {
00482       Usb_ack_vbus_transition();
00483       if (Is_usb_vbus_high())
00484       {
00485         usb_start_device();
00486         Usb_send_event(EVT_USB_POWERED);
00487         Usb_vbus_on_action();
00488       }
00489       else
00490       {
00491         Usb_unfreeze_clock();
00492         Usb_detach();
00493         usb_connected = FALSE;
00494         usb_configuration_nb = 0;
00495         Usb_send_event(EVT_USB_UNPOWERED);
00496         Usb_vbus_off_action();
00497   #ifdef FREERTOS_USED
00498         // Release the semaphore in order to start a new device/host task
00499         taskENTER_CRITICAL();
00500         xSemaphoreGiveFromISR(usb_tsk_semphr, &task_woken);
00501         taskEXIT_CRITICAL();
00502   #endif
00503       }
00504     }
00505     // Device Start-of-Frame received
00506     if (Is_usb_sof() && Is_usb_sof_interrupt_enabled())
00507     {
00508       Usb_ack_sof();
00509       Usb_sof_action();
00510     }
00511     // Device Suspend event (no more USB activity detected)
00512     if (Is_usb_suspend() && Is_usb_suspend_interrupt_enabled())
00513     {
00514       Usb_ack_suspend();
00515       Usb_enable_wake_up_interrupt();
00516       (void)Is_usb_wake_up_interrupt_enabled();
00517       Usb_freeze_clock();
00518       Usb_send_event(EVT_USB_SUSPEND);
00519       Usb_suspend_action();
00520     }
00521     // Wake-up event (USB activity detected): Used to resume
00522     if (Is_usb_wake_up() && Is_usb_wake_up_interrupt_enabled())
00523     {
00524       Usb_unfreeze_clock();
00525       (void)Is_usb_clock_frozen();
00526       Usb_ack_wake_up();
00527       Usb_disable_wake_up_interrupt();
00528       Usb_wake_up_action();
00529       Usb_send_event(EVT_USB_WAKE_UP);
00530     }
00531     // Resume state bus detection
00532     if (Is_usb_resume() && Is_usb_resume_interrupt_enabled())
00533     {
00534       Usb_disable_wake_up_interrupt();
00535       Usb_ack_resume();
00536       Usb_disable_resume_interrupt();
00537       Usb_resume_action();
00538       Usb_send_event(EVT_USB_RESUME);
00539     }
00540     // USB bus reset detection
00541     if (Is_usb_reset() && Is_usb_reset_interrupt_enabled())
00542     {
00543       Usb_ack_reset();
00544       usb_init_device();
00545       Usb_reset_action();
00546       Usb_send_event(EVT_USB_RESET);
00547     }
00548   }
00549 #endif  // End DEVICE FEATURE MODE
00550 
00551 // ---------- HOST events management -------------------------------------------
00552 #if USB_HOST_FEATURE == ENABLED
00553   #if USB_DEVICE_FEATURE == ENABLED
00554   // If both device and host features are enabled, check if host mode is engaged
00555   // (accessing the USB registers of a non-engaged mode, even with load operations,
00556   // may corrupt USB FIFO data).
00557   else
00558   #endif
00559   {
00560     // The device has been disconnected
00561     if (Is_host_device_disconnection() && Is_host_device_disconnection_interrupt_enabled())
00562     {
00563       host_disable_all_pipes();
00564       Host_ack_device_disconnection();
00565   #if USB_HOST_PIPE_INTERRUPT_TRANSFER == ENABLE
00566       reset_it_pipe_str();
00567   #endif
00568       device_state = DEVICE_UNATTACHED;
00569       LOG_STR(log_device_disconnected);
00570       Usb_send_event(EVT_HOST_DISCONNECTION);
00571       Host_device_disconnection_action();
00572   #ifdef FREERTOS_USED
00573       // Release the semaphore in order to start a new device/host task
00574       taskENTER_CRITICAL();
00575       xSemaphoreGiveFromISR(usb_tsk_semphr, &task_woken);
00576       taskEXIT_CRITICAL();
00577   #endif
00578     }
00579     // Device connection
00580     if (Is_host_device_connection() && Is_host_device_connection_interrupt_enabled())
00581     {
00582       Host_ack_device_connection();
00583       host_disable_all_pipes();
00584       Host_device_connection_action();
00585     }
00586     // Host Start-of-Frame has been sent
00587     if (Is_host_sof() && Is_host_sof_interrupt_enabled())
00588     {
00589       Host_ack_sof();
00590       Usb_send_event(EVT_HOST_SOF);
00591 #if (USB_HIGH_SPEED_SUPPORT==ENABLED)
00592       if( Is_usb_full_speed_mode() )
00593       {
00594          private_sof_counter++;
00595       }else{
00596          private_sof_counter_HS++;
00597          if( 0 == (private_sof_counter_HS%8) )
00598          {
00599             private_sof_counter++;
00600          }
00601       }
00602 #else
00603       private_sof_counter++;
00604 #endif      
00605       // Delay time-out management for interrupt tranfer mode in host mode
00606   #if USB_HOST_PIPE_INTERRUPT_TRANSFER == ENABLE && TIMEOUT_DELAY_ENABLE == ENABLE
00607       if (private_sof_counter >= 250) // Count 250 ms (SOF @ 1 ms)
00608       {
00609         private_sof_counter = 0;
00610         for (i = 0; i < MAX_PEP_NB; i++)
00611         {
00612           if (it_pipe_str[i].enable &&
00613               ++it_pipe_str[i].timeout > TIMEOUT_DELAY && Host_get_pipe_type(i) != TYPE_INTERRUPT)
00614           {
00615             it_pipe_str[i].enable = FALSE;
00616             it_pipe_str[i].status = PIPE_DELAY_TIMEOUT;
00617             Host_reset_pipe(i);
00618             if (!is_any_interrupt_pipe_active() && !g_sav_int_sof_enable) // If no more transfer is armed
00619             {
00620               Host_disable_sof_interrupt();
00621             }
00622             it_pipe_str[i].handler(PIPE_DELAY_TIMEOUT, it_pipe_str[i].nb_byte_processed);
00623           }
00624         }
00625       }
00626   #endif
00627       Host_sof_action();
00628     }
00629     // Host Wake-up has been received
00630     if (Is_host_hwup() && Is_host_hwup_interrupt_enabled())
00631     {
00632       // CAUTION: HWUP can be cleared only when USB clock is active (not frozen)!
00634       //Pll_start_auto();               // First Restart the PLL for USB operation
00635       //Wait_pll_ready();               // Make sure PLL is locked
00636       Usb_unfreeze_clock();           // Enable clock on USB interface
00637       (void)Is_usb_clock_frozen();    // Make sure USB interface clock is enabled
00638       Host_disable_hwup_interrupt();  // Wake-up interrupt should be disabled as host is now awoken!
00639       Host_ack_hwup();                // Clear HWUP interrupt flag
00640       Usb_send_event(EVT_HOST_HWUP);  // Send software event
00641       Host_hwup_action();             // Map custom action
00642     }
00643   #if USB_HOST_PIPE_INTERRUPT_TRANSFER == ENABLE
00644     // Host pipe interrupts
00645     while ((i = Host_get_interrupt_pipe_number()) < MAX_PEP_NB) usb_pipe_interrupt(i);
00646   #endif
00647   }
00648 #endif  // End HOST FEATURE MODE
00649 
00650 #ifdef FREERTOS_USED
00651   return task_woken;
00652 #endif
00653 }


Variable Documentation

volatile U8 g_old_usb_mode [static]

Definition at line 162 of file usb_task.c.

Referenced by usb_general_interrupt_non_naked(), and usb_task().

volatile Bool g_sav_int_sof_enable

volatile S_pipe_int it_pipe_str[MAX_PEP_NB]

Definition at line 79 of file usb_host_task.c.

const char log_device_disconnected[] = "Device disconnected\n" [static]

Definition at line 131 of file usb_task.c.

Referenced by usb_general_interrupt_non_naked().

const char log_pin_id_changed[] = "Pin Id changed\n" [static]

Definition at line 155 of file usb_task.c.

Referenced by usb_general_interrupt_non_naked().

U8 private_sof_counter_HS = 0 [static]

Definition at line 108 of file usb_task.c.

Referenced by usb_general_interrupt_non_naked().

volatile Bool usb_connected

Public: Bool usb_connected usb_connected is set to TRUE when VBus has been detected usb_connected is set to FALSE otherwise Used with USB_DEVICE_FEATURE == ENABLED only.

Definition at line 80 of file usb_device_task.c.

Referenced by usb_device_task(), usb_device_task_init(), usb_general_interrupt_non_naked(), and usb_start_device().

xTaskHandle usb_device_tsk

Handle to the USB Device task.

Definition at line 84 of file usb_device_task.c.

Referenced by usb_device_task_init(), and usb_task().

xTaskHandle usb_host_tsk

Handle to the USB Host task.

Definition at line 122 of file usb_host_task.c.

Referenced by usb_host_task_init(), and usb_task().

xSemaphoreHandle usb_tsk_semphr = NULL [static]

Handle to the USB task semaphore.

Definition at line 169 of file usb_task.c.

Referenced by usb_general_interrupt_non_naked(), usb_task(), and usb_task_init().


Generated on Fri Feb 19 02:27:52 2010 for AVR32 - USB Enumeration Example by  doxygen 1.5.5