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

📄 xusbps_endpoint.c

📁 定制简单LED的IP核的设计源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/******************************************************************************** (c) Copyright 2010-12 Xilinx, Inc. All rights reserved.** This file contains confidential and proprietary information of Xilinx, Inc.* and is protected under U.S. and international copyright and other* intellectual property laws.** DISCLAIMER* This disclaimer is not a license and does not grant any rights to the* materials distributed herewith. Except as otherwise provided in a valid* license issued to you by Xilinx, and to the maximum extent permitted by* applicable law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND WITH ALL* FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, EXPRESS,* IMPLIED, OR STATUTORY, INCLUDING BUT NOT LIMITED TO WARRANTIES OF* MERCHANTABILITY, NON-INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE;* and (2) Xilinx shall not be liable (whether in contract or tort, including* negligence, or under any other theory of liability) for any loss or damage* of any kind or nature related to, arising under or in connection with these* materials, including for any direct, or any indirect, special, incidental,* or consequential loss or damage (including loss of data, profits, goodwill,* or any type of loss or damage suffered as a result of any action brought by* a third party) even if such damage or loss was reasonably foreseeable or* Xilinx had been advised of the possibility of the same.** CRITICAL APPLICATIONS* Xilinx products are not designed or intended to be fail-safe, or for use in* any application requiring fail-safe performance, such as life-support or* safety devices or systems, Class III medical devices, nuclear facilities,* applications related to the deployment of airbags, or any other applications* that could lead to death, personal injury, or severe property or* environmental damage (individually and collectively, "Critical* Applications"). Customer assumes the sole risk and liability of any use of* Xilinx products in Critical Applications, subject only to applicable laws* and regulations governing limitations on product liability.** THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS PART OF THIS FILE* AT ALL TIMES.*******************************************************************************//******************************************************************************//** * @file xusbps_endpoint.c * * Endpoint specific function implementations. * * @note     None. * * <pre> * MODIFICATION HISTORY: * * Ver   Who  Date     Changes * ----- ---- -------- -------------------------------------------------------- * 1.00a jz  10/10/10 First release * </pre> ******************************************************************************//***************************** Include Files **********************************/#include <string.h> /* for bzero() */#include <stdio.h>#include "xusbps.h"#include "xusbps_endpoint.h"/************************** Constant Definitions ******************************//**************************** Type Definitions ********************************//************************** Variable Definitions ******************************//************************** Function Prototypes ******************************/static void XUsbPs_EpListInit(XUsbPs_DeviceConfig *DevCfgPtr);static void XUsbPs_dQHInit(XUsbPs_DeviceConfig *DevCfgPtr);static int  XUsbPs_dTDInit(XUsbPs_DeviceConfig *DevCfgPtr);static int  XUsbPs_dTDAttachBuffer(XUsbPs_dTD *dTDPtr,					const u8 *BufferPtr, u32 BufferLen);static void XUsbPs_dQHSetMaxPacketLenISO(XUsbPs_dQH *dQHPtr, u32 Len);/* Functions to reconfigure endpoint upon host's set alternate interface * request. */static void XUsbPs_dQHReinitEp(XUsbPs_DeviceConfig *DevCfgPtr,					int EpNum, unsigned short NewDirection);static int XUsbPs_dTDReinitEp(XUsbPs_DeviceConfig *DevCfgPtr,					int EpNum, unsigned short NewDirection);/******************************* Functions ************************************//*****************************************************************************//** * * This function configures the DEVICE side of the controller. The caller needs * to pass in the desired configuration (e.g. number of endpoints) and a * DMAable buffer that will hold the Queue Head List and the Transfer * Descriptors. The required size for this buffer can be obtained by the caller * using the: XUsbPs_DeviceMemRequired() macro. * * @param	InstancePtr is a pointer to the XUsbPs instance of the *		controller. * @param	CfgPtr is a pointer to the configuration structure that contains *		the desired DEVICE side configuration. * * @return *		- XST_SUCCESS: The operation completed successfully. *		- XST_FAILURE: An error occured. * * @note * 		The caller may configure the controller for both, DEVICE and * 		HOST side. * ******************************************************************************/int XUsbPs_ConfigureDevice(XUsbPs *InstancePtr,			    const XUsbPs_DeviceConfig *CfgPtr){	int	Status;	u32 ModeValue = 0x0;	Xil_AssertNonvoid(InstancePtr != NULL);	Xil_AssertNonvoid(CfgPtr      != NULL);	/* Copy the configuration data over into the local instance structure */	InstancePtr->DeviceConfig = *CfgPtr;	/* Align the buffer to a 2048 byte (XUSBPS_dQH_BASE_ALIGN) boundary.*/	InstancePtr->DeviceConfig.PhysAligned =		(InstancePtr->DeviceConfig.DMAMemPhys +					 XUSBPS_dQH_BASE_ALIGN) &						~(XUSBPS_dQH_BASE_ALIGN -1);	/* Clear out the buffer.*/	memset((void *) InstancePtr->DeviceConfig.DMAMemPhys, 0,		XUsbPs_DeviceMemRequired(&InstancePtr->DeviceConfig));	/* Initialize the endpoint pointer list data structure. */	XUsbPs_EpListInit(&InstancePtr->DeviceConfig);	/* Initialize the Queue Head structures in DMA memory. */	XUsbPs_dQHInit(&InstancePtr->DeviceConfig);	/* Initialize the Transfer Descriptors in DMA memory.*/	Status = XUsbPs_dTDInit(&InstancePtr->DeviceConfig);	if (XST_SUCCESS != Status) {		return XST_FAILURE;	}	/* Changing the DEVICE mode requires a controller RESET. */	if (XST_SUCCESS != XUsbPs_Reset(InstancePtr)) {		return XST_FAILURE;	}	/* Set the Queue Head List address. */	XUsbPs_WriteReg(InstancePtr->Config.BaseAddress,				XUSBPS_EPLISTADDR_OFFSET,				InstancePtr->DeviceConfig.PhysAligned);	/* Set the USB mode register to configure DEVICE mode.	 *	 * XUSBPS_MODE_SLOM_MASK note:	 *   Disable Setup Lockout. Setup Lockout is not required as we	 *   will be using the tripwire mechanism when handling setup	 *   packets.	 */	ModeValue = XUSBPS_MODE_CM_DEVICE_MASK | XUSBPS_MODE_SLOM_MASK;	XUsbPs_WriteReg(InstancePtr->Config.BaseAddress,				XUSBPS_MODE_OFFSET, ModeValue);	XUsbPs_SetBits(InstancePtr, XUSBPS_OTGCSR_OFFSET,				XUSBPS_OTGSC_OT_MASK);	return XST_SUCCESS;}/*****************************************************************************//*** This function sends a given data buffer.** @param	InstancePtr is a pointer to XUsbPs instance of the controller.* @param	EpNum is the number of the endpoint to receive data from.* @param	BufferPtr is a pointer to the buffer to send.* @param	BufferLen is the Buffer length.** @return*		- XST_SUCCESS: The operation completed successfully.*		- XST_FAILURE: An error occured.*		- XST_USB_BUF_TOO_BIG: Provided buffer is too big (>16kB).*		- XST_USB_NO_DESC_AVAILABLE: No TX descriptor is available.*******************************************************************************/int XUsbPs_EpBufferSend(XUsbPs *InstancePtr, u8 EpNum,				const u8 *BufferPtr, u32 BufferLen){	int		Status;	u32		Token;	XUsbPs_EpIn	*Ep;	XUsbPs_dTD	*DescPtr;	u32 		Length;	u32		PipeEmpty = 1;	u32		Mask = 0x00010000;	u32		BitMask = Mask << EpNum;	u32		RegValue;	u32		Temp;	Xil_AssertNonvoid(InstancePtr  != NULL);	Xil_AssertNonvoid(EpNum < InstancePtr->DeviceConfig.NumEndpoints);	/* Locate the next available buffer in the ring. A buffer is available	 * if its descriptor is not active.	 */	Ep = &InstancePtr->DeviceConfig.Ep[EpNum].In;	Xil_DCacheFlushRange((unsigned int)BufferPtr, BufferLen);	if(Ep->dTDTail != Ep->dTDHead) {		PipeEmpty = 0;	}	XUsbPs_dTDInvalidateCache(Ep->dTDHead);	/* Tell the caller if we do not have any descriptors available. */	if (XUsbPs_dTDIsActive(Ep->dTDHead)) {		return XST_USB_NO_DESC_AVAILABLE;	}	/* Remember the current head. */	DescPtr = Ep->dTDHead;	do {		Length = (BufferLen > XUSBPS_dTD_BUF_MAX_SIZE) ? XUSBPS_dTD_BUF_MAX_SIZE : BufferLen;		/* Attach the provided buffer to the current descriptor.*/		Status = XUsbPs_dTDAttachBuffer(Ep->dTDHead, BufferPtr, Length);		if (XST_SUCCESS != Status) {			return XST_FAILURE;		}		BufferLen -= Length;		BufferPtr += Length;		XUsbPs_dTDSetActive(Ep->dTDHead);		if(BufferLen == 0)			XUsbPs_dTDSetIOC(Ep->dTDHead);		XUsbPs_dTDClrTerminate(Ep->dTDHead);		XUsbPs_dTDFlushCache(Ep->dTDHead);		/* Advance the head descriptor pointer to the next descriptor. */		Ep->dTDHead = XUsbPs_dTDGetNLP(Ep->dTDHead);		/* Terminate the next descriptor and flush the cache.*/		XUsbPs_dTDInvalidateCache(Ep->dTDHead);		/* Tell the caller if we do not have any descriptors available. */		if (XUsbPs_dTDIsActive(Ep->dTDHead)) {			return XST_USB_NO_DESC_AVAILABLE;		}	} while(BufferLen);	XUsbPs_dTDSetTerminate(Ep->dTDHead);	XUsbPs_dTDFlushCache(Ep->dTDHead);	if(!PipeEmpty) {		/* Read the endpoint prime register. */		RegValue = XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, XUSBPS_EPPRIME_OFFSET);		if(RegValue & BitMask) {			return XST_SUCCESS;		}		do {			RegValue = XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, XUSBPS_CMD_OFFSET);			XUsbPs_WriteReg(InstancePtr->Config.BaseAddress, XUSBPS_CMD_OFFSET,						RegValue | XUSBPS_CMD_ATDTW_MASK);			Temp = XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, XUSBPS_EPRDY_OFFSET)						& BitMask;		} while(!(XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, XUSBPS_CMD_OFFSET) &				XUSBPS_CMD_ATDTW_MASK));		RegValue = XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, XUSBPS_CMD_OFFSET);		XUsbPs_WriteReg(InstancePtr->Config.BaseAddress, XUSBPS_CMD_OFFSET,					RegValue & ~XUSBPS_CMD_ATDTW_MASK);		if(Temp) {			return XST_SUCCESS;		}	}	/* Check, if the DMA engine is still running. If it is running, we do	 * not clear Queue Head fields.	 *	 * Same cache rule as for the Transfer Descriptor applies for the Queue	 * Head.	 */	XUsbPs_dQHInvalidateCache(Ep->dQH);	/* Add the dTD to the dQH */	XUsbPs_WritedQH(Ep->dQH, XUSBPS_dQHdTDNLP, DescPtr);	Token = XUsbPs_ReaddQH(Ep->dQH, XUSBPS_dQHdTDTOKEN);	Token &= ~(XUSBPS_dTDTOKEN_ACTIVE_MASK | XUSBPS_dTDTOKEN_HALT_MASK);	XUsbPs_WritedQH(Ep->dQH, XUSBPS_dQHdTDTOKEN, Token);	XUsbPs_dQHFlushCache(Ep->dQH);	Status = XUsbPs_EpPrime(InstancePtr, EpNum, XUSBPS_EP_DIRECTION_IN);	return Status;}/*****************************************************************************//** * This function receives a data buffer from the endpoint of the given endpoint * number. * * @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	BufferPtr (OUT param) is a pointer to the buffer pointer to hold *		the reference of the data buffer. * @param	BufferLenPtr (OUT param) is a pointer to the integer that will *		hold the buffer length. * @param	Handle is the opaque handle to be used when the buffer is *		released. * * @return *		- XST_SUCCESS: The operation completed successfully. *		- XST_FAILURE: An error occured. *		- XST_USB_NO_BUF: No buffer available. * * @note * 		After handling the data in the buffer, the user MUST release * 		the buffer using the Handle by calling the * 		XUsbPs_EpBufferRelease() function. * ******************************************************************************/int XUsbPs_EpBufferReceive(XUsbPs *InstancePtr, u8 EpNum,				u8 **BufferPtr, u32 *BufferLenPtr, u32 *Handle){	XUsbPs_EpOut	*Ep;	XUsbPs_EpSetup	*EpSetup;	u32 length = 0;	Xil_AssertNonvoid(InstancePtr  != NULL);	Xil_AssertNonvoid(BufferPtr    != NULL);	Xil_AssertNonvoid(BufferLenPtr != NULL);	Xil_AssertNonvoid(Handle       != NULL);	Xil_AssertNonvoid(EpNum < InstancePtr->DeviceConfig.NumEndpoints);	/* Locate the next available buffer in the ring. A buffer is available	 * if its descriptor is not active.	 */	Ep = &InstancePtr->DeviceConfig.Ep[EpNum].Out;	XUsbPs_dTDInvalidateCache(Ep->dTDCurr);	if (XUsbPs_dTDIsActive(Ep->dTDCurr)) {		return XST_USB_NO_BUF;	}	/* The buffer is not active which means that it has been processed by	 * the DMA engine and contains valid data.	 */	EpSetup = &InstancePtr->DeviceConfig.EpCfg[EpNum].Out;	/* Use the buffer pointer stored in the "user data" field of the	 * Transfer Descriptor.	 */	*BufferPtr = (u8 *) XUsbPs_ReaddTD(Ep->dTDCurr,						XUSBPS_dTDUSERDATA);	length = EpSetup->BufSize -			XUsbPs_dTDGetTransferLen(Ep->dTDCurr);	if(length > 0) {		*BufferLenPtr = length;	}else {		*BufferLenPtr = 0;	}	*Handle	= (u32) Ep->dTDCurr;	/* Reset the descriptor's BufferPointer0 and Transfer Length fields to	 * their original value. Note that we can not yet re-activate the	 * descriptor as the caller will be using the attached buffer. Once the	 * caller releases the buffer by calling XUsbPs_EpBufferRelease(), we	 * can re-activate the descriptor.	 */	XUsbPs_WritedTD(Ep->dTDCurr, XUSBPS_dTDBPTR0, *BufferPtr);	XUsbPs_dTDSetTransferLen(Ep->dTDCurr, EpSetup->BufSize);	XUsbPs_dTDFlushCache(Ep->dTDCurr);	return XST_SUCCESS;}/*****************************************************************************//*** This function returns a previously received data buffer to the driver.** @param	Handle is a pointer to the buffer that is returned.** @return	None.*******************************************************************************/void XUsbPs_EpBufferRelease(u32 Handle){	XUsbPs_dTD		*dTDPtr;	/* Perform sanity check on Handle.*/	Xil_AssertVoid((0 != Handle) && (0 == (Handle % XUSBPS_dTD_ALIGN)));	/* Activate the descriptor and clear the Terminate bit. Make sure to do	 * the proper cache handling.	 */	dTDPtr = (XUsbPs_dTD *) Handle;	XUsbPs_dTDInvalidateCache(dTDPtr);	XUsbPs_dTDClrTerminate(dTDPtr);	XUsbPs_dTDSetActive(dTDPtr);	XUsbPs_dTDSetIOC(dTDPtr);	XUsbPs_dTDFlushCache(dTDPtr);}/*****************************************************************************//** * This function sets the handler for endpoint events. * * @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	Direction is the direction of the endpoint (bitfield): * 			- XUSBPS_EP_DIRECTION_OUT * 			- XUSBPS_EP_DIRECTION_IN * @param	CallBackFunc is the Handler callback function. *		Can be NULL if the user wants to disable the handler entry. * @param	CallBackRef is the user definable data pointer that will be *		passed back if the handler is called. May be NULL. * * @return *		- XST_SUCCESS: The operation completed successfully. *		- XST_FAILURE: An error occured. *		- XST_INVALID_PARAM: Invalid parameter passed. * * @note * 		The user can disable a handler by setting the callback function * 		pointer to NULL. * ******************************************************************************/int XUsbPs_EpSetHandler(XUsbPs *InstancePtr, u8 EpNum, u8 Direction,			 XUsbPs_EpHandlerFunc CallBackFunc,			 void *CallBackRef){	XUsbPs_Endpoint	*Ep;	Xil_AssertNonvoid(InstancePtr  != NULL);	Xil_AssertNonvoid(CallBackFunc != NULL);	Xil_AssertNonvoid(EpNum < InstancePtr->DeviceConfig.NumEndpoints);

⌨️ 快捷键说明

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