当前位置: 亚洲城ca88 > ca88 > 正文

DMA使用解析及环路测验,SOC快速展开算法验证通

时间:2019-09-22 02:40来源:ca88
上篇该类别博文中描述W5500收到到上位机传输的数额,此后亟需将数据缓存起来。当数据量一点都不小如故其余数据带宽较高的境况下,片上缓存已无法满意须求,那时要求将大气数目

  上篇该类别博文中描述W5500收到到上位机传输的数额,此后亟需将数据缓存起来。当数据量一点都不小如故其余数据带宽较高的境况下,片上缓存已无法满意须求,那时要求将大气数目保存在外挂的DDLANDSDRAM中。

一、AXI DMA介绍

一、前言

  最简便易行的点子是行使Xilinx的读写地址库函数Xil_In32()和Xil_Out32(),当然不止帮衬32bit位宽,还包涵8 16和64bit。但这种措施每一趟读写都要占用CPU,不能够在读写的还要接受三回九转数据或许对从前的数目进一步管理,也就不可能变成类似FPGA逻辑设计中的“流水生产线结构”,此时前段多少缓存进度中,后段数据会被屏弃。所以,需求利用PS端CPU子系统内的专项使用硬件DMA完成急迅的批量数码搬移职业。

  本篇博文汇报AXI DMA的局地行使总计,硬件IP子系统搭建与SDK C代码封装参照他事他说加以考察米联客ZYNQ教程。若想让ZYNQ的PS与PL两有的高速数据传输,须要选拔PS的HP接口通过AXI_DMA实现多少搬移,那正适合PG021 AXI DMA v7.1 LogiCORE IP Product Guide中介绍的AXI DMA的选择场景:The AXI DMA provides high-speed data movement between system memory and an AXI4-Stream-based target IP such as AXI Ethernet.

  利用FPGA设总结法长期以来都以看好,同样也是难点。将复杂的数学公式 模型通过硬件系统来搭建,在低延时 高并行性等优势背后强大拉长了设计难度和开荒周期。Xilinx公司的sysGen(system generator)工具扩张了MATLAB的simulink,提供比非常多IP Catalog中绝非的底蕴模块和针对性DSP应用的硬件模型。程序猿利用丰硕的模块和MATLAB强大的数目管理及可视化工夫能够更迅捷到位规划与虚假验证专门的学业。

ca88 1

  如图,AXI DMA重要总结Memory Map和 Stream两有的接口,后面一个连接PS子系统,前面一个则连接带有流接口的PL IP核。

二、sysGen算法系统规划

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

ca88 2

  本文以个最轻松易行的例证陈述利用sysGen搭建算法IP核,并集成到IP Integrator中作为ZYNQ PS端CPU的“定制外设”。仅用于测验目标。设计供给:在sysGen中搭建系统,将输入定点整数数据*2后输出,输入位宽为8bit。

ca88 3ca88 4

  其最轻巧易行的事平素贮存器格局(Simple DMA),这里须求注意地址对齐的主题素材:当未有使能地址重对齐的意况下,假若AXI Memory Map数据位宽是32bit,则搬移数据所在地方必得在0x0,0x4,0x8等初始地址上。接下来关怀DMA IP核配置界面重要参数:

ca88 5

  1 #include <stdio.h>  2 #include <stdlib.h>  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 failedrn"); 91         return XST_FAILURE; 92     } 93  94     xil_printf("XDMaPs_Example_W_Intr passedrn"); 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 =  Src;135     DmaCmd.BD.DstAddr =  Dst;136     DmaCmd.BD.Length = DMA_LENGTH * sizeof(int);137 138 139     /*140      * Initialize the DMA Driver141      */142     DmaCfg = XDmaPs_LookupConfig;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 < TEST_ROUNDS; TestRound  ) {167         xil_printf("Test round %drn", TestRound);168         for (Channel = 0;169              Channel < XDMAPS_CHANNELS_PER_DEV;170              Channel  ) {171 172 173             /* Initialize source */174             for (Index = 0; Index < DMA_LENGTH; Index  )175                 Src[Index] = DMA_LENGTH - Index;176 177             /* Clear destination */178             for (Index = 0; Index < DMA_LENGTH; 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 to223  * the processor.  This function is seperate to allow it to be customized for224  * each application. Each processor or RTOS may require unique processing to225  * 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 to246      * 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 hardware261      * interrupt handling logic in the processor.262      */263     Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_IRQ_INT,264                  (Xil_ExceptionHandler)XScuGic_InterruptHandler,265                  GicPtr);266 #endif267     /*268      * Connect the device driver handlers that will be called when an interrupt269      * for the device occurs, the device driver handler performs the specific270      * interrupt processing for the device271      */272 273     /*274      * Connect the Fault ISR275      */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 0286      */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 device325      */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 < DMA_LENGTH; 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 }

ca88 6

  在System Generator token中设定仿真步长为1sec。点击须求观察的数字信号连线,右击选拔Xilinx add to viewer。运维仿真并运维Xilinx waveform viewer:

ps_dma_demo

  AXI DMA能够有五个传输方向:读通道和写通道,依次为MM2S和S2MM方向。也正是说“读”和“写”是DMA主动对CPU发起的操作。着重查阅以下多少个参数:

ca88 7

  其实demo中做的操作极其简单,仅仅是概念了多个数组Src和Dst,之后选拔PS_DMA将Src中多少搬移到Dst中,搬移完毕后跻身暂停函数相比较两有个别地点数据是或不是一律。Xilinx的SDK软件代码有定点的覆辙,“上有政策,下有对策”,大家得以将其封装成固定格式的一个个子函数,方便未来调用。这里把任何工程分为:系统暂停,PS_DMA专有中断以及主函数八个部分。

1 Width of Buffer Length Register:

  本质上便是调用Vivado的XSim工具实行行为仿真。仿真结果可知实现预期目的,现双击System Generator token ,选取Compiliation类型为IP Catalog并勾选Create testbench,按下Generate生成IP核。

ca88 8ca88 9

  在间接寄放器形式下,它钦点在MM2S_LENGTH和S2MM_LENGTH贮存器的得力比特数。MM2S_LENGTH贮存器钦点了MM2S坦途传输数据字节数,当CPU写入非零值时最初开展PS到PL的多寡搬移,而S2MM_LENGTH对应另一个数据流方向。比特数直接与相应贮存器可写入的最大数直接有关,传输最大字节数= 2^(Width of Buffer Length Register)。此处保持默许14bit,也正是说运行DMA传输的最大数据量是16384byte。

ca88 10

 1 #include "xscugic.h" 2 #include "sys_intr.h" 3  4 int sys_IntrInit(XScuGic *GicPtr) 5 { 6     XScuGic_Config *GicConfig; 7     /* 8     * Initialize the interrupt controller driver so that it is ready to 9     * use.10     */11     int Status;12     GicConfig = XScuGic_LookupConfig(INTC_DEVICE_ID);13     if (NULL == GicConfig) {14         return XST_FAILURE;15     }16 17     Status = XScuGic_CfgInitialize(GicPtr, GicConfig,18                        GicConfig->CpuBaseAddress);19     if (Status != XST_SUCCESS) {20         return XST_FAILURE;21     }22     return XST_SUCCESS;23 }24 25 void setupIntrException(XScuGic *GicPtr)26 {27     Xil_ExceptionInit();28     /*29     * Connect the interrupt controller interrupt handler to the hardware30     * interrupt handling logic in the processor.31     */32     Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_IRQ_INT,33                    (Xil_ExceptionHandler)XScuGic_InterruptHandler,34                    GicPtr);35     Xil_ExceptionEnable();36 }

2 Memory Map Data Width:

三、仿真测量检验

sys_intr.cca88 11ca88 12

  该参数内定了Memory Map侧数据接口宽度,选定32bit后搬移数据所在内部存款和储蓄器地址必需与4对齐。

  依据User Guide介绍sysGen是“周期和比特精准的”,大家依旧在Vivado蒙受下再一次印证下。netlist文件夹内子文件夹ip_catalog中为IP核示例工程,由于自动生成了testbench,展开后直接举办行为仿真。sysGen在创制testbench时会将由此gatein和gateout的数据存款和储蓄到文件中,testbench举办的专业为:将gatein数据作为测验慰勉送入到相应安插输入端口,之后把规划输出获得结果与gateout文件数据开展逐项相比从而证实陈设是或不是与sysGen碰到下仿真结果一律。

1 #ifndef SRC_SYS_INTR_H_2 #define SRC_SYS_INTR_H_3 4 #define INTC_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID5 6 int sys_IntrInit(XScuGic *GicPtr);7 void setupIntrException(XScuGic *GicPtr);8 9 #endif /* SRC_SYS_INTR_H_ */

3 Max Burst Size:

  开采个相比较风趣的情景,自动生成的testbench中clock生成并约束的50MHz,而是以为进行了举行。

sys_intr.hca88 13ca88 14

  在此以前在授课PS子系统里头的DMA时介绍过DMA的Burst概念,即分批次传输数据块。官方IP核文书档案解释为:

ca88 15

  1 #include "xil_types.h"  2 #include "xdmaps.h"  3 #include "xscugic.h"  4 #include "psdma_intr.h"  5   6 int PS_DMA_IntrInit(XDmaPs *DmaInst,u16 DeviceId)  7 {  8     /*  9     * Initialize the DMA Driver 10     */ 11     int Status; 12     XDmaPs_Config *DmaCfg = NULL; 13     DmaCfg = XDmaPs_LookupConfig; 14     if (DmaCfg == NULL) { 15         return XST_FAILURE; 16     } 17  18     Status = XDmaPs_CfgInitialize(DmaInst, 19                    DmaCfg, 20                    DmaCfg->BaseAddress); 21     if (Status != XST_SUCCESS) { 22         return XST_FAILURE; 23     } 24     return XST_SUCCESS; 25 } 26  27 int PS_DMA_SetupIntr(XScuGic *GicPtr,XDmaPs *DmaPtr,unsigned Channel) 28 { 29     int Status; 30     /* 31     * Connect the device driver handlers that will be called when an interrupt 32     * for the device occurs, the device driver handler performs the specific 33     * interrupt processing for the device 34     */ 35  36     /* 37     * Connect the Fault ISR 38     */ 39     Status = XScuGic_Connect(GicPtr, 40                  DMA_FAULT_INTR, 41                  (Xil_InterruptHandler)XDmaPs_FaultISR, 42                  (void *)DmaPtr); 43     if (Status != XST_SUCCESS) { 44         return XST_FAILURE; 45     } 46  47     /* 48      * Connect the Done ISR for all 8 channels of DMA 0 49      */ 50     Status = XScuGic_Connect(GicPtr, 51                  DMA_DONE_INTR_0, 52                  (Xil_InterruptHandler)XDmaPs_DoneISR_0, 53                  (void *)DmaPtr); 54     /*Status |= XScuGic_Connect(GicPtr, 55                  DMA_DONE_INTR_1, 56                  (Xil_InterruptHandler)XDmaPs_DoneISR_1, 57                  DmaPtr); 58     Status |= XScuGic_Connect(GicPtr, 59                  DMA_DONE_INTR_2, 60                  (Xil_InterruptHandler)XDmaPs_DoneISR_2, 61                  DmaPtr); 62     Status |= XScuGic_Connect(GicPtr, 63                  DMA_DONE_INTR_3, 64                  (Xil_InterruptHandler)XDmaPs_DoneISR_3, 65                  DmaPtr); 66     Status |= XScuGic_Connect(GicPtr, 67                  DMA_DONE_INTR_4, 68                  (Xil_InterruptHandler)XDmaPs_DoneISR_4, 69                  DmaPtr); 70     Status |= XScuGic_Connect(GicPtr, 71                  DMA_DONE_INTR_5, 72                  (Xil_InterruptHandler)XDmaPs_DoneISR_5, 73                  DmaPtr); 74     Status |= XScuGic_Connect(GicPtr, 75                  DMA_DONE_INTR_6, 76                  (Xil_InterruptHandler)XDmaPs_DoneISR_6, 77                  DmaPtr); 78     Status |= XScuGic_Connect(GicPtr, 79                  DMA_DONE_INTR_7, 80                  (Xil_InterruptHandler)XDmaPs_DoneISR_7, 81                  DmaPtr);*/ 82  83     if (Status != XST_SUCCESS) 84         return XST_FAILURE; 85  86     /* Set the Done interrupt handler */ 87     XDmaPs_SetDoneHandler(DmaPtr, 88                 Channel,//Channel 89                 DmaDoneHandler,//真正的中断函数 90                 (void *)Checked); 91  92     /* 93      * Enable the interrupts for the device 94      */ 95     XScuGic_Enable(GicPtr, DMA_DONE_INTR_0); 96     /* 97     XScuGic_Enable(GicPtr, DMA_DONE_INTR_1); 98     XScuGic_Enable(GicPtr, DMA_DONE_INTR_2); 99     XScuGic_Enable(GicPtr, DMA_DONE_INTR_3);100     XScuGic_Enable(GicPtr, DMA_DONE_INTR_4);101     XScuGic_Enable(GicPtr, DMA_DONE_INTR_5);102     XScuGic_Enable(GicPtr, DMA_DONE_INTR_6);103     XScuGic_Enable(GicPtr, DMA_DONE_INTR_7);*/104     XScuGic_Enable(GicPtr, DMA_FAULT_INTR);105 106     return XST_SUCCESS;107 }108 109 void DmaDoneHandler(unsigned int Channel, XDmaPs_Cmd *DmaCmd, void *CallbackRef)110 {111 112     /* done handler */113     volatile int *Checked = (volatile int *)CallbackRef;114     //int Index;115     int Status = 1;116 117     xil_printf("Enter into the interruptn");118     Checked[Channel] = Status;119 }120 121 void PS_DMA_InitPara(XDmaPs_Cmd* DmaCmd)122 {123 124     memset(DmaCmd, 0, sizeof(XDmaPs_Cmd));125 126     DmaCmd->ChanCtrl.SrcBurstSize = 4;127     DmaCmd->ChanCtrl.SrcBurstLen = 4;128     DmaCmd->ChanCtrl.SrcInc = 1;129     DmaCmd->ChanCtrl.DstBurstSize = 4;130     DmaCmd->ChanCtrl.DstBurstLen = 4;131     DmaCmd->ChanCtrl.DstInc = 1;132     DmaCmd->BD.SrcAddr =  Src;133     DmaCmd->BD.DstAddr =  DDR_BASEADDR;//Dst134     DmaCmd->BD.Length = DMA_LENGTH * sizeof(int);135 }

ca88 16

  仿真波形如图:

psdma_intr.cca88 17ca88 18

  精晓起来burst size鲜明了产生周期的最大数值,也正是burst size越大,突发粒度越大(单次传输的多寡个数越来越多)。那与PS端DMA有所区别,显明与 PS DMA的burst length意义周边。作者也进行过尝试,当运营传输数据量相同时,burst size设置极大动静下,每批次传输数据量越来越多。

ca88 19

 1 #ifndef SRC_PSDMA_INTR_H_ 2 #define SRC_PSDMA_INTR_H_ 3  4 #define DMA_DONE_INTR_0            XPAR_XDMAPS_0_DONE_INTR_0 5 #define DMA_DONE_INTR_1            XPAR_XDMAPS_0_DONE_INTR_1 6 #define DMA_DONE_INTR_2            XPAR_XDMAPS_0_DONE_INTR_2 7 #define DMA_DONE_INTR_3            XPAR_XDMAPS_0_DONE_INTR_3 8 #define DMA_DONE_INTR_4            XPAR_XDMAPS_0_DONE_INTR_4 9 #define DMA_DONE_INTR_5            XPAR_XDMAPS_0_DONE_INTR_510 #define DMA_DONE_INTR_6            XPAR_XDMAPS_0_DONE_INTR_611 #define DMA_DONE_INTR_7            XPAR_XDMAPS_0_DONE_INTR_712 #define DMA_FAULT_INTR            XPAR_XDMAPS_0_FAULT_INTR13 14 #define DDR_BASEADDR 0x00600000//XPAR_PS7_DDR_0_S_AXI_BASEADDR 0x0010000015 #define DMA_LENGTH    1024    /* Length of the Dma Transfers */16 17 int Src[DMA_LENGTH] __attribute__ ((aligned (32)));18 volatile int Checked[XDMAPS_CHANNELS_PER_DEV];19 20 int PS_DMA_IntrInit(XDmaPs *DmaInst,u16 DeviceId);21 int PS_DMA_SetupIntr(XScuGic *GicPtr,XDmaPs *DmaPtr,unsigned Channel);22 void DmaDoneHandler(unsigned int Channel, XDmaPs_Cmd *DmaCmd, void *CallbackRef);23 void PS_DMA_InitPara(XDmaPs_Cmd* DmaCmd);24 25 #endif /* SRC_PSDMA_INTR_H_ */

二、AXI DMA Loop IP子系统

  将clock处改换为50MHz后,经过测验开采只要系统一齐先就输入数据,前多少个数据尚未被真正管理,输出错误。也许是软件BUG吧,可是这种情况也非常的少见,实际系统中输入数据大约情况会运营一段时间后才输入。这里等待100ns后再开发银行clock翻转:

psdma_intr.hca88 20ca88 21

  在利用ZYNQ搭建系统时,常常索要运用种种IP核做所谓的“总括加快”,将重复性高 计算量大 占用相当的大CPU财富的底层处理交给各类IP核完毕。那时PS ->DMA ->PL -> DMA -> PS的环路架构非常适用。这里运用AXI Stream Data FIFO取代自定义IP核作为示范,硬件IP子系统如下:

ca88 22

  1 #include <stdio.h>  2 #include <stdlib.h>  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 #include "sys_intr.h" 15 #include "psdma_intr.h" 16  17  18 #define DMA_DEVICE_ID             XPAR_XDMAPS_1_DEVICE_ID 19 #define INTC_DEVICE_ID            XPAR_SCUGIC_SINGLE_DEVICE_ID 20  21  22 #define TEST_ROUNDS    1    /* Number of loops that the Dma transfers run.*/ 23 #define TIMEOUT_LIMIT     0x2000    /* Loop count for timeout */ 24  25  26 static XScuGic GicInstance; 27 static XDmaPs DmaInstance; 28 static XDmaPs_Cmd DmaCmd; 29 unsigned int Channel = 0; 30  31 /************************** Function Prototypes ******************************/ 32  33 int PS_DMA_WriteTest(); 34 int SetupInterruptSystem(XScuGic *GicPtr, XDmaPs *DmaPtr); 35 void DmaDoneHandler(unsigned int Channel, XDmaPs_Cmd *DmaCmd, 36             void *CallbackRef); 37 int dataCheck(u32 baseAddr,u32 len); 38 int systemInit(XScuGic *GicPtr,u16 DeviceId); 39  40  41 int main(void) 42 { 43     int Status; 44     Status = systemInit(&GicInstance,DMA_DEVICE_ID); 45     if (Status != XST_SUCCESS) { 46             xil_printf("System initialization is failedrn"); 47             return XST_FAILURE; 48         } 49  50     Status = PS_DMA_WriteTest(); 51     if (Status != XST_SUCCESS) { 52         xil_printf("Error: XDMaPs_Example_W_Intr failedrn"); 53         return XST_FAILURE; 54     } 55     xil_printf("Checking data...n"); 56     Status = dataCheck(DDR_BASEADDR,DMA_LENGTH); 57     if(Status != XST_SUCCESS) 58     { 59         xil_printf("Error:check failedn"); 60         return XST_FAILURE; 61     } 62  63     xil_printf("Writing data to DDR using DMA test passed!rn"); 64     return XST_SUCCESS; 65  66 } 67  68 int dataCheck(u32 baseAddr,u32 len) 69 { 70     u32 DDR_ReadData[1024]; 71     int i; 72     for(i=0;i<len;i  ) 73     { 74         DDR_ReadData[i] = Xil_In32(baseAddr i*4); 75         if(DDR_ReadData[i]!=Src[i]) 76             return XST_FAILURE; 77         //else  //将写入DDR数据读回 并打印 78         //    xil_printf("data at %x is %dn",baseAddr i*4,DDR_ReadData[i]); 79     } 80     return XST_SUCCESS; 81 } 82  83  84 /*****************************************************************************/ 85 /** 86  * 87  * Interrupt Example to test the DMA. 88  * 89  * @param    DeviceId is the Device ID of the DMA controller. 90  * 91  * @return    XST_SUCCESS to indicate success, otherwise XST_FAILURE. 92  * 93  * @note    None. 94  * 95  ****************************************************************************/ 96 int PS_DMA_WriteTest() 97 { 98     int Index; 99     int Status;100     int TestStatus;101     int TestRound;102     int TimeOutCnt;103 104     TestStatus = XST_SUCCESS;105 106     for (TestRound = 0; TestRound < TEST_ROUNDS; TestRound  ) {107         xil_printf("Test round %drn", TestRound);108         for (Channel = 0;Channel < 1;Channel  )109         {110             /* Initialize source */111             for (Index = 0; Index < DMA_LENGTH; Index  )112                 Src[Index] = DMA_LENGTH - Index;113 114             Checked[Channel] = 0;115 116             Status = XDmaPs_Start(&DmaInstance, Channel, &DmaCmd, 0);117             if (Status != XST_SUCCESS) {118                 xil_printf("Starting the DMA is failed.n");119                 return XST_FAILURE;120             }121             xil_printf("Starting the DMA is successful.n");122             TimeOutCnt = 0;123 124             while (!Checked[Channel]125                    && TimeOutCnt < TIMEOUT_LIMIT) {126                 TimeOutCnt  ;127             }128             /* Now the DMA is done */129             xil_printf("Jump out of the interruptn");130             if (TimeOutCnt >= TIMEOUT_LIMIT) {131                 xil_printf("Overtime!n");132                 TestStatus = XST_FAILURE;133             }134 135             if (Checked[Channel] < 0) {136                 /* DMA controller failed */137                 xil_printf("Checking failure!n");138                 TestStatus = XST_FAILURE;139             }140         }141     }142 143     return TestStatus;144 145 }146 147 int systemInit(XScuGic *GicPtr,u16 DeviceId)148 {149     xil_printf("Start to initialize interrupt system.n");150 151     PS_DMA_InitPara(&DmaCmd);//主要设置DMA的源目的地址152     //xil_printf("Configuring DMA parameters is successful.n");153 154     int Status;155 156     Status = PS_DMA_IntrInit(&DmaInstance,DeviceId);157     if (Status != XST_SUCCESS) {158             xil_printf("DMA initialization is failed.n");159             return XST_FAILURE;160         }161     //xil_printf("DMA initialization is successful.n");162 163     Status = sys_IntrInit;164     if (Status != XST_SUCCESS) {165             xil_printf("Initialization of the interrupt system  is failed.n");166             return XST_FAILURE;167         }168     //xil_printf("Initialization of the interrupt system  is successful.n");169 170     setupIntrException;171 172     Status = PS_DMA_SetupIntr(GicPtr,&DmaInstance,Channel);//////////////////////////DMA中断入口///////////////////////173     if (Status != XST_SUCCESS) {174         xil_printf("Setting up DMA interrupt is failed.n");175         return XST_FAILURE;176     }177     //xil_printf("Setting up DMA interrupt is successful.n");178 179     xil_printf("System initialization is finished.n");180     xil_printf("------------------------------------------n");181     return XST_SUCCESS;182 }

ca88 23

  退换后仿真波形:

main.c

三、SDK 官方demo解析

ca88 24

  上述代码的包装格局参考了米联客教程中的思想。先表明系统暂停部分:sys_IntrInit()函数中进行查找表配置和脚刹踏板调控器初阶化操作,setupIntrException()函数担当使能暂停分外管理。再来讲说PS_DMA中断部分:PS_DMA_IntrInit()函数与系统中断中sys_IntrInit()从操作到格式大概做到同样,亦是查找表配置和DMA的早先化。PS_DMA_SetupIntr()函数完结了中断源和脚刹踏板调控器的总是和安装中断管理器,以及脚刹踏板使能,也正是负有PS_DMA的专项使用中断操作。

  率先剖析下官方的demo。ca88 25

四、AXI-Stream总线情势IP

  PS_DMA_SetupIntr()内最关键的一对是XDmaPs_SetDoneHandler(),其也正是二个调用中断函数的通用管理框架,它的第4个参数DoneHandler才是实在的间歇处理函数。这里涉及到C语言的高档次和品级话题:函数通过函数指针调用另二个函数,被函数指针调用的函数便是无独有偶讲的“回调函数”了。指针调用函数的章程兼顾了前后相继的通用架商谈灵活性,具体参照他事他说加以考察小说:**不懂C语言回调函数,那就看那篇作品吧!

ca88 26ca88 27

  到此算法IP的规划与认证结束。如若想将这几个IP核导入到IP Integrator中作为CPU的外设,其接口必得知足AXI总线规范,由此回到sysGen中改造端口名称和位宽。端口要符合AXI-Stream标准数字信号名称,位宽为8bit整数倍。

  • 简书在该程序中,中断回调函数为DmaDoneHandler()。
  1 /******************************************************************************  2 *  3 * Copyright  2010 - 2016 Xilinx, Inc.  All rights reserved.  4 *  5 * Permission is hereby granted, free of charge, to any person obtaining a copy  6 * of this software and associated documentation files (the "Software"), to deal  7 * in the Software without restriction, including without limitation the rights  8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell  9 * copies of the Software, and to permit persons to whom the Software is 10 * furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice shall be included in 13 * all copies or substantial portions of the Software. 14 * 15 * Use of the Software is limited solely to applications: 16 *  running on a Xilinx device, or 17 *  that interact with a Xilinx device through a bus or interconnect. 18 * 19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 22 * XILINX  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF 24 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 25 * SOFTWARE. 26 * 27 * Except as contained in this notice, the name of the Xilinx shall not be used 28 * in advertising or otherwise to promote the sale, use or other dealings in 29 * this Software without prior written authorization from Xilinx. 30 * 31 ******************************************************************************/ 32 /*****************************************************************************/ 33 /** 34  * 35  * @file xaxidma_example_simple_intr.c 36  * 37  * This file demonstrates how to use the xaxidma driver on the Xilinx AXI 38  * DMA core  to transfer packets.in interrupt mode when the AXIDMA core 39  * is configured in simple mode 40  * 41  * This code assumes a loopback hardware widget is connected to the AXI DMA 42  * core for data packet loopback. 43  * 44  * To see the debug print, you need a Uart16550 or uartlite in your system, 45  * and please set "-DDEBUG" in your compiler options. You need to rebuild your 46  * software executable. 47  * 48  * Make sure that MEMORY_BASE is defined properly as per the HW system. The 49  * h/w system built in Area mode has a maximum DDR memory limit of 64MB. In 50  * throughput mode, it is 512MB.  These limits are need to ensured for 51  * proper operation of this code. 52  * 53  * 54  * <pre> 55  * MODIFICATION HISTORY: 56  * 57  * Ver   Who  Date     Changes 58  * ----- ---- -------- ------------------------------------------------------- 59  * 4.00a rkv  02/22/11 New example created for simple DMA, this example is for 60  *                  simple DMA,Added interrupt support for Zynq. 61  * 4.00a srt  08/04/11 Changed a typo in the RxIntrHandler, changed 62  *               XAXIDMA_DMA_TO_DEVICE to XAXIDMA_DEVICE_TO_DMA 63  * 5.00a srt  03/06/12 Added Flushing and Invalidation of Caches to fix CRs 64  *               648103, 648701. 65  *               Added V7 DDR Base Address to fix CR 649405. 66  * 6.00a srt  03/27/12 Changed API calls to support MCDMA driver. 67  * 7.00a srt  06/18/12 API calls are reverted back for backward compatibility. 68  * 7.01a srt  11/02/12 Buffer sizes (Tx and Rx) are modified to meet maximum 69  *               DDR memory limit of the h/w system built with Area mode 70  * 7.02a srt  03/01/13 Updated DDR base address for IPI designs (CR 703656). 71  * 9.1   adk  01/07/16 Updated DDR base address for Ultrascale (CR 799532) and 72  *               removed the defines for S6/V6. 73  * 9.2   vak  15/04/16 Fixed compilation warnings in the example 74  * </pre> 75  * 76  * *************************************************************************** 77  */ 78  79 /***************************** Include Files *********************************/ 80  81 #include "xaxidma.h" 82 #include "xparameters.h" 83 #include "xil_exception.h" 84 #include "xdebug.h" 85  86 #ifdef XPAR_UARTNS550_0_BASEADDR 87 #include "xuartns550_l.h"       /* to use uartns550 */ 88 #endif 89  90  91 #ifdef XPAR_INTC_0_DEVICE_ID 92  #include "xintc.h" 93 #else 94  #include "xscugic.h" 95 #endif 96  97 /************************** Constant Definitions *****************************/ 98  99 /*100  * Device hardware build related constants.101  */102 103 #define DMA_DEV_ID        XPAR_AXIDMA_0_DEVICE_ID104 105 #ifdef XPAR_AXI_7SDDR_0_S_AXI_BASEADDR106 #define DDR_BASE_ADDR        XPAR_AXI_7SDDR_0_S_AXI_BASEADDR107 #elif XPAR_MIG7SERIES_0_BASEADDR108 #define DDR_BASE_ADDR    XPAR_MIG7SERIES_0_BASEADDR109 #elif XPAR_MIG_0_BASEADDR110 #define DDR_BASE_ADDR    XPAR_MIG_0_BASEADDR111 #elif XPAR_PSU_DDR_0_S_AXI_BASEADDR112 #define DDR_BASE_ADDR    XPAR_PSU_DDR_0_S_AXI_BASEADDR113 #endif114 115 #ifndef DDR_BASE_ADDR116 #warning CHECK FOR THE VALID DDR ADDRESS IN XPARAMETERS.H, 117         DEFAULT SET TO 0x01000000118 #define MEM_BASE_ADDR        0x01000000119 #else120 #define MEM_BASE_ADDR        (DDR_BASE_ADDR   0x1000000)121 #endif122 123 #ifdef XPAR_INTC_0_DEVICE_ID124 #define RX_INTR_ID        XPAR_INTC_0_AXIDMA_0_S2MM_INTROUT_VEC_ID125 #define TX_INTR_ID        XPAR_INTC_0_AXIDMA_0_MM2S_INTROUT_VEC_ID126 #else127 #define RX_INTR_ID        XPAR_FABRIC_AXIDMA_0_S2MM_INTROUT_VEC_ID128 #define TX_INTR_ID        XPAR_FABRIC_AXIDMA_0_MM2S_INTROUT_VEC_ID129 #endif130 131 #define TX_BUFFER_BASE        (MEM_BASE_ADDR   0x00100000)132 #define RX_BUFFER_BASE        (MEM_BASE_ADDR   0x00300000)133 #define RX_BUFFER_HIGH        (MEM_BASE_ADDR   0x004FFFFF)134 135 #ifdef XPAR_INTC_0_DEVICE_ID136 #define INTC_DEVICE_ID          XPAR_INTC_0_DEVICE_ID137 #else138 #define INTC_DEVICE_ID          XPAR_SCUGIC_SINGLE_DEVICE_ID139 #endif140 141 #ifdef XPAR_INTC_0_DEVICE_ID142  #define INTC        XIntc143  #define INTC_HANDLER    XIntc_InterruptHandler144 #else145  #define INTC        XScuGic146  #define INTC_HANDLER    XScuGic_InterruptHandler147 #endif148 149 150 /* Timeout loop counter for reset151  */152 #define RESET_TIMEOUT_COUNTER    10000153 154 #define TEST_START_VALUE    0xC155 /*156  * Buffer and Buffer Descriptor related constant definition157  */158 #define MAX_PKT_LEN        0x100159 160 #define NUMBER_OF_TRANSFERS    10161 162 /* The interrupt coalescing threshold and delay timer threshold163  * Valid range is 1 to 255164  *165  * We set the coalescing threshold to be the total number of packets.166  * The receive side will only get one completion interrupt for this example.167  */168 169 /**************************** Type Definitions *******************************/170 171 172 /***************** Macros (Inline Functions) Definitions *********************/173 174 175 /************************** Function Prototypes ******************************/176 #ifndef DEBUG177 extern void xil_printf(const char *format, ...);178 #endif179 180 #ifdef XPAR_UARTNS550_0_BASEADDR181 static void Uart550_Setup(void);182 #endif183 184 static int CheckData(int Length, u8 StartValue);185 static void TxIntrHandler(void *Callback);186 static void RxIntrHandler(void *Callback);187 188 189 190 191 static int SetupIntrSystem(INTC * IntcInstancePtr,192                XAxiDma * AxiDmaPtr, u16 TxIntrId, u16 RxIntrId);193 static void DisableIntrSystem(INTC * IntcInstancePtr,194                     u16 TxIntrId, u16 RxIntrId);195 196 197 198 /************************** Variable Definitions *****************************/199 /*200  * Device instance definitions201  */202 203 204 static XAxiDma AxiDma;        /* Instance of the XAxiDma */205 206 static INTC Intc;    /* Instance of the Interrupt Controller */207 208 /*209  * Flags interrupt handlers use to notify the application context the events.210  */211 volatile int TxDone;212 volatile int RxDone;213 volatile int Error;214 215 /*****************************************************************************/216 /**217 *218 * Main function219 *220 * This function is the main entry of the interrupt test. It does the following:221 *    Set up the output terminal if UART16550 is in the hardware build222 *    Initialize the DMA engine223 *    Set up Tx and Rx channels224 *    Set up the interrupt system for the Tx and Rx interrupts225 *    Submit a transfer226 *    Wait for the transfer to finish227 *    Check transfer status228 *    Disable Tx and Rx interrupts229 *    Print test status and exit230 *231 * @param    None232 *233 * @return234 *        - XST_SUCCESS if example finishes successfully235 *        - XST_FAILURE if example fails.236 *237 * @note        None.238 *239 ******************************************************************************/240 int main(void)241 {242     int Status;243     XAxiDma_Config *Config;244     int Tries = NUMBER_OF_TRANSFERS;245     int Index;246     u8 *TxBufferPtr;247     u8 *RxBufferPtr;248     u8 Value;249 250     TxBufferPtr = (u8 *)TX_BUFFER_BASE ;251     RxBufferPtr = (u8 *)RX_BUFFER_BASE;252     /* Initial setup for Uart16550 */253 #ifdef XPAR_UARTNS550_0_BASEADDR254 255     Uart550_Setup();256 257 #endif258 259     xil_printf("rn--- Entering main() --- rn");260 261     Config = XAxiDma_LookupConfig(DMA_DEV_ID);262     if (!Config) {263         xil_printf("No config found for %drn", DMA_DEV_ID);264 265         return XST_FAILURE;266     }267 268     /* Initialize DMA engine */269     Status = XAxiDma_CfgInitialize(&AxiDma, Config);270 271     if (Status != XST_SUCCESS) {272         xil_printf("Initialization failed %drn", Status);273         return XST_FAILURE;274     }275 276     if(XAxiDma_HasSg(&AxiDma)){277         xil_printf("Device configured as SG mode rn");278         return XST_FAILURE;279     }280 281     /* Set up Interrupt system  */282     Status = SetupIntrSystem(&Intc, &AxiDma, TX_INTR_ID, RX_INTR_ID);283     if (Status != XST_SUCCESS) {284 285         xil_printf("Failed intr setuprn");286         return XST_FAILURE;287     }288 289     /* Disable all interrupts before setup */290 291     XAxiDma_IntrDisable(&AxiDma, XAXIDMA_IRQ_ALL_MASK,292                         XAXIDMA_DMA_TO_DEVICE);293 294     XAxiDma_IntrDisable(&AxiDma, XAXIDMA_IRQ_ALL_MASK,295                 XAXIDMA_DEVICE_TO_DMA);296 297     /* Enable all interrupts */298     XAxiDma_IntrEnable(&AxiDma, XAXIDMA_IRQ_ALL_MASK,299                             XAXIDMA_DMA_TO_DEVICE);300 301 302     XAxiDma_IntrEnable(&AxiDma, XAXIDMA_IRQ_ALL_MASK,303                             XAXIDMA_DEVICE_TO_DMA);304 305     /* Initialize flags before start transfer test  */306     TxDone = 0;307     RxDone = 0;308     Error = 0;309 310     Value = TEST_START_VALUE;311 312     for(Index = 0; Index < MAX_PKT_LEN; Index   ) {313             TxBufferPtr[Index] = Value;314 315             Value = (Value   1) & 0xFF;316     }317 318     /* Flush the SrcBuffer before the DMA transfer, in case the Data Cache319      * is enabled320      */321     Xil_DCacheFlushRangeTxBufferPtr, MAX_PKT_LEN);322 #ifdef __aarch64__323     Xil_DCacheFlushRangeRxBufferPtr, MAX_PKT_LEN);324 #endif325 326     /* Send a packet */327     for(Index = 0; Index < Tries; Index   ) {328 329         Status = XAxiDma_SimpleTransfer(&AxiDma, RxBufferPtr,330                     MAX_PKT_LEN, XAXIDMA_DEVICE_TO_DMA);331 332         if (Status != XST_SUCCESS) {333             return XST_FAILURE;334         }335 336         Status = XAxiDma_SimpleTransfer(&AxiDma, TxBufferPtr,337                     MAX_PKT_LEN, XAXIDMA_DMA_TO_DEVICE);338 339         if (Status != XST_SUCCESS) {340             return XST_FAILURE;341         }342 343 344         /*345          * Wait TX done and RX done346          */347         while (!TxDone && !RxDone && !Error) {348                 /* NOP */349         }350 351         if  {352             xil_printf("Failed test transmit%s done, "353             "receive%s donern", TxDone? "":" not",354                             RxDone? "":" not");355 356             goto Done;357 358         }359 360         /*361          * Test finished, check data362          */363         Status = CheckData(MAX_PKT_LEN, 0xC);364         if (Status != XST_SUCCESS) {365             xil_printf("Data check failedrn");366             goto Done;367         }368     }369 370 371     xil_printf("AXI DMA interrupt example test passedrn");372 373 374     /* Disable TX and RX Ring interrupts and return success */375 376     DisableIntrSystem(&Intc, TX_INTR_ID, RX_INTR_ID);377 378 Done:379     xil_printf("--- Exiting main() --- rn");380 381     return XST_SUCCESS;382 }383 384 #ifdef XPAR_UARTNS550_0_BASEADDR385 /*****************************************************************************/386 /*387 *388 * Uart16550 setup routine, need to set baudrate to 9600 and data bits to 8389 *390 * @param    None391 *392 * @return    None393 *394 * @note        None.395 *396 ******************************************************************************/397 static void Uart550_Setup(void)398 {399 400     XUartNs550_SetBaud(XPAR_UARTNS550_0_BASEADDR,401             XPAR_XUARTNS550_CLOCK_HZ, 9600);402 403     XUartNs550_SetLineControlReg(XPAR_UARTNS550_0_BASEADDR,404             XUN_LCR_8_DATA_BITS);405 }406 #endif407 408 /*****************************************************************************/409 /*410 *411 * This function checks data buffer after the DMA transfer is finished.412 *413 * We use the static tx/rx buffers.414 *415 * @param    Length is the length to check416 * @param    StartValue is the starting value of the first byte417 *418 * @return419 *        - XST_SUCCESS if validation is successful420 *        - XST_FAILURE if validation is failure.421 *422 * @note        None.423 *424 ******************************************************************************/425 static int CheckData(int Length, u8 StartValue)426 {427     u8 *RxPacket;428     int Index = 0;429     u8 Value;430 431     RxPacket = (u8 *) RX_BUFFER_BASE;432     Value = StartValue;433 434     /* Invalidate the DestBuffer before receiving the data, in case the435      * Data Cache is enabled436      */437 #ifndef __aarch64__438     Xil_DCacheInvalidateRangeRxPacket, Length);439 #endif440 441     for(Index = 0; Index < Length; Index  ) {442         if (RxPacket[Index] != Value) {443             xil_printf("Data error %d: %x/%xrn",444                 Index, RxPacket[Index], Value);445 446             return XST_FAILURE;447         }448         Value = (Value   1) & 0xFF;449     }450 451     return XST_SUCCESS;452 }453 454 /*****************************************************************************/455 /*456 *457 * This is the DMA TX Interrupt handler function.458 *459 * It gets the interrupt status from the hardware, acknowledges it, and if any460 * error happens, it resets the hardware. Otherwise, if a completion interrupt461 * is present, then sets the TxDone.flag462 *463 * @param    Callback is a pointer to TX channel of the DMA engine.464 *465 * @return    None.466 *467 * @note        None.468 *469 ******************************************************************************/470 static void TxIntrHandler(void *Callback)471 {472 473     u32 IrqStatus;474     int TimeOut;475     XAxiDma *AxiDmaInst = (XAxiDma *)Callback;476 477     /* Read pending interrupts */478     IrqStatus = XAxiDma_IntrGetIrq(AxiDmaInst, XAXIDMA_DMA_TO_DEVICE);479 480     /* Acknowledge pending interrupts */481 482 483     XAxiDma_IntrAckIrq(AxiDmaInst, IrqStatus, XAXIDMA_DMA_TO_DEVICE);484 485     /*486      * If no interrupt is asserted, we do not do anything487      */488     if (!(IrqStatus & XAXIDMA_IRQ_ALL_MASK)) {489 490         return;491     }492 493     /*494      * If error interrupt is asserted, raise error flag, reset the495      * hardware to recover from the error, and return with no further496      * processing.497      */498     if ((IrqStatus & XAXIDMA_IRQ_ERROR_MASK)) {499 500         Error = 1;501 502         /*503          * Reset should never fail for transmit channel504          */505         XAxiDma_Reset(AxiDmaInst);506 507         TimeOut = RESET_TIMEOUT_COUNTER;508 509         while  {510             if (XAxiDma_ResetIsDone(AxiDmaInst)) {511                 break;512             }513 514             TimeOut -= 1;515         }516 517         return;518     }519 520     /*521      * If Completion interrupt is asserted, then set the TxDone flag522      */523     if ((IrqStatus & XAXIDMA_IRQ_IOC_MASK)) {524 525         TxDone = 1;526     }527 }528 529 /*****************************************************************************/530 /*531 *532 * This is the DMA RX interrupt handler function533 *534 * It gets the interrupt status from the hardware, acknowledges it, and if any535 * error happens, it resets the hardware. Otherwise, if a completion interrupt536 * is present, then it sets the RxDone flag.537 *538 * @param    Callback is a pointer to RX channel of the DMA engine.539 *540 * @return    None.541 *542 * @note        None.543 *544 ******************************************************************************/545 static void RxIntrHandler(void *Callback)546 {547     u32 IrqStatus;548     int TimeOut;549     XAxiDma *AxiDmaInst = (XAxiDma *)Callback;550 551     /* Read pending interrupts */552     IrqStatus = XAxiDma_IntrGetIrq(AxiDmaInst, XAXIDMA_DEVICE_TO_DMA);553 554     /* Acknowledge pending interrupts */555     XAxiDma_IntrAckIrq(AxiDmaInst, IrqStatus, XAXIDMA_DEVICE_TO_DMA);556 557     /*558      * If no interrupt is asserted, we do not do anything559      */560     if (!(IrqStatus & XAXIDMA_IRQ_ALL_MASK)) {561         return;562     }563 564     /*565      * If error interrupt is asserted, raise error flag, reset the566      * hardware to recover from the error, and return with no further567      * processing.568      */569     if ((IrqStatus & XAXIDMA_IRQ_ERROR_MASK)) {570 571         Error = 1;572 573         /* Reset could fail and hang574          * NEED a way to handle this or do not call it??575          */576         XAxiDma_Reset(AxiDmaInst);577 578         TimeOut = RESET_TIMEOUT_COUNTER;579 580         while  {581             if(XAxiDma_ResetIsDone(AxiDmaInst)) {582                 break;583             }584 585             TimeOut -= 1;586         }587 588         return;589     }590 591     /*592      * If completion interrupt is asserted, then set RxDone flag593      */594     if ((IrqStatus & XAXIDMA_IRQ_IOC_MASK)) {595 596         RxDone = 1;597     }598 }599 600 /*****************************************************************************/601 /*602 *603 * This function setups the interrupt system so interrupts can occur for the604 * DMA, it assumes INTC component exists in the hardware system.605 *606 * @param    IntcInstancePtr is a pointer to the instance of the INTC.607 * @param    AxiDmaPtr is a pointer to the instance of the DMA engine608 * @param    TxIntrId is the TX channel Interrupt ID.609 * @param    RxIntrId is the RX channel Interrupt ID.610 *611 * @return612 *        - XST_SUCCESS if successful,613 *        - XST_FAILURE.if not succesful614 *615 * @note        None.616 *617 ******************************************************************************/618 static int SetupIntrSystem(INTC * IntcInstancePtr,619                XAxiDma * AxiDmaPtr, u16 TxIntrId, u16 RxIntrId)620 {621     int Status;622 623 #ifdef XPAR_INTC_0_DEVICE_ID624 625     /* Initialize the interrupt controller and connect the ISRs */626     Status = XIntc_Initialize(IntcInstancePtr, INTC_DEVICE_ID);627     if (Status != XST_SUCCESS) {628 629         xil_printf("Failed init intcrn");630         return XST_FAILURE;631     }632 633     Status = XIntc_Connect(IntcInstancePtr, TxIntrId,634                    (XInterruptHandler) TxIntrHandler, AxiDmaPtr);635     if (Status != XST_SUCCESS) {636 637         xil_printf("Failed tx connect intcrn");638         return XST_FAILURE;639     }640 641     Status = XIntc_Connect(IntcInstancePtr, RxIntrId,642                    (XInterruptHandler) RxIntrHandler, AxiDmaPtr);643     if (Status != XST_SUCCESS) {644 645         xil_printf("Failed rx connect intcrn");646         return XST_FAILURE;647     }648 649     /* Start the interrupt controller */650     Status = XIntc_Start(IntcInstancePtr, XIN_REAL_MODE);651     if (Status != XST_SUCCESS) {652 653         xil_printf("Failed to start intcrn");654         return XST_FAILURE;655     }656 657     XIntc_Enable(IntcInstancePtr, TxIntrId);658     XIntc_Enable(IntcInstancePtr, RxIntrId);659 660 #else661 662     XScuGic_Config *IntcConfig;663 664 665     /*666      * Initialize the interrupt controller driver so that it is ready to667      * use.668      */669     IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID);670     if (NULL == IntcConfig) {671         return XST_FAILURE;672     }673 674     Status = XScuGic_CfgInitialize(IntcInstancePtr, IntcConfig,675                     IntcConfig->CpuBaseAddress);676     if (Status != XST_SUCCESS) {677         return XST_FAILURE;678     }679 680 681     XScuGic_SetPriorityTriggerType(IntcInstancePtr, TxIntrId, 0xA0, 0x3);682 683     XScuGic_SetPriorityTriggerType(IntcInstancePtr, RxIntrId, 0xA0, 0x3);684     /*685      * Connect the device driver handler that will be called when an686      * interrupt for the device occurs, the handler defined above performs687      * the specific interrupt processing for the device.688      */689     Status = XScuGic_Connect(IntcInstancePtr, TxIntrId,690                 (Xil_InterruptHandler)TxIntrHandler,691                 AxiDmaPtr);692     if (Status != XST_SUCCESS) {693         return Status;694     }695 696     Status = XScuGic_Connect(IntcInstancePtr, RxIntrId,697                 (Xil_InterruptHandler)RxIntrHandler,698                 AxiDmaPtr);699     if (Status != XST_SUCCESS) {700         return Status;701     }702 703     XScuGic_Enable(IntcInstancePtr, TxIntrId);704     XScuGic_Enable(IntcInstancePtr, RxIntrId);705 706 707 #endif708 709     /* Enable interrupts from the hardware */710 711     Xil_ExceptionInit();712     Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,713             (Xil_ExceptionHandler)INTC_HANDLER,714             (void *)IntcInstancePtr);715 716     Xil_ExceptionEnable();717 718     return XST_SUCCESS;719 }720 721 /*****************************************************************************/722 /**723 *724 * This function disables the interrupts for DMA engine.725 *726 * @param    IntcInstancePtr is the pointer to the INTC component instance727 * @param    TxIntrId is interrupt ID associated w/ DMA TX channel728 * @param    RxIntrId is interrupt ID associated w/ DMA RX channel729 *730 * @return    None.731 *732 * @note        None.733 *734 ******************************************************************************/735 static void DisableIntrSystem(INTC * IntcInstancePtr,736                     u16 TxIntrId, u16 RxIntrId)737 {738 #ifdef XPAR_INTC_0_DEVICE_ID739     /* Disconnect the interrupts for the DMA TX and RX channels */740     XIntc_Disconnect(IntcInstancePtr, TxIntrId);741     XIntc_Disconnect(IntcInstancePtr, RxIntrId);742 #else743     XScuGic_Disconnect(IntcInstancePtr, TxIntrId);744     XScuGic_Disconnect(IntcInstancePtr, RxIntrId);745 #endif746 }

ca88 28

  PS_DMA_InitPara()是自行增加的PS_DMA参数伊始化函数,内部的参数更是根本了,大家来查阅Xilinx官方文书档案ug585的DMA Controller章节。

xaxidma_example_simple_intr.c

  生成IP核后,张开新的工程,导入该IP核到repository。

ca88 29

 主函数中各类实现了:DMA初叶化,创建中断系统,使能DMA中断,开始化标记位及发送数据,运行DMA传输以及数额检查测量试验。中断部分的内容与PS DMA非常周边,传输达成后步入的间歇函数中仅置位了发送或收到完结标志位:

ca88 30

  简要来讲,DMA以burst格局传输数据,意思是分批次搬移。手册表明原或指标burst_size位宽无法超过64bit,那也是其挂载AXI总线的多少位宽。PS_DMA_InitPara()里的SrcBurstSize为源突发传输位宽字节数,最大为8.SrcBurstLen是手册中所说的“burst length”,即突发传输数据个数。SrcInc代表burst types为地方自增照旧地点固定格局。指标调节字同理。剩下的三个参数最主要:SrcAddrDstAddrLength分别代表源首地址

ca88 31ca88 32

五、Block Design系统搭建

目标首地址和累计必要搬移的多寡字节数。须求注意的是,绝对要满意srcburstsize*srcburstlen

dstburstsize*dstburstlen,不然爆发错误。那点也比较好掌握,约等于FPGA逻辑设计中的异步FIFO两边数据带宽要合作。

  那么要想完毕OCM到DD路虎极光的数额搬移,更动下地址就能够嘛。由于读写DDLAND要拜会纯属地址,所以要极其小心读写操作的地点无法和DDR内部存款和储蓄器储程序代码和中间数据的地点段重叠。防止程序崩溃很简短的做法便是在XPA汉兰达_PS7_DDR_0_S_AXI_BASEADDLAND的基本功上加一段偏移量,具体扩张少的主题素材自身亦不是很明朗,希望见到的意中人能在评头论足中引导一二。

  对于ZYNQ这一SOC架构来讲,PS端连接如以太网,USB等高带宽外设计接口尤其惠及,所以PS_DMA的灵活运用幸好是拾叁分须要的,越来越灵敏火速的应用这一硬件能源还要前期持续深究。PS端和PL端高速数据交互就供给用到另贰个DMA成员AXI_DMA,能够说它选取片内总线打破了CPU FPGA架构的质量瓶颈,该有的内容就要持续表明。

  1 static void TxIntrHandler(void *Callback)  2 {  3   4     u32 IrqStatus;  5     int TimeOut;  6     XAxiDma *AxiDmaInst = (XAxiDma *)Callback;  7   8     /* Read pending interrupts */  9     IrqStatus = XAxiDma_IntrGetIrq(AxiDmaInst, XAXIDMA_DMA_TO_DEVICE); 10  11     /* Acknowledge pending interrupts */ 12  13  14     XAxiDma_IntrAckIrq(AxiDmaInst, IrqStatus, XAXIDMA_DMA_TO_DEVICE); 15  16     /* 17      * If no interrupt is asserted, we do not do anything 18      */ 19     if (!(IrqStatus & XAXIDMA_IRQ_ALL_MASK)) { 20  21         return; 22     } 23  24     /* 25      * If error interrupt is asserted, raise error flag, reset the 26      * hardware to recover from the error, and return with no further 27      * processing. 28      */ 29     if ((IrqStatus & XAXIDMA_IRQ_ERROR_MASK)) { 30  31         Error = 1; 32  33         /* 34          * Reset should never fail for transmit channel 35          */ 36         XAxiDma_Reset(AxiDmaInst); 37  38         TimeOut = RESET_TIMEOUT_COUNTER; 39  40         while  { 41             if (XAxiDma_ResetIsDone(AxiDmaInst)) { 42                 break; 43             } 44  45             TimeOut -= 1; 46         } 47  48         return; 49     } 50  51     /* 52      * If Completion interrupt is asserted, then set the TxDone flag 53      */ 54     if ((IrqStatus & XAXIDMA_IRQ_IOC_MASK)) { 55  56         TxDone = 1; 57     } 58 } 59  60 /*****************************************************************************/ 61 /* 62 * 63 * This is the DMA RX interrupt handler function 64 * 65 * It gets the interrupt status from the hardware, acknowledges it, and if any 66 * error happens, it resets the hardware. Otherwise, if a completion interrupt 67 * is present, then it sets the RxDone flag. 68 * 69 * @param    Callback is a pointer to RX channel of the DMA engine. 70 * 71 * @return    None. 72 * 73 * @note        None. 74 * 75 ******************************************************************************/ 76 static void RxIntrHandler(void *Callback) 77 { 78     u32 IrqStatus; 79     int TimeOut; 80     XAxiDma *AxiDmaInst = (XAxiDma *)Callback; 81  82     /* Read pending interrupts */ 83     IrqStatus = XAxiDma_IntrGetIrq(AxiDmaInst, XAXIDMA_DEVICE_TO_DMA); 84  85     /* Acknowledge pending interrupts */ 86     XAxiDma_IntrAckIrq(AxiDmaInst, IrqStatus, XAXIDMA_DEVICE_TO_DMA); 87  88     /* 89      * If no interrupt is asserted, we do not do anything 90      */ 91     if (!(IrqStatus & XAXIDMA_IRQ_ALL_MASK)) { 92         return; 93     } 94  95     /* 96      * If error interrupt is asserted, raise error flag, reset the 97      * hardware to recover from the error, and return with no further 98      * processing. 99      */100     if ((IrqStatus & XAXIDMA_IRQ_ERROR_MASK)) {101 102         Error = 1;103 104         /* Reset could fail and hang105          * NEED a way to handle this or do not call it??106          */107         XAxiDma_Reset(AxiDmaInst);108 109         TimeOut = RESET_TIMEOUT_COUNTER;110 111         while  {112             if(XAxiDma_ResetIsDone(AxiDmaInst)) {113                 break;114             }115 116             TimeOut -= 1;117         }118 119         return;120     }121 122     /*123      * If completion interrupt is asserted, then set RxDone flag124      */125     if ((IrqStatus & XAXIDMA_IRQ_IOC_MASK)) {126 127         RxDone = 1;128     }129 }

 系统结构与上一篇该连串博文类似,均是以AXI DMA为骨干的Loop系统,只是将AXI-Stream Data FIFO改成了自定义IP核。由于IP核slave和master接口只蕴涵tdata和tvalid功率信号,由此供给加上接口衔接的有个别简易逻辑。tready功率信号和tkeep时限信号直接连接constant使用常数驱动,DMA的s_axis_s2mm接口的tlast由wrapper内计数器逻辑驱动,将system中FCLK_CLK0 peripheral_aresetn m_axis_tvalid和s_axis_s2mm_tlast信号引出到wrapper中。

intrHandler

ca88 33

  DMA运转传输部分如下,调用库函数XAxiDma_SimpleTransfer。以首个为例,是将安德拉xBufferPtr为数量首地址,MAX_PKT_LEN为字节数,XAXIDMA_DEVICE_TO_DMA为传输方向运转DMA传输数据。MAX_PKT_ca88,LEN不能够超出从前IP核配置参数钦命的16384byte,XAXIDMA_DEVICE_TO_DMA和XAXIDMA_DMA_TO_DEVICE依次指PL-> DMA ->PS以及PS->DMA -> PL方向,约等于PL正是里面的DEVICE。DMA运维函数唯有贰个地址,那是与PS端DMA最大的界别,因为数量搬移的另一侧是满含无地址的流接口的IP核,该侧“地址”由硬件连接决定。ca88 34

  有一点点相比较坑:自定义IP通过AXI总线与DMA互联时,总线下相应的接口不肯定会不错对应,所以须求各自将两端的各样接口相连。能够透过展开综合后的布置性来承认连线正确。

  再来看看搬移数据内部存款和储蓄器首地址TucsonxBufferPtr和TxBufferPtr.从底下的概念可知MEM_BASE_ADDR是DDR_BASE_ADDOdyssey加上一段偏移量的结果,DDEvoque营地址数值从xparameters.h中查看。

  自动生成wrapper后退换增添代码如下:

ca88 35

ca88 36ca88 37

ca88 38

  1 `timescale 1 ps / 1 ps  2   3 module user_wrapper  4    (DC,  5     DDR_addr,  6     DDR_ba,  7     DDR_cas_n,  8     DDR_ck_n,  9     DDR_ck_p, 10     DDR_cke, 11     DDR_cs_n, 12     DDR_dm, 13     DDR_dq, 14     DDR_dqs_n, 15     DDR_dqs_p, 16     DDR_odt, 17     DDR_ras_n, 18     DDR_reset_n, 19     DDR_we_n, 20     //FCLK_CLK0, 21     FIXED_IO_ddr_vrn, 22     FIXED_IO_ddr_vrp, 23     FIXED_IO_mio, 24     FIXED_IO_ps_clk, 25     FIXED_IO_ps_porb, 26     FIXED_IO_ps_srstb, 27     RES, 28     SCLK, 29     SDIN, 30     VBAT, 31     VDD 32     //m_axis_tvalid, 33     //peripheral_aresetn, 34     //s_axis_s2mm_tlast 35 ); 36   output DC; 37   inout [14:0]DDR_addr; 38   inout [2:0]DDR_ba; 39   inout DDR_cas_n; 40   inout DDR_ck_n; 41   inout DDR_ck_p; 42   inout DDR_cke; 43   inout DDR_cs_n; 44   inout [3:0]DDR_dm; 45   inout [31:0]DDR_dq; 46   inout [3:0]DDR_dqs_n; 47   inout [3:0]DDR_dqs_p; 48   inout DDR_odt; 49   inout DDR_ras_n; 50   inout DDR_reset_n; 51   inout DDR_we_n; 52   //output FCLK_CLK0; 53   inout FIXED_IO_ddr_vrn; 54   inout FIXED_IO_ddr_vrp; 55   inout [53:0]FIXED_IO_mio; 56   inout FIXED_IO_ps_clk; 57   inout FIXED_IO_ps_porb; 58   inout FIXED_IO_ps_srstb; 59   output RES; 60   output SCLK; 61   output SDIN; 62   output VBAT; 63   output VDD; 64   //output [0:0]m_axis_tvalid; 65   //output [0:0]peripheral_aresetn; 66   //input s_axis_s2mm_tlast; 67  68  69   localparam DATA_NUM = 256; 70  71   wire DC; 72   wire [14:0]DDR_addr; 73   wire [2:0]DDR_ba; 74   wire DDR_cas_n; 75   wire DDR_ck_n; 76   wire DDR_ck_p; 77   wire DDR_cke; 78   wire DDR_cs_n; 79   wire [3:0]DDR_dm; 80   wire [31:0]DDR_dq; 81   wire [3:0]DDR_dqs_n; 82   wire [3:0]DDR_dqs_p; 83   wire DDR_odt; 84   wire DDR_ras_n; 85   wire DDR_reset_n; 86   wire DDR_we_n; 87   wire FCLK_CLK0; 88   wire FIXED_IO_ddr_vrn; 89   wire FIXED_IO_ddr_vrp; 90   wire [53:0]FIXED_IO_mio; 91   wire FIXED_IO_ps_clk; 92   wire FIXED_IO_ps_porb; 93   wire FIXED_IO_ps_srstb; 94   wire RES; 95   wire SCLK; 96   wire SDIN; 97   wire VBAT; 98   wire VDD; 99   wire [0:0]m_axis_tvalid;100   wire [0:0]peripheral_aresetn;101   wire s_axis_s2mm_tlast;102 103   reg [8-1:0] cnt;104   wire add_cnt;105   wire end_cnt;106 107   system system_i108        ,109         .DDR_addr,110         .DDR_ba,111         .DDR_cas_n(DDR_cas_n),112         .DDR_ck_n,113         .DDR_ck_p,114         .DDR_cke,115         .DDR_cs_n,116         .DDR_dm,117         .DDR_dq,118         .DDR_dqs_n(DDR_dqs_n),119         .DDR_dqs_p(DDR_dqs_p),120         .DDR_odt,121         .DDR_ras_n(DDR_ras_n),122         .DDR_reset_n(DDR_reset_n),123         .DDR_we_n,124         .FCLK_CLK0(FCLK_CLK0),125         .FIXED_IO_ddr_vrn(FIXED_IO_ddr_vrn),126         .FIXED_IO_ddr_vrp(FIXED_IO_ddr_vrp),127         .FIXED_IO_mio(FIXED_IO_mio),128         .FIXED_IO_ps_clk(FIXED_IO_ps_clk),129         .FIXED_IO_ps_porb(FIXED_IO_ps_porb),130         .FIXED_IO_ps_srstb(FIXED_IO_ps_srstb),131         .RES,132         .SCLK,133         .SDIN,134         .VBAT,135         .VDD,136         .m_axis_tvalid(m_axis_tvalid),137         .peripheral_aresetn(peripheral_aresetn),138         .s_axis_s2mm_tlast(s_axis_s2mm_tlast));139 140     always @(posedge FCLK_CLK0)begin141         if(!peripheral_aresetn)begin142             cnt <= 0;143         end144         else ifbegin145             if146                 cnt <= 0;147             else148                 cnt <= cnt   1;149         end150     end151 152     assign add_cnt = m_axis_tvalid;       153     assign end_cnt = add_cnt && cnt== DATA_NUM-1;   154 155     assign s_axis_s2mm_tlast = end_cnt;156 157 endmodule

ca88 39

user_wrapper

四、函数重用封装

  当自定义IP核输出2六拾个数据时,拉高tlast时限信号甘休传输。张开综合后的统一希图,加多调节和测量试验探针,抓取DMA与自定义IP之间的接口功率信号,set up debug后完结接下去的流程。

  官方的代码相比较乱,都写在main函数里,米联客教程init_intr_sys()函数达成总体中断系统的创设,将法定demo中main函数DMA测验此前关于中断部分的代码全体包装个中,包含DMA中断最初化,中断控制器初叶化,使能暂停至极,连接DMA发送与接纳中断,DMA中断使能八个过程。

六、软硬件联调

ca88 40

  在硬件系统中定义数据帧长度为258个,数据位宽为16bit,因而C代码中DMA运行传输函数中数量长度参数为512byte。测验数据变动与检验代码非常轻易:

五、AXI总线复信号ILA波形深入分析 

ca88 41ca88 42

AXI Stream首要接口:

  我们间接查看ILA抓取AXI S总线波形:

  tdata:数据    tkeep:字节有效提醒    tlast:帧尾提示    tready:准备就绪    tvalid:数据有效提醒

ca88 43

  MM2S主旋律一旦tvalid拉高则触发ILA抓取时限信号波形。一帧多少有陆十六个,种种数据32bit,一共正好为C代码中MAX_PKT_LEN数值,即256byte。

ca88 44

ca88 45

  看到CPU发生多少从1到4重新递增,IP核输出结果从2到8重复递增,输出为输入的2倍。

  里面他keep复信号相比较关键。如当stream位宽为16bit,传输数据量为255byte时,tkeep非确定性信号在最后二个stream数据对应地点是2'b01提醒第1贰二十个16bit数中最后二个数的高字节为upsize进度中没用填充数据。

ca88 46

ca88 47

  传输达成后跻身DMA发送和收受中断,软件检查测量检验结果正确。在Memory窗口能够一直查看内部存款和储蓄器相对地址里的数额,选定DD奥迪Q5接收缓存区初步地址,个中的多少与AXI总线传回数据一致,表明系统联调成功。之后自由算法模块均可选用本文格局开展统一希图和集成,能够说一劳永逸!

  后续本身会使用System Generator设总计法IP,之后集成到IP Integerator中作为CPU外设举行板级验证。继续求学!

编辑:ca88 本文来源:DMA使用解析及环路测验,SOC快速展开算法验证通

关键词: 亚洲城ca88