📄 usb_hcd.c
字号:
}
else
{
g_UsbHcdInfo.tx_curent_index = -1;
/* next even odd */
g_UsbHcdInfo.tx_even_odd = even_odd^1;
}
/* toggel data 01, return to original data 01*/
g_UsbHcdInfo.ep_info[current_ep_index].data01^=1;
/* fast mode timeout error */
if(FastErrorStatus&(VUSB_FM_ERR_NAK_ERR|VUSB_FM_ERR_SUC_ERR))
{
USB_HCD_Stop_DMA_Channel();
g_UsbHcdInfo.b_wait_dma = KAL_FALSE;
/* the actaul size that fast mode complete */
g_UsbHcdInfo.fast_mode_data_size =
(DRV_Reg8(USB_FM_PKT_CNTL) + (DRV_Reg8(USB_FM_PKT_CNTH)<<8)) << 6;
/* decide the next even/odd BDT*/
if(direction==USB_BDT_RX)
{
fm_even_odd = (DRV_Reg8(USB_FM_CTL)&(1<<VUSB_FM_CTL_EP_RX_ODD_SHIFT))>>VUSB_FM_CTL_EP_RX_ODD_SHIFT;
g_UsbHcdInfo.rx_even_odd = fm_even_odd;
}
else
{
fm_even_odd = (DRV_Reg8(USB_FM_CTL)&(1<<VUSB_FM_CTL_EP_TX_ODD_SHIFT))>>VUSB_FM_CTL_EP_TX_ODD_SHIFT;
g_UsbHcdInfo.tx_even_odd = fm_even_odd;
}
/* this data01 is nak by device, so next data01 is this one*/
g_UsbHcdInfo.ep_info[current_ep_index].data01 = (DRV_Reg8(USB_FM_CTL)&(1<<VUSB_FM_CTL_EP_TOG_BIT_SHIFT))>>VUSB_FM_CTL_EP_TOG_BIT_SHIFT;
/* Since it is timeout, there should not be short error */
if(FastErrorStatus&VUSB_FM_ERR_SHORT_ERR)
{
EXT_ASSERT(0, FastErrorStatus, g_UsbHcdInfo.fast_mode_data_size, 0);
}
/* callback to application */
if(g_UsbHcdInfo.ep_hdlr[current_ep_index]!=NULL)
g_UsbHcdInfo.ep_hdlr[current_ep_index](USB_HCD_TIMEOUT, g_UsbHcdInfo.fast_mode_data_size);
}
else if(status==VUSB_BDT_STALL_PID)
{
/* If in fast mode, stop DMA */
if(g_UsbHcdInfo.dma_running==KAL_TRUE)
{
USB_HCD_Stop_DMA_Channel();
g_UsbHcdInfo.b_wait_dma = KAL_FALSE;
/* the actaul size that fast mode complete */
g_UsbHcdInfo.fast_mode_data_size =
(DRV_Reg8(USB_FM_PKT_CNTL) + (DRV_Reg8(USB_FM_PKT_CNTH)<<8)) << 6;
b_fast_mode = KAL_TRUE;
/* decide the next even/odd BDT*/
if(direction==USB_BDT_RX)
{
fm_even_odd = (DRV_Reg8(USB_FM_CTL)&(1<<VUSB_FM_CTL_EP_RX_ODD_SHIFT))>>VUSB_FM_CTL_EP_RX_ODD_SHIFT;
g_UsbHcdInfo.rx_even_odd = fm_even_odd;
}
else
{
fm_even_odd = (DRV_Reg8(USB_FM_CTL)&(1<<VUSB_FM_CTL_EP_TX_ODD_SHIFT))>>VUSB_FM_CTL_EP_TX_ODD_SHIFT;
g_UsbHcdInfo.tx_even_odd = fm_even_odd;
}
}
/* callback to USB stack, stall error*/
if(g_UsbHcdInfo.ep_hdlr[current_ep_index]!=NULL)
{
if(b_fast_mode==KAL_TRUE)
g_UsbHcdInfo.ep_hdlr[current_ep_index](USB_HCD_STALL, g_UsbHcdInfo.fast_mode_data_size);
else
g_UsbHcdInfo.ep_hdlr[current_ep_index](USB_HCD_STALL, g_UsbHcdInfo.ep_info[current_ep_index].sofar);
}
}
/* if ep0 dose not response*/
else if(status==VUSB_BDT_BUS_TIMEOUT_PID)
{
/* When plug out cable and dma done but not doing DMA HISR , it may happen for fast mode*/
if(g_UsbHcdInfo.dma_running==KAL_TRUE)
{
/* g_UsbHcdInfo.processing_ep_id may be set to -1 in TOKEN_DONE intr handler */
if(g_UsbHcdInfo.dma_index==-1)
EXT_ASSERT(0, g_UsbHcdInfo.dma_index, g_UsbHcdInfo.processing_ep_id, 0);
if(g_UsbHcdInfo.ep_hdlr[g_UsbHcdInfo.dma_index]!=NULL)
g_UsbHcdInfo.ep_hdlr[g_UsbHcdInfo.dma_index](USB_HCD_NO_RESPONSE, 0);
USB_HCD_Stop_DMA_Channel();
g_UsbHcdInfo.b_wait_dma = KAL_FALSE;
g_UsbHcdInfo.processing_ep_id = -1;
}
else
{
g_UsbHcdInfo.ep_info[current_ep_index].no_response_count++;
if(g_UsbHcdInfo.ep_info[current_ep_index].no_response_count>=3)
{
if(g_UsbHcdInfo.ep_hdlr[current_ep_index]!=NULL)
g_UsbHcdInfo.ep_hdlr[current_ep_index](USB_HCD_NO_RESPONSE, g_UsbHcdInfo.ep_info[current_ep_index].sofar);
/* do not queue this packet*/
}
else
{
/* queue to the end */
USB_HCD_Queue_Pkt(current_ep_index);
}
}
}
else /* may be NAK */
{
if(g_UsbHcdInfo.dma_running==KAL_TRUE)
{
/* g_UsbHcdInfo.processing_ep_id may be set to -1 in TOKEN_DONE intr handler */
if(g_UsbHcdInfo.dma_index==-1)
EXT_ASSERT(0, g_UsbHcdInfo.dma_index, g_UsbHcdInfo.processing_ep_id, 0);
if(g_UsbHcdInfo.ep_hdlr[g_UsbHcdInfo.dma_index]!=NULL)
g_UsbHcdInfo.ep_hdlr[g_UsbHcdInfo.dma_index](USB_HCD_NO_RESPONSE, 0);
USB_HCD_Stop_DMA_Channel();
g_UsbHcdInfo.b_wait_dma = KAL_FALSE;
g_UsbHcdInfo.processing_ep_id = -1;
}
else
{
/* queue to the end */
USB_HCD_Queue_Pkt(current_ep_index);
}
}
//b_schedule = KAL_TRUE;
b_dis_schedule = KAL_TRUE;
}
else /*VUSB_BDT_BUS_TIMEOUT_PID || VUSB_BDT_NAK_PID || VUSB_BDT_ERROR_PID */
{
/* Token done without error status */
/* update status and copy to user memory*/
if(direction==USB_BDT_RX)
{
if(g_UsbHcdInfo.rx_curent_index==-1)
EXT_ASSERT(0, 0, 0, 0);
current_ep_index = g_UsbHcdInfo.rx_curent_index;
g_UsbHcdInfo.rx_curent_index = -1;
if(current_ep_index == g_UsbHcdInfo.dma_index)
{
/* fast mode packet */
if(g_UsbHcdInfo.dma_dir!=USB_IN_EP_TYPE)
EXT_ASSERT(0, g_UsbHcdInfo.dma_dir, g_UsbHcdInfo.dma_index, 0);
/* decide the next even/odd BDT*/
fm_even_odd = (DRV_Reg8(USB_FM_CTL)&(1<<VUSB_FM_CTL_EP_RX_ODD_SHIFT))>>VUSB_FM_CTL_EP_RX_ODD_SHIFT;
g_UsbHcdInfo.rx_even_odd = fm_even_odd;
/* calculate the received packet size */
/* fast mode size = fast count *64*/
g_UsbHcdInfo.fast_mode_data_size =
(DRV_Reg8(USB_FM_PKT_CNTL) + (DRV_Reg8(USB_FM_PKT_CNTH)<<8)) << 6;
/* the last received packet size */
if(FastErrorStatus&VUSB_FM_ERR_SHORT_ERR)
{
/* got the short packet length according to current BDT */
pkt_length = (READ_EP0_BDT_PID(USB_BDT_RX, fm_even_odd^1)&VUSB_BDT_BC_MASK)
>>VUSB_BDT_BC_SHIFT;
/* The short one should be subtracted */
g_UsbHcdInfo.fast_mode_data_size -= 64;
g_UsbHcdInfo.fast_mode_data_size += pkt_length;
/* this data01 is sent by device, so next data01 is this one*/
g_UsbHcdInfo.ep_info[current_ep_index].data01 = (DRV_Reg8(USB_FM_CTL)&(1<<VUSB_FM_CTL_EP_TOG_BIT_SHIFT))>>VUSB_FM_CTL_EP_TOG_BIT_SHIFT;
}
if(g_UsbHcdInfo.fast_mode_data_size==0)
{
/* no need DMA, stop it. Otherwise it will hang */
USB_HCD_Stop_DMA_Channel();
g_UsbHcdInfo.b_wait_dma = KAL_FALSE;
}
if( (DRV_Reg8(USB_FM_PKT_NUML) + (DRV_Reg8(USB_FM_PKT_NUMH)<<8))
!=(DRV_Reg8(USB_FM_PKT_CNTL) + (DRV_Reg8(USB_FM_PKT_CNTH)<<8)) )
{
/* no need DMA, stop it. Otherwise it will hang */
USB_HCD_Stop_DMA_Channel();
g_UsbHcdInfo.b_wait_dma = KAL_FALSE;
}
if(g_UsbHcdInfo.b_wait_dma == KAL_FALSE)
{
if(g_UsbHcdInfo.ep_hdlr[g_UsbHcdInfo.dma_index]!=NULL)
g_UsbHcdInfo.ep_hdlr[g_UsbHcdInfo.dma_index](USB_HCD_OK, g_UsbHcdInfo.fast_mode_data_size );
//b_schedule = KAL_TRUE;
b_dis_schedule = KAL_TRUE;
}
g_UsbHcdInfo.b_wait_fm_done = KAL_FALSE;
}
else
{
/* normal mode, copy to user memory */
pkt_length = (READ_EP0_BDT_PID(USB_BDT_RX, even_odd)&VUSB_BDT_BC_MASK)
>>VUSB_BDT_BC_SHIFT;
if(pkt_length>g_UsbHcdInfo.ep_info[current_ep_index].data_length)
{
EXT_ASSERT(0, current_ep_index, pkt_length,
g_UsbHcdInfo.ep_info[current_ep_index].data_length);
}
if((g_UsbHcdInfo.ep_info[current_ep_index].sofar+pkt_length)>g_UsbHcdInfo.ep_info[current_ep_index].data_length)
{
EXT_ASSERT(0, current_ep_index, g_UsbHcdInfo.ep_info[current_ep_index].sofar,
g_UsbHcdInfo.ep_info[current_ep_index].data_length);
}
kal_mem_cpy(&g_UsbHcdInfo.ep_info[current_ep_index].p_data[g_UsbHcdInfo.ep_info[current_ep_index].sofar],
(void*)READ_EP0_BDT_ADDR(USB_BDT_RX, even_odd), pkt_length);
g_UsbHcdInfo.ep_info[current_ep_index].sofar+=pkt_length;
/* This one is recvd, software will fill next packet*/
g_UsbHcdInfo.rx_even_odd = even_odd^1;
if((g_UsbHcdInfo.ep_info[current_ep_index].sofar==g_UsbHcdInfo.ep_info[current_ep_index].data_length)
|| (pkt_length<g_UsbHcdInfo.ep_info[current_ep_index].max_packet_size))
{
/* callback to USB stack*/
if(g_UsbHcdInfo.ep_hdlr[current_ep_index]!=NULL)
g_UsbHcdInfo.ep_hdlr[current_ep_index](USB_HCD_OK, g_UsbHcdInfo.ep_info[current_ep_index].sofar);
}
else
{
//queue to scheduler
USB_HCD_Queue_Pkt(current_ep_index);
}
//b_schedule = KAL_TRUE;
b_dis_schedule = KAL_TRUE;
}
}
else
{
if(g_UsbHcdInfo.tx_curent_index==-1)
EXT_ASSERT(0, 0, 0, 0);
current_ep_index = g_UsbHcdInfo.tx_curent_index;
g_UsbHcdInfo.tx_curent_index = -1;
if(current_ep_index == g_UsbHcdInfo.dma_index)
{
/* fast mode packet */
if(g_UsbHcdInfo.dma_dir!=USB_OUT_EP_TYPE)
EXT_ASSERT(0, g_UsbHcdInfo.dma_dir, g_UsbHcdInfo.dma_index, 0);
if(g_UsbHcdInfo.fast_mode_tx_ep != 0)
{
/* This is Fast mode token done intr */
g_UsbHcdInfo.fast_mode_tx_ep = 0;
/* calculate the sent packet size */
/* fast mode size = fast count *64*/
g_UsbHcdInfo.fast_mode_data_size =
(DRV_Reg8(USB_FM_PKT_CNTL) + (DRV_Reg8(USB_FM_PKT_CNTH)<<8)) << 6;
/* tx should not send short pkt, the last one should use tx_res method */
if(FastErrorStatus&VUSB_FM_ERR_SHORT_ERR)
{
EXT_ASSERT(0, FastErrorStatus, g_UsbHcdInfo.fast_mode_data_size, current_ep_index);
}
if(g_UsbHcdInfo.dma_res_tx_ep==0)
{
/* No TX data residue */
/* decide the next even odd */
fm_even_odd = (DRV_Reg8(USB_FM_CTL)&(1<<VUSB_FM_CTL_EP_TX_ODD_SHIFT))>>VUSB_FM_CTL_EP_TX_ODD_SHIFT;
g_UsbHcdInfo.tx_even_odd = fm_even_odd;
if(g_UsbHcdInfo.b_wait_dma == KAL_FALSE)
{
if(g_UsbHcdInfo.ep_hdlr[g_UsbHcdInfo.dma_index]!=NULL)
g_UsbHcdInfo.ep_hdlr[g_UsbHcdInfo.dma_index](USB_HCD_OK, g_UsbHcdInfo.fast_mode_data_size );
//b_schedule = KAL_TRUE;
b_dis_schedule = KAL_TRUE;
}
g_UsbHcdInfo.b_wait_fm_done = KAL_FALSE;
}
}
else if(g_UsbHcdInfo.dma_res_tx_ep != 0)
{
/* This is the last residue packet token done intr*/
g_UsbHcdInfo.dma_res_tx_ep = 0;
//read the sent packet length
pkt_length = (READ_EP0_BDT_PID(USB_BDT_TX, even_odd)&VUSB_BDT_BC_MASK)
>>VUSB_BDT_BC_SHIFT;
g_UsbHcdInfo.fast_mode_data_size+=pkt_length;
if(g_UsbHcdInfo.fast_mode_data_size>g_UsbHcdInfo.ep_info[current_ep_index].data_length)
{
EXT_ASSERT(0, current_ep_index, pkt_length,
g_UsbHcdInfo.ep_info[current_ep_index].data_length);
}
/* This one is transmitted, software will fill next packet*/
/* Note that the last res packet is sent in normal mode so use BDT even odd indication*/
g_UsbHcdInfo.tx_even_odd = even_odd^1;
if(g_UsbHcdInfo.ep_hdlr[current_ep_index]!=NULL)
g_UsbHcdInfo.ep_hdlr[current_ep_index](USB_HCD_OK, g_UsbHcdInfo.fast_mode_data_size);
//b_schedule = KAL_TRUE;
b_dis_schedule = KAL_TRUE;
}
}
else
{
/* Normal mode */
//read the sent packet length
pkt_length = (READ_EP0_BDT_PID(USB_BDT_TX, even_odd)&VUSB_BDT_BC_MASK)
>>VUSB_BDT_BC_SHIFT;
if(pkt_length>g_UsbHcdInfo.ep_info[current_ep_index].data_length)
{
EXT_ASSERT(0, current_ep_index, pkt_length,
g_UsbHcdInfo.ep_info[current_ep_index].data_length);
}
if((g_UsbHcdInfo.ep_info[current_ep_index].sofar+pkt_length)>g_UsbHcdInfo.ep_info[current_ep_index].data_length)
{
EXT_ASSERT(0, current_ep_index, g_UsbHcdInfo.ep_info[current_ep_index].sofar,
g_UsbHcdInfo.ep_info[current_ep_index].data_length);
}
g_UsbHcdInfo.ep_info[current_ep_index].sofar+=pkt_length;
/* This one is transmitted, software will fill next packet*/
g_UsbHcdInfo.tx_even_odd = even_odd^1;
if((g_UsbHcdInfo.ep_info[current_ep_index].sofar==g_UsbHcdInfo.ep_info[current_ep_index].data_length)
|| (pkt_length<g_UsbHcdInfo.ep_info[current_ep_index].max_packet_size))
{
/* callback to USB stack*/
if(g_UsbHcdInfo.ep_hdlr[current_ep_index]!=NULL)
g_UsbHcdInfo.ep_hdlr[current_ep_index](USB_HCD_OK, g_UsbHcdInfo.ep_info[current_ep_index].sofar);
}
else
{
//queue to scheduler
USB_HCD_Queue_Pkt(current_ep_index);
}
//b_schedule = KAL_TRUE;
b_dis_schedule = KAL_TRUE;
}
}
} /* End VUSB_BDT_BUS_TIMEOUT_PID || VUSB_BDT_NAK_PID || VUSB_BDT_ERROR_PID */
} /* End VUSB_INT_STAT_TOKEN_DONE*/
if(IntrStatus&VUSB_INT_STAT_SOF)
{
USB_HCD_Update_Interval();
if((g_UsbHcdInfo.processing_ep_id==-1)
&& (g_UsbHcdInfo.b_wait_dma==KAL_FALSE) && (g_UsbHcdInfo.b_wait_fm_done == KAL_FALSE))
{
b_schedule = KAL_TRUE;
}
} /* End VUSB_INT_STAT_SOF*/
if((OTG_Get_State()==OTG_STATE_A_WAIT_BCON) || (OTG_Get_State()==OTG_STATE_B_WAIT_ACON))
{
if(IntrStatus&VUSB_INT_STAT_ATTACH)
{
if(DRV_Reg8(USB_CTL)&VUSB_CTL_JSTATE)
{
DRV_WriteReg8(USB_INT_ENB, DRV_Reg8(USB_INT_ENB)&(~VUSB_INT_ENB_ATTACH));
USB_HCD_Process_Attach();
}
g_UsbHcdInfo.rx_curent_index = -1;
g_UsbHcdInfo.tx_curent_index = -1;
g_UsbHcdInfo.processing_ep_id = -1;
} /* End VUSB_INT_STAT_ATTACH*/
}
if(IntrStatus&VUSB_INT_STAT_RESUME)
{
USB_HCD_Resume();
} /* End VUSB_INT_STAT_RESUME*/
if (IntrStatus & VUSB_INT_STAT_SLEEP)
{
USB_HCD_Suspend();
} /* End VUSB_INT_STAT_SLEEP */
if (IntrStatus & VUSB_INT_STAT_ERROR)
{
}/* End VUSB_INT_STAT_ERROR */
if((b_schedule==KAL_TRUE) &&(b_dis_schedule==KAL_FALSE))
USB_HCD_Sched_Pending_Pkts();
}
#endif /* __OTG_ENABLE__ */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -