背景:自定义了一个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);
}
}
}
|