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

📄 xiicps_master.c

📁 自学ZedBoard:使用IP通过ARM PS访问FPGA(源代码)
💻 C
📖 第 1 页 / 共 2 页
字号:
			/* Tell slave to send more to us */			if (BytesToRecv > XIICPS_FIFO_DEPTH) {				XIicPs_WriteReg(BaseAddr,					XIICPS_TRANS_SIZE_OFFSET,					XIICPS_FIFO_DEPTH);			} else{				XIicPs_WriteReg(BaseAddr,					XIICPS_TRANS_SIZE_OFFSET, BytesToRecv);			}			BytesToRead = XIICPS_FIFO_DEPTH - TransSize;		}		Tmp = 0;		IntrStatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_ISR_OFFSET);		while ((Tmp < BytesToRead) &&				((IntrStatusReg & Intrs) == 0)) {			StatusReg = XIicPs_ReadReg(BaseAddr,					XIICPS_SR_OFFSET);			IntrStatusReg = XIicPs_ReadReg(BaseAddr,					XIICPS_ISR_OFFSET);			if ((StatusReg & XIICPS_SR_RXDV_MASK) == 0) {				/* No data in fifo */				continue;			}			XIicPs_RecvByte(InstancePtr);			Tmp ++;		}	}	if (IntrStatusReg & Intrs) {		return XST_FAILURE;	}	return XST_SUCCESS;}/*****************************************************************************//*** This function enables the slave monitor mode.** It enables slave monitor in the control register and enables* slave ready interrupt. It then does an address transfer to slave.* Interrupt handler will signal the caller if slave responds to* the address transfer.** @param	InstancePtr is a pointer to the XIicPs instance.* @param	SlaveAddr is the address of the slave we want to contact.** @return	None.** @note		None.*****************************************************************************/void XIicPs_EnableSlaveMonitor(XIicPs *InstancePtr, u16 SlaveAddr){	u32 BaseAddr;	Xil_AssertVoid(InstancePtr != NULL);	BaseAddr = InstancePtr->Config.BaseAddress;	/*	 * Enable slave monitor mode in control register.	 */	XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET,	XIicPs_ReadReg(BaseAddr, XIICPS_CR_OFFSET) |				XIICPS_CR_MS_MASK |				XIICPS_CR_NEA_MASK |				XIICPS_CR_SLVMON_MASK );	/*	 * Set up interrupt flag for slave monitor interrupt.	 */	XIicPs_EnableInterrupts(BaseAddr, XIICPS_IXR_TO_MASK |		XIICPS_IXR_NACK_MASK | XIICPS_IXR_SLV_RDY_MASK);	/*	 * Initialize the slave monitor register.	 */	XIicPs_WriteReg(BaseAddr, XIICPS_SLV_PAUSE_OFFSET, 0xF);	/*	 * Set the slave address to start the slave address transmission.	 */	XIicPs_WriteReg(BaseAddr, XIICPS_ADDR_OFFSET, SlaveAddr);	return;}/*****************************************************************************//*** This function disables slave monitor mode.** @param	InstancePtr is a pointer to the XIicPs instance.** @return	None.** @note		None.*****************************************************************************/void XIicPs_DisableSlaveMonitor(XIicPs *InstancePtr){	u32 BaseAddr;	Xil_AssertVoid(InstancePtr != NULL);	BaseAddr = InstancePtr->Config.BaseAddress;	/*	 * Clear slave monitor control bit.	 */	XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET,		XIicPs_ReadReg(BaseAddr, XIICPS_CR_OFFSET)			& (~XIICPS_CR_SLVMON_MASK));	/*	 * Clear interrupt flag for slave monitor interrupt.	 */	XIicPs_DisableInterrupts(BaseAddr, XIICPS_IXR_SLV_RDY_MASK);	return;}/*****************************************************************************//*** The interrupt handler for the master mode. It does the protocol handling for* the interrupt-driven transfers.** Completion events and errors are signaled to upper layer for proper handling.** <pre>* The interrupts that are handled are:* - DATA*	This case is handled only for master receive data.*	The master has to request for more data (if there is more data to*	receive) and read the data from the FIFO .** - COMP*	If the Master is transmitting data and there is more data to be*	sent then the data is written to the FIFO. If there is no more data to*	be transmitted then a completion event is signalled to the upper layer*	by calling the callback handler.**	If the Master is receiving data then the data is read from the FIFO and*	the Master has to request for more data (if there is more data to*	receive). If all the data has been received then a completion event*	is signalled to the upper layer by calling the callback handler.*	It is an error if the amount of received data is more than expected.** - NAK and SLAVE_RDY*	This is signalled to the upper layer by calling the callback handler.** - All Other interrupts*	These interrupts are marked as error. This is signalled to the upper*	layer by calling the callback handler.** </pre>** @param	InstancePtr is a pointer to the XIicPs instance.** @return	None.** @note 	None.*****************************************************************************/void XIicPs_MasterInterruptHandler(XIicPs *InstancePtr){	u32 IntrStatusReg;	u32 IsSend = 0;	u32 StatusEvent = 0;	u32 BaseAddr;	int Tmp;	int BytesToRecv;	/*	 * Assert validates the input arguments.	 */	Xil_AssertVoid(InstancePtr != NULL);	Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);	BaseAddr = InstancePtr->Config.BaseAddress;	/*	 * Read the Interrupt status register.	 */	IntrStatusReg = XIicPs_ReadReg(BaseAddr,					 XIICPS_ISR_OFFSET);	/*	 * Write the status back to clear the interrupts so no events are missed	 * while processing this interrupt.	 */	XIicPs_WriteReg(BaseAddr, XIICPS_ISR_OFFSET, IntrStatusReg);	/*	 * Use the Mask register AND with the Interrupt Status register so	 * disabled interrupts are not processed.	 */	IntrStatusReg &= ~(XIicPs_ReadReg(BaseAddr, XIICPS_IMR_OFFSET));	/*	 * Data interrupt.	 *	 * In master mode, this means master receiving needs to put more data	 * into the FIFO. In order to avoid slave times out waiting for ack,	 * transfer size register must be set before data is processed.	 *	 */	if (0 != (IntrStatusReg & XIICPS_IXR_DATA_MASK)) {		/*		 * Only greater than FIFO size is handled here, otherwise, the		 * COMP interrupt will be triggered shortly, and we will handle		 * those receives there.		 */		if ((InstancePtr->RecvByteCount) > XIICPS_FIFO_DEPTH){			/* First find out how many bytes slave has sent us */			BytesToRecv = XIICPS_FIFO_DEPTH -					XIicPs_ReadReg(BaseAddr,						XIICPS_TRANS_SIZE_OFFSET);			if ((InstancePtr->RecvByteCount - BytesToRecv)					> XIICPS_FIFO_DEPTH) {				XIicPs_WriteReg(BaseAddr,					XIICPS_TRANS_SIZE_OFFSET,					XIICPS_FIFO_DEPTH);			} else {				XIicPs_WriteReg(BaseAddr,					XIICPS_TRANS_SIZE_OFFSET,					(InstancePtr->RecvByteCount -					BytesToRecv));			}			/*			 * Receive the data out of the FIFO.			 */			for(Tmp = 0; Tmp < BytesToRecv; Tmp ++) {				XIicPs_RecvByte(InstancePtr);			}			/*			 * For receiving of larger than FIFO size, this is all			 * the handling we need to do.			 */			return;	 	}	}	/*	 * Determine whether the device is sending.	 */	if (InstancePtr->RecvBufferPtr == NULL) {		IsSend = 1;	}	/*	 * Complete flag.	 */	if (0 != (IntrStatusReg & XIICPS_IXR_COMP_MASK)) {		if (IsSend) {			if (InstancePtr->SendByteCount > 0) {				MasterSendData(InstancePtr);			} else {				StatusEvent |= XIICPS_EVENT_COMPLETE_SEND;			}		} else {			/*			 * Get the data out of FIFO first, if not done,			 * tell the slave to send more.			 */			while (XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET) &					XIICPS_SR_RXDV_MASK) {				XIicPs_RecvByte(InstancePtr);			}			/*			 * Continue to tell slave to send data if not done.			 */			if (InstancePtr->RecvByteCount > XIICPS_FIFO_DEPTH) {				XIicPs_WriteReg(					InstancePtr->Config.BaseAddress,					XIICPS_TRANS_SIZE_OFFSET,					XIICPS_FIFO_DEPTH);			} else if (InstancePtr->RecvByteCount > 0) {				XIicPs_WriteReg(					InstancePtr->Config.BaseAddress,					XIICPS_TRANS_SIZE_OFFSET,					InstancePtr->RecvByteCount);			}			/*			 * If all done, tell the application.			 */			if (InstancePtr->RecvByteCount == 0){				StatusEvent |= XIICPS_EVENT_COMPLETE_RECV;			}			/*			 * If received more than expected, it is an error.			 */			if (InstancePtr->RecvByteCount < 0){				StatusEvent |= XIICPS_EVENT_ERROR;			}		}	}	/*	 * Slave ready interrupt, it is only meaningful for master mode.	 */	if (0 != (IntrStatusReg & XIICPS_IXR_SLV_RDY_MASK)) {		StatusEvent |= XIICPS_EVENT_SLAVE_RDY;	}	if (0 != (IntrStatusReg & XIICPS_IXR_NACK_MASK)) {		StatusEvent |= XIICPS_EVENT_NACK;	}	/*	 * All other interrupts are treated as error.	 */	if (0 != (IntrStatusReg & (XIICPS_IXR_TO_MASK | XIICPS_IXR_NACK_MASK |			XIICPS_IXR_ARB_LOST_MASK | XIICPS_IXR_RX_UNF_MASK |			XIICPS_IXR_TX_OVR_MASK | XIICPS_IXR_RX_OVR_MASK))) {		StatusEvent |= XIICPS_EVENT_ERROR;	}	/*	 * Signal application if there are any events.	 */	if (0 != StatusEvent) {		InstancePtr->StatusHandler(InstancePtr->CallBackRef,					   StatusEvent);	}}/*****************************************************************************//** This function prepares a device to transfers as a master.** @param	InstancePtr is a pointer to the XIicPs instance.** @param	Role specifies whether the device is sending or receiving.** @return*		- XST_SUCCESS if everything went well.*		- XST_FAILURE if bus is busy.** @note		Interrupts are always disabled, device which needs to use*		interrupts needs to setup interrupts after this call.*****************************************************************************/static int XIicPs_SetupMaster(XIicPs *InstancePtr, int Role){	u32 ControlReg;	u32 BaseAddr;	u32 EnabledIntr = 0x0;	Xil_AssertNonvoid(InstancePtr != NULL);	BaseAddr = InstancePtr->Config.BaseAddress;	ControlReg = XIicPs_ReadReg(BaseAddr, XIICPS_CR_OFFSET);	/*	 * Only check if bus is busy when repeated start option is not set.	 */	if ((ControlReg & XIICPS_CR_HOLD_MASK) == 0) {		if (XIicPs_BusIsBusy(InstancePtr)) {			return XST_FAILURE;		}	}	/*	 * Set up master, AckEn, nea and also clear fifo.	 */	ControlReg |= XIICPS_CR_ACKEN_MASK | XIICPS_CR_CLR_FIFO_MASK |		 	XIICPS_CR_NEA_MASK | XIICPS_CR_MS_MASK;	if (Role == RECVING_ROLE) {		ControlReg |= XIICPS_CR_RD_WR_MASK;		EnabledIntr = XIICPS_IXR_DATA_MASK |XIICPS_IXR_RX_OVR_MASK;	}else {		ControlReg &= ~XIICPS_CR_RD_WR_MASK;	}	EnabledIntr |= XIICPS_IXR_COMP_MASK | XIICPS_IXR_ARB_LOST_MASK;	XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET, ControlReg);	XIicPs_DisableAllInterrupts(BaseAddr);	return XST_SUCCESS;}/*****************************************************************************//** This function handles continuation of sending data. It is invoked* from interrupt handler.** @param	InstancePtr is a pointer to the XIicPs instance.** @return	None.** @note		None.*****************************************************************************/static void MasterSendData(XIicPs *InstancePtr){	TransmitFifoFill(InstancePtr);	/*	 * Clear repeated start if done, so stop can be sent out.	 */	if (InstancePtr->SendByteCount == 0) {		/*		 * If user has enabled repeated start as an option,		 * do not disable it.		 */		if ((InstancePtr->Options & XIICPS_REP_START_OPTION) == 0) {			XIicPs_WriteReg(InstancePtr->Config.BaseAddress,				XIICPS_CR_OFFSET,				XIicPs_ReadReg(InstancePtr->Config.BaseAddress,				XIICPS_CR_OFFSET) & ~ XIICPS_CR_HOLD_MASK);		}	}	return;}

⌨️ 快捷键说明

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