⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 usb_hcd.c

📁 8032底层驱动部分。因为可以移植 所以单独来拿出来
💻 C
📖 第 1 页 / 共 5 页
字号:
	
	/* 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 + -