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

📄 xdmaps.c

📁 自学ZedBoard:使用IP通过ARM PS访问FPGA(源代码)
💻 C
📖 第 1 页 / 共 4 页
字号:
				Cmd->BD.DstAddr,				Cmd->BD.Length);		if (Cmd->ChanCtrl.SrcInc) {			PDBG("DCachFlushRange for Src 0x%x, Len 0x%x \r\n",					Cmd->BD.SrcAddr, Cmd->BD.Length);			Xil_DCacheFlushRange(Cmd->BD.SrcAddr, Cmd->BD.Length);		}		if (Cmd->ChanCtrl.DstInc) {			PDBG("DCachInvalidateRange for Dst 0x%x, Len 0x%x \r\n",					Cmd->BD.DstAddr, Cmd->BD.Length);			Xil_DCacheInvalidateRange(Cmd->BD.DstAddr,					Cmd->BD.Length);		}		Status = XDmaPs_Exec_DMAGO(InstPtr->Config.BaseAddress,					    Channel, DmaProg);	}	else {		InstPtr->Chans[Channel].DmaCmdToHw = NULL;		Status = XST_FAILURE;	}	return Status;}/****************************************************************************//**** Checks  whether the DMA channel is active or idle.** @param	InstPtr is the DMA instance.* @param	Channel is the DMA channel number.** @return	0: if the channel is idle* 		1: otherwise** @note		None.******************************************************************************/int XDmaPs_IsActive(XDmaPs *InstPtr, unsigned int Channel){	Xil_AssertNonvoid(InstPtr != NULL);	/* Need to assert Channel is in range */	if (Channel > XDMAPS_CHANNELS_PER_DEV)		return  0;	return InstPtr->Chans[Channel].DmaCmdToHw != NULL;}/****************************************************************************//**** Allocate a buffer of the DMA program buffer from the pool.** @param	Pool the DMA program pool.** @return	The allocated buffer, NULL if there is any error.** @note		None.******************************************************************************/static void *XDmaPs_BufPool_Allocate(XDmaPs_ProgBuf *Pool){	int Index;	Xil_AssertNonvoid(Pool != NULL);	for (Index = 0; Index < XDMAPS_MAX_CHAN_BUFS; Index++) {		if (!Pool[Index].Allocated) {			PDBG("Allocate buf %d\r\n", Index);			Pool[Index].Allocated = 1;			return Pool[Index].Buf;		}	}	return NULL;}/*****************************************************************************//**** Driver done interrupt service routine for channel 0. We need this done ISR* mainly because the driver needs to release the DMA program buffer.* This is the one that connects the GIC** @param	InstPtr is the DMA instance.** @return	None.** @note		None.*******************************************************************************/void XDmaPs_DoneISR_0(XDmaPs *InstPtr){	XDmaPs_DoneISR_n(InstPtr, 0);}/*****************************************************************************//**** Driver done interrupt service routine for channel 1. We need this done ISR* mainly because the driver needs to release the DMA program buffer.* This is the one that connects the GIC** @param	InstPtr is the DMA instance.** @return	None.** @note		None.*******************************************************************************/void XDmaPs_DoneISR_1(XDmaPs *InstPtr){	XDmaPs_DoneISR_n(InstPtr, 1);}/*****************************************************************************//**** Driver done interrupt service routine for channel 2. We need this done ISR* mainly because the driver needs to release the DMA program buffer.* This is the one that connects the GIC** @param	InstPtr is the DMA instance.** @return	None.** @note		None.*******************************************************************************/void XDmaPs_DoneISR_2(XDmaPs *InstPtr){	XDmaPs_DoneISR_n(InstPtr, 2);}/*****************************************************************************//**** Driver done interrupt service routine for channel 3. We need this done ISR* mainly because the driver needs to release the DMA program buffer.* This is the one that connects the GIC** @param	InstPtr is the DMA instance.** @return	None.** @note		None.*******************************************************************************/void XDmaPs_DoneISR_3(XDmaPs *InstPtr){	XDmaPs_DoneISR_n(InstPtr, 3);}/*****************************************************************************//**** Driver done interrupt service routine for channel 4. We need this done ISR* mainly because the driver needs to release the DMA program buffer.* This is the one that connects the GIC** @param	InstPtr is the DMA instance.** @return	None.** @note		None.*******************************************************************************/void XDmaPs_DoneISR_4(XDmaPs *InstPtr){	XDmaPs_DoneISR_n(InstPtr, 4);}/*****************************************************************************//**** Driver done interrupt service routine for channel 5. We need this done ISR* mainly because the driver needs to release the DMA program buffer.* This is the one that connects the GIC** @param	InstPtr is the DMA instance.** @return	None.** @note		None.*******************************************************************************/void XDmaPs_DoneISR_5(XDmaPs *InstPtr){	XDmaPs_DoneISR_n(InstPtr, 5);}/*****************************************************************************//**** Driver done interrupt service routine for channel 6. We need this done ISR* mainly because the driver needs to release the DMA program buffer.* This is the one that connects the GIC** @param	InstPtr is the DMA instance.** @return	None.** @note		None.*******************************************************************************/void XDmaPs_DoneISR_6(XDmaPs *InstPtr){	XDmaPs_DoneISR_n(InstPtr, 6);}/*****************************************************************************//**** Driver done interrupt service routine for channel 7. We need this done ISR* mainly because the driver needs to release the DMA program buffer.* This is the one that connects the GIC** @param	InstPtr is the DMA instance.** @return	None.** @note		None.*******************************************************************************/void XDmaPs_DoneISR_7(XDmaPs *InstPtr){	XDmaPs_DoneISR_n(InstPtr, 7);}#ifndef XDMAPS_MAX_WAIT#define XDMAPS_MAX_WAIT 4000#endif/****************************************************************************//*** Use the debug registers to kill the DMA thread.** @param	BaseAddr is DMA device base address.* @param	Channel is the DMA channel number.* @param	Thread is Debug thread encoding.* 		0: DMA manager thread, 1: DMA channel.** @return	0 on success, -1 on time out** @note		None.******************************************************************************/static int XDmaPs_Exec_DMAKILL(u32 BaseAddr,				unsigned int Channel,				unsigned int Thread){	u32 DbgInst0;	int WaitCount;	PDBG("Inside XDmaPs_Exec_DMAKILL\r\n");	DbgInst0 = XDmaPs_DBGINST0(0, 0x01, Channel, Thread);	/* wait while debug status is busy */	WaitCount = 0;	PDBG("Checking DBGSTATUS\r\n");	while ((XDmaPs_ReadReg(BaseAddr, XDMAPS_DBGSTATUS_OFFSET)	       & XDMAPS_DBGSTATUS_BUSY)	       && (WaitCount < XDMAPS_MAX_WAIT))		WaitCount++;	if (WaitCount >= XDMAPS_MAX_WAIT) {		/* wait time out */		xil_printf("PL330 device at %x debug status busy time out\n",		       BaseAddr);		return -1;	}	/* write debug instruction 0 */	PDBG("XDmaPs_Exec_DMAKILL: writing DbgInst0 %#08x\n", DbgInst0);	XDmaPs_WriteReg(BaseAddr, XDMAPS_DBGINST0_OFFSET, DbgInst0);	PDBG("pl330_exec_dmakill: writing DbgInst1 %#08x\n", 0);	XDmaPs_WriteReg(BaseAddr, XDMAPS_DBGINST1_OFFSET, 0);	/* run the command in DbgInst0 and DbgInst1 */	XDmaPs_WriteReg(BaseAddr, XDMAPS_DBGCMD_OFFSET, 0);	return 0;}/****************************************************************************//***** Free a buffer of the DMA program buffer.* @param	Pool the DMA program pool.* @param	Buf the DMA program buffer to be release.** @return	None** @note		None.******************************************************************************/static void XDmaPs_BufPool_Free(XDmaPs_ProgBuf *Pool, void *Buf){	int Index;	int Found = 0;	Xil_AssertVoid(Pool != NULL);	for (Index = 0; Index < XDMAPS_MAX_CHAN_BUFS; Index++) {		if (Pool[Index].Buf == Buf) {			if (Pool[Index].Allocated) {				PDBG("Freed buf %d\r\n", Index);				Pool[Index].Allocated = 0;			} else {				PDBG("Trying to free a free buf %d\r\n", Index);			}			Found = 1;		}	}	if (!Found)		PDBG("Trying to free a buf that is not in the pool\r\n");}/*****************************************************************************//*** XDmaPs_Exec_DMAGO - Execute the DMAGO to start a channel.** @param	BaseAddr PL330 device base address* @param	Channel Channel number for the device* @param	DmaProg DMA program starting address, this should be DMA address** @return	0 on success, -1 on time out** @note		None.*****************************************************************************/static int XDmaPs_Exec_DMAGO(u32 BaseAddr, unsigned int Channel, u32 DmaProg){	char DmaGoProg[8];	u32 DbgInst0;	u32 DbgInst1;	int WaitCount;	PDBG("XDmaPs_Exec_DMAGO: entering\r\n");	XDmaPs_Instr_DMAGO(DmaGoProg, Channel, DmaProg, 0);	DbgInst0 = XDmaPs_DBGINST0(*(DmaGoProg + 1), *DmaGoProg, 0, 0);	DbgInst1 = (u32)DmaProg;	PDBG("inside XDmaPs_Exec_DMAGO: base %x, Channel %d, DmaProg %x\r\n",	     BaseAddr, Channel, DmaProg);	PDBG("inside XDmaPs_Exec_DMAGO: DbgInst0 %x, DbgInst1 %x\r\n",	     DbgInst0, DbgInst1);	/* wait while debug status is busy */	WaitCount = 0;	PDBG("Checking DBGSTATUS\r\n");	while ((XDmaPs_ReadReg(BaseAddr, XDMAPS_DBGSTATUS_OFFSET)	       & XDMAPS_DBGSTATUS_BUSY)	       && (WaitCount < XDMAPS_MAX_WAIT)) {		PDBG("dbgstatus %x\r\n",		     XDmaPs_ReadReg(BaseAddr, XDMAPS_DBGSTATUS_OFFSET));		WaitCount++;	}	if (WaitCount >= XDMAPS_MAX_WAIT) {		xil_printf("PL330 device at %x debug status busy time out\r\n",			   BaseAddr);		return -1;	}	PDBG("dbgstatus idle\r\n");	/* write debug instruction 0 */	XDmaPs_WriteReg(BaseAddr, XDMAPS_DBGINST0_OFFSET, DbgInst0);	/* write debug instruction 1 */	XDmaPs_WriteReg(BaseAddr, XDMAPS_DBGINST1_OFFSET, DbgInst1);	/* wait while the DMA Manager is busy */	WaitCount = 0;	while ((XDmaPs_ReadReg(BaseAddr,				XDMAPS_DS_OFFSET) & XDMAPS_DS_DMA_STATUS)	       != XDMAPS_DS_DMA_STATUS_STOPPED	       && WaitCount <= XDMAPS_MAX_WAIT) {		PDBG("ds %x\r\n",		       XDmaPs_ReadReg(BaseAddr, XDMAPS_DS_OFFSET));		WaitCount++;	}	if (WaitCount >= XDMAPS_MAX_WAIT) {		xil_printf("PL330 device at %x debug status busy time out\r\n",			   BaseAddr);		return -1;	}	/* run the command in DbgInst0 and DbgInst1 */	XDmaPs_WriteReg(BaseAddr, XDMAPS_DBGCMD_OFFSET, 0);	PDBG("XDmaPs_Exec_DMAGO done\r\n");	return 0;}/****************************************************************************//**** It's the generic Done ISR.* @param	InstPtr is the DMA instance.* @param	Channel is the DMA channel numer.** @return	None.*** @note		None.******************************************************************************/static void XDmaPs_DoneISR_n(XDmaPs *InstPtr, unsigned Channel){	void *DmaProgBuf;	XDmaPs_ChannelData *ChanData;	XDmaPs_Cmd *DmaCmd;	u32 Value;	ChanData = InstPtr->Chans + Channel;	PDBG("inside Done ISR Channel %d\r\n", ChanData->ChanId);	Value = XDmaPs_ReadReg(InstPtr->Config.BaseAddress,			XDMAPS_INTSTATUS_OFFSET);	PDBG("Interrupt status before clearing %x\r\n", Value);	/* clear the interrupt status */	PDBG("Clear the interrupt status %x\r\n", 1<< ChanData->ChanId);	XDmaPs_WriteReg(InstPtr->Config.BaseAddress,			XDMAPS_INTCLR_OFFSET,			1 << ChanData->ChanId);	Value = XDmaPs_ReadReg(InstPtr->Config.BaseAddress,			XDMAPS_INTSTATUS_OFFSET);	PDBG("Interrupt status after clearing %x\r\n", Value);	if (Value) {		PDBG("Interrupt status %x\r\n", Value);	}	if ((DmaCmd = ChanData->DmaCmdToHw)) {		if (!ChanData->HoldDmaProg) {			DmaProgBuf = (void *)DmaCmd->GeneratedDmaProg;			if (DmaProgBuf)				XDmaPs_BufPool_Free(ChanData->ProgBufPool,						     DmaProgBuf);			DmaCmd->GeneratedDmaProg = NULL;		}		DmaCmd->DmaStatus = 0;		ChanData->DmaCmdToHw = NULL;		ChanData->DmaCmdFromHw = DmaCmd;		if (ChanData->DoneHandler)			ChanData->DoneHandler(Channel, DmaCmd,					      ChanData->DoneRef);	}}/****************************************************************************//*** Prints the content of the buffer in bytes* @param	Buf is the buffer.* @param	Length is the length of the DMA program.** @return	None.** @note		None.****************************************************************************/static void XDmaPs_Print_DmaProgBuf(char *Buf, int Length){	int Index;	for (Index = 0; Index < Length; Index++)		xil_printf("[%x] %x\r\n", Index, Buf[Index]);}/****************************************************************************//*** Print the Dma Prog Contents.** @param	Cmd is the command buffer.** @return	None.** @note		None.******************************************************************************/ void XDmaPs_Print_DmaProg(XDmaPs_Cmd *Cmd){	if (Cmd->GeneratedDmaProg && Cmd->GeneratedDmaProgLength) {		xil_printf("Generated DMA program (%d):\r\n",			   Cmd->GeneratedDmaProgLength);		XDmaPs_Print_DmaProgBuf((char *)Cmd->GeneratedDmaProg,					 Cmd->GeneratedDmaProgLength);	}	if (Cmd->UserDmaProg && Cmd->UserDmaProgLength) {		xil_printf("User defined DMA program (%d):\r\n",			   Cmd->UserDmaProgLength);		XDmaPs_Print_DmaProgBuf((char *)Cmd->UserDmaProg,					 Cmd->UserDmaProgLength);	}}

⌨️ 快捷键说明

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