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

📄 xqspips.c

📁 自学ZedBoard:使用IP通过ARM PS访问FPGA(源代码)
💻 C
📖 第 1 页 / 共 3 页
字号:
* calls when it encounters conditions that should be reported to upper* layer software. The handler executes in an interrupt context, so it must* minimize the amount of processing performed. One of the following status* events is passed to the status handler.** <pre>* XST_SPI_MODE_FAULT		A mode fault error occurred, meaning the device*				is selected as slave while being a master.** XST_SPI_TRANSFER_DONE		The requested data transfer is done** XST_SPI_TRANSMIT_UNDERRUN	As a slave device, the master clocked data*				but there were none available in the transmit*				register/FIFO. This typically means the slave*				application did not issue a transfer request*				fast enough, or the processor/driver could not*				fill the transmit register/FIFO fast enough.** XST_SPI_RECEIVE_OVERRUN	The QSPI device lost data. Data was received*				but the receive data register/FIFO was full.** XST_SPI_SLAVE_MODE_FAULT	A slave QSPI device was selected as a slave*				while it was disabled. This indicates the*				master is already transferring data (which is*				being dropped until the slave application*				issues a transfer).* </pre>* @param	InstancePtr is a pointer to the XQspiPs instance.* @param	CallBackRef is the upper layer callback reference passed back*		when the callback function is invoked.* @param	FuncPtr is the pointer to the callback function.** @return	None.** @note** The handler is called within interrupt context, so it should do its work* quickly and queue potentially time-consuming work to a task-level thread.*******************************************************************************/void XQspiPs_SetStatusHandler(XQspiPs *InstancePtr, void *CallBackRef,				XQspiPs_StatusHandler FuncPtr){	Xil_AssertVoid(InstancePtr != NULL);	Xil_AssertVoid(FuncPtr != NULL);	Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);	InstancePtr->StatusHandler = FuncPtr;	InstancePtr->StatusRef = CallBackRef;}/*****************************************************************************//**** This is a stub for the status callback. The stub is here in case the upper* layers forget to set the handler.** @param	CallBackRef is a pointer to the upper layer callback reference* @param	StatusEvent is the event that just occurred.* @param	ByteCount is the number of bytes transferred up until the event*		occurred.** @return	None.** @note		None.*******************************************************************************/static void StubStatusHandler(void *CallBackRef, u32 StatusEvent,				unsigned ByteCount){	(void) CallBackRef;	(void) StatusEvent;	(void) ByteCount;	Xil_AssertVoidAlways();}/*****************************************************************************//**** The interrupt handler for QSPI interrupts. This function must be connected* by the user to an interrupt controller.** The interrupts that are handled are:** - Mode Fault Error. This interrupt is generated if this device is selected*   as a slave when it is configured as a master. The driver aborts any data*   transfer that is in progress by resetting FIFOs (if present) and resetting*   its buffer pointers. The upper layer software is informed of the error.** - Data Transmit Register (FIFO) Empty. This interrupt is generated when the*   transmit register or FIFO is empty. The driver uses this interrupt during a*   transmission to continually send/receive data until the transfer is done.** - Data Transmit Register (FIFO) Underflow. This interrupt is generated when*   the QSPI device, when configured as a slave, attempts to read an empty*   DTR/FIFO.  An empty DTR/FIFO usually means that software is not giving the*   device data in a timely manner. No action is taken by the driver other than*   to inform the upper layer software of the error.** - Data Receive Register (FIFO) Overflow. This interrupt is generated when the*   QSPI device attempts to write a received byte to an already full DRR/FIFO.*   A full DRR/FIFO usually means software is not emptying the data in a timely*   manner.  No action is taken by the driver other than to inform the upper*   layer software of the error.** @param	InstancePtr is a pointer to the XQspiPs instance.** @return	None.** @note** The slave select register is being set to deselect the slave when a transfer* is complete.  This is being done regardless of whether it is a slave or a* master since the hardware does not drive the slave select as a slave.*******************************************************************************/void XQspiPs_InterruptHandler(void *InstancePtr){	XQspiPs *SpiPtr = (XQspiPs *)InstancePtr;	u32 IntrStatus;	u32 ControlReg;	unsigned BytesDone; /* Number of bytes done so far. */	Xil_AssertVoid(InstancePtr != NULL);	Xil_AssertVoid(SpiPtr->IsReady == XIL_COMPONENT_IS_READY);	/*	 * Immediately clear the interrupts in case the ISR causes another	 * interrupt to be generated. If we clear at the end of the ISR,	 * we may miss newly generated interrupts. This occurs because we	 * transmit from within the ISR, which could potentially cause another	 * TX_EMPTY interrupt.	 */	IntrStatus = XQspiPs_ReadReg(SpiPtr->Config.BaseAddress,				      XQSPIPS_SR_OFFSET);	XQspiPs_WriteReg(SpiPtr->Config.BaseAddress, XQSPIPS_SR_OFFSET,			  IntrStatus);	/*	 * Check for mode fault error. We want to check for this error first,	 * before checking for progress of a transfer, since this error needs	 * to abort any operation in progress.	 */	if (XQSPIPS_IXR_MODF_MASK == (IntrStatus & XQSPIPS_IXR_MODF_MASK)) {		BytesDone = SpiPtr->RequestedBytes - SpiPtr->RemainingBytes;		/*		 * Abort any operation currently in progress. This includes		 * clearing the mode fault condition by reading the status		 * register. Note that the status register should be read after		 * the abort, since reading the status register clears the mode		 * fault condition and would cause the device to restart any		 * transfer that may be in progress.		 */		XQspiPs_Abort(SpiPtr);		SpiPtr->StatusHandler(SpiPtr->StatusRef, XST_SPI_MODE_FAULT,					BytesDone);		return; /* Do not continue servicing other interrupts. */	}	while(TRUE){		u32 Data;		/*		 * A transmit has just completed. Process received data and		 * check for more data to transmit.		 * First get the data received as a result of the transmit that		 * just completed.  Always get the received data, but only fill		 * the receive buffer if it is not null (it can be null when the		 * device does not care to receive data).		 */		if (0 !=(IntrStatus & XQSPIPS_IXR_RXNEMPTY_MASK)){			Data = XQspiPs_ReadReg(SpiPtr->Config.BaseAddress,						XQSPIPS_RXD_OFFSET);			if (SpiPtr->RequestedBytes < 4) {				XQspiPs_GetReadData(SpiPtr, Data,						     SpiPtr->RequestedBytes);			} else {				XQspiPs_GetReadData(SpiPtr, Data, 4);			}		}		/*		 * See if there is more data to send and RX FIFO is not full.		 */		if ((SpiPtr->RemainingBytes > 0) && (0 == (IntrStatus &		    (XQSPIPS_IXR_TXFULL_MASK | XQSPIPS_IXR_RXFULL_MASK)))) {			/*			 * Send more data.			 */			if (SpiPtr->RemainingBytes < 4) {				XQspiPs_GetWriteData(SpiPtr, &Data,						      SpiPtr->RemainingBytes);			} else {				XQspiPs_GetWriteData(SpiPtr, &Data, 4);			}			XQspiPs_WriteReg(SpiPtr->Config.BaseAddress,					  XQSPIPS_TXD_00_OFFSET, Data);		}		/*		 * Exit the loop if all the data available at this time has been		 * received and either there is no more data to send, or the		 * FIFO is above the water mark.		 */		IntrStatus = XQspiPs_ReadReg(SpiPtr->Config.BaseAddress,					      XQSPIPS_SR_OFFSET);		if ((0 == (IntrStatus & XQSPIPS_IXR_RXNEMPTY_MASK)) &&		    ((0 == (IntrStatus & XQSPIPS_IXR_TXOW_MASK)) ||		     (0 == SpiPtr->RemainingBytes))) {			break;		}	}	ControlReg = XQspiPs_ReadReg(SpiPtr->Config.BaseAddress,				      XQSPIPS_CR_OFFSET);	if ((SpiPtr->RemainingBytes == 0) && (SpiPtr->RequestedBytes == 0)) {		/*		 * No more data to send.  Disable the interrupt and inform the		 * upper layer software that the transfer is done. The interrupt		 * will be re-enabled when another transfer is initiated.		 */		XQspiPs_WriteReg(SpiPtr->Config.BaseAddress,				  XQSPIPS_IDR_OFFSET, XQSPIPS_IXR_DFLT_MASK);		SpiPtr->IsBusy = FALSE;		/*		 * Disable the device.		 */		XQspiPs_Disable(SpiPtr->Config.BaseAddress);		/*		 * If the Slave select lines are being manually controlled,		 * disable them because the transfer is complete.		 */		if (0 != (ControlReg & XQSPIPS_CR_SSFORCE_MASK)) {			ControlReg |= XQSPIPS_CR_SSCTRL_MASK;			XQspiPs_WriteReg(SpiPtr->Config.BaseAddress,					  XQSPIPS_CR_OFFSET, ControlReg);		}		SpiPtr->StatusHandler(SpiPtr->StatusRef,					XST_SPI_TRANSFER_DONE,					SpiPtr->RequestedBytes);	} else {		/*		 * If, in Manual Start mode, start the transfer.		 */		if ((ControlReg & (XQSPIPS_CR_MSTREN_MASK |				   XQSPIPS_CR_MANSTRTEN_MASK)) ==		    (XQSPIPS_CR_MSTREN_MASK | XQSPIPS_CR_MANSTRTEN_MASK)) {			ControlReg |= XQSPIPS_CR_MANSTRT_MASK;			XQspiPs_WriteReg(SpiPtr->Config.BaseAddress,					  XQSPIPS_CR_OFFSET, ControlReg);		}	}	/*	 * Check for overflow and underflow errors.	 */	if (IntrStatus & XQSPIPS_IXR_RXOVR_MASK) {		BytesDone = SpiPtr->RequestedBytes - SpiPtr->RemainingBytes;		SpiPtr->IsBusy = FALSE;		/*		 * If the Slave select lines are being manually controlled,		 * disable them because the transfer is complete.		 */		if (0 != (ControlReg & XQSPIPS_CR_SSFORCE_MASK)){			ControlReg |= XQSPIPS_CR_SSCTRL_MASK;			XQspiPs_WriteReg(SpiPtr->Config.BaseAddress,				XQSPIPS_CR_OFFSET, ControlReg);		}		SpiPtr->StatusHandler(SpiPtr->StatusRef,			XST_SPI_RECEIVE_OVERRUN, BytesDone);	}	if (IntrStatus & XQSPIPS_IXR_TXUF_MASK) {		BytesDone = SpiPtr->RequestedBytes - SpiPtr->RemainingBytes;		SpiPtr->IsBusy = FALSE;		/*		 * If the Slave select lines are being manually controlled,		 * disable them because the transfer is complete.		 */		if (0 != (ControlReg & XQSPIPS_CR_SSFORCE_MASK)){			ControlReg |= XQSPIPS_CR_SSCTRL_MASK;			XQspiPs_WriteReg(SpiPtr->Config.BaseAddress,					  XQSPIPS_CR_OFFSET, ControlReg);		}		SpiPtr->StatusHandler(SpiPtr->StatusRef,				      XST_SPI_TRANSMIT_UNDERRUN, BytesDone);	}}/*****************************************************************************//**** Copies data from the Transmit buffer. Since QSPI supports only 32-bit* transfers, this function appends 0xFF if the requested size is less than 4.** @param	InstancePtr is a pointer to the XQspiPs instance.* @param	Data is a ouput parameter, to which the data read from the*		Transmit buffer is to be copied.* @param	Size is the number of bytes to be copied from the Transmit*		buffer.** @return	None.** @note		None.*******************************************************************************/static void XQspiPs_GetWriteData(XQspiPs *InstancePtr, u32 *Data, u8 Size){	if (InstancePtr->SendBufferPtr) {		switch (Size) {		case 1:			*Data = *((u8 *)InstancePtr->SendBufferPtr);			InstancePtr->SendBufferPtr += 1;			*Data |= 0xFFFFFF00;			break;		case 2:			*Data = *((u16 *)InstancePtr->SendBufferPtr);			InstancePtr->SendBufferPtr += 2;			*Data |= 0xFFFF0000;			break;		case 3:			*Data = *((u16 *)InstancePtr->SendBufferPtr);			InstancePtr->SendBufferPtr += 2;			*Data |= (*((u8 *)InstancePtr->SendBufferPtr) << 16);			InstancePtr->SendBufferPtr += 1;			*Data |= 0xFF000000;			break;		case 4:			*Data = *((u32 *)InstancePtr->SendBufferPtr);			InstancePtr->SendBufferPtr += 4;			break;		default:			/* This will never execute */			break;		}	} else		*Data = 0;	InstancePtr->RemainingBytes -= Size;	if (InstancePtr->RemainingBytes < 0) {		InstancePtr->RemainingBytes = 0;	}}/*****************************************************************************//**** Copies data from Data to the Receive buffer.** @param	InstancePtr is a pointer to the XQspiPs instance.* @param	Data is the data which needs to be copied to the Rx buffer.* @param	Size is the number of bytes to be copied to the Receive buffer.** @return	None.** @note		None.*******************************************************************************/static void XQspiPs_GetReadData(XQspiPs *InstancePtr, u32 Data, u8 Size){	u8 byte3;	if (InstancePtr->RecvBufferPtr) {		switch (Size) {		case 1:			*((u8 *)InstancePtr->RecvBufferPtr) = Data;			InstancePtr->RecvBufferPtr += 1;			break;		case 2:			*((u16 *)InstancePtr->RecvBufferPtr) = Data;			InstancePtr->RecvBufferPtr += 2;			break;		case 3:			*((u16 *)InstancePtr->RecvBufferPtr) = Data;			InstancePtr->RecvBufferPtr += 2;			byte3 = (u8)(Data >> 16);			*((u8 *)InstancePtr->RecvBufferPtr) = byte3;			InstancePtr->RecvBufferPtr += 1;			break;		case 4:			(*(u32 *)InstancePtr->RecvBufferPtr) = Data;			InstancePtr->RecvBufferPtr += 4;			break;		default:			/* This will never execute */			break;		}	}	InstancePtr->RequestedBytes -= Size;	if (InstancePtr->RequestedBytes < 0) {		InstancePtr->RequestedBytes = 0;	}}

⌨️ 快捷键说明

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