热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

利用ZYNQSOC快速打开算法验证通路(3)——PS端DMA缓存数据到PS端DDR

上篇该系列博文中讲述W5500接收到上位机传输的数据,此后需要将数据缓存起来。当数据量较大或者其他数据带宽较高的情况下,片上缓存(OCM)已无法满足需求,这时需要将大量数据保存在外

  上篇该系列博文中讲述W5500接收到上位机传输的数据,此后需要将数据缓存起来。当数据量较大或者其他数据带宽较高的情况下,片上缓存(OCM)已无法满足需求,这时需要将大量数据保存在外挂的DDR SDRAM中。

  最简单的方式是使用Xilinx的读写地址库函数Xil_In32()和Xil_Out32(),当然不仅支持32bit位宽,还包括8 16和64bit。但这种方式每次读写都要占用CPU,无法在读写的同时接收后续数据或者对之前的数据进一步处理,也就无法形成类似FPGA逻辑设计中的“流水线结构”,此时前段数据缓存过程中,后段数据会被丢弃。所以,需要利用PS端CPU子系统内的专用硬件DMA完成高速的批量数据搬移工作。

利用ZYNQ SOC快速打开算法验证通路(3)——PS端DMA缓存数据到PS端DDR

  在Xilinx SDK的system.mss页面下直接导入ps_dma示例工程。

  1 #include 
  2 #include 
  3 #include "sleep.h"
  4 #include "xparameters.h"
  5 #include "xil_types.h"
  6 #include "xil_assert.h"
  7 #include "xil_io.h"
  8 #include "xil_exception.h"
  9 #include "xil_cache.h"
 10 #include "xil_printf.h"
 11 #include "xscugic.h"
 12 #include "xdmaps.h"
 13 
 14 /************************** Constant Definitions *****************************/
 15 /*
 16  * The following constants map to the XPAR parameters created in the
 17  * xparameters.h file. They are defined here such that a user can easily
 18  * change all the needed parameters in one place.
 19  */
 20 #define DMA_DEVICE_ID             XPAR_XDMAPS_1_DEVICE_ID
 21 #define INTC_DEVICE_ID            XPAR_SCUGIC_SINGLE_DEVICE_ID
 22 
 23 #define DMA_DONE_INTR_0            XPAR_XDMAPS_0_DONE_INTR_0
 24 #define DMA_DONE_INTR_1            XPAR_XDMAPS_0_DONE_INTR_1
 25 #define DMA_DONE_INTR_2            XPAR_XDMAPS_0_DONE_INTR_2
 26 #define DMA_DONE_INTR_3            XPAR_XDMAPS_0_DONE_INTR_3
 27 #define DMA_DONE_INTR_4            XPAR_XDMAPS_0_DONE_INTR_4
 28 #define DMA_DONE_INTR_5            XPAR_XDMAPS_0_DONE_INTR_5
 29 #define DMA_DONE_INTR_6            XPAR_XDMAPS_0_DONE_INTR_6
 30 #define DMA_DONE_INTR_7            XPAR_XDMAPS_0_DONE_INTR_7
 31 #define DMA_FAULT_INTR            XPAR_XDMAPS_0_FAULT_INTR
 32 
 33 
 34 
 35 #define TEST_ROUNDS    1    /* Number of loops that the Dma transfers run.*/
 36 #define DMA_LENGTH    1024    /* Length of the Dma Transfers */
 37 #define TIMEOUT_LIMIT     0x2000    /* Loop count for timeout */
 38 
 39 /**************************** Type Definitions *******************************/
 40 
 41 
 42 /***************** Macros (Inline Functions) Definitions *********************/
 43 
 44 
 45 /************************** Function Prototypes ******************************/
 46 
 47 int XDmaPs_Example_W_Intr(XScuGic *GicPtr, u16 DeviceId);
 48 int SetupInterruptSystem(XScuGic *GicPtr, XDmaPs *DmaPtr);
 49 void DmaDoneHandler(unsigned int Channel, XDmaPs_Cmd *DmaCmd,
 50             void *CallbackRef);
 51 
 52 /************************** Macro Definitions *****************************/
 53 
 54 
 55 /************************** Variable Definitions *****************************/
 56 #ifdef __ICCARM__
 57 #pragma data_alignment=32
 58 static int Src[DMA_LENGTH];
 59 static int Dst[DMA_LENGTH];
 60 #pragma data_alignment=4
 61 #else
 62 static int Src[DMA_LENGTH] __attribute__ ((aligned (32)));
 63 static int Dst[DMA_LENGTH] __attribute__ ((aligned (32)));
 64 #endif
 65 
 66 XDmaPs DmaInstance;
 67 #ifndef TESTAPP_GEN
 68 XScuGic GicInstance;
 69 #endif
 70 
 71 /****************************************************************************/
 72 /**
 73 *
 74 * This is the main function for the DmaPs interrupt example.
 75 *
 76 * @param    None.
 77 *
 78 * @return    XST_SUCCESS to indicate success, otherwise XST_FAILURE.
 79 *
 80 * @note        None.
 81 *
 82 ****************************************************************************/
 83 #ifndef TESTAPP_GEN
 84 int main(void)
 85 {
 86     int Status;
 87 
 88     Status = XDmaPs_Example_W_Intr(&GicInstance,DMA_DEVICE_ID);
 89     if (Status != XST_SUCCESS) {
 90         xil_printf("Error: XDMaPs_Example_W_Intr failed\r\n");
 91         return XST_FAILURE;
 92     }
 93 
 94     xil_printf("XDMaPs_Example_W_Intr passed\r\n");
 95     return XST_SUCCESS;
 96 
 97 }
 98 #endif
 99 
100 
101 /*****************************************************************************/
102 /**
103  *
104  * Interrupt Example to test the DMA.
105  *
106  * @param    DeviceId is the Device ID of the DMA controller.
107  *
108  * @return    XST_SUCCESS to indicate success, otherwise XST_FAILURE.
109  *
110  * @note    None.
111  *
112  ****************************************************************************/
113 int XDmaPs_Example_W_Intr(XScuGic *GicPtr, u16 DeviceId)
114 {
115     int Index;
116     unsigned int Channel = 0;
117     int Status;
118     int TestStatus;
119     int TestRound;
120     int TimeOutCnt;
121     volatile int Checked[XDMAPS_CHANNELS_PER_DEV];
122     XDmaPs_Config *DmaCfg;
123     XDmaPs *DmaInst = &DmaInstance;
124     XDmaPs_Cmd DmaCmd;
125 
126     memset(&DmaCmd, 0, sizeof(XDmaPs_Cmd));
127 
128     DmaCmd.ChanCtrl.SrcBurstSize = 4;
129     DmaCmd.ChanCtrl.SrcBurstLen = 4;
130     DmaCmd.ChanCtrl.SrcInc = 1;
131     DmaCmd.ChanCtrl.DstBurstSize = 4;
132     DmaCmd.ChanCtrl.DstBurstLen = 4;
133     DmaCmd.ChanCtrl.DstInc = 1;
134     DmaCmd.BD.SrcAddr = (u32) Src;
135     DmaCmd.BD.DstAddr = (u32) Dst;
136     DmaCmd.BD.Length = DMA_LENGTH * sizeof(int);
137 
138 
139     /*
140      * Initialize the DMA Driver
141      */
142     DmaCfg = XDmaPs_LookupConfig(DeviceId);
143     if (DmaCfg == NULL) {
144         return XST_FAILURE;
145     }
146 
147     Status = XDmaPs_CfgInitialize(DmaInst,
148                    DmaCfg,
149                    DmaCfg->BaseAddress);
150     if (Status != XST_SUCCESS) {
151         return XST_FAILURE;
152     }
153 
154 
155     /*
156      * Setup the interrupt system.
157      */
158     Status = SetupInterruptSystem(GicPtr, DmaInst);
159     if (Status != XST_SUCCESS) {
160         return XST_FAILURE;
161     }
162 
163 
164     TestStatus = XST_SUCCESS;
165 
166     for (TestRound = 0; TestRound ) {
167         xil_printf("Test round %d\r\n", TestRound);
168         for (Channel = 0;
169              Channel < XDMAPS_CHANNELS_PER_DEV;
170              Channel++) {
171 
172 
173             /* Initialize source */
174             for (Index = 0; Index )
175                 Src[Index] = DMA_LENGTH - Index;
176 
177             /* Clear destination */
178             for (Index = 0; Index )
179                 Dst[Index] = 0;
180 
181             Checked[Channel] = 0;
182 
183             /* Set the Done interrupt handler */
184             XDmaPs_SetDoneHandler(DmaInst,
185                            Channel,
186                            DmaDoneHandler,
187                            (void *)Checked);
188 
189 
190             Status = XDmaPs_Start(DmaInst, Channel, &DmaCmd, 0);
191             if (Status != XST_SUCCESS) {
192                 return XST_FAILURE;
193             }
194 
195             TimeOutCnt = 0;
196 
197             /* Now the DMA is done */
198             while (!Checked[Channel]
199                    && TimeOutCnt < TIMEOUT_LIMIT) {
200                 TimeOutCnt++;
201             }
202 
203             if (TimeOutCnt >= TIMEOUT_LIMIT) {
204                 TestStatus = XST_FAILURE;
205             }
206 
207             if (Checked[Channel] <0) {
208                 /* DMA controller failed */
209                 TestStatus = XST_FAILURE;
210             }
211         }
212     }
213 
214     return TestStatus;
215 
216 }
217 
218 
219 /******************************************************************************/
220 /**
221  *
222  * This function connects the interrupt handler of the interrupt controller to
223  * the processor.  This function is seperate to allow it to be customized for
224  * each application. Each processor or RTOS may require unique processing to
225  * connect the interrupt handler.
226  *
227  * @param    GicPtr is the GIC instance pointer.
228  * @param    DmaPtr is the DMA instance pointer.
229  *
230  * @return    None.
231  *
232  * @note    None.
233  *
234  ****************************************************************************/
235 int SetupInterruptSystem(XScuGic *GicPtr, XDmaPs *DmaPtr)
236 {
237     int Status;
238 #ifndef TESTAPP_GEN    
239     XScuGic_Config *GicConfig;
240 
241 
242     Xil_ExceptionInit();
243 
244     /*
245      * Initialize the interrupt controller driver so that it is ready to
246      * use.
247      */
248     GicCOnfig= XScuGic_LookupConfig(INTC_DEVICE_ID);
249     if (NULL == GicConfig) {
250         return XST_FAILURE;
251     }
252 
253     Status = XScuGic_CfgInitialize(GicPtr, GicConfig,
254                        GicConfig->CpuBaseAddress);
255     if (Status != XST_SUCCESS) {
256         return XST_FAILURE;
257     }
258 
259     /*
260      * Connect the interrupt controller interrupt handler to the hardware
261      * interrupt handling logic in the processor.
262      */
263     Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_IRQ_INT,
264                  (Xil_ExceptionHandler)XScuGic_InterruptHandler,
265                  GicPtr);
266 #endif
267     /*
268      * Connect the device driver handlers that will be called when an interrupt
269      * for the device occurs, the device driver handler performs the specific
270      * interrupt processing for the device
271      */
272 
273     /*
274      * Connect the Fault ISR
275      */
276     Status = XScuGic_Connect(GicPtr,
277                  DMA_FAULT_INTR,
278                  (Xil_InterruptHandler)XDmaPs_FaultISR,
279                  (void *)DmaPtr);
280     if (Status != XST_SUCCESS) {
281         return XST_FAILURE;
282     }
283 
284     /*
285      * Connect the Done ISR for all 8 channels of DMA 0
286      */
287     Status = XScuGic_Connect(GicPtr,
288                  DMA_DONE_INTR_0,
289                  (Xil_InterruptHandler)XDmaPs_DoneISR_0,
290                  (void *)DmaPtr);
291     Status |= XScuGic_Connect(GicPtr,
292                  DMA_DONE_INTR_1,
293                  (Xil_InterruptHandler)XDmaPs_DoneISR_1,
294                  (void *)DmaPtr);
295     Status |= XScuGic_Connect(GicPtr,
296                  DMA_DONE_INTR_2,
297                  (Xil_InterruptHandler)XDmaPs_DoneISR_2,
298                  (void *)DmaPtr);
299     Status |= XScuGic_Connect(GicPtr,
300                  DMA_DONE_INTR_3,
301                  (Xil_InterruptHandler)XDmaPs_DoneISR_3,
302                  (void *)DmaPtr);
303     Status |= XScuGic_Connect(GicPtr,
304                  DMA_DONE_INTR_4,
305                  (Xil_InterruptHandler)XDmaPs_DoneISR_4,
306                  (void *)DmaPtr);
307     Status |= XScuGic_Connect(GicPtr,
308                  DMA_DONE_INTR_5,
309                  (Xil_InterruptHandler)XDmaPs_DoneISR_5,
310                  (void *)DmaPtr);
311     Status |= XScuGic_Connect(GicPtr,
312                  DMA_DONE_INTR_6,
313                  (Xil_InterruptHandler)XDmaPs_DoneISR_6,
314                  (void *)DmaPtr);
315     Status |= XScuGic_Connect(GicPtr,
316                  DMA_DONE_INTR_7,
317                  (Xil_InterruptHandler)XDmaPs_DoneISR_7,
318                  (void *)DmaPtr);
319 
320     if (Status != XST_SUCCESS)
321         return XST_FAILURE;
322 
323     /*
324      * Enable the interrupts for the device
325      */
326     XScuGic_Enable(GicPtr, DMA_DONE_INTR_0);
327     XScuGic_Enable(GicPtr, DMA_DONE_INTR_1);
328     XScuGic_Enable(GicPtr, DMA_DONE_INTR_2);
329     XScuGic_Enable(GicPtr, DMA_DONE_INTR_3);
330     XScuGic_Enable(GicPtr, DMA_DONE_INTR_4);
331     XScuGic_Enable(GicPtr, DMA_DONE_INTR_5);
332     XScuGic_Enable(GicPtr, DMA_DONE_INTR_6);
333     XScuGic_Enable(GicPtr, DMA_DONE_INTR_7);
334     XScuGic_Enable(GicPtr, DMA_FAULT_INTR);
335 
336     Xil_ExceptionEnable();
337 
338     return XST_SUCCESS;
339 
340 }
341 
342 
343 /*****************************************************************************/
344 /**
345 *
346 * DmaDoneHandler.
347 *
348 * @param    Channel is the Channel number.
349 * @param    DmaCmd is the Dma Command.
350 * @param    CallbackRef is the callback reference data.
351 *
352 * @return    None.
353 *
354 * @note        None.
355 *
356 ******************************************************************************/
357 void DmaDoneHandler(unsigned int Channel, XDmaPs_Cmd *DmaCmd, void *CallbackRef)
358 {
359 
360     /* done handler */
361     volatile int *Checked = (volatile int *)CallbackRef;
362     int Index;
363     int Status = 1;
364     int *Src;
365     int *Dst;
366 
367     Src = (int *)DmaCmd->BD.SrcAddr;
368     Dst = (int *)DmaCmd->BD.DstAddr;
369 
370     /* DMA successful */
371     /* compare the src and dst buffer */
372     for (Index = 0; Index ) {
373         if ((Src[Index] != Dst[Index]) ||
374                 (Dst[Index] != DMA_LENGTH - Index)) {
375             Status = -XST_FAILURE;
376         }
377     }
378 
379 
380     Checked[Channel] = Status;
381 }
ps_dma_demo
推荐阅读
  • 本文介绍了一个来自AIZU ONLINE JUDGE平台的问题,即清洁机器人2.0。该问题来源于某次编程竞赛,涉及复杂的算法逻辑与实现技巧。 ... [详细]
  • 题目概述:Sereja 拥有一个由 n 个整数组成的数组 a1, a2, ..., an。他计划执行 m 项操作,这些操作包括更新数组中的特定元素、增加数组中所有元素的值,以及查询数组中的特定元素。 ... [详细]
  • Python网络编程:深入探讨TCP粘包问题及解决方案
    本文详细探讨了TCP协议下的粘包现象及其产生的原因,并提供了通过自定义报头解决粘包问题的具体实现方案。同时,对比了TCP与UDP协议在数据传输上的不同特性。 ... [详细]
  • 题目描述:Balala Power! 时间限制:4000/2000 MS (Java/Other) 内存限制:131072/131072 K (Java/Other)。题目背景及问题描述详见正文。 ... [详细]
  • Gradle 是 Android Studio 中默认的构建工具,了解其基本配置对于开发效率的提升至关重要。本文将详细介绍如何在 Gradle 中定义和使用共享变量,以确保项目的一致性和可维护性。 ... [详细]
  • 本文针对HDU 1042 N! 问题提供详细的解析和代码实现。题目要求计算给定整数N(0 ≤ N ≤ 10000)的阶乘N!。文章不仅提供了算法思路,还附上了C++语言的具体实现。 ... [详细]
  • 本文探讨了Linux环境下线程私有数据(Thread-Specific Data, TSD)的概念及其重要性,介绍了如何通过TSD技术避免多线程间全局变量冲突的问题,并提供了具体的实现方法和示例代码。 ... [详细]
  • 探讨了一个包含纯虚函数的C++代码片段,分析了其中的语法错误及逻辑问题,并提出了修正方案。 ... [详细]
  • 本文详细介绍了在Luat OS中如何实现C与Lua的混合编程,包括在C环境中运行Lua脚本、封装可被Lua调用的C语言库,以及C与Lua之间的数据交互方法。 ... [详细]
  • 函子(Functor)是函数式编程中的一个重要概念,它不仅是一个特殊的容器,还提供了一种优雅的方式来处理值和函数。本文将详细介绍函子的基本概念及其在函数式编程中的应用,包括如何通过函子控制副作用、处理异常以及进行异步操作。 ... [详细]
  • 在1995年,Simon Plouffe 发现了一种特殊的求和方法来表示某些常数。两年后,Bailey 和 Borwein 在他们的论文中发表了这一发现,这种方法被命名为 Bailey-Borwein-Plouffe (BBP) 公式。该问题要求计算圆周率 π 的第 n 个十六进制数字。 ... [详细]
  • 问题描述现在,不管开发一个多大的系统(至少我现在的部门是这样的),都会带一个日志功能;在实际开发过程中 ... [详细]
  • 本问题涉及在给定的无向图中寻找一个至少包含三个节点的环,该环上的节点不重复,并且环上所有边的长度之和最小。目标是找到并输出这个最小环的具体方案。 ... [详细]
  • 洛谷 P4009 汽车加油行驶问题 解析
    探讨了经典算法题目——汽车加油行驶问题,通过网络流和费用流的视角,深入解析了该问题的解决方案。本文将详细阐述如何利用最短路径算法解决这一问题,并提供详细的代码实现。 ... [详细]
  • 入门指南:使用FastRPC技术连接Qualcomm Hexagon DSP
    本文旨在为初学者提供关于如何使用FastRPC技术连接Qualcomm Hexagon DSP的基础知识。FastRPC技术允许开发者在本地客户端实现远程调用,从而简化Hexagon DSP的开发和调试过程。 ... [详细]
author-avatar
飞儿gxj_505
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有