📄 usb_host_task.c
字号:
Host_enable_device_disconnection_interrupt();
c = 0;
while(c<200) // wait 200ms after USB reset
{
if (Is_usb_event(EVT_HOST_SOF)) { Usb_ack_event(EVT_HOST_SOF); c++; }
if (Is_host_emergency_exit() || Is_usb_bconnection_error_interrupt()) {break;}
}
Host_select_pipe(PIPE_CONTROL);
Host_disable_pipe();
Host_unallocate_memory();
Host_enable_pipe();
// Re-Configure the Ctrl Pipe according to the device ctrl EP
host_configure_pipe(PIPE_CONTROL, \
TYPE_CONTROL, \
TOKEN_SETUP, \
EP_CONTROL, \
host_determine_pipe_size((U16)data_stage[OFFSET_FIELD_MAXPACKETSIZE]),\
ONE_BANK, \
0 );
// Give an absolute device address
host_set_address(DEVICE_ADDRESS);
Host_configure_address(DEVICE_ADDRESS);
device_state = DEVICE_ADDRESSED;
}
else
{ device_state = DEVICE_ERROR; }
break;
//------------------------------------------------------
// DEVICE_ADDRESSED state
//
// - Check if VID PID is in supported list
//
case DEVICE_ADDRESSED :
if (CONTROL_GOOD == host_get_device_descriptor())
{
// Detect if the device connected belongs to the supported devices table
if (HOST_TRUE == host_check_VID_PID())
{
Host_set_device_supported();
Host_device_supported_action();
device_state = DEVICE_CONFIGURED;
}
else
{
Host_device_not_supported_action();
#if (HOST_STRICT_VID_PID_TABLE==ENABLE)
device_state = DEVICE_ERROR;
#else
device_state = DEVICE_CONFIGURED;
#endif
}
}
else // Can not get device descriptor
{ device_state = DEVICE_ERROR; }
break;
//------------------------------------------------------
// DEVICE_CONFIGURED state
//
// - Configure pipes for the supported interface
// - Send Set_configuration() request
// - Goto full operating mode (device ready)
//
case DEVICE_CONFIGURED :
if (CONTROL_GOOD == host_get_configuration_descriptor())
{
if (HOST_FALSE != host_check_class()) // Class support OK?
{
#if (HOST_AUTO_CFG_ENDPOINT==ENABLE)
host_auto_configure_endpoint();
#else
User_configure_endpoint(); // User call here instead of autoconfig
Host_set_configured(); // Assumes config is OK with user config
#endif
if (Is_host_configured())
{
if (CONTROL_GOOD== host_set_configuration(1)) // Send Set_configuration
{
//host_set_interface(interface_bound,interface_bound_alt_set);
// device and host are now fully configured
// goto DEVICE READY normal operation
device_state = DEVICE_READY;
// monitor device disconnection under interrupt
Host_enable_device_disconnection_interrupt();
// If user host application requires SOF interrupt event
// Keep SOF interrupt enable otherwize, disable this interrupt
#if (HOST_CONTINUOUS_SOF_INTERRUPT==DISABLE)
Host_disable_sof_interrupt();
#endif
new_device_connected=TRUE;
Enable_interrupt();
LOG_STR_CODE(log_device_enumerated);
}
else// Problem during Set_configuration request...
{ device_state = DEVICE_ERROR; }
}
}
else // device class not supported...
{
device_state = DEVICE_ERROR;
LOG_STR_CODE(log_device_unsupported);
Host_device_class_not_supported_action();
}
}
else // Can not get configuration descriptors...
{ device_state = DEVICE_ERROR; }
break;
//------------------------------------------------------
// DEVICE_READY state
//
// - Full std operatinf mode
// - Nothing to do...
//
case DEVICE_READY: // Host full std operating mode!
new_device_connected=FALSE;
break;
//------------------------------------------------------
// DEVICE_ERROR state
//
// - Error state
// - Do custom action call (probably go to default mode...)
//
case DEVICE_ERROR : // TODO !!!!
#if (HOST_ERROR_RESTART==ENABLE)
device_state=DEVICE_UNATTACHED;
#endif
Host_device_error_action();
break;
//------------------------------------------------------
// DEVICE_SUSPENDED state
//
// - Host application request to suspend the device activity
// - State machine comes here thanks to Host_request_suspend()
//
case DEVICE_SUSPENDED :
if(Is_device_supports_remote_wakeup()) // If the connected device supports remote wake up
{
host_set_feature_remote_wakeup(); // Enable this feature...
}
LOG_STR_CODE(log_going_to_suspend);
c = Is_host_sof_interrupt_enabled(); //Save current sof interrupt enable state
Host_disable_sof_interrupt();
Host_ack_sof();
Host_disable_sof(); // Stop start of frame generation, this generates the suspend state
Host_ack_hwup();
Host_enable_hwup_interrupt(); // Enable host wake-up interrupt
// (this is the unique USB interrupt able to wake up the CPU core from power-down mode)
Usb_freeze_clock();
Stop_pll();
Host_suspend_action(); // Custom action here! (for example go to power-save mode...)
device_state=DEVICE_WAIT_RESUME; // wait for device resume event
break;
//------------------------------------------------------
// DEVICE_WAIT_RESUME state
//
// - Wait in this state till the host receives an upstream resume from the device
// - or the host software request the device to resume
//
case DEVICE_WAIT_RESUME :
if(Is_usb_event(EVT_HOST_HWUP)|| Is_host_request_resume())// Remote wake up has been detected
// or Local resume request has been received
{
if(Is_host_request_resume()) // Not a remote wakeup, but an host application request
{
Host_disable_hwup_interrupt(); // Wake up interrupt should be disable host is now wake up !
// CAUTION HWUP can be cleared only when USB clock is active
Pll_start_auto(); // First Restart the PLL for USB operation
Wait_pll_ready(); // Get sure pll is lock
Usb_unfreeze_clock(); // Enable clock on USB interface
Host_ack_hwup(); // Clear HWUP interrupt flag
}
Host_enable_sof();
Host_send_resume(); // Send down stream resume
while (Is_host_down_stream_resume()==FALSE); // Wait Down stream resume sent
Host_ack_remote_wakeup(); // Ack remote wake-up reception
Host_ack_request_resume(); // Ack software request
Host_ack_down_stream_resume(); // Ack down stream resume sent
Usb_ack_event(EVT_HOST_HWUP); // Ack software event
if(c) { Host_enable_sof_interrupt(); } // Restore SOF interrupt enable state before suspend
device_state=DEVICE_READY; // Come back to full operating mode
LOG_STR_CODE(log_usb_resumed);
}
break;
//------------------------------------------------------
// DEVICE_DISCONNECTED state
//
// - Device disconnection has been detected
// - Run scheduler in this state at least two times to get sure event is detected by all host application tasks
// - Go to DEVICE_DISCONNECTED_ACK state before DEVICE_UNATTACHED, to get sure scheduler calls all app tasks...
//
case DEVICE_DISCONNECTED :
device_state = DEVICE_DISCONNECTED_ACK;
break;
//------------------------------------------------------
// DEVICE_DISCONNECTED_ACK state
//
// - Device disconnection has been detected and managed bu applicatives tasks
// - Go to DEVICE_UNATTACHED state
//
case DEVICE_DISCONNECTED_ACK :
device_state = DEVICE_UNATTACHED;
break;
//------------------------------------------------------
// default state
//
// - Default case: ERROR
// - Goto no device state
//
default :
device_state = DEVICE_UNATTACHED;
break;
}
}
//___ F U N C T I O N S F O R P O L L I N G M A N A G E D D A T A F L O W S _________________________
/**
* @brief This function send nb_data pointed with *buf with the pipe number specified
*
* @note This function will activate the host sof interrupt to detect timeout. The
* interrupt enable sof will be restore.
*
* @param pipe
* @param nb_data
* @param buf
*
* @return status
*/
U8 host_send_data(U8 pipe, U16 nb_data, U8 *buf)
{
U8 c;
U8 status=PIPE_GOOD;
U8 sav_int_sof_enable;
U8 nak_timeout;
U16 cpt_nak;
U8 nb_data_loaded;
sav_int_sof_enable=Is_host_sof_interrupt_enabled(); // Save state of enable sof interrupt
Host_enable_sof_interrupt();
Host_select_pipe(pipe);
Host_set_token_out();
Host_ack_out_sent();
while (nb_data != 0) // While there is something to send...
{
Host_unfreeze_pipe();
// Prepare data to be sent
c = Host_get_pipe_length();
if ( (U16)c > nb_data)
{
nb_data_loaded = (U8)nb_data;
c = nb_data;
}
else
{ nb_data_loaded = c; }
while (c!=0) // Load Pipe buffer
{
Host_write_byte(*buf++);
c--;
}
private_sof_counter=0; // Reset the counter in SOF detection sub-routine
cpt_nak=0;
nak_timeout=0;
Host_ack_out_sent();
Host_send_out();
while (!Is_host_out_sent())
{
if (Is_host_emergency_exit())// Async disconnection or role change detected under interrupt
{
status=PIPE_DELAY_TIMEOUT;
Host_reset_pipe(pipe);
goto host_send_data_end;
}
#if (TIMEOUT_DELAY_ENABLE==ENABLE)
if (private_sof_counter>=250) // Count 250ms (250sof)
{
private_sof_counter=0;
if (nak_timeout++>=TIMEOUT_DELAY) // Inc timeout and check for overflow
{
status=PIPE_DELAY_TIMEOUT;
Host_reset_pipe(pipe);
goto host_send_data_end;
}
}
#endif
if (Is_host_pipe_error()) // Any error ?
{
status = Host_error_status();
Host_ack_all_errors();
goto host_send_data_end;
}
if (Is_host_stall()) // Stall management
{
status =PIPE_STALL;
Host_ack_stall();
goto host_send_data_end;
}
#if (NAK_TIMEOUT_ENABLE==ENABLE)
if(Is_host_nak_received()) //NAK received
{
Host_ack_nak_received();
if (cpt_nak++>NAK_SEND_TIMEOUT)
{
status = PIPE_NAK_TIMEOUT;
Host_reset_pipe(pipe);
goto host_send_data_end;
}
}
#endif
}
// Here OUT sent
nb_data -= nb_data_loaded;
status=PIPE_GOOD; // Frame correctly sent
Host_ack_out_sent();
}
Host_freeze_pipe();
host_send_data_end:
// Restore sof interrupt enable state
if (sav_int_sof_enable==FALSE) {Host_disable_sof_interrupt();}
// And return...
return ((U8)status);
}
/**
* @brief This function receives nb_data pointed with *buf with the pipe number specified
*
* The nb_data parameter is passed as a U16 pointer, thus the data pointed by this pointer
* is updated with the final number of data byte received.
*
* @param pipe
* @param nb_data
* @param buf
*
* @return status
*/
U8 host_get_data(U8 pipe, U16 *nb_data, U8 *buf)
{
U8 status=PIPE_GOOD;
U8 sav_int_sof_enable;
U8 nak_timeout;
U16 n,i;
U16 cpt_nak;
n=*nb_data;
*nb_data=0;
sav_int_sof_enable=Is_host_sof_interrupt_enabled();
Host_enable_sof_interrupt();
Host_select_pipe(pipe);
Host_continuous_in_mode();
Host_set_token_in();
Host_ack_in_received();
while (n) // While missing data...
{
Host_unfreeze_pipe();
Host_send_in();
private_sof_counter=0; // Reset the counter in SOF detection sub-routine
nak_timeout=0;
cpt_nak=0;
while (!Is_host_in_received())
{
if (Is_host_emergency_exit()) // Async disconnection or role change detected under interrupt
{
status=PIPE_DELAY_TIMEOUT;
Host_reset_pipe(pipe);
goto host_get_data_end;
}
#if (TIMEOUT_DELAY_ENABLE==ENABLE)
if (private_sof_counter>=250) // Timeout management
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -