请选择 进入手机版 | 继续访问电脑版
[X]关闭

ZYNQ 7020 中DMA传输tReady信号不拉高的问题

文档创建者:小青山
浏览次数:4407
最后更新:2020-12-13
背景:自定义了一个IP核,主要功能是接收ADC的数据并且选取特定的数据传到DMA中,并且在每一段需要传输的最后一个数发送时tLast信号拉高。
问题:在SDK中对DMA进行初始化,但是通过ILA查看tReady信号时钟没有拉高,怀疑是自己SDK程序有问题,请各位大佬指点迷津,谢谢。
--------------------------------------------------------------------------------------------------------------------

--------------------------------------------------------------------------------------------------------------------

#include <stdio.h>
#include "platform.h"
#include "xil_printf.h"

#include "pluseProcess.h"
#include "xparameters.h"
#include "xil_io.h"
#include "sleep.h"
#include "xaxidma.h"
#include "xscugic.h"


/* DMA redefines */
#define MAX_DMA_LEN      0x800000      /* DMA max length in byte */
#define DMA_DEV_ID       XPAR_AXIDMA_0_DEVICE_ID
#define S2MM_INTR_ID     XPAR_FABRIC_AXI_DMA_0_S2MM_INTROUT_INTR
/* Interrupt defines */
#define INT_DEVICE_ID    XPAR_SCUGIC_SINGLE_DEVICE_ID
#define ADC_BYTE                   2                         /* ADC数据长度(字节) */
#define ADC_CAPTURELEN     1920          /* ADC capture length */

short DmaRxBuffer[MAX_DMA_LEN/sizeof(short)]  __attribute__ ((aligned(64)));

/* 实例化DMA */
XAxiDma AxiDma;
/* 实例化中断 */
XScuGic INST;
/* 自定义函数声明 */

int SetInterruptInit(XScuGic *InstancePtr, u16 IntrID) ;
int XAxiDma_Initial(u16 DeviceId, u16 IntrID, XAxiDma *XAxiDma, XScuGic*InstancePtr);
void Dma_Interrupt_Handler(void *CallBackRef);
void systemStart(u32 controlAddr, u32 triggerThreshold, u32 endThreshold);
void systemEnd(u32 controlAddr);

/* 主函数  */
int main()
{
        int Status;

    init_platform();

    print("Hello World\n\r");

    /* Initialize ScuGic interrupt  */
    Status = SetInterruptInit(&INST, INT_DEVICE_ID);
        if (Status == XST_SUCCESS) {
                xil_printf("ScuGic interrupt initialized successfully\n\r");
        }
        else{
                return XST_FAILURE;
        }

    /* 初始化DMA & 中断连接  */
        Status = XAxiDma_Initial(DMA_DEV_ID, S2MM_INTR_ID, &AxiDma, &INST) ;
        if (Status == XST_SUCCESS) {
                xil_printf("DMA initialized successfully\n\r");
        }
        else{
                return XST_FAILURE;
        }

    /* DMA传输开始 */
        Status = XAxiDma_SimpleTransfer(&AxiDma,(UINTPTR) DmaRxBuffer, ADC_BYTE*ADC_CAPTURELEN, XAXIDMA_DEVICE_TO_DMA);
        if (Status == XST_SUCCESS) {
                xil_printf("DMA started successfully\n\r");
        }
        else{
                return XST_FAILURE;
        }

    /* 测量开始 & 设置触发和结束阈值  */
    systemStart(XPAR_PLUSEPROCESS_0_S00_AXI_BASEADDR, 300, 180);
        xil_printf("Measurement start\n\r");
        sleep(20);
        xil_printf("Measurement end\n\r");

    cleanup_platform();
    return 0;
}

/*--------------------------------------------------------------------------------------------------------------*/

/* 测量开始函数 */
/* controlAddr      基地址
* triggerThreshold 触发阈值[12位,最大4096]
* endThreshold     结束阈值[12位,最大4096]
*/
void systemStart(u32 controlAddr, u32 triggerThreshold, u32 endThreshold)
{
        /* 测量开始  */
        PLUSEPROCESS_mWriteReg(controlAddr, PLUSEPROCESS_S00_AXI_SLV_REG0_OFFSET, 1);
        /* 脉冲开始触发阈值 */
        PLUSEPROCESS_mWriteReg(controlAddr, PLUSEPROCESS_S00_AXI_SLV_REG1_OFFSET, triggerThreshold);
        /* 脉冲结束触发阈值 */
        PLUSEPROCESS_mWriteReg(controlAddr, PLUSEPROCESS_S00_AXI_SLV_REG2_OFFSET, endThreshold);
}

/* 测量结束函数 */
/* controlAddr 基地址[结束测量&清空触发&结束阈值寄存器]
*/
void systemEnd(u32 controlAddr)
{
        /* 测量开始  */
        PLUSEPROCESS_mWriteReg(controlAddr, PLUSEPROCESS_S00_AXI_SLV_REG0_OFFSET, 0);
        /* 脉冲开始触发阈值 */
        PLUSEPROCESS_mWriteReg(controlAddr, PLUSEPROCESS_S00_AXI_SLV_REG1_OFFSET, 0);
        /* 脉冲结束触发阈值 */
        PLUSEPROCESS_mWriteReg(controlAddr, PLUSEPROCESS_S00_AXI_SLV_REG2_OFFSET, 0);
}

/*--------------------------------------------------------------------------------------------------------------*/

/* DMA初始化函数 */
int XAxiDma_Initial(u16 DeviceId, u16 IntrID, XAxiDma *XAxiDma, XScuGic*InstancePtr)
{
        XAxiDma_Config *CfgPtr;
        int Status;
        /* Look up the hardware configuration for a device instance */
        /* Return the configuration structure for the device. If the device ID is not found,a NULL pointer is returned. */
        CfgPtr = XAxiDma_LookupConfig(DeviceId);
        if (!CfgPtr) {
                xil_printf("No Configuration found for %d\r\n", DeviceId);
                return XST_FAILURE;
        }

        /* initializes a DMA engine.*/
        /* Return XST_SUCCESS for successful initialization. */
        Status = XAxiDma_CfgInitialize(XAxiDma, CfgPtr);
        if (Status != XST_SUCCESS) {
                xil_printf("Initialization failed %d\r\n", Status);
                return XST_FAILURE;
        }

        /* SG mode DMA judgment.*/
        if(XAxiDma_HasSg(XAxiDma)){
                xil_printf("Device configured as SG mode \r\n");
                return XST_FAILURE;
        }

        /* 中断初始化函数 */
        /* Makes the connection between the Int_Id of the interrupt source and the associated handler. */
        /* Return XST_SUCCESS if the handler was connected correctly. */
        Status = XScuGic_Connect(InstancePtr, IntrID,
                        (Xil_ExceptionHandler)Dma_Interrupt_Handler,
                        XAxiDma) ;
        if (Status != XST_SUCCESS) {
                        return Status;
        }

        XScuGic_Enable(InstancePtr, IntrID);


        /* Disable MM2S interrupt, Enable S2MM interrupt IOC */
        XAxiDma_IntrEnable(XAxiDma, XAXIDMA_IRQ_IOC_MASK,
                        XAXIDMA_DEVICE_TO_DMA);
        XAxiDma_IntrDisable(XAxiDma, XAXIDMA_IRQ_ALL_MASK,
                        XAXIDMA_DMA_TO_DEVICE);


        return XST_SUCCESS ;
}

/* 系统中断初始化 */
int SetInterruptInit(XScuGic *InstancePtr, u16 IntrID)
{

        XScuGic_Config * Config ;
        int Status ;

        Config = XScuGic_LookupConfig(IntrID) ;

        Status = XScuGic_CfgInitialize(InstancePtr, Config, Config->CpuBaseAddress) ;
        if (Status != XST_SUCCESS)
                return XST_FAILURE ;

        Xil_ExceptionInit();
        Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
                        (Xil_ExceptionHandler) XScuGic_InterruptHandler,
                        InstancePtr);

        Xil_ExceptionEnable();

        return XST_SUCCESS ;
}


/*--------------------------------------------------------------------------------------------------------------*/

/* 回调函数 */
/* 检查中断状态 & 数据存储*/
void Dma_Interrupt_Handler(void *CallBackRef)
{
        XAxiDma *XAxiDmaPtr ;
        XAxiDmaPtr = (XAxiDma *) CallBackRef ;

        int s2mm_sr ;

        s2mm_sr = XAxiDma_IntrGetIrq(XAxiDmaPtr, XAXIDMA_DEVICE_TO_DMA) ;

        if (s2mm_sr & XAXIDMA_IRQ_IOC_MASK)
        {
                /* Clear interrupt */
                XAxiDma_IntrAckIrq(XAxiDmaPtr, XAXIDMA_IRQ_IOC_MASK,
                                XAXIDMA_DEVICE_TO_DMA) ;
                if (XAxiDmaPtr->RegBase == XPAR_AXIDMA_0_BASEADDR)
                {
                        /* Invalidate the Data cache for the given address range */
                        Xil_DCacheInvalidateRange((INTPTR)DmaRxBuffer, ADC_BYTE*ADC_CAPTURELEN);
                }

        }
}

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则