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

📄 hc_otg.c

📁 一个USB主机核的驱动程序
💻 C
📖 第 1 页 / 共 2 页
字号:
		SetBitOTGReg32(otg_DMA_Ctrl, (DMA_Ctrl_EnDMA | DMA_Ctrl_Direction | DMA_Ctrl_Mode | DMA_Ctrl_IntrEn));
		/* get max packet size value */
		temp = ed->MaxPacketSize;
		temp |= ((BULK_EP_FIFO_SIZE / ed->MaxPacketSize - 1) << 11);
		WriteOTGReg16(otg_IndexedCSR_TxMaxP, temp);
		/* config CSR */
		SetBitOTGReg16(otg_IndexedCSR_TxCSR, (TxCSR_hrw_AutoSet | TxCSR_hrw_DMAReqEnab | TxCSR_hrw_DMAReqMode)); //config TxCSR

		/* wait DMA load data */
		to = TRANSACTION_TIME_OUT;
		while(to)
		{
			temp1 = ReadOTGReg32(otg_DMA_Intr);
			if ((temp1 & DMA_Intr_Ch1) != 0)	
				break;
			to--;
		}/* end while */
		if (to == 0)
			return DEVICE_NOT_RESPONDING;

		ClrBitOTGReg16(otg_IndexedCSR_TxCSR, (TxCSR_hrw_AutoSet | TxCSR_hrw_DMAReqEnab | TxCSR_hrw_DMAReqMode));
		ClrBitOTGReg32(otg_DMA_Ctrl, (DMA_Ctrl_EnDMA | DMA_Ctrl_Direction | DMA_Ctrl_Mode | DMA_Ctrl_IntrEn));
		temp = ReadOTGReg16(otg_IndexedCSR_RxCSR);

			/* check CSR response */
		if ((temp & TxCSR_hrc_RxStall) != 0)
		{
			ClrBitOTGReg16(otg_IndexedCSR_TxCSR, TxCSR_hrc_RxStall);		/* get STALL response */
			return STALL;
		}
		else if ((temp & TxCSR_hrc_Error) != 0)
		{
			ClrBitOTGReg16(otg_IndexedCSR_TxCSR, TxCSR_hrc_Error);			/* get ERROR response */
			return ERR;
		}
		else if ((temp & TxCSR_hrc_NAKTimeout_IncompTx) != 0)
		{
			ClrBitOTGReg16(otg_IndexedCSR_TxCSR, TxCSR_hrc_NAKTimeout_IncompTx);		/* get NAK timeoue response */
			return NAK_TIME_OUT;
		}
		else
		{
			return NO_ERROR;			/* no STALL, ERROR, NAKTimeout */
		}	
	}/* end else */
}
/*------------------------------------------------------------------------------------*/



/*-------------------------------HC source allocate ----------------------------------*/
/*
 * 	allocate host controller source
 */
extern HC*
AllocHc(VOID)
{
	BYTE	DATA	i;
	HC* 	DATA	hc;

	i = SearchMapZero(&gHcMap, MAX_HC_NUM);
	if (i == MAX_HC_NUM)
		return NULL;

	SetMap(&gHcMap, i);
	hc = &gHc[i];
	memset(hc, 0, sizeof(HC));
	hc->Set = i;

	return &gHc[i];
}

/*
 * 	free host controller source
 */
extern VOID
FreeHc(
	HC		*hc
	)
{
	ClearMap(&gHcMap, hc->Set);
}


extern HC_EP*
HcAllocHcEndpoint(
	HC		*hc,
	BYTE	epNum
	)
{
	BYTE	DATA	i;
	HC_EP*	DATA	ep;

	if (epNum == 0)
	{
		SetMap(&hc->HcEpMap, 0);
		ep = &hc->Ep[0];
		ep->Index = 0;
	}
	else
	{
		i = SearchMapZero(&hc->HcEpMap, MAX_HC_ENDPOINT_NUM);
		if (i == MAX_HC_ENDPOINT_NUM)
			return NULL;
	
		SetMap(&hc->HcEpMap, i);
		ep = &hc->Ep[i];
		ep->Index = i;	
	}

	return ep;
}


/*
 * 	free one HC endpoint
 */
extern VOID
HcFreeHcEndpoint(
	HC		*hc,
	HC_EP	*ep
	)
{
	ClearMap(&hc->HcEpMap, ep->Index);
}


/*
 * 	open one HC endpoint
 */
extern VOID
OpenHcEndpoint(
	HC		*hc,
	HC_ED	*ed
	)
{
	WORD	DATA	temp;

	hc = hc;
	if (ed->EndPointNum == 0)
	{
		/* set function address */
	//	WriteOTGReg8(otg_CommonUSB_FAddr, ed->FuncAddr);
		/* set endpoint number index */
		WriteOTGReg8(otg_CommonUSB_Index, 0);
		SetBitOTGReg16(otg_IndexedCSR_CSR0, CSR0_hs_FlushFIFO);
		return;
	}/* end if (ed->EndPointNum == 0) */

	/* set function address */
//	WriteOTGReg8(otg_CommonUSB_FAddr, ed->FuncAddr);
	/* set endpoint number index */
	WriteOTGReg8(otg_CommonUSB_Index, ed->Ep->Index);

	if (ed->Direction == USB_DIR_IN)
	{
		ClrBitOTGReg16(otg_IndexedCSR_TxCSR, TxCSR_hrw_Mode);	/* Rx endpoint */
		WriteOTGReg8(otg_IndexedCSR_host_RxType, 0);
		WriteOTGReg8(otg_IndexedCSR_host_RxType, ed->EndPointNum);		/* set transfer type */
		ClrBitOTGReg8(otg_IndexedCSR_host_RxType, RxType_rw_Protocol);
		SetBitOTGReg8(otg_IndexedCSR_host_RxType, (ed->TransferType << 4));				
		WriteOTGReg16(otg_IndexedCSR_RxMaxP, ed->MaxPacketSize);		/* set max packet size */
		WriteOTGReg8(otg_IndexedCSR_host_RxInterval, ed->Interval);	/* set endpoint interval */
//			SetBitOTGReg16(otg_IndexedCSR_RxCSR, RxCSR_hs_ClrDataTog);	/* clear data toggle */
//		if ((ReadOTGReg16(otg_IndexedCSR_RxCSR) & RxCSR_hrc_RxPktRdy) != 0)
//				SetBitOTGReg16(otg_IndexedCSR_RxCSR, RxCSR_hs_FlushFIFO);		/* flush FIFO */
		temp = ReadOTGReg16(otg_IndexedCSR_RxCSR);
		if ((temp & RxCSR_hrc_RxStall) != 0)
		{
			ClrBitOTGReg16(otg_IndexedCSR_RxCSR, RxCSR_hrc_RxStall);		/* get STALL response */
		}
		else if ((temp & RxCSR_hrc_Error) != 0)
		{
			ClrBitOTGReg16(otg_IndexedCSR_RxCSR, RxCSR_hrc_Error);		/* get ERROR response */
		}
		else if ((temp & RxCSR_hrc_DataError_NAKTimeout) != 0)
		{
			ClrBitOTGReg16(otg_IndexedCSR_RxCSR, RxCSR_hrc_DataError_NAKTimeout);		/* get NAK timeoue response */
		}	
	}
	else
	{
		SetBitOTGReg16(otg_IndexedCSR_TxCSR, TxCSR_hrw_Mode);	/* Tx endpoint */
		WriteOTGReg8(otg_IndexedCSR_host_TxType, 0);
		WriteOTGReg8(otg_IndexedCSR_host_TxType, ed->EndPointNum);		/* set transfer type */
		ClrBitOTGReg8(otg_IndexedCSR_host_TxType, TxType_rw_Protocol);
		SetBitOTGReg8(otg_IndexedCSR_host_TxType, (ed->TransferType << 4));
		WriteOTGReg16(otg_IndexedCSR_TxMaxP, ed->MaxPacketSize);		/* set max packet size */
		WriteOTGReg8(otg_IndexedCSR_host_TxInterval, ed->Interval);	/* set endpoint interval */
//		SetBitOTGReg16(otg_IndexedCSR_TxCSR, TxCSR_hs_ClrDataTog);	/* clear data toggle */
//		if ((ReadOTGReg16(otg_IndexedCSR_TxCSR) & TxCSR_hrc_FIFONotEmpty) != 0)
//			SetBitOTGReg16(otg_IndexedCSR_TxCSR, TxCSR_hs_FlushFIFO);		/* flush FIFO */
		temp = ReadOTGReg16(otg_IndexedCSR_TxCSR);
		if ((temp & TxCSR_hrc_RxStall) != 0)
		{
			ClrBitOTGReg16(otg_IndexedCSR_TxCSR, TxCSR_hrc_RxStall);		/* get STALL response */
		}
		else if ((temp & TxCSR_hrc_Error) != 0)
		{
			ClrBitOTGReg16(otg_IndexedCSR_TxCSR, TxCSR_hrc_Error);			/* get ERROR response */
		}
		else if ((temp & TxCSR_hrc_NAKTimeout_IncompTx) != 0)
		{
			ClrBitOTGReg16(otg_IndexedCSR_TxCSR, TxCSR_hrc_NAKTimeout_IncompTx);		/* get NAK timeoue response */
		}
	}
}


/*------------------------------------------------------------------------------------*/




/*----------------------------------HC status control---------------------------------*/
/*
 * 	host reset USB
 */
extern VOID
HcResetUsb(
	HC		*hc
	)
{
	hc = hc;
	SetBitOTGReg8(otg_CommonUSB_Power, Power_hrw_Reset);
	WaitMs(20);
	ClrBitOTGReg8(otg_CommonUSB_Power, Power_hrw_Reset);
}


/*
 * 	host suspend USB
 */
extern VOID
HcSuspendUsb(
	HC		*hc
	)
{
	hc = hc;
	SetBitOTGReg8(otg_CommonUSB_Power, Power_hs_SuspendMode);
}


/*
 * 	host resume USB from suspend
 */
extern VOID
HcResumeUsb(
	HC		*hc
	)
{
	hc = hc;
	SetBitOTGReg8(otg_CommonUSB_Power, Power_hrw_Resume);
	WaitMs(20);
	ClrBitOTGReg8(otg_CommonUSB_Power, Power_hrw_Resume);
}
/*------------------------------------------------------------------------------------*/



/*----------------------------------HC frame---------------------------------*/
/*
 * 	get current frame number
 */
extern DWORD
HcGetFrameNum(
	HC		*hc
	)
{
	hc = hc;
	return ReadOTGReg16(otg_CommonUSB_Frame);	
}
/*--------------------------------------------------------------------------*/


/*--------------------------------HC init----------------------------*/
/*
 * 	open host controller
 */
extern VOID
OpenHc(
	HC		*hc
	)
{
	BYTE	DATA	i;	

	hc->HcType = "otg_host";
	hc->HcIDStr = "mvsilicon";
	memset(&hc->Ep[0], 0, sizeof(hc->Ep));
	hc->HcEpMap = 0;
	hc->IsRHPortConn = FALSE;
	memset(&hc->Port, 0, sizeof(hc->Port));

	/* init otg host mode */	
	ForceOTGADevMode();
	ForceOTGVBusValid();
	if (HIGH_SPEED_EN)
		SetBitOTGReg8(otg_CommonUSB_Power, Power_hrw_HSEnab);
	else
		ClrBitOTGReg8(otg_CommonUSB_Power, Power_hrw_HSEnab);

	if (PHY_SUSPEND_MODE_PIN_EN)
		SetBitOTGReg8(otg_CommonUSB_Power, Power_hrw_EnSuspendMode);
	else
		ClrBitOTGReg8(otg_CommonUSB_Power, Power_hrw_EnSuspendMode);

	/* enable all usb interrupt */
	WriteOTGReg8(otg_CommonUSB_IntrUSBE, 0xFF);

	/* clear endpoint data toggle and flush fifo */
	for (i = 1; i < MAX_HC_ENDPOINT_NUM; ++i)
	{
		WriteOTGReg8(otg_CommonUSB_Index, i);
		SetBitOTGReg16(otg_IndexedCSR_RxCSR, RxCSR_hs_ClrDataTog);	/* clear data toggle */
		SetBitOTGReg16(otg_IndexedCSR_RxCSR, RxCSR_hs_FlushFIFO);		/* flush FIFO */
		SetBitOTGReg16(otg_IndexedCSR_TxCSR, TxCSR_hs_ClrDataTog);	/* clear data toggle */
		SetBitOTGReg16(otg_IndexedCSR_TxCSR, TxCSR_hs_FlushFIFO);		/* flush FIFO */
	}

	/* start a session */
	SetBitOTGReg8(otg_CtrlFIFO_DevCtl, DevCtl_rw_Session);		/* check the ID pin sensing and verify the core and PHY IDDIG input. */
}
/*--------------------------------------------------------------------*/




/*------------------------------HC root hub------------------------------*/

BOOL	XDATA	gIsPortConn = FALSE;		/* support only one port */

/*
 * 	open root hub polling interrupt
 *	the interval of polling is 250ms
 */
extern VOID
HcOpenRootHubPollInt(
	HC		*hc
	)
{	
	hc = hc;

	TMOD = 0x11;		/* set timer0 16bit counter */
	TL1 = 0xB0;			/* time unit is 50ms */
	TH1 = 0x3C;

	ET1 = 1;
	TR1 = 1;

	EA = 1;	
}


/*
 * 	root hub polling interrupt service
 */
extern VOID
HcRootHubPollInt(VOID) interrupt 3 using 2
{
	BYTE	DATA	temp;
	static	BYTE	DATA	cnt = 0;

	TL1 = 0xB0;			/* time unit is 50ms */
	TH1 = 0x3C;

	if (cnt < 5)	/* poll interval = 250ms */
	{
		cnt++;
		return;
	}	

	cnt = 0;
	/* read register */
	temp = *otg_CommonUSB_IntrUSB;				

	/* check OTG_STATUS_READ_OK signal, wait OTG_STATUS_READ_OK == 1 */
	while((*otg_op_status & OTG_STATUS_READ_OK) == 0);	

	/* check OTG_READ_REQ signal */
	if ((*otg_op_status & OTG_READ_REQ) != 0)		/* OTG_READ_REQ == 1 */
		temp = *otg_rd_read_data;	

	if ((temp & IntUSB_Conn) != 0)
		gIsPortConn = TRUE;
	else if ((temp & IntUSB_DisCon) != 0)
		gIsPortConn = FALSE;
}


/*
 *	Get root hub port status and change information
 *	Return port status and port change. port status field is the low word of return value, 
 * 	port change field is the high word of return value.
 */
extern DWORD						
HcGetRootHubPortStatus(
	HC			*hc,
	BYTE		portNum
	)
{
	DWORD		retVal = 0;
	BOOL		temp;

	if (portNum != 0)		/* support only one port */
		return 0;

	/* update port connect status */
	EnterCritical();
	temp = gIsPortConn;
	ExitCritical();

	if (!hc->IsRHPortConn && temp)		/* new device connection */
	{
		hc->IsRHPortConn = TRUE;
		hc->Port.PortStatus |= (HUB_PORT_CONNECTION | HUB_PORT_POWER);
		hc->Port.PortChange |= HUB_C_PORT_CONNECTION;
	}
	else if (hc->IsRHPortConn && !temp)		/* device disconnection */
	{
		hc->IsRHPortConn = FALSE;
		hc->Port.PortStatus &= ~(HUB_PORT_CONNECTION | HUB_PORT_ENABLE | HUB_PORT_POWER);
		hc->Port.PortChange |= HUB_C_PORT_CONNECTION;
	}
	else
	{
		hc->Port.PortChange &= ~HUB_C_PORT_CONNECTION;
	}

	retVal =  hc->Port.PortChange;
	retVal <<= 16;
	retVal += hc->Port.PortStatus;
	
	return retVal;
}


/*
 *	enable root hub one port
 */
extern BOOL
HcEnableRootHubPort(
	HC			*hc,
	BYTE		portNum
	)
{
	BYTE	DATA	temp;

	if (portNum != 0)		/* support only one port */
		return FALSE;

	hc->Port.PortStatus &= ~HUB_PORT_ENABLE;

	/* check host mode */
	temp = ReadOTGReg8(otg_CtrlFIFO_DevCtl);
	if ((temp & DevCtl_r_HostMode) == 0)
		return FALSE;		/* not host mode */

	HcResetUsb(hc);
	
	/* check device speed */
	temp = ReadOTGReg8(otg_CtrlFIFO_DevCtl);
	if ((temp & DevCtl_r_LSDev) != 0)
	{
		hc->Port.PortStatus |= HUB_PORT_LOW_SPEED;		/* low-speed device connected */
		hc->Port.PortStatus &= ~HUB_PORT_HIGH_SPEED;
	}
	else if ((temp & DevCtl_r_FSDev) != 0)
	{
		temp = ReadOTGReg8(otg_CommonUSB_Power);	
		if ((temp & Power_hr_HSMode) == 0)	
		{
			hc->Port.PortStatus &= ~HUB_PORT_LOW_SPEED;		/* full-speed device connected */
			hc->Port.PortStatus &= ~HUB_PORT_HIGH_SPEED;
		}
		else
		{
			hc->Port.PortStatus &= ~HUB_PORT_LOW_SPEED;		/* high-speed device connected */
			hc->Port.PortStatus |= HUB_PORT_HIGH_SPEED;
		}
	}
	else
	{
		return FALSE;
	}		

	/* wait SOF send */
	while(1)
	{
		temp = ReadOTGReg8(otg_CommonUSB_IntrUSB);
		if ((temp & IntUSB_SOF) != 0)
			break;
	}

	hc->Port.PortStatus |= HUB_PORT_ENABLE;

	return TRUE;
}

/*----------------------------------------------------------------------*/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -