📄 usb_hcd.c
字号:
/* toggel data01*/
g_UsbHcdInfo.ep_info[index].data01^=1;
/* determine endpoint control type*/
if(g_UsbHcdInfo.ep_info[index].ep_type!=USB_HCD_ENDPT_CTRL)
EXT_ASSERT(0, index, g_UsbHcdInfo.ep_info[index].ep_type, 0);
ep_ctrl_type = VUSB_ENDPT_CONTROL;
DRV_WriteReg8(USB_ENDPT_CTL(0), ep_ctrl_type);
/* send token in the last step*/
DRV_WriteReg8(USB_TOKEN, VUSB_TOKEN_SETUP|(g_UsbHcdInfo.ep_info[index].ep_num&VUSB_TOKEN_ENDPT));
}
static void USB_HCD_Send_Data (kal_uint8 index)
{
kal_uint8 ep_ctrl_type;
kal_uint16 todo;
#ifdef __PRODUCTION_RELEASE__
while(DRV_Reg8(USB_CTL)&VUSB_CTL_TOKEN_BUSY)
{
/* wait until the previous done*/
}
#else
if(DRV_Reg8(USB_CTL)&VUSB_CTL_TOKEN_BUSY)
{
// token should be sent only when the previous has been completed
ASSERT(0);
}
#endif
/* make sure no other tx EP is processing*/
if(g_UsbHcdInfo.tx_curent_index != -1)
EXT_ASSERT(0, g_UsbHcdInfo.tx_curent_index, 0, 0);
g_UsbHcdInfo.tx_curent_index = index;
if(g_UsbHcdInfo.ep_info[index].b_fast_mode_enable==KAL_TRUE)
{
USB_HCD_DMA_Setup(index, USB_OUT_EP_TYPE, (kal_uint32)g_UsbHcdInfo.ep_info[index].p_data,
g_UsbHcdInfo.ep_info[index].data_length, KAL_FALSE);
}
else
{
if((g_UsbHcdInfo.ep_info[index].data_length-g_UsbHcdInfo.ep_info[index].sofar)
>g_UsbHcdInfo.ep_info[index].max_packet_size)
todo = g_UsbHcdInfo.ep_info[index].max_packet_size;
else
todo = g_UsbHcdInfo.ep_info[index].data_length-g_UsbHcdInfo.ep_info[index].sofar;
/* copy data to FIFO*/
kal_mem_cpy((void*)READ_EP0_BDT_ADDR(USB_BDT_TX, g_UsbHcdInfo.tx_even_odd),
&g_UsbHcdInfo.ep_info[index].p_data[g_UsbHcdInfo.ep_info[index].sofar], todo);
/* setup bdt. include own bit. */
WRITE_EP0_BDT_PID(USB_BDT_TX, g_UsbHcdInfo.tx_even_odd,
(todo<<VUSB_BDT_BC_SHIFT)
|(g_UsbHcdInfo.ep_info[index].data01<<VUSB_BDT_DATA01_SHIFT)|VUSB_BDT_OWNS_BIT);
/* toggel data01*/
g_UsbHcdInfo.ep_info[index].data01^=1;
/* determine endpoint control type*/
switch(g_UsbHcdInfo.ep_info[index].ep_type)
{
case USB_HCD_ENDPT_CTRL:
ep_ctrl_type = VUSB_ENDPT_CONTROL;
break;
case USB_HCD_ENDPT_BULK:
ep_ctrl_type = VUSB_ENDPT_BULK_TX;
break;
case USB_HCD_ENDPT_INTR:
ep_ctrl_type = VUSB_ENDPT_BULK_TX;
break;
case USB_HCD_ENDPT_ISO:
ep_ctrl_type = VUSB_ENDPT_ISO_TX;
break;
default:
ep_ctrl_type = 0;
ASSERT(0);
break;
}
DRV_WriteReg8(USB_ENDPT_CTL(0), ep_ctrl_type);
/* send token in the last step*/
DRV_WriteReg8(USB_TOKEN, VUSB_TOKEN_OUT|(g_UsbHcdInfo.ep_info[index].ep_num&VUSB_TOKEN_ENDPT));
}
}
static void USB_HCD_Recv_Data (kal_uint8 index)
{
kal_uint8 ep_ctrl_type;
kal_uint16 todo;
#ifdef __PRODUCTION_RELEASE__
while(DRV_Reg8(USB_CTL)&VUSB_CTL_TOKEN_BUSY)
{
/* wait until the previous done*/
}
#else
if(DRV_Reg8(USB_CTL)&VUSB_CTL_TOKEN_BUSY)
{
// token should be sent only when the previous has been completed
ASSERT(0);
}
#endif
/* make sure no other tx EP is processing*/
if(g_UsbHcdInfo.rx_curent_index != -1)
EXT_ASSERT(0, g_UsbHcdInfo.rx_curent_index, 0, 0);
g_UsbHcdInfo.rx_curent_index = index;
if(g_UsbHcdInfo.ep_info[index].b_fast_mode_enable==KAL_TRUE)
{
USB_HCD_DMA_Setup(index, USB_IN_EP_TYPE, (kal_uint32)g_UsbHcdInfo.ep_info[index].p_data,
g_UsbHcdInfo.ep_info[index].data_length, KAL_FALSE);
}
else
{
if((g_UsbHcdInfo.ep_info[index].data_length-g_UsbHcdInfo.ep_info[index].sofar)
>g_UsbHcdInfo.ep_info[index].max_packet_size)
todo = g_UsbHcdInfo.ep_info[index].max_packet_size;
else
todo = g_UsbHcdInfo.ep_info[index].data_length-g_UsbHcdInfo.ep_info[index].sofar;
/* setup bdt. include own bit. */
WRITE_EP0_BDT_PID(USB_BDT_RX, g_UsbHcdInfo.rx_even_odd,
(todo<<VUSB_BDT_BC_SHIFT)
|(g_UsbHcdInfo.ep_info[index].data01<<VUSB_BDT_DATA01_SHIFT)|VUSB_BDT_OWNS_BIT);
/* toggel data01*/
g_UsbHcdInfo.ep_info[index].data01^=1;
/* determine endpoint control type*/
switch(g_UsbHcdInfo.ep_info[index].ep_type)
{
case USB_HCD_ENDPT_CTRL:
ep_ctrl_type = VUSB_ENDPT_CONTROL;
break;
case USB_HCD_ENDPT_BULK:
ep_ctrl_type = VUSB_ENDPT_BULK_RX;
break;
case USB_HCD_ENDPT_INTR:
ep_ctrl_type = VUSB_ENDPT_BULK_RX;
break;
case USB_HCD_ENDPT_ISO:
ep_ctrl_type = VUSB_ENDPT_ISO_RX;
break;
default:
ep_ctrl_type = 0;
ASSERT(0);
break;
}
DRV_WriteReg8(USB_ENDPT_CTL(0), ep_ctrl_type);
/* send token in the last step*/
DRV_WriteReg8(USB_TOKEN, VUSB_TOKEN_IN|(g_UsbHcdInfo.ep_info[index].ep_num&VUSB_TOKEN_ENDPT));
}
}
static void USB_HCD_Queue_Pkt(kal_uint8 index)
{
kal_int8 *p_head;
kal_int8 *p_tail;
switch(g_UsbHcdInfo.ep_info[index].ep_type)
{
case USB_HCD_ENDPT_BULK:
p_head = &g_UsbHcdInfo.bulk_pipe_head;
p_tail = &g_UsbHcdInfo.bulk_pipe_tail;
break;
case USB_HCD_ENDPT_CTRL:
p_head = &g_UsbHcdInfo.ctrl_pipe_head;
p_tail = &g_UsbHcdInfo.ctrl_pipe_tail;
break;
case USB_HCD_ENDPT_INTR:
p_head = &g_UsbHcdInfo.intr_pipe_head;
p_tail = &g_UsbHcdInfo.intr_pipe_tail;
break;
case USB_HCD_ENDPT_ISO:
p_head = &g_UsbHcdInfo.iso_pipe_head;
p_tail = &g_UsbHcdInfo.iso_pipe_tail;
break;
default:
p_head = 0;
p_tail = 0;
EXT_ASSERT(0, index, g_UsbHcdInfo.ep_info[index].ep_type, 0);
break;
}
if((*p_head)==-1)
{
g_UsbHcdInfo.ep_info[index].next_ep_id = -1;
*p_head = index;
*p_tail = index;
}
else
{
g_UsbHcdInfo.ep_info[*p_tail].next_ep_id = index;
g_UsbHcdInfo.ep_info[index].next_ep_id = -1;
*p_tail = index;
}
}
static void USB_HCD_Remove_Pkt(kal_uint8 index)
{
kal_int8 *p_head;
kal_int8 *p_tail;
switch(g_UsbHcdInfo.ep_info[index].ep_type)
{
case USB_HCD_ENDPT_BULK:
p_head = &g_UsbHcdInfo.bulk_pipe_head;
p_tail = &g_UsbHcdInfo.bulk_pipe_tail;
break;
case USB_HCD_ENDPT_CTRL:
p_head = &g_UsbHcdInfo.ctrl_pipe_head;
p_tail = &g_UsbHcdInfo.ctrl_pipe_tail;
break;
case USB_HCD_ENDPT_INTR:
p_head = &g_UsbHcdInfo.intr_pipe_head;
p_tail = &g_UsbHcdInfo.intr_pipe_tail;
break;
case USB_HCD_ENDPT_ISO:
p_head = &g_UsbHcdInfo.iso_pipe_head;
p_tail = &g_UsbHcdInfo.iso_pipe_tail;
break;
default:
p_head = 0;
p_tail = 0;
EXT_ASSERT(0, index, g_UsbHcdInfo.ep_info[index].ep_type, 0);
break;
}
if(g_UsbHcdInfo.ep_info[index].next_ep_id==-1)
{
*p_head = -1;
*p_tail = -1;
}
else
{
*p_head = g_UsbHcdInfo.ep_info[index].next_ep_id;
g_UsbHcdInfo.ep_info[index].next_ep_id = -1;
}
}
static kal_int8 USB_HCD_Get_Pending_Pkts(void)
{
kal_int8 head = -1;
if(g_UsbHcdInfo.iso_pipe_head!=-1)
{
head = g_UsbHcdInfo.iso_pipe_head;
// note that it needs to modified if more than one iso pipe
if(head!=-1)
{
if(g_UsbHcdInfo.ep_info[head].current_interval!=0)
head = -1;
}
}
else if(g_UsbHcdInfo.intr_pipe_head!=-1)
{
// note that it needs to modified if more than one intr pipe
head = g_UsbHcdInfo.intr_pipe_head;
if(head!=-1)
{
if(g_UsbHcdInfo.ep_info[head].current_interval!=0)
head = -1;
}
}
else if(g_UsbHcdInfo.ctrl_pipe_head!=-1)
{
head = g_UsbHcdInfo.ctrl_pipe_head;
if(head!=-1)
{
if(g_UsbHcdInfo.ep_info[head].current_interval==0)
{
USB_HCD_Remove_Pkt(head);
/* callback to USB stack, timeout error*/
if(g_UsbHcdInfo.ep_hdlr[head]!=NULL)
g_UsbHcdInfo.ep_hdlr[head](USB_HCD_TIMEOUT, g_UsbHcdInfo.ep_info[head].sofar);
head = -1;
}
}
}
else if(g_UsbHcdInfo.bulk_pipe_head!=-1)
{
head = g_UsbHcdInfo.bulk_pipe_head;
if(head!=-1)
{
if((g_UsbHcdInfo.ep_info[head].current_interval==0) && (g_UsbHcdInfo.ep_info[head].b_fast_mode_enable==KAL_FALSE))
{
USB_HCD_Remove_Pkt(head);
/* callback to USB stack, timeout error*/
if(g_UsbHcdInfo.ep_hdlr[head]!=NULL)
g_UsbHcdInfo.ep_hdlr[head](USB_HCD_TIMEOUT, g_UsbHcdInfo.ep_info[head].sofar);
head = -1;
}
}
}
return head;
}
static void USB_HCD_Sched_Pending_Pkts(void)
{
kal_int8 head = -1;
head = USB_HCD_Get_Pending_Pkts();
g_UsbHcdInfo.processing_ep_id = head;
if((head==0) && (g_UsbHcdInfo.ep0_setup==KAL_TRUE))
{
USB_HCD_Send_Setup(head);
}
else if(head!=-1)
{
if(g_UsbHcdInfo.ep_info[head].direction==USB_HCD_PIPE_DIR_IN)
{
USB_HCD_Recv_Data(head);
}
else
{
USB_HCD_Send_Data(head);
}
}
}
/* return value means if there is any pipe timeout*/
static void USB_HCD_Update_Interval(void)
{
kal_int8 pipe_id;
pipe_id = g_UsbHcdInfo.iso_pipe_head;
while(pipe_id!=-1)
{
if(g_UsbHcdInfo.ep_info[pipe_id].current_interval!=0)
{
g_UsbHcdInfo.ep_info[pipe_id].current_interval--;
}
pipe_id = g_UsbHcdInfo.ep_info[pipe_id].next_ep_id;
}
pipe_id = g_UsbHcdInfo.intr_pipe_head;
while(pipe_id!=-1)
{
if(g_UsbHcdInfo.ep_info[pipe_id].current_interval!=0)
{
g_UsbHcdInfo.ep_info[pipe_id].current_interval--;
}
pipe_id = g_UsbHcdInfo.ep_info[pipe_id].next_ep_id;
}
pipe_id = g_UsbHcdInfo.ctrl_pipe_head;
while(pipe_id!=-1)
{
if(g_UsbHcdInfo.ep_info[pipe_id].current_interval!=0)
{
g_UsbHcdInfo.ep_info[pipe_id].current_interval--;
}
pipe_id = g_UsbHcdInfo.ep_info[pipe_id].next_ep_id;
}
pipe_id = g_UsbHcdInfo.bulk_pipe_head;
while(pipe_id!=-1)
{
if(g_UsbHcdInfo.ep_info[pipe_id].current_interval!=0)
{
g_UsbHcdInfo.ep_info[pipe_id].current_interval--;
}
pipe_id = g_UsbHcdInfo.ep_info[pipe_id].next_ep_id;
}
}
/************************************************************
Fast mode (DMA) functions
*************************************************************/
/* get dma channel for logical endpoint. Only one channel is needed becuase host knows each transfer direction */
void USB_HCD_Get_DMA_Channel(void)
{
g_UsbHcdInfo.dma_port = DMA_GetChannel(DMA_USB1TX);
}
/* stop DMA channel*/
void USB_HCD_Stop_DMA_Channel(void)
{
kal_uint32 savedMask;
kal_uint32 fm_dma_index;
/* Stop generic DMA */
if(g_UsbHcdInfo.dma_port != 0)
{
if (DMA_CheckRunStat(g_UsbHcdInfo.dma_port))
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -