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

📄 xusbps_intr.c

📁 自学ZedBoard:使用IP通过ARM PS访问FPGA(源代码)
💻 C
字号:
/******************************************************************************** (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_intr.c * * This file contains the functions that are related to interrupt processing * for the EPB USB driver. * * <pre> * MODIFICATION HISTORY: * * Ver   Who  Date     Changes * ----- ---- -------- ---------------------------------------------------------- * 1.00a jz  10/10/10 First release * </pre> ******************************************************************************//***************************** Include Files **********************************/#include "xusbps.h"#include "xusbps_endpoint.h"/************************** Constant Definitions ******************************//**************************** Type Definitions ********************************//***************** Macros (Inline Functions) Definitions **********************//************************** Variable Definitions ******************************//************************** Function Prototypes *******************************/static void XUsbPs_IntrHandleTX(XUsbPs *InstancePtr, u32 EpCompl);static void XUsbPs_IntrHandleRX(XUsbPs *InstancePtr, u32 EpCompl);static void XUsbPs_IntrHandleReset(XUsbPs *InstancePtr, u32 IrqSts);static void XUsbPs_IntrHandleEp0Setup(XUsbPs *InstancePtr);/*****************************************************************************//*** This function is the first-level interrupt handler for the USB core. All USB* interrupts will be handled here. Depending on the type of the interrupt,* second level interrupt handler may be called. Second level interrupt* handlers will be registered by the user using the:*    XUsbPs_IntrSetHandler()* and/or*    XUsbPs_EpSetHandler()* functions.*** @param	HandlerRef is a Reference passed to the interrupt register*		function. In our case this will be a pointer to the XUsbPs*		instance.** @return	None** @note		None*******************************************************************************/void XUsbPs_IntrHandler(void *HandlerRef){	XUsbPs	*InstancePtr;	u32	IrqSts;	Xil_AssertVoid(HandlerRef != NULL);	InstancePtr = (XUsbPs *) HandlerRef;	/* Handle controller (non-endpoint) related interrupts. */	IrqSts = XUsbPs_ReadReg(InstancePtr->Config.BaseAddress,				XUSBPS_ISR_OFFSET);	/* Clear the interrupt status register. */	XUsbPs_WriteReg(InstancePtr->Config.BaseAddress,				XUSBPS_ISR_OFFSET, IrqSts);	/* Nak interrupt, used to respond to host's IN request */	if(IrqSts & XUSBPS_IXR_NAK_MASK) {		/* Ack the hardware	 */		XUsbPs_WriteReg(InstancePtr->Config.BaseAddress,					XUSBPS_EPNAKISR_OFFSET,			XUsbPs_ReadReg(InstancePtr->Config.BaseAddress,						XUSBPS_EPNAKISR_OFFSET));	}	/***************************************************************	 *	 * Handle general interrupts. Endpoint interrupts will be handler	 * later.	 *	 */	/* RESET interrupt.*/	if (IrqSts & XUSBPS_IXR_UR_MASK) {		XUsbPs_IntrHandleReset(InstancePtr, IrqSts);		return;	}	/* Check if we have a user handler that needs to be called. Note that	 * this is the handler for general interrupts. Endpoint interrupts will	 * be handled below.	 */	if ((IrqSts & InstancePtr->HandlerMask) && InstancePtr->HandlerFunc) {		(InstancePtr->HandlerFunc)(InstancePtr->HandlerRef, IrqSts);	}	/***************************************************************	 *	 * Handle Endpoint interrupts.	 *	 */	if (IrqSts & XUSBPS_IXR_UI_MASK) {		u32	EpStat;		u32	EpCompl;		/* ENDPOINT 0 SETUP PACKET HANDLING		 *		 * Check if we got a setup packet on endpoint 0. Currently we		 * only check for setup packets on endpoint 0 as we would not		 * expect setup packets on any other endpoint (even though it		 * is possible to send setup packets on other endpoints).		 */		EpStat = XUsbPs_ReadReg(InstancePtr->Config.BaseAddress,						XUSBPS_EPSTAT_OFFSET);		/* ACK the setup status interrupts. */		XUsbPs_WriteReg(InstancePtr->Config.BaseAddress,					XUSBPS_EPSTAT_OFFSET, EpStat);		if (EpStat & 0x0001) {			/* Re-Prime the endpoint.			 * Endpoint is de-primed if a setup packet comes in.	 		 */			XUsbPs_EpPrime(InstancePtr, 0, XUSBPS_EP_DIRECTION_OUT);			XUsbPs_IntrHandleEp0Setup(InstancePtr);		}		/* Check for RX and TX complete interrupts. */		EpCompl = XUsbPs_ReadReg(InstancePtr->Config.BaseAddress,						XUSBPS_EPCOMPL_OFFSET);		/* ACK the complete interrupts. */		XUsbPs_WriteReg(InstancePtr->Config.BaseAddress,					XUSBPS_EPCOMPL_OFFSET, EpCompl);		/* Check OUT (RX) endpoints. */		if (EpCompl & XUSBPS_EP_OUT_MASK) {			XUsbPs_IntrHandleRX(InstancePtr, EpCompl);		}		/* Check IN (TX) endpoints. */		if (EpCompl & XUSBPS_EP_IN_MASK) {			XUsbPs_IntrHandleTX(InstancePtr, EpCompl);		}	}}/*****************************************************************************//*** This function registers the user callback handler for controller* (non-endpoint) interrupts.** @param	InstancePtr is a pointer to the XUsbPs instance of the*		controller.* @param	CallBackFunc is the Callback function to register.*		CallBackFunc may be NULL to clear the entry.* @param	CallBackRef is the user data reference passed to the*		callback function. CallBackRef may be NULL.* @param	Mask is the User interrupt mask. Defines which interrupts*		will cause the callback to be called.** @return*		- XST_SUCCESS: Callback registered successfully.*		- XST_FAILURE: Callback could not be registered.** @note		None.*******************************************************************************/int XUsbPs_IntrSetHandler(XUsbPs *InstancePtr,			   XUsbPs_IntrHandlerFunc CallBackFunc,			   void *CallBackRef, u32 Mask){	Xil_AssertNonvoid(InstancePtr != NULL);	InstancePtr->HandlerFunc	= CallBackFunc;	InstancePtr->HandlerRef		= CallBackRef;	InstancePtr->HandlerMask	= Mask;	return XST_SUCCESS;}/*****************************************************************************//*** This function handles TX buffer interrupts. It is called by the interrupt* when a transmit complete interrupt occurs. It returns buffers of completed* descriptors to the caller.** @param	InstancePtr is a pointer to the XUsbPs instance of the*		controller.* @param	EpCompl is the Bit mask of endpoints that caused a transmit*		complete interrupt.** @return	None** @note		None.*******************************************************************************/static void XUsbPs_IntrHandleTX(XUsbPs *InstancePtr, u32 EpCompl){	int Index;	u32 Mask;	int NumEp;	/* Check all endpoints for TX complete bits.	 */	Mask	= 0x00010000;	NumEp	= InstancePtr->DeviceConfig.NumEndpoints;	/* Check for every endpoint if its TX complete bit is	 * set.	 */	for (Index = 0; Index < NumEp; Index++, Mask <<= 1) {		XUsbPs_EpIn	*Ep;		if (!(EpCompl & Mask)) {			continue;		}		/* The TX complete bit for this endpoint is		 * set. Walk the list of descriptors to see		 * which ones are completed.		 */		Ep = &InstancePtr->DeviceConfig.Ep[Index].In;		while (Ep->dTDTail != Ep->dTDHead) {			XUsbPs_dTDInvalidateCache(Ep->dTDTail);			/* If the descriptor is not active then the buffer has			 * not been sent yet.			 */			if (XUsbPs_dTDIsActive(Ep->dTDTail)) {				break;			}			if (Ep->HandlerFunc) {				void *BufPtr;				BufPtr = (void *) XUsbPs_ReaddTD(Ep->dTDTail,							XUSBPS_dTDUSERDATA);				Ep->HandlerFunc(Ep->HandlerRef, Index,						XUSBPS_EP_EVENT_DATA_TX,								BufPtr);			}			Ep->dTDTail = XUsbPs_dTDGetNLP(Ep->dTDTail);		}	}}/*****************************************************************************//** * This function handles RX buffer interrupts. It is called by the interrupt * when a receive complete interrupt occurs. It notifies the callback functions * that have been registered with the individual endpoints that data has been * received. * * @param	InstancePtr * 		Pointer to the XUsbPs instance of the controller. * * @param	EpCompl * 		Bit mask of endpoints that caused a receive complete interrupt. * @return *		none * ******************************************************************************/static void XUsbPs_IntrHandleRX(XUsbPs *InstancePtr, u32 EpCompl){	XUsbPs_EpOut	*Ep;	int		Index;	u32		Mask;	int		NumEp;	/* Check all endpoints for RX complete bits. */	Mask	= 0x00000001;	NumEp	= InstancePtr->DeviceConfig.NumEndpoints;	/* Check for every endpoint if its RX complete bit is set.*/	for (Index = 0; Index < NumEp; Index++, Mask <<= 1) {		int numP = 0;		if (!(EpCompl & Mask)) {			continue;		}		Ep = &InstancePtr->DeviceConfig.Ep[Index].Out;		XUsbPs_dTDInvalidateCache(Ep->dTDCurr);		/* Handle all finished dTDs */		while (!XUsbPs_dTDIsActive(Ep->dTDCurr)) {			numP += 1;			if (Ep->HandlerFunc) {				Ep->HandlerFunc(Ep->HandlerRef, Index,						XUSBPS_EP_EVENT_DATA_RX, NULL);			}			Ep->dTDCurr = XUsbPs_dTDGetNLP(Ep->dTDCurr);			XUsbPs_dTDInvalidateCache(Ep->dTDCurr);		}		/* Re-Prime the endpoint.*/		XUsbPs_EpPrime(InstancePtr, Index, XUSBPS_EP_DIRECTION_OUT);	}}/*****************************************************************************//*** This function handles a RESET interrupt. It will notify the interrupt* handler callback of the RESET condition.** @param	InstancePtr is pointer to the XUsbPs instance of the controller* @param	IrqSts is the Interrupt status register content.*		To be passed on to the user.** @return	None** @Note		None.*******************************************************************************/static void XUsbPs_IntrHandleReset(XUsbPs *InstancePtr, u32 IrqSts){	int Timeout;	/* Clear all setup token semaphores by reading the	 * XUSBPS_EPSTAT_OFFSET register and writing its value back to	 * itself.	 */	XUsbPs_WriteReg(InstancePtr->Config.BaseAddress, XUSBPS_EPSTAT_OFFSET,		XUsbPs_ReadReg(InstancePtr->Config.BaseAddress,				XUSBPS_EPSTAT_OFFSET));	/* Clear all the endpoint complete status bits by reading the	 * XUSBPS_EPCOMPL_OFFSET register and writings its value back	 * to itself.	 */	XUsbPs_WriteReg(InstancePtr->Config.BaseAddress,			XUSBPS_EPCOMPL_OFFSET,		XUsbPs_ReadReg(InstancePtr->Config.BaseAddress,				XUSBPS_EPCOMPL_OFFSET));	/* Cancel all endpoint prime status by waiting until all bits	 * in XUSBPS_EPPRIME_OFFSET are 0 and then writing 0xFFFFFFFF	 * to XUSBPS_EPFLUSH_OFFSET.	 *	 * Avoid hanging here by using a Timeout counter...	 */	Timeout = XUSBPS_TIMEOUT_COUNTER;	while ((XUsbPs_ReadReg(InstancePtr->Config.BaseAddress,					XUSBPS_EPPRIME_OFFSET) &					XUSBPS_EP_ALL_MASK) && --Timeout) {		/* NOP */	}	XUsbPs_WriteReg(InstancePtr->Config.BaseAddress,				XUSBPS_EPFLUSH_OFFSET, 0xFFFFFFFF);	/* Make sure that the reset bit in XUSBPS_PORTSCR1_OFFSET is	 * still set at this point. If the code gets to this point and	 * the reset bit has already been cleared we are in trouble and	 * hardware reset is necessary.	 */	if (!(XUsbPs_ReadReg(InstancePtr->Config.BaseAddress,				XUSBPS_PORTSCR1_OFFSET) &				XUSBPS_PORTSCR_PR_MASK)) {		/* Send a notification to the user that a hardware		 * RESET is required. At this point we can only hope		 * that the user registered an interrupt handler and		 * will issue a hardware RESET.		 */		if (InstancePtr->HandlerFunc) {			(InstancePtr->HandlerFunc)(InstancePtr->HandlerRef,						   IrqSts);		}		else {			for (;;);		}		/* If we get here there is nothing more to do. The user		 * should have reset the core.		 */		return;	}	/* Check if we have a user handler that needs to be called.	 */	if (InstancePtr->HandlerFunc) {		(InstancePtr->HandlerFunc)(InstancePtr->HandlerRef, IrqSts);	}	/* We are done. After RESET we don't proceed in the interrupt	 * handler.	 */}/*****************************************************************************//*** This function handles a Setup Packet interrupt. It will notify the interrupt* handler callback of the RESET condition.** @param	InstancePtr is a pointer to the XUsbPs instance of the*		controller.** @return	None** @Note 	None*******************************************************************************/static void XUsbPs_IntrHandleEp0Setup(XUsbPs *InstancePtr){	XUsbPs_EpOut	*Ep;	/* Notifiy the user. */	Ep = &InstancePtr->DeviceConfig.Ep[0].Out;	if (Ep->HandlerFunc) {		Ep->HandlerFunc(Ep->HandlerRef, 0,				XUSBPS_EP_EVENT_SETUP_DATA_RECEIVED, NULL);	}}

⌨️ 快捷键说明

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