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 676 of file usb_task.c.

References private_sof_counter.

Referenced by host_transfer_control().

00677 {
00678   return private_sof_counter;
00679 }

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 195 of file usb_task.c.

References usb_general_interrupt_non_naked().

Referenced by usb_task().

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

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 401 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().

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


Variable Documentation

volatile U8 g_old_usb_mode [static]

Definition at line 163 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 132 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 156 of file usb_task.c.

Referenced by usb_general_interrupt_non_naked().

U8 private_sof_counter_HS = 0 [static]

Definition at line 109 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 170 of file usb_task.c.

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


Generated on Thu Dec 17 20:00:26 2009 for AVR32 - USB Enumeration Example by  doxygen 1.5.5