📄 usb_host_task.c
字号:
private_sof_counter=0; // Done in host SOF interrupt
if (nak_timeout++>=TIMEOUT_DELAY)// Check for local timeout
{
status=PIPE_DELAY_TIMEOUT;
Host_reset_pipe(pipe);
goto host_get_data_end;
}
}
#endif
if(Is_host_pipe_error()) // Error management
{
status = Host_error_status();
Host_ack_all_errors();
goto host_get_data_end;
}
if(Is_host_stall()) // STALL management
{
status =PIPE_STALL;
Host_reset_pipe(pipe);
Host_ack_stall();
goto host_get_data_end;
}
#if (NAK_TIMEOUT_ENABLE==ENABLE)
if(Is_host_nak_received()) //NAK received
{
Host_ack_nak_received();
if (cpt_nak++>NAK_RECEIVE_TIMEOUT)
{
status = PIPE_NAK_TIMEOUT;
Host_reset_pipe(pipe);
goto host_get_data_end;
}
}
#endif
}
status=PIPE_GOOD;
Host_freeze_pipe();
if (Host_byte_counter()<=n)
{
if ((Host_byte_counter() < n)&&(Host_byte_counter()<Host_get_pipe_length()))
{ n=0;}
else
{ n-=Host_byte_counter();}
(*nb_data)+=Host_byte_counter(); // Update nb of byte received
for (i=Host_byte_counter();i;i--)
{ *buf=Host_read_byte(); buf++;}
}
else // more bytes received than expected
{ // TODO error code management
*nb_data+=n;
for (i=n;i;i--) // Byte number limited to the initial request (limit tab over pb)
{ *buf=Host_read_byte(); buf++; }
n=0;
}
Host_ack_in_received();
}
Host_freeze_pipe();
host_get_data_end:
if (sav_int_sof_enable==FALSE)
{
Host_disable_sof_interrupt();
}
return ((U8)status);
}
//___ F U N C T I O N S F O R I N T E R R U P T M A N A G E D D A T A F L O W S _________________________
#if (USB_HOST_PIPE_INTERRUPT_TRANSFER == ENABLE)
void reset_it_pipe_str(void)
{
U8 i;
for(i=0;i<MAX_EP_NB;i++)
{
it_pipe_str[i].enable=DISABLE;
it_pipe_str[i].timeout=0;
}
}
U8 is_any_interrupt_pipe_active(void)
{
U8 i;
for(i=0;i<MAX_EP_NB;i++)
{
if(it_pipe_str[i].enable==ENABLE) return TRUE;
}
return FALSE;
}
/**
* @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
* @param handle call back function pointer
*
* @return status
*/
U8 host_get_data_interrupt(U8 pipe, U16 nb_data, U8 *buf,void(*handle)(U8 status, U16 nb_byte))
{
Host_select_pipe(pipe);
if(it_pipe_str[pipe].enable==ENABLE)
{
return HOST_FALSE;
}
else
{
if(is_any_interrupt_pipe_active()==FALSE)
{
g_sav_int_sof_enable=Is_host_sof_interrupt_enabled();
Host_enable_sof_interrupt();
}
it_pipe_str[pipe].enable=ENABLE;
it_pipe_str[pipe].nb_byte_to_process=nb_data;
it_pipe_str[pipe].nb_byte_processed=0;
it_pipe_str[pipe].ptr_buf=buf;
it_pipe_str[pipe].handle=handle;
it_pipe_str[pipe].timeout=0;
it_pipe_str[pipe].nak_timeout=NAK_RECEIVE_TIMEOUT;
private_sof_counter=0; // Reset the counter in SOF detection sub-routine
Host_reset_pipe(pipe);
Host_enable_stall_interrupt();
#if (NAK_TIMEOUT_ENABLE==ENABLE)
Host_enable_nak_interrupt();
#endif
Host_enable_error_interrupt();
Host_enable_receive_interrupt();
Host_ack_stall();
Host_ack_nak_received();
Host_continuous_in_mode();
Host_set_token_in();
Host_unfreeze_pipe();
return HOST_TRUE;
}
}
/**
* @brief This function send nb_data pointed with *buf with the pipe number specified
*
*
* @param pipe
* @param nb_data
* @param buf
* @param handle call back function pointer
*
* @return status
*/
U8 host_send_data_interrupt(U8 pipe, U16 nb_data, U8 *buf, void(*handle)(U8 status, U16 nb_byte))
{
U8 i;
U8 *ptr_buf=buf;
Host_select_pipe(pipe);
if(it_pipe_str[pipe].enable==ENABLE)
{
return HOST_FALSE;
}
else
{
if(is_any_interrupt_pipe_active()==FALSE)
{
g_sav_int_sof_enable=Is_host_sof_interrupt_enabled();
Host_enable_sof_interrupt();
}
it_pipe_str[pipe].enable=ENABLE;
it_pipe_str[pipe].nb_byte_to_process=nb_data;
it_pipe_str[pipe].nb_byte_processed=0;
it_pipe_str[pipe].ptr_buf=buf;
it_pipe_str[pipe].handle=handle;
it_pipe_str[pipe].timeout=0;
it_pipe_str[pipe].nak_timeout=NAK_SEND_TIMEOUT;
it_pipe_str[pipe].nb_byte_on_going=0;
Host_reset_pipe(pipe);
Host_unfreeze_pipe();
// Prepare data to be sent
i = Host_get_pipe_length();
if ( i > nb_data) // Pipe size> remaining data
{
i = nb_data;
nb_data = 0;
}
else // Pipe size < remaining data
{
nb_data -= i;
}
it_pipe_str[pipe].nb_byte_on_going+=i; // Update nb data processed
while (i!=0) // Load Pipe buffer
{ Host_write_byte(*ptr_buf++); i--;
}
private_sof_counter=0; // Reset the counter in SOF detection sub-routine
it_pipe_str[pipe].timeout=0; // Refresh timeout counter
Host_ack_out_sent();
Host_ack_stall();
Host_ack_nak_received();
Host_enable_stall_interrupt();
Host_enable_error_interrupt();
#if (NAK_TIMEOUT_ENABLE==ENABLE)
Host_enable_nak_interrupt();
#endif
Host_enable_transmit_interrupt();
Host_send_out(); // Send the USB frame
return HOST_TRUE;
}
}
//! @brief USB pipe interrupt subroutine
//!
//! @param none
//!
//! @return none
#ifdef AVRGCC
ISR(USB_COM_vect)
#else
#pragma vector = USB_ENDPOINT_PIPE_vect
__interrupt void usb_pipe_interrupt()
#endif
{
U8 pipe_nb;
U8 *ptr_buf;
void (*fct_handle)(U8 status,U16 nb_byte);
U16 n;
U8 i;
U8 do_call_back=FALSE;
pipe_nb_save = Host_get_selected_pipe(); // Important! Save here working pipe number
pipe_nb=usb_get_nb_pipe_interrupt(); // work with the correct pipe number that generates the interrupt
Host_select_pipe(pipe_nb); // Select this pipe
fct_handle=*(it_pipe_str[pipe_nb].handle);
// Now try to detect what event generate an interrupt...
if (Is_host_pipe_error()) // Any error ?
{
it_pipe_str[pipe_nb].status = Host_error_status();
it_pipe_str[pipe_nb].enable=DISABLE;
Host_stop_pipe_interrupt(pipe_nb);
Host_ack_all_errors();
do_call_back=TRUE;
goto usb_pipe_interrupt_end;
}
if (Is_host_stall()) // Stall handshake received ?
{
it_pipe_str[pipe_nb].status=PIPE_STALL;
it_pipe_str[pipe_nb].enable=DISABLE;
Host_stop_pipe_interrupt(pipe_nb);
do_call_back=TRUE;
goto usb_pipe_interrupt_end;
}
#if (NAK_TIMEOUT_ENABLE==ENABLE)
if (Is_host_nak_received()) // NAK ?
{
Host_ack_nak_received();
// check if number of NAK timeout error occurs (not for interrupt type pipe)
if((--it_pipe_str[pipe_nb].nak_timeout==0) && (Host_get_pipe_type()!=TYPE_INTERRUPT))
{
it_pipe_str[pipe_nb].status=PIPE_NAK_TIMEOUT;
it_pipe_str[pipe_nb].enable=DISABLE;
Host_stop_pipe_interrupt(pipe_nb);
do_call_back=TRUE;
goto usb_pipe_interrupt_end;
}
}
#endif
if (Is_host_in_received()) // Pipe IN reception ?
{
ptr_buf=it_pipe_str[pipe_nb].ptr_buf+it_pipe_str[pipe_nb].nb_byte_processed; // Build pointer to data buffer
n=it_pipe_str[pipe_nb].nb_byte_to_process-it_pipe_str[pipe_nb].nb_byte_processed; // Remaining data bytes
Host_freeze_pipe();
if (Host_byte_counter()<=n)
{
if ((Host_byte_counter() < n)&&(Host_byte_counter()<Host_get_pipe_length())) //Received less than remaining, but less than pipe capacity
//TODO: error code
{
n=0;
}
else
{
n-=Host_byte_counter();
}
it_pipe_str[pipe_nb].nb_byte_processed+=Host_byte_counter(); // Update nb of byte received
for (i=Host_byte_counter();i;i--)
{ *ptr_buf=Host_read_byte(); ptr_buf++;}
}
else // more bytes received than expected
{ // TODO error code management
it_pipe_str[pipe_nb].nb_byte_processed+=n;
for (i=n;i;i--) // Byte number limited to the initial request (limit tab over pb)
{ *ptr_buf=Host_read_byte(); ptr_buf++;}
n=0;
}
Host_ack_in_received();
if(n>0) //still something to process
{
Host_unfreeze_pipe(); // Request another IN transfer
Host_send_in();
private_sof_counter=0; // Reset the counter in SOF detection sub-routine
it_pipe_str[pipe_nb].timeout=0; // Reset timeout
it_pipe_str[pipe_nb].nak_timeout=NAK_RECEIVE_TIMEOUT;
}
else //end of transfer
{
it_pipe_str[pipe_nb].enable=DISABLE;
it_pipe_str[pipe_nb].status=PIPE_GOOD;
Host_stop_pipe_interrupt(pipe_nb);
do_call_back=TRUE;
}
}
if(Is_host_out_sent()) // Pipe OUT sent ?
{
Host_ack_out_sent();
it_pipe_str[pipe_nb].nb_byte_processed+=it_pipe_str[pipe_nb].nb_byte_on_going;
it_pipe_str[pipe_nb].nb_byte_on_going=0;
ptr_buf=it_pipe_str[pipe_nb].ptr_buf+it_pipe_str[pipe_nb].nb_byte_processed; // Build pointer to data buffer
n=it_pipe_str[pipe_nb].nb_byte_to_process-it_pipe_str[pipe_nb].nb_byte_processed; // Remaining data bytes
if(n>0) // Still data to process...
{
Host_unfreeze_pipe();
// Prepare data to be sent
i = Host_get_pipe_length();
if ( i > n) // Pipe size> remaining data
{
i = n;
n = 0;
}
else // Pipe size < remaining data
{ n -= i; }
it_pipe_str[pipe_nb].nb_byte_on_going+=i; // Update nb data processed
while (i!=0) // Load Pipe buffer
{
Host_write_byte(*ptr_buf++); i--;
}
private_sof_counter=0; // Reset the counter in SOF detection sub-routine
it_pipe_str[pipe_nb].timeout=0; // Refresh timeout counter
it_pipe_str[pipe_nb].nak_timeout=NAK_SEND_TIMEOUT;
Host_send_out(); // Send the USB frame
}
else //n==0 Transfer is finished
{
it_pipe_str[pipe_nb].enable=DISABLE; // Tranfer end
it_pipe_str[pipe_nb].status=PIPE_GOOD; // Status OK
Host_stop_pipe_interrupt(pipe_nb);
do_call_back=TRUE;
}
}
usb_pipe_interrupt_end:
Host_select_pipe(pipe_nb_save); // Restore pipe number !!!!
if (is_any_interrupt_pipe_active()==FALSE) // If no more transfer is armed
{
if (g_sav_int_sof_enable==FALSE)
{
Host_disable_sof_interrupt();
}
}
if(do_call_back) // Any callback functions to perform ?
{
fct_handle(it_pipe_str[pipe_nb].status,it_pipe_str[pipe_nb].nb_byte_processed);
}
}
#endif
#endif // USB_HOST_FEATURE ENABLE
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -