dma example阅读

/******************************************************************************
*
* Copyright (C) 2009 - 2015 Xilinx, Inc.  All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal 
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* XILINX  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF 
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/****************************************************************************/
/**
*
* @file xdmaps_example_w_intr.c
*
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver   Who      Date     Changes
* ----- ------ -------- ----------------------------------------------
* 1.00    hbm    08/19/2010 First Release
* 1.01a nm     03/05/2012 Initializing DmaCmd structure compatible to armcc.
*                         Modified base address to secure register base
*                         address.
* 1.02a sg     05/16/2012 Some code cleanup and reorganisation of the
*              functions within the example.
* 1.06a kpc    04/24/2012 Modified the APIs to make this file compatible with 
*                         peripheral test suite.                             
* 2.1   kpc    08/23/2014 Fixed IAR compiler reported error.
* 2.3   ms     01/23/17  Modified xil_printf statement in main function to
*                        ensure that "Successfully ran" and "Failed" strings are
*                        available in all examples. This is a fix for CR-965028.
* </pre>
*
*****************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include "sleep.h"
#include "xparameters.h"
#include "xil_types.h"
#include "xil_assert.h"
#include "xil_io.h"
#include "xil_exception.h"
#include "xil_cache.h"
#include "xil_printf.h"
#include "xscugic.h"
#include "xdmaps.h"

/************************** Constant Definitions *****************************/
/*
 * The following constants map to the XPAR parameters created in the
 * xparameters.h file. They are defined here such that a user can easily
 * change all the needed parameters in one place.
 */

//改常量?怎么改?看地址映射?
#define DMA_DEVICE_ID             XPAR_XDMAPS_1_DEVICE_ID
#define INTC_DEVICE_ID            XPAR_SCUGIC_SINGLE_DEVICE_ID//gic

#define DMA_DONE_INTR_0            XPAR_XDMAPS_0_DONE_INTR_0//0通道isr(中断服务程序?
#define DMA_DONE_INTR_1            XPAR_XDMAPS_0_DONE_INTR_1
#define DMA_DONE_INTR_2            XPAR_XDMAPS_0_DONE_INTR_2
#define DMA_DONE_INTR_3            XPAR_XDMAPS_0_DONE_INTR_3
#define DMA_DONE_INTR_4            XPAR_XDMAPS_0_DONE_INTR_4
#define DMA_DONE_INTR_5            XPAR_XDMAPS_0_DONE_INTR_5
#define DMA_DONE_INTR_6            XPAR_XDMAPS_0_DONE_INTR_6
#define DMA_DONE_INTR_7            XPAR_XDMAPS_0_DONE_INTR_7
#define DMA_FAULT_INTR            XPAR_XDMAPS_0_FAULT_INTR



#define TEST_ROUNDS    1    /* Number of loops that the Dma transfers run.测试轮数*/
#define DMA_LENGTH    1024    /* Length of the Dma Transfers数据长度 */
#define TIMEOUT_LIMIT     0x2000    /* Loop count for timeout 计数,超时?*/

/**************************** Type Definitions *******************************/


/***************** Macros (Inline Functions) Definitions *********************/


/************************** Function Prototypes ******************************/

int XDmaPs_Example_W_Intr(XScuGic *GicPtr, u16 DeviceId);
int SetupInterruptSystem(XScuGic *GicPtr, XDmaPs *DmaPtr);
void DmaDoneHandler(unsigned int Channel, XDmaPs_Cmd *DmaCmd,
            void *CallbackRef);

/************************** Macro Definitions *****************************/


/************************** Variable Definitions *****************************/
#ifdef __ICCARM__
#pragma data_alignment=32
static int Src[DMA_LENGTH];
static int Dst[DMA_LENGTH];
#pragma data_alignment=4
#else
static int Src[DMA_LENGTH] __attribute__ ((aligned (32)));
//static int * Src = (int*)XPAR_AXI_BRAM_CTRL_0_S_AXI_BASEADDR;//板上的地址?
static int Dst[DMA_LENGTH] __attribute__ ((aligned (32)));
#endif

XDmaPs DmaInstance;
#ifndef TESTAPP_GEN
XScuGic GicInstance;
#endif

/****************************************************************************/
/**
*
* This is the main function for the DmaPs interrupt example.
*
* @param    None.
*
* @return    XST_SUCCESS to indicate success, otherwise XST_FAILURE.
*
* @note        None.
*
****************************************************************************/
#ifndef TESTAPP_GEN
int main(void)
{
    int Status;

    Status = XDmaPs_Example_W_Intr(&GicInstance,DMA_DEVICE_ID);//调用
    if (Status != XST_SUCCESS) {
        xil_printf("Error: XDMaPs_Example_W_Intr failed\r\n");
        return XST_FAILURE;
    }

    xil_printf("Successfully ran XDMaPs_Example_W_Intr\r\n");
    return XST_SUCCESS;

}
#endif


/*****************************************************************************/
/**
 *
 * Interrupt Example to test the DMA.//这里只有写入,调用DmaDoneHandler负责回读检查
 *ID是不是需要按具体的实现改?
 * @param    DeviceId is the Device ID of the DMA controller.
 *
 * @return    XST_SUCCESS to indicate success, otherwise XST_FAILURE.
 *
 * @note    None.
 *
 ****************************************************************************/
int XDmaPs_Example_W_Intr(XScuGic *GicPtr, u16 DeviceId)
{
    int Index;//循环变量
    unsigned int Channel = 0;
    int Status;
    int TestStatus;
    int TestRound;
    int TimeOutCnt;
    volatile int Checked[XDMAPS_CHANNELS_PER_DEV];//这是啥?
    XDmaPs_Config *DmaCfg;
    XDmaPs *DmaInst = &DmaInstance;
    XDmaPs_Cmd DmaCmd;

    memset(&DmaCmd, 0, sizeof(XDmaPs_Cmd));//给DmaCmd结构体分空间。dma直接使,不用经过axi。给

    //用cmd控制dma读写
    DmaCmd.ChanCtrl.SrcBurstSize = 4;//设置cmd参数
    DmaCmd.ChanCtrl.SrcBurstLen = 4;
    DmaCmd.ChanCtrl.SrcInc = 1;
    DmaCmd.ChanCtrl.DstBurstSize = 4;
    DmaCmd.ChanCtrl.DstBurstLen = 4;
    DmaCmd.ChanCtrl.DstInc = 1;
    DmaCmd.BD.SrcAddr = (u32) Src;//
    DmaCmd.BD.DstAddr = (u32) Dst;
    DmaCmd.BD.Length = DMA_LENGTH * sizeof(int);


    /*
     * Initialize the DMA Driver
     */
    DmaCfg = XDmaPs_LookupConfig(DeviceId);//由id找设备?
    if (DmaCfg == NULL) {
        return XST_FAILURE;
    }

    Status = XDmaPs_CfgInitialize(DmaInst,//初始化dma
                   DmaCfg,
                   DmaCfg->BaseAddress);
    if (Status != XST_SUCCESS) {
        return XST_FAILURE;
    }


    /*
     * Setup the interrupt system.设置中断
     */
    Status = SetupInterruptSystem(GicPtr, DmaInst);//子函数,不是库函数
    if (Status != XST_SUCCESS) {
        return XST_FAILURE;
    }


    TestStatus = XST_SUCCESS;//开始测试,初始化为成功,不成功段的代码改为fail

    for (TestRound = 0; TestRound < TEST_ROUNDS; TestRound++) {
        xil_printf("Test round %d\r\n", TestRound);
        for (Channel = 0;
             Channel < XDMAPS_CHANNELS_PER_DEV;
             Channel++) { //一层循环channel XDMAPS_CHANNELS_PER_DEV是怎么来的?干什么的?
            //每个通道都测

            /* Initialize source 给源数据赋值*/
            for (Index = 0; Index < DMA_LENGTH; Index++)
                Src[Index] = DMA_LENGTH - Index;//已经在访存板上地址

            /* Clear destination 清空结果数组*/
            for (Index = 0; Index < DMA_LENGTH; Index++)
                Dst[Index] = 0;

            Checked[Channel] = 0;//每个channel检查结果初始化为0

            /* Set the Done interrupt handler 设置完成中断?因为dma不经cpu控制,所以需要中断*/
            XDmaPs_SetDoneHandler(DmaInst,//中断待???channel是什么??怎么和设备映射的??
                           Channel,
                           DmaDoneHandler, //DmaDoneHandler是子函数,如果有中断跳到这里
                           (void *)Checked);


            Status = XDmaPs_Start(DmaInst, Channel, &DmaCmd, 0);//开始,之前cmd的参数已经设置好了
            //cmd包括写什么,怎么写
            if (Status != XST_SUCCESS) {
                return XST_FAILURE;
            }//返回的是开始成功

            TimeOutCnt = 0;

            /* Now the DMA is done 计时等待完成,忙等中断,回写部分可参考*/
            while (!Checked[Channel] //checked数组和中断连,不是和dma,dma给中断,中断给
                   && TimeOutCnt < TIMEOUT_LIMIT) {
                TimeOutCnt++;
            }

            if (TimeOutCnt >= TIMEOUT_LIMIT) {//超时
                TestStatus = XST_FAILURE;
            }

            if (Checked[Channel] < 0) {
                /* DMA controller failed 失败的中断*/
                TestStatus = XST_FAILURE;
            }
        }
    }

    return TestStatus;

}


/******************************************************************************/
/**
 *把系统连上中断,可以直接抄,但要改啥??
 * This function connects the interrupt handler of the interrupt controller to
 * the processor.  This function is seperate to allow it to be customized for
 * each application. Each processor or RTOS may require unique processing to
 * connect the interrupt handler.
 *
 * @param    GicPtr is the GIC instance pointer. GIC是ARM公司提供的一个通用的中断控制器=驱动?
 * @param    DmaPtr is the DMA instance pointer. dma硬件?
 *
 * @return    None.
 *
 * @note    None.
 *
 ****************************************************************************/
int SetupInterruptSystem(XScuGic *GicPtr, XDmaPs *DmaPtr)
{
    int Status;
#ifndef TESTAPP_GEN    //这是干什么的?没见过这个宏
    XScuGic_Config *GicConfig;


    Xil_ExceptionInit();//初始化溢出

    /*
     * Initialize the interrupt controller driver so that it is ready to
     * use.初始化dma控制器
     */
    GicConfig = XScuGic_LookupConfig(INTC_DEVICE_ID);//找设备,把设备赋给地址,待??
    if (NULL == GicConfig) {//没找着
        return XST_FAILURE;
    }

    Status = XScuGic_CfgInitialize(GicPtr, GicConfig,//初始化fic,什么时候使什么??
                       GicConfig->CpuBaseAddress);//config是板子上数据(设备设置,ptr是本地指针
    if (Status != XST_SUCCESS) {
        return XST_FAILURE;
    }

    /*
     * Connect the interrupt controller interrupt handler to the hardware
     * interrupt handling logic in the processor.
     */
    Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_IRQ_INT,
                 (Xil_ExceptionHandler)XScuGic_InterruptHandler,//这都啥,填异常处理表?
                 GicPtr);
#endif
    /*
     * Connect the device driver handlers that will be called when an interrupt
     * for the device occurs, the device driver handler performs the specific
     * interrupt processing for the device
     */

    /*
     * Connect the Fault ISR 啥?错误中断处理程序?是中断都要连吗?
     */
    Status = XScuGic_Connect(GicPtr,
                 DMA_FAULT_INTR,
                 (Xil_InterruptHandler)XDmaPs_FaultISR,
                 (void *)DmaPtr);
    if (Status != XST_SUCCESS) {
        return XST_FAILURE;
    }

    /*
     * Connect the Done ISR for all 8 channels of DMA 0 DMA都是8通道?连这个干什么的?
     */
    Status = XScuGic_Connect(GicPtr,
                 DMA_DONE_INTR_0,
                 (Xil_InterruptHandler)XDmaPs_DoneISR_0,//这是一个xdmaps.c函数。没看懂干嘛的??
                 (void *)DmaPtr);
    Status |= XScuGic_Connect(GicPtr,
                 DMA_DONE_INTR_1,
                 (Xil_InterruptHandler)XDmaPs_DoneISR_1,
                 (void *)DmaPtr);
    Status |= XScuGic_Connect(GicPtr,
                 DMA_DONE_INTR_2,
                 (Xil_InterruptHandler)XDmaPs_DoneISR_2,
                 (void *)DmaPtr);
    Status |= XScuGic_Connect(GicPtr,
                 DMA_DONE_INTR_3,
                 (Xil_InterruptHandler)XDmaPs_DoneISR_3,
                 (void *)DmaPtr);
    Status |= XScuGic_Connect(GicPtr,
                 DMA_DONE_INTR_4,
                 (Xil_InterruptHandler)XDmaPs_DoneISR_4,
                 (void *)DmaPtr);
    Status |= XScuGic_Connect(GicPtr,
                 DMA_DONE_INTR_5,
                 (Xil_InterruptHandler)XDmaPs_DoneISR_5,
                 (void *)DmaPtr);
    Status |= XScuGic_Connect(GicPtr,
                 DMA_DONE_INTR_6,
                 (Xil_InterruptHandler)XDmaPs_DoneISR_6,
                 (void *)DmaPtr);
    Status |= XScuGic_Connect(GicPtr,
                 DMA_DONE_INTR_7,
                 (Xil_InterruptHandler)XDmaPs_DoneISR_7,
                 (void *)DmaPtr);

    if (Status != XST_SUCCESS)
        return XST_FAILURE;

    /*使能所有通道的gic
     * Enable the interrupts for the device
     */
    XScuGic_Enable(GicPtr, DMA_DONE_INTR_0);
    XScuGic_Enable(GicPtr, DMA_DONE_INTR_1);
    XScuGic_Enable(GicPtr, DMA_DONE_INTR_2);
    XScuGic_Enable(GicPtr, DMA_DONE_INTR_3);
    XScuGic_Enable(GicPtr, DMA_DONE_INTR_4);
    XScuGic_Enable(GicPtr, DMA_DONE_INTR_5);
    XScuGic_Enable(GicPtr, DMA_DONE_INTR_6);
    XScuGic_Enable(GicPtr, DMA_DONE_INTR_7);
    XScuGic_Enable(GicPtr, DMA_FAULT_INTR);

    Xil_ExceptionEnable();//使能异常,看来异常包括了中断

    return XST_SUCCESS;

}


/*****************************************************************************/
/**
*
* DmaDoneHandler.
*
* @param    Channel is the Channel number.
* @param    DmaCmd is the Dma Command.
* @param    CallbackRef is the callback reference data.
*
* @return    None.
*
* @note        None.
*
******************************************************************************/
void DmaDoneHandler(unsigned int Channel, XDmaPs_Cmd *DmaCmd, void *CallbackRef)
{

    /* done handler */
    volatile int *Checked = (volatile int *)CallbackRef;
    int Index;
    int Status = 1;
    int *Src;//局部变量
    int *Dst;

    Src = (int *)DmaCmd->BD.SrcAddr;//重新赋值?
    Dst = (int *)DmaCmd->BD.DstAddr;

    /* DMA successful 不用手动存,dma自己存在了dst,把外存存到了内存(数组)*/
    //怎么映射的?需要显示指明什么?
    //怎么交互的?怎么指挥外存地址?src和dst存的什么?
    /* compare the src and dst buffer */
    for (Index = 0; Index < DMA_LENGTH; Index++) {
        if ((Src[Index] != Dst[Index]) ||
                (Dst[Index] != DMA_LENGTH - Index)) {
            Status = -XST_FAILURE;
        }
    }


    Checked[Channel] = Status;
}

猜你喜欢

转载自www.cnblogs.com/iwanna/p/10011943.html
DMA