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

📄 xusbps_endpoint.c

📁 定制简单LED的IP核的设计源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	Ep = &InstancePtr->DeviceConfig.Ep[EpNum];	if(Direction & XUSBPS_EP_DIRECTION_OUT) {		Ep->Out.HandlerFunc	= CallBackFunc;		Ep->Out.HandlerRef	= CallBackRef;	}	if(Direction & XUSBPS_EP_DIRECTION_IN) {		Ep->In.HandlerFunc	= CallBackFunc;		Ep->In.HandlerRef	= CallBackRef;	}	return XST_SUCCESS;}/*****************************************************************************//*** This function primes an endpoint.** @param	InstancePtr is pointer to the XUsbPs instance.* @param	EpNum is the number of the endpoint to receive data from.* @param	Direction is the direction of the endpoint (bitfield):* 			- XUSBPS_EP_DIRECTION_OUT* 			- XUSBPS_EP_DIRECTION_IN** @return*		- XST_SUCCESS: The operation completed successfully.*		- XST_FAILURE: An error occured.*		- XST_INVALID_PARAM: Invalid parameter passed.** @note		None.*******************************************************************************/int XUsbPs_EpPrime(XUsbPs *InstancePtr, u8 EpNum, u8 Direction){	u32	Mask;	Xil_AssertNonvoid(InstancePtr  != NULL);	Xil_AssertNonvoid(EpNum < InstancePtr->DeviceConfig.NumEndpoints);	/* Get the right bit mask for the endpoint direction. */	switch (Direction) {	case XUSBPS_EP_DIRECTION_OUT:		Mask = 0x00000001;		break;	case XUSBPS_EP_DIRECTION_IN:		Mask = 0x00010000;		break;	default:		return XST_INVALID_PARAM;	}	/* Write the endpoint prime register. */	XUsbPs_WriteReg(InstancePtr->Config.BaseAddress,				XUSBPS_EPPRIME_OFFSET, Mask << EpNum);	return XST_SUCCESS;}/*****************************************************************************//*** This function extracts the Setup Data from a given endpoint.** @param	InstancePtr is a pointer to the XUsbPs instance of the*		controller.* @param	EpNum is the number of the endpoint to receive data from.* @param	SetupDataPtr is a pointer to the setup data structure to be*		filled.** @return*		- XST_SUCCESS: The operation completed successfully.*		- XST_FAILURE: An error occured.** @note		None.******************************************************************************/int XUsbPs_EpGetSetupData(XUsbPs *InstancePtr, int EpNum,				XUsbPs_SetupData *SetupDataPtr){	XUsbPs_EpOut	*Ep;	u32	Data[2];	u8	*p;	int Timeout;	Xil_AssertNonvoid(InstancePtr  != NULL);	Xil_AssertNonvoid(SetupDataPtr != NULL);	Xil_AssertNonvoid(EpNum < InstancePtr->DeviceConfig.NumEndpoints);	Ep = &InstancePtr->DeviceConfig.Ep[EpNum].Out;	/* Clear the pending endpoint setup stat bit.	 */	XUsbPs_WriteReg(InstancePtr->Config.BaseAddress,				XUSBPS_EPSTAT_OFFSET, 1 << EpNum);	/* Get the data from the Queue Heads Setup buffer into local variables	 * so we can extract the setup data values.	 */	do {		/* Arm the tripwire. The tripwire will tell us if a new setup		 * packet arrived (in which case the tripwire bit will be		 * cleared) while we were reading the buffer. If a new setup		 * packet arrived the buffer is corrupted and we continue		 * reading.		 */		XUsbPs_SetTripwire(InstancePtr);		XUsbPs_dQHInvalidateCache(Ep->dQH);		Data[0] = XUsbPs_ReaddQH(Ep->dQH, XUSBPS_dQHSUB0);		Data[1] = XUsbPs_ReaddQH(Ep->dQH, XUSBPS_dQHSUB1);	} while (FALSE == XUsbPs_TripwireIsSet(InstancePtr));	/* Clear the Tripwire bit and continue.	 */	XUsbPs_ClrTripwire(InstancePtr);	/* Data in the setup buffer is being converted by the core to big	 * endian format. We have to take care of proper byte swapping when	 * reading the setup data values.	 *	 * Need to check if there is a smarter way to do this and take the	 * processor/memory-controller endianess into account?	 */	p = (u8 *) Data;	SetupDataPtr->bmRequestType	= p[0];	SetupDataPtr->bRequest		= p[1];	SetupDataPtr->wValue		= (p[3] << 8) | p[2];	SetupDataPtr->wIndex		= (p[5] << 8) | p[4];	SetupDataPtr->wLength		= (p[7] << 8) | p[6];	/* Before we leave we need to make sure that the endpoint setup bit has	 * cleared. It needs to be 0 before the endpoint can be re-primed.	 *	 * Note: According to the documentation this endpoint setup bit should	 * clear within 1-2us after it has been written above. This means that	 * we should never catch it being 1 here. However, we still need to	 * poll it to make sure. Just in case, we use a counter 'Timeout' so we	 * won't hang here if the bit is stuck for some reason.	 */	Timeout = XUSBPS_TIMEOUT_COUNTER;	while ((XUsbPs_ReadReg(InstancePtr->Config.BaseAddress,				XUSBPS_EPSTAT_OFFSET) &				(1 << EpNum)) && --Timeout) {		/* NOP */	}	if (0 == Timeout) {		return XST_FAILURE;	}	return XST_SUCCESS;}/*****************************************************************************//**** This function initializes the endpoint pointer data structure.** The function sets up the local data structure with the aligned addresses for* the Queue Head and Transfer Descriptors.** @param	DevCfgPtr is pointer to the XUsbPs DEVICE configuration*		structure.** @return	none** @note* 		Endpoints of type XUSBPS_EP_TYPE_NONE are not used in the* 		system. Therefore no memory is reserved for them.*******************************************************************************/static void XUsbPs_EpListInit(XUsbPs_DeviceConfig *DevCfgPtr){	int	EpNum;	u8	*p;	XUsbPs_Endpoint	*Ep;	XUsbPs_EpConfig	*EpCfg;	/* Set up the XUsbPs_Endpoint array. This array is used to define the	 * location of the Queue Head list and the Transfer Descriptors in the	 * block of DMA memory that has been passed into the driver.	 *	 * 'p' is used to set the pointers in the local data structure.	 * Initially 'p' is pointed to the beginning of the DMAable memory	 * block. As pointers are assigned, 'p' is incremented by the size of	 * the respective object.	 */	Ep	= DevCfgPtr->Ep;	EpCfg	= DevCfgPtr->EpCfg;	/* Start off with 'p' pointing to the (aligned) beginning of the DMA	 * buffer.	 */	p = (u8 *) DevCfgPtr->PhysAligned;	/* Initialize the Queue Head pointer list.	 *	 * Each endpoint has two Queue Heads. One for the OUT direction and one	 * for the IN direction. An OUT Queue Head is always followed by an IN	 * Queue Head.	 *	 * Queue Head alignment is XUSBPS_dQH_ALIGN.	 *	 * Note that we have to reserve space here for unused endpoints.	 */	for (EpNum = 0; EpNum < DevCfgPtr->NumEndpoints; ++EpNum) {		/* OUT Queue Head */		Ep[EpNum].Out.dQH = (XUsbPs_dQH *) p;		p += XUSBPS_dQH_ALIGN;		/* IN Queue Head */		Ep[EpNum].In.dQH = (XUsbPs_dQH *) p;		p += XUSBPS_dQH_ALIGN;	}	/* 'p' now points to the first address after the Queue Head list. The	 * Transfer Descriptors start here.	 *	 * Each endpoint has a variable number of Transfer Descriptors	 * depending on user configuration.	 *	 * Transfer Descriptor alignment is XUSBPS_dTD_ALIGN.	 */	for (EpNum = 0; EpNum < DevCfgPtr->NumEndpoints; ++EpNum) {		/* OUT Descriptors.		 */		if (XUSBPS_EP_TYPE_NONE != EpCfg[EpNum].Out.Type) {			Ep[EpNum].Out.dTDs		= (XUsbPs_dTD *) p;			Ep[EpNum].Out.dTDCurr	= (XUsbPs_dTD *) p;			p += XUSBPS_dTD_ALIGN * EpCfg[EpNum].Out.NumBufs;		}		/* IN Descriptors.		 */		if (XUSBPS_EP_TYPE_NONE != EpCfg[EpNum].In.Type) {			Ep[EpNum].In.dTDs		= (XUsbPs_dTD *) p;			Ep[EpNum].In.dTDHead	= (XUsbPs_dTD *) p;			Ep[EpNum].In.dTDTail	= (XUsbPs_dTD *) p;			p += XUSBPS_dTD_ALIGN * EpCfg[EpNum].In.NumBufs;		}	}	/* 'p' now points to the first address after the Transfer Descriptors.	 * The data buffers for the OUT Transfer Desciptors start here.	 *	 * Note that IN (TX) Transfer Descriptors are not assigned buffers at	 * this point. Buffers will be assigned when the user calls the send()	 * function.	 */	for (EpNum = 0; EpNum < DevCfgPtr->NumEndpoints; ++EpNum) {		if (XUSBPS_EP_TYPE_NONE != EpCfg[EpNum].Out.Type) {			/* If BufSize for this endpoint is set to 0 it means			 * that we do not need to attach a buffer to this			 * descriptor. We also initialize it's buffer pointer			 * to NULL.			 */			if (0 == EpCfg[EpNum].Out.BufSize) {				Ep[EpNum].Out.dTDBufs = NULL;				continue;			}			Ep[EpNum].Out.dTDBufs = p;			p += EpCfg[EpNum].Out.BufSize * EpCfg[EpNum].Out.NumBufs;		}	}	/* Initialize the endpoint event handlers to NULL.	 */	for (EpNum = 0; EpNum < DevCfgPtr->NumEndpoints; ++EpNum) {		Ep[EpNum].Out.HandlerFunc = NULL;		Ep[EpNum].In.HandlerFunc  = NULL;	}}/*****************************************************************************//**** This function initializes the Queue Head List in memory.** @param	DevCfgPtr is a pointer to the XUsbPs DEVICE configuration*		structure.** @return	None** @note		None.*******************************************************************************/static void XUsbPs_dQHInit(XUsbPs_DeviceConfig *DevCfgPtr){	int	EpNum;	XUsbPs_Endpoint	*Ep;	XUsbPs_EpConfig	*EpCfg;	/* Setup pointers for simpler access. */	Ep	= DevCfgPtr->Ep;	EpCfg	= DevCfgPtr->EpCfg;	/* Go through the list of Queue Head entries and:	 *	 * - Set Transfer Descriptor addresses	 * - Set Maximum Packet Size	 * - Disable Zero Length Termination (ZLT) for non-isochronous transfers	 * - Enable Interrupt On Setup (IOS)	 *	 */	for (EpNum = 0; EpNum < DevCfgPtr->NumEndpoints; ++EpNum) {		/* OUT Queue Heads.*/		if (XUSBPS_EP_TYPE_NONE != EpCfg[EpNum].Out.Type) {			XUsbPs_WritedQH(Ep[EpNum].Out.dQH,					XUSBPS_dQHCPTR, Ep[EpNum].Out.dTDs);			/* For isochronous, ep max packet size translates to different			 * values in queue head than other types.			 * Also	enable ZLT for isochronous.			 */			if(XUSBPS_EP_TYPE_ISOCHRONOUS == EpCfg[EpNum].Out.Type) {				XUsbPs_dQHSetMaxPacketLenISO(Ep[EpNum].Out.dQH,                        EpCfg[EpNum].Out.MaxPacketSize);				XUsbPs_dQHEnableZLT(Ep[EpNum].Out.dQH);			}else {				XUsbPs_dQHSetMaxPacketLen(Ep[EpNum].Out.dQH,					    EpCfg[EpNum].Out.MaxPacketSize);				XUsbPs_dQHDisableZLT(Ep[EpNum].Out.dQH);			}			/* Only control OUT needs this */			if(XUSBPS_EP_TYPE_CONTROL == EpCfg[EpNum].Out.Type) {				XUsbPs_dQHSetIOS(Ep[EpNum].Out.dQH);			}			/* Set up the overlay next dTD pointer. */			XUsbPs_WritedQH(Ep[EpNum].Out.dQH,					XUSBPS_dQHdTDNLP, Ep[EpNum].Out.dTDs);			XUsbPs_dQHFlushCache(Ep[EpNum].Out.dQH);		}		/* IN Queue Heads. */		if (XUSBPS_EP_TYPE_NONE != EpCfg[EpNum].In.Type) {			XUsbPs_WritedQH(Ep[EpNum].In.dQH,				  XUSBPS_dQHCPTR, Ep[EpNum].In.dTDs);			/* Isochronous ep packet size can be larger than 1024.*/			if(XUSBPS_EP_TYPE_ISOCHRONOUS == EpCfg[EpNum].In.Type) {				XUsbPs_dQHSetMaxPacketLenISO(Ep[EpNum].In.dQH,						EpCfg[EpNum].In.MaxPacketSize);				XUsbPs_dQHEnableZLT(Ep[EpNum].In.dQH);			}else {				XUsbPs_dQHSetMaxPacketLen(Ep[EpNum].In.dQH,					    EpCfg[EpNum].In.MaxPacketSize);				XUsbPs_dQHDisableZLT(Ep[EpNum].In.dQH);			}			XUsbPs_dQHFlushCache(Ep[EpNum].In.dQH);		}	}}/*****************************************************************************//** * * This function initializes the Transfer Descriptors lists in memory. * * @param	DevCfgPtr is a pointer to the XUsbPs DEVICE configuration *		structure. * * @return *		- XST_SUCCESS: The operation completed successfully. *		- XST_FAILURE: An error occured. * ******************************************************************************/static int XUsbPs_dTDInit(XUsbPs_DeviceConfig *DevCfgPtr){	int	EpNum;	XUsbPs_Endpoint	*Ep;	XUsbPs_EpConfig	*EpCfg;	/* Setup pointers for simpler access. */	Ep	= DevCfgPtr->Ep;	EpCfg	= DevCfgPtr->EpCfg;	/* Walk through the list of endpoints and initialize their Transfer	 * Descriptors.	 */	for (EpNum = 0; EpNum < DevCfgPtr->NumEndpoints; ++EpNum) {		int	Td;		int	NumdTD;		XUsbPs_EpOut	*Out = &Ep[EpNum].Out;		XUsbPs_EpIn	*In  = &Ep[EpNum].In;		/* OUT Descriptors		 * ===============		 *		 * + Set the next link pointer		 * + Set the interrupt complete and the active bit		 * + Attach the buffer to the dTD		 */		if (XUSBPS_EP_TYPE_NONE != EpCfg[EpNum].Out.Type) {			NumdTD = EpCfg[EpNum].Out.NumBufs;		}		else {			NumdTD = 0;		}		for (Td = 0; Td < NumdTD; ++Td) {			int	Status;			int NextTd = (Td + 1) % NumdTD;			XUsbPs_dTDInvalidateCache(&Out->dTDs[Td]);			/* Set NEXT link pointer. */			XUsbPs_WritedTD(&Out->dTDs[Td], XUSBPS_dTDNLP,					  &Out->dTDs[NextTd]);			/* Set the OUT descriptor ACTIVE and enable the			 * interrupt on complete.			 */			XUsbPs_dTDSetActive(&Out->dTDs[Td]);			XUsbPs_dTDSetIOC(&Out->dTDs[Td]);			/* Set up the data buffer with the descriptor. If the			 * buffer pointer is NULL it means that we do not need			 * to attach a buffer to this descriptor.			 */			if (NULL == Out->dTDBufs) {				XUsbPs_dTDFlushCache(&Out->dTDs[Td]);				continue;			}			Status = XUsbPs_dTDAttachBuffer(					&Out->dTDs[Td],					Out->dTDBufs +

⌨️ 快捷键说明

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