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

📄 xdmaps.c

📁 自学ZedBoard:使用IP通过ARM PS访问FPGA(源代码)
💻 C
📖 第 1 页 / 共 4 页
字号:
* @param	Lc is the Loop counter register, can either be 0 or 1.* @param	LoopIterations: the number of interations, LoopInterations - 1*		will be encoded in the DMALP instruction.** @return 	The number of bytes for this instruction which is 2.** @note		None.******************************************************************************/inline int XDmaPs_Instr_DMALP(char *DmaProg, unsigned Lc,			       unsigned LoopIterations){	/*	 * DMALP encoding	 * 15   ...   8 7 6 5 4 3 2 1  0	 * | iter[7:0] |0 0 1 0 0 0 lc 0	 */	*DmaProg = (u8)(0x20 | ((Lc & 1) << 1));	*(DmaProg + 1) = (u8)(LoopIterations - 1);	return 2;}/****************************************************************************//**** Construction function for DMALPEND instruction. This function fills the* program buffer with the constructed instruction.** @param	DmaProg is the DMA program buffer, it's the starting address*		for the instruction being constructed* @param	BodyStart is the starting address of the loop body. It is used* 		to calculate the bytes of backward jump.* @param	Lc is the Loop counter register, can either be 0 or 1.** @return 	The number of bytes for this instruction which is 2.** @note	None.******************************************************************************/inline int XDmaPs_Instr_DMALPEND(char *DmaProg, char *BodyStart, unsigned Lc){	/*	 * DMALPEND encoding	 * 15       ...        8 7 6 5 4  3 2  1  0	 * | backward_jump[7:0] |0 0 1 nf 1 lc bs x	 *	 * lc: loop counter	 * nf is for loop forever. The driver does not support loop forever,	 * so nf is 1.	 * The driver does not support conditional LPEND, so bs is 0, x is 0.	 */	*DmaProg = 0x38 | ((Lc & 1) << 2);	*(DmaProg + 1) = (u8)(DmaProg - BodyStart);	return 2;}/* * Register number for the DMAMOV instruction */#define XDMAPS_MOV_SAR 0x0#define XDMAPS_MOV_CCR 0x1#define XDMAPS_MOV_DAR 0x2/****************************************************************************//**** Construction function for DMAMOV instruction. This function fills the* program buffer with the constructed instruction.** @param	DmaProg is the DMA program buffer, it's the starting address*		for the instruction being constructed* @param	Rd is the register id, 0 for SAR, 1 for CCR, and 2 for DAR* @param	Imm is the 32-bit immediate number** @return 	The number of bytes for this instruction which is 6.** @note		None.******************************************************************************/inline int XDmaPs_Instr_DMAMOV(char *DmaProg, unsigned Rd, u32 Imm){	/*	 * DMAMOV encoding	 * 15 4 3 2 1 10 ... 8 7 6 5 4 3 2 1 0	 *  0 0 0 0 0 |rd[2:0]|1 0 1 1 1 1 0 0	 *	 * 47 ... 16	 *  imm[32:0]	 *	 * rd: b000 for SAR, b001 CCR, b010 DAR	 */	*DmaProg = 0xBC;	*(DmaProg + 1) = Rd & 0x7;	// *((u32 *)(DmaProg + 2)) = Imm;	XDmaPs_Memcpy4(DmaProg + 2, (char *)&Imm);	return 6;}/****************************************************************************//**** Construction function for DMANOP instruction. This function fills the* program buffer with the constructed instruction.** @param	DmaProg is the DMA program buffer, it's the starting address*		for the instruction being constructed* @return 	The number of bytes for this instruction which is 1.** @note		None.******************************************************************************/inline int XDmaPs_Instr_DMANOP(char *DmaProg){	/*	 * DMANOP encoding	 * 7 6 5 4 3 2 1 0	 * 0 0 0 1 1 0 0 0	 */	*DmaProg = 0x18;	return 1;}/****************************************************************************//**** Construction function for DMARMB instruction. This function fills the* program buffer with the constructed instruction.** @param	DmaProg is the DMA program buffer, it's the starting address*		for the instruction being constructed** @return 	The number of bytes for this instruction which is 1.** @note		None.******************************************************************************/inline int XDmaPs_Instr_DMARMB(char *DmaProg){	/*	 * DMARMB encoding	 * 7 6 5 4 3 2 1 0	 * 0 0 0 1 0 0 1 0	 */	*DmaProg = 0x12;	return 1;}/****************************************************************************//**** Construction function for DMASEV instruction. This function fills the* program buffer with the constructed instruction.** @param	DmaProg is the DMA program buffer, it's the starting address*		for the instruction being constructed* @param	EventNumber is the Event number to signal.** @return 	The number of bytes for this instruction which is 2.** @note		None.******************************************************************************/inline int XDmaPs_Instr_DMASEV(char *DmaProg, unsigned int EventNumber){	/*	 * DMASEV encoding	 * 15 4 3 2 1  10 9 8 7 6 5 4 3 2 1 0	 * |event[4:0]| 0 0 0 0 0 1 1 0 1 0 0	 */	*DmaProg = 0x34;	*(DmaProg + 1) = (u8)(EventNumber << 3);	return 2;}/****************************************************************************//**** Construction function for DMAST instruction. This function fills the* program buffer with the constructed instruction.** @param	DmaProg is the DMA program buffer, it's the starting address*		for the instruction being constructed** @return 	The number of bytes for this instruction which is 1.** @note		None.******************************************************************************/inline int XDmaPs_Instr_DMAST(char *DmaProg){	/*	 * DMAST encoding	 * 7 6 5 4 3 2 1  0	 * 0 0 0 0 1 0 bs x	 *	 * Note: this driver doesn't support conditional load or store,	 * so the bs bit is 0 and x bit is 0.	 */	*DmaProg = 0x08;	return 1;}/****************************************************************************//**** Construction function for DMAWMB instruction. This function fills the* program buffer with the constructed instruction.** @param	DmaProg is the DMA program buffer, it's the starting address*		for the instruction being constructed** @return 	The number of bytes for this instruction which is 1.** @note		None.******************************************************************************/inline int XDmaPs_Instr_DMAWMB(char *DmaProg){	/*	 * DMAWMB encoding	 * 7 6 5 4 3 2 1 0	 * 0 0 0 1 0 0 1 0	 */	*DmaProg = 0x13;	return 1;}/****************************************************************************//**** Conversion function from the endian swap size to the bit encoding of the CCR** @param	EndianSwapSize is the endian swap size, in terms of bits, it*		could be 8, 16, 32, 64, or 128(We are using DMA assembly syntax)** @return	The endian swap size bit encoding for the CCR.** @note	None.******************************************************************************/inline unsigned XDmaPs_ToEndianSwapSizeBits(unsigned int EndianSwapSize){	switch (EndianSwapSize) {	case 0:	case 8:		return 0;	case 16:		return 1;	case 32:		return 2;	case 64:		return 3;	case 128:		return 4;	default:		return 0;	}}/****************************************************************************//**** Conversion function from the burst size to the bit encoding of the CCR** @param	BurstSize is the burst size. It's the data width.*		In terms of bytes, it could be 1, 2, 4, 8, 16, 32, 64, or 128.*		It must be no larger than the bus width.*		(We are using DMA assembly syntax.)** @note		None.******************************************************************************/inline unsigned XDmaPs_ToBurstSizeBits(unsigned BurstSize){	switch (BurstSize) {	case 1:		return 0;	case 2:		return 1;	case 4:		return 2;	case 8:		return 3;	case 16:		return 4;	case 32:		return 5;	case 64:		return 6;	case 128:		return 7;	default:		return 0;	}}/****************************************************************************//**** Conversion function from PL330 bus transfer descriptors to CCR value. All the* values passed to the functions are in terms of assembly languages, not in* terms of the register bit encoding.** @param	ChanCtrl is the Instance of XDmaPs_ChanCtrl.** @return	The 32-bit CCR value.** @note		None.******************************************************************************/u32 XDmaPs_ToCCRValue(XDmaPs_ChanCtrl *ChanCtrl){	/*	 * Channel Control Register encoding	 * [31:28] - endian_swap_size	 * [27:25] - dst_cache_ctrl	 * [24:22] - dst_prot_ctrl	 * [21:18] - dst_burst_len	 * [17:15] - dst_burst_size	 * [14]    - dst_inc	 * [13:11] - src_cache_ctrl	 * [10:8] - src_prot_ctrl	 * [7:4]  - src_burst_len	 * [3:1]  - src_burst_size	 * [0]     - src_inc	 */	unsigned es =		XDmaPs_ToEndianSwapSizeBits(ChanCtrl->EndianSwapSize);	unsigned dst_burst_size =		XDmaPs_ToBurstSizeBits(ChanCtrl->DstBurstSize);	unsigned dst_burst_len = (ChanCtrl->DstBurstLen - 1) & 0x0F;	unsigned dst_cache_ctrl = (ChanCtrl->DstCacheCtrl & 0x03)		| ((ChanCtrl->DstCacheCtrl & 0x08) >> 1);	unsigned dst_prot_ctrl = ChanCtrl->DstProtCtrl & 0x07;	unsigned dst_inc_bit = ChanCtrl->DstInc & 1;	unsigned src_burst_size =		XDmaPs_ToBurstSizeBits(ChanCtrl->SrcBurstSize);	unsigned src_burst_len = (ChanCtrl->SrcBurstLen - 1) & 0x0F;	unsigned src_cache_ctrl = (ChanCtrl->SrcCacheCtrl & 0x03)		| ((ChanCtrl->SrcCacheCtrl & 0x08) >> 1);	unsigned src_prot_ctrl = ChanCtrl->SrcProtCtrl & 0x07;	unsigned src_inc_bit = ChanCtrl->SrcInc & 1;	u32 ccr_value = (es << 28)		| (dst_cache_ctrl << 25)		| (dst_prot_ctrl << 22)		| (dst_burst_len << 18)		| (dst_burst_size << 15)		| (dst_inc_bit << 14)		| (src_cache_ctrl << 11)		| (src_prot_ctrl << 8)		| (src_burst_len << 4)		| (src_burst_size << 1)		| (src_inc_bit);	PDBG("CCR: es %x\r\n", es);	PDBG("CCR: dca %x, dpr %x, dbl %x, dbs %x, di %x\r\n",	     dst_cache_ctrl, dst_prot_ctrl,	     dst_burst_len, dst_burst_size, dst_inc_bit);	PDBG("CCR: sca %x, spr %x, sbl %x, sbs %x, si %x\r\n",	     src_cache_ctrl, src_prot_ctrl,	     src_burst_len,  src_burst_size, src_inc_bit);	return ccr_value;}/****************************************************************************//*** Construct a loop with only DMALD and DMAST as the body using loop counter 0.* The function also makes sure the loop body and the lpend is in the same* cache line.** @param	DmaProgStart is the very start address of the DMA program.*		This is used to calculate whether the loop is in a cache line.* @param	CacheLength is the icache line length, in terms of bytes.*		If it's zero, the performance enhancement feature will be*		turned off.* @param	DmaProgLoopStart The starting address of the loop (DMALP).* @param	LoopCount The inner loop count. Loop count - 1 will be used to* 		initialize the loop counter.** @return	The number of bytes the loop has.** @note		None.******************************************************************************/int XDmaPs_ConstructSingleLoop(char *DmaProgStart,				int CacheLength,				char *DmaProgLoopStart,				int LoopCount){	int CacheStartOffset;	int CacheEndOffset;	int NumNops;	char *DmaProgBuf = DmaProgLoopStart;	PDBG("Contructing single loop: loop count %d\r\n", LoopCount);	DmaProgBuf += XDmaPs_Instr_DMALP(DmaProgBuf, 0, LoopCount);	if (CacheLength > 0) {		/*		 * the CacheLength > 0 switch is ued to turn on/off nop		 * insertion		 */		CacheStartOffset = DmaProgBuf - DmaProgStart;		CacheEndOffset = CacheStartOffset + 3;		/*		 * check whether the body and lpend fit in one cache line		 */		if (CacheStartOffset / CacheLength		    != CacheEndOffset / CacheLength) {			/* insert the nops */			NumNops = CacheLength				- CacheStartOffset % CacheLength;			while (NumNops--) {				DmaProgBuf +=					XDmaPs_Instr_DMANOP(DmaProgBuf);			}		}	}	DmaProgBuf += XDmaPs_Instr_DMALD(DmaProgBuf);	DmaProgBuf += XDmaPs_Instr_DMAST(DmaProgBuf);	DmaProgBuf += XDmaPs_Instr_DMALPEND(DmaProgBuf,					     DmaProgBuf - 2, 0);	return DmaProgBuf - DmaProgLoopStart;}/*** Construct a nested loop with only DMALD and DMAST in the inner loop body.* It uses loop counter 1 for the outer loop and loop counter 0 for the* inner loop. * @param DmaProgStart The very start address of the DMA program. This is used * 	to caculate whether the loop is in a cache line. * @param CacheLength The icache line length, in terms of bytes. If it's zero, * 	the performance enhancement feture will be turned off. * @param DmaProgLoopStart The starting address of the loop (DMALP). * @param LoopCountOuter The outer loop count. Loop count - 1 will be used to * 	initialize the loop counter. * @param LoopCountInner The inner loop count. Loop count - 1 will be used to * 	initialize the loop counter. * @return the number byes the nested loop program has. *//****************************************************************************//*** Construct a nested loop with only DMALD and DMAST in the inner loop body.* It uses loop counter 1 for the outer loop and loop counter 0 for the* inner loop.** @param	DmaProgStart is the very start address of the DMA program.*		This is used to calculate whether the loop is in a cache line.* @param	CacheLength is the icache line length, in terms of bytes.*		If it's zero, the performance enhancement feature will be*		turned off.* @param	DmaProgLoopStart The starting address of the loop (DMALP).* @param	LoopCountOuter The outer loop count. Loop count - 1 will be*		used to initialize the loop counter.* @param	LoopCountInner The inner loop count. Loop count - 1 will be*		used to initialize the loop counter.** @return	The number byes the nested loop program has.** @note		None.******************************************************************************/int XDmaPs_ConstructNestedLoop(char *DmaProgStart,				int CacheLength,				char *DmaProgLoopStart,				unsigned int LoopCountOuter,				unsigned int LoopCountInner){	int CacheStartOffset;	int CacheEndOffset;	int NumNops;	char *InnerLoopStart;	char *DmaProgBuf = DmaProgLoopStart;	PDBG("Contructing nested loop outer %d, inner %d\r\n",	     LoopCountOuter, LoopCountInner);	DmaProgBuf += XDmaPs_Instr_DMALP(DmaProgBuf, 1, LoopCountOuter);	InnerLoopStart = DmaProgBuf;	if (CacheLength > 0) {		/*		 * the CacheLength > 0 switch is ued to turn on/off nop		 * insertion		 */		if (CacheLength < 8) {			/*			 * if the cache line is too small to fit both loops			 * just align the inner loop			 */			DmaProgBuf +=				XDmaPs_ConstructSingleLoop(DmaProgStart,							    CacheLength,							    DmaProgBuf,							    LoopCountInner);			/* outer loop end */			DmaProgBuf +=				XDmaPs_Instr_DMALPEND(DmaProgBuf,						       InnerLoopStart,						       1);			/*			 * the nested loop is constructed for			 * smaller cache line			 */			return DmaProgBuf - DmaProgLoopStart;		}		/*		 * Now let's handle the case where a cache line can		 * fit the nested loops.

⌨️ 快捷键说明

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