📄 usb_hcd.c
字号:
/* assert reset on the USB */
DRV_WriteReg8(USB_CTL, VUSB_CTL_HOST_MODE_EN | VUSB_CTL_RESET);
g_UsbHcdInfo.reset_reason = reset_reason;
/* Delay for the reset process to complete */
GPTI_StartItem(g_UsbHcdInfo.gpt_handle, USB_HCD_RESET_DELAY,
USB_HCD_Reset_Timeout, &g_UsbHcdInfo);
}
/* GPT timeout function*/
static void USB_HCD_Delay_Reset_Timeout(void *parameter)
{
kal_uint32 reset_reason = (kal_uint32)parameter;
GPTI_StopItem(g_UsbHcdInfo.gpt_handle);
USB_HCD_Reset_Device((USB_HCD_STATUS)reset_reason);
}
/* Reset after timeout, note that timeout unit is 10ms */
void USB_HCD_Delay_Reset_Device(USB_HCD_STATUS reset_reason, kal_uint32 timeout)
{
if(timeout>0)
GPTI_StartItem(g_UsbHcdInfo.gpt_handle, timeout,
USB_HCD_Delay_Reset_Timeout, (void*)reset_reason);
else
USB_HCD_Reset_Device(reset_reason);
}
/* GPT timeout function*/
static void USB_HCD_Debounce_Timeout(void *parameter)
{
GPTI_StopItem(g_UsbHcdInfo.gpt_handle);
if(g_UsbHcdInfo.b_disable_attach==KAL_TRUE)
{
GPTI_StartItem(g_UsbHcdInfo.gpt_handle, USB_HCD_DEBOUNCE_DELAY,
USB_HCD_Debounce_Timeout, &g_UsbHcdInfo);
}
else
{
USB_HCD_Debounce_Attach();
}
}
static void USB_HCD_Debounce_Attach(void)
{
kal_uint8 control_value;
control_value = DRV_Reg8(USB_CTL);
DRV_WriteReg8(USB_ADDR, 0);
/* currently full speed */
if (control_value & VUSB_CTL_SINGLE_ENDED_0)
{
// add error handling
//ASSERT(0);
USB_HCD_Process_Detach();
if(g_UsbHcdInfo.b_unmask_irq == KAL_FALSE)
{
/* unmask USB IRQ*/
g_UsbHcdInfo.b_unmask_irq = KAL_TRUE;
IRQUnmask(IRQ_USB_CODE);
}
return;
}
else
{
DRV_WriteReg8(USB_ADDR, 0);
/* Add for OTG function*/
if(OTG_Get_Plug_Type()==OTG_PLUG_A)
OTG_Set_Status(OTG_STATUS_A_DETECT_B_CONN, KAL_TRUE);
else
OTG_Set_Status(OTG_STATUS_B_DETECT_A_CONN, KAL_TRUE);
}
/* enable ep0 */
DRV_WriteReg8(USB_ENDPT_CTL(0), VUSB_ENDPT_CONTROL);
/* Reset the device */
USB_HCD_Reset_Device(USB_HCD_OK);
}
static void USB_HCD_Process_Attach(void)
{
OTG_STATE otg_state;
/* Enable all errors */
DRV_WriteReg8(USB_ERR_ENB, 0xff);
/* Zero the control register. It is okay to do this because JSTATE
** and SE0 are read-only bits
*/
DRV_WriteReg8(USB_CTL, VUSB_CTL_HOST_MODE_EN);
otg_state = OTG_Get_State();
if(((otg_state!=OTG_STATE_A_SUSPEND) && (otg_state!=OTG_STATE_B_WAIT_ACON))
|| (g_UsbHcdInfo.b_disable_attach==KAL_TRUE))
{
GPTI_StartItem(g_UsbHcdInfo.gpt_handle, USB_HCD_DEBOUNCE_DELAY,
USB_HCD_Debounce_Timeout, &g_UsbHcdInfo);
g_UsbHcdInfo.b_unmask_irq = KAL_FALSE;
}
else
{
USB_HCD_Debounce_Attach();
}
}
static void USB_HCD_Process_Detach(void)
{
/* Cancel if there are any pending tokens */
g_UsbHcdInfo.processing_ep_id = -1;
/* Reset all the attached device specific values */
DRV_WriteReg8(USB_ADDR, 0);
if(OTG_Get_State()==OTG_STATE_B_IDLE)
return;
/* enable ep0 */
DRV_WriteReg8(USB_ENDPT_CTL(0), VUSB_ENDPT_CONTROL);
/* Set the ODD/EVEN BDT to even and enable the host mode */
DRV_WriteReg8(USB_CTL, VUSB_CTL_ODD_RST);
DRV_WriteReg8(USB_CTL, VUSB_CTL_HOST_MODE_EN);
/* Clear all interrupts */
DRV_WriteReg8(USB_INT_STAT, 0xff);
/* Enable attach interrupt */
DRV_WriteReg8(USB_INT_ENB, VUSB_INT_ENB_ATTACH);
/* Add for OTG function*/
if(OTG_Get_Plug_Type()==OTG_PLUG_A)
OTG_Set_Status(OTG_STATUS_A_DETECT_B_CONN, KAL_FALSE);
else
OTG_Set_Status(OTG_STATUS_B_DETECT_A_CONN, KAL_FALSE);
/* Call the callback function if there was one registered for a detach
** event
*/
if(g_UsbHcdInfo.detach_hdlr==NULL)
EXT_ASSERT(0, 0, 0, 0);
g_UsbHcdInfo.detach_hdlr(USB_HCD_OK, 0);
} /* Endbody */
void USB_HCD_Bus_Control(USB_HCD_BUS_TYPE type)
{
switch(type)
{
case USB_HCD_BUS_SUSPEND_SOF:
DRV_WriteReg8(USB_CTL, VUSB_CTL_HOST_MODE_EN);
/* Enable the resume interrupt when suspended */
DRV_WriteReg8(USB_INT_ENB, DRV_Reg8(USB_INT_ENB)|VUSB_INT_ENB_RESUME);
break;
case USB_HCD_BUS_RESUME_SOF:
case USB_HCD_BUS_DEASSERT_RESUME:
DRV_WriteReg8(USB_CTL, VUSB_CTL_HOST_MODE_EN|VUSB_CTL_SOF_EN);
/* disable the resume interrupt when resumed */
DRV_WriteReg8(USB_INT_ENB, DRV_Reg8(USB_INT_ENB)&(~VUSB_INT_ENB_RESUME));
break;
case USB_HCD_BUS_ASSERT_RESUME:
DRV_WriteReg8(USB_CTL, VUSB_CTL_HOST_MODE_EN|VUSB_CTL_RESUME);
/* disable the resume interrupt when resumed */
DRV_WriteReg8(USB_INT_ENB, DRV_Reg8(USB_INT_ENB)&(~VUSB_INT_ENB_RESUME));
break;
default:
ASSERT(0);
break;
}
}
/************************************************************
EP ctrl functinos
*************************************************************/
kal_uint8 USB_HCD_Get_EP_Channel(void)
{
kal_uint32 index;
for(index=1; index<USB_HCD_MAX_EP_NUM; index++)
{
if(g_UsbHcdInfo.ep_info[index].b_in_use==KAL_FALSE)
{
g_UsbHcdInfo.ep_info[index].b_in_use = KAL_TRUE;
g_UsbHcdInfo.ep_info[index].b_enable = KAL_FALSE;
break;
}
}
if(index>=USB_HCD_MAX_EP_NUM)
EXT_ASSERT(0, index, 0, 0);
return index;
}
void USB_HCD_Free_EP_Channel(void)
{
kal_uint32 index;
for(index=1; index<USB_HCD_MAX_EP_NUM; index++)
{
g_UsbHcdInfo.ep_info[index].b_in_use=KAL_FALSE;
g_UsbHcdInfo.ep_info[index].b_enable = KAL_FALSE;
}
}
void USB_HCD_Set_EP_Max_Pkt(kal_uint8 index, kal_uint16 max_pkt_size)
{
g_UsbHcdInfo.ep_info[index].max_packet_size = max_pkt_size;
}
void USB_HCD_Clear_Data01(kal_uint8 index)
{
g_UsbHcdInfo.ep_info[index].data01 = 0;
}
void USB_HCD_EP0En(void)
{
g_UsbHcdInfo.ep_info[0].b_in_use = KAL_TRUE;
g_UsbHcdInfo.ep_info[0].b_enable = KAL_TRUE;
g_UsbHcdInfo.ep_info[0].ep_type = USB_HCD_ENDPT_CTRL;
g_UsbHcdInfo.ep_info[0].ep_num = 0;
g_UsbHcdInfo.ep_info[0].data01 = 0;
g_UsbHcdInfo.ep_info[0].interval = 2048;
g_UsbHcdInfo.ep_info[0].current_interval = g_UsbHcdInfo.ep_info[0].interval;
g_UsbHcdInfo.ep_info[0].no_response_count = 0;
}
/* Note that the interval unit is 64ms */
void USB_HCD_InEPEn(kal_uint8 index, kal_uint8 no, USB_HCD_ENDPT_TYPE ep_type, kal_uint8 interval, kal_bool bDMA)
{
if((index>=USB_HCD_MAX_EP_NUM) || (g_UsbHcdInfo.ep_info[index].b_in_use==KAL_FALSE))
EXT_ASSERT(0, index, 0, 0);
g_UsbHcdInfo.ep_info[index].b_enable = KAL_TRUE;
g_UsbHcdInfo.ep_info[index].ep_type = ep_type;
g_UsbHcdInfo.ep_info[index].ep_num = no;
g_UsbHcdInfo.ep_info[index].data01 = 0;
g_UsbHcdInfo.ep_info[index].direction = USB_HCD_PIPE_DIR_IN;
if(bDMA==KAL_FALSE)
g_UsbHcdInfo.ep_info[index].interval = interval*64;
else
g_UsbHcdInfo.ep_info[index].interval = interval;
g_UsbHcdInfo.ep_info[index].current_interval = g_UsbHcdInfo.ep_info[index].interval;
g_UsbHcdInfo.ep_info[index].no_response_count = 0;
g_UsbHcdInfo.ep_info[index].b_fast_mode_enable = bDMA;
}
void USB_HCD_OutEPEn(kal_uint8 index, kal_uint8 no, USB_HCD_ENDPT_TYPE ep_type, kal_uint8 interval, kal_bool bDMA)
{
if((index>=USB_HCD_MAX_EP_NUM) || (g_UsbHcdInfo.ep_info[index].b_in_use==KAL_FALSE))
EXT_ASSERT(0, index, 0, 0);
g_UsbHcdInfo.ep_info[index].b_enable = KAL_TRUE;
g_UsbHcdInfo.ep_info[index].ep_type = ep_type;
g_UsbHcdInfo.ep_info[index].ep_num = no;
g_UsbHcdInfo.ep_info[index].data01 = 0;
g_UsbHcdInfo.ep_info[index].direction = USB_HCD_PIPE_DIR_OUT;
if(bDMA==KAL_FALSE)
g_UsbHcdInfo.ep_info[index].interval = interval*64;
else
g_UsbHcdInfo.ep_info[index].interval = interval;
g_UsbHcdInfo.ep_info[index].current_interval = g_UsbHcdInfo.ep_info[index].interval;
g_UsbHcdInfo.ep_info[index].no_response_count = 0;
g_UsbHcdInfo.ep_info[index].b_fast_mode_enable = bDMA;
}
void USB_HCD_InEPDis(kal_uint8 index)
{
if((index>=USB_HCD_MAX_EP_NUM) || (g_UsbHcdInfo.ep_info[index].b_in_use==KAL_FALSE))
EXT_ASSERT(0, index, 0, 0);
g_UsbHcdInfo.ep_info[index].b_enable = KAL_FALSE;
}
void USB_HCD_OutEPDis(kal_uint8 index)
{
if((index>=USB_HCD_MAX_EP_NUM) || (g_UsbHcdInfo.ep_info[index].b_in_use==KAL_FALSE))
EXT_ASSERT(0, index, 0, 0);
g_UsbHcdInfo.ep_info[index].b_enable = KAL_TRUE;
}
kal_bool USB_HCD_Recv_Req(kal_uint8 index, kal_uint16 nBytes, void *pDst)
{
if((index>=USB_HCD_MAX_EP_NUM) || (g_UsbHcdInfo.ep_info[index].b_in_use==KAL_FALSE)
|| (g_UsbHcdInfo.ep_info[index].b_enable==KAL_FALSE))
return KAL_FALSE;
g_UsbHcdInfo.ep_info[index].p_data = pDst;
g_UsbHcdInfo.ep_info[index].data_length = nBytes;
g_UsbHcdInfo.ep_info[index].current_interval = g_UsbHcdInfo.ep_info[index].interval;
g_UsbHcdInfo.ep_info[index].no_response_count = 0;
g_UsbHcdInfo.ep_info[index].sofar = 0;
//queue to scheduler
USB_HCD_Queue_Pkt(index);
return KAL_TRUE;
}
kal_bool USB_HCD_Send_Req(kal_uint8 index, kal_uint16 nBytes, void *pSrc)
{
if((index>=USB_HCD_MAX_EP_NUM) || (g_UsbHcdInfo.ep_info[index].b_in_use==KAL_FALSE)
|| (g_UsbHcdInfo.ep_info[index].b_enable==KAL_FALSE))
return KAL_FALSE;
g_UsbHcdInfo.ep_info[index].p_data = pSrc;
g_UsbHcdInfo.ep_info[index].data_length = nBytes;
g_UsbHcdInfo.ep_info[index].current_interval = g_UsbHcdInfo.ep_info[index].interval;
g_UsbHcdInfo.ep_info[index].no_response_count = 0;
g_UsbHcdInfo.ep_info[index].sofar = 0;
//queue to scheduler
USB_HCD_Queue_Pkt(index);
return KAL_TRUE;
}
void USB_HCD_EP0_Setup_Req(kal_uint16 nBytes, void *pSrc)
{
g_UsbHcdInfo.ep0_setup = KAL_TRUE;
g_UsbHcdInfo.ep_info[0].data01 = 0;
g_UsbHcdInfo.ep_info[0].p_data = pSrc;
g_UsbHcdInfo.ep_info[0].data_length = nBytes;
g_UsbHcdInfo.ep_info[0].current_interval = g_UsbHcdInfo.ep_info[0].interval;
g_UsbHcdInfo.ep_info[0].no_response_count = 0;
g_UsbHcdInfo.ep_info[0].sofar = 0;
//queue to scheduler
USB_HCD_Queue_Pkt(0);
}
void USB_HCD_EP0_Data_Req(USB_HCD_PIPE_DIRECTION direction, kal_uint16 nBytes, void *pData)
{
g_UsbHcdInfo.ep0_setup = KAL_FALSE;
g_UsbHcdInfo.ep_info[0].direction = direction;
g_UsbHcdInfo.ep_info[0].p_data = pData;
g_UsbHcdInfo.ep_info[0].data_length = nBytes;
g_UsbHcdInfo.ep_info[0].current_interval = g_UsbHcdInfo.ep_info[0].interval;
g_UsbHcdInfo.ep_info[0].no_response_count = 0;
g_UsbHcdInfo.ep_info[0].sofar = 0;
//queue to scheduler
USB_HCD_Queue_Pkt(0);
}
void USB_HCD_EP0_Status_Req(USB_HCD_PIPE_DIRECTION direction)
{
g_UsbHcdInfo.ep0_setup = KAL_FALSE;
g_UsbHcdInfo.ep_info[0].direction = direction;
g_UsbHcdInfo.ep_info[0].data01 = 1;
g_UsbHcdInfo.ep_info[0].p_data = NULL;
g_UsbHcdInfo.ep_info[0].data_length = 0;
g_UsbHcdInfo.ep_info[0].current_interval = g_UsbHcdInfo.ep_info[0].interval;
g_UsbHcdInfo.ep_info[0].no_response_count = 0;
g_UsbHcdInfo.ep_info[0].sofar = 0;
//queue to scheduler
USB_HCD_Queue_Pkt(0);
}
static void USB_HCD_Send_Setup (kal_uint8 index)
{
kal_uint8 ep_ctrl_type;
#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;
g_UsbHcdInfo.ep_info[index].sofar = 0;
/* 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].data_length);
/* setup bdt. include own bit. */
WRITE_EP0_BDT_PID(USB_BDT_TX, g_UsbHcdInfo.tx_even_odd,
(g_UsbHcdInfo.ep_info[index].data_length<<VUSB_BDT_BC_SHIFT)
|(g_UsbHcdInfo.ep_info[index].data01<<VUSB_BDT_DATA01_SHIFT)|VUSB_BDT_OWNS_BIT);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -