DMA 簡介#
DMA 是現代計算機的特色之一,是硬體實現儲存器與儲存器、儲存器與 I/O 設備之間直接進行高速數據傳輸的內存技術,它允許不同速率的設備進行溝通,而不需要依靠 CPU 的中斷負載。
如果不使用 DMA,那麼 CPU 需要從數據源把每一個片段的數據複製到寄存器中,這個過程會一直佔用 CPU 的資源。當使用 DMA 時,CPU 向 DMA 發送一個存儲傳輸請求,當 DMA 控制器收到請求時就會將數據從源地址搬運到目的地址,搬運過程中不消耗 CPU 的資源,當傳輸完成後 DMA 控制器以中斷的方式通知 CPU。
為了發起傳輸事務,DMA 控制器必須有:
- 源地址
- 目的地址
- 傳輸長度
DMA 存儲傳輸的過程如下: - 處理器向 DMA 控制器發送一條 DMA 命令
- DMA 控制器把數據從外設傳輸到儲存器或從儲存器搬運到儲存器,而讓 CPU 騰出手來做其它操作
- 數據傳輸完成後,DMA 控制器向 CPU 發出一個中斷,來通知處理器 DMA 傳輸完成
ZYNQ 提供兩種 DMA,一種是集成在 PS 中的硬核 DMA,一種是 PL 中的軟核 AXI DMA IP。
各種接口方式的比較如下:
PL 的 DMA 和 AXI_HP 接口的傳輸適用於大量數據的高性能傳輸,帶寬高,傳輸方式的拓撲圖如下:
AXI DMA IP#
AXI Direct Memory Access(AXI DMA)IP 核在 AXI 4 內存映射和 AXI 4-Stream IP 接口之間提供高帶寬直接儲存訪問。
AXI DMA 用到了三種總線。AXI 4-Lite 用於對寄存器進行配置,AXI 4 Memory Map 總線用於讀寫 DDR 中的數據,AXI 4 Stream 總線用於 AXI DMA 對外設數據的讀寫,其中 AXI 4 Stream Master(MM 2 S,Memory Map to Stream)接口用於向 PL 寫入數據,AXI 4-Stream Slave (S 2 MM,Stream to Memory Map) 接口用於從 PL 讀取數據。
AXI DMA 提供 3 種模式,分別是 Direct Register 模式、Scatter/Gather 模式和 Cyclic DMA(循環 DMA)模式,常用的是 Direct Register 模式。
Direct Register DMA 模式即 Simple DMA 模式。Direct Register 模式提供了一種配置,用於在 MM 2 S 和 S 2 MM 通道上執行簡單的 DMA 傳輸。Simple DMA(簡單 DMA)允許應用程序在 DMA 和 Device 之間定義單個事務。它有兩個通道:一個從 DMA 到 Device,另一個從 Device 到 DMA。這裡有個地方需要大家注意下,在編寫 Simple DMA(簡單 DMA)代碼時必須設置緩衝區地址和長度字段以啟動相應通道中的傳輸。(其中 PL 對應 Device)
Vivado 中的 IP 配置#
Enable Scatter Gather Engine
選中此選項可啟用 Scatter Gather 模式操作,並在 AXI DMA 中包含 Scatter Gather Engine。取消選中此選項可啟用 Direct Register 模式操作,但不包括 AXI DMA 中的 Scatter Gather Engine。禁用 Scatter Gather Engine 會使 Scatter/Gather Engine 的所有輸出端口都綁定為零,並且所有輸入端口都將保持打開狀態。此處我們取消勾選 Enable Scatter Gather Engine
Enable Micro DMA
使能後會生成高度優化的 DMA,資源消耗較少,用於極少量數據的傳輸
Width of Buffer Length Register
該選項配置了 AXI DMA 單次最大能搬運多少個字節,字節數 $=2^{Width}$
Address Width (32 - 64)
指定地址空間的寬度,可以是 32 到 64 之間的任意值
Enable Read Channel
開啟 AXI DMA 的讀通道 MM 2 S,相關配置如下:
- Number of Channels:指定通道數。保持默認值 1
- Memory Map Data Width:AXI MM 2 S 儲存映射讀取數據總線的數據位寬。有效值為 32、64、128、256、512 和 1024。此處保持默認值 32
- Stream Data Width:AXI MM 2 S AXI 4-Stream 數據總線的數據位寬。該值必須小於或等於 Memory Map Data Width。有效值為 8、16、32、64、128、512 和 1024。此處保持默認值 32
- Max Burst Size:突發分區粒度設置。此設置指定 MM 2 S 的 AXI 4-Memory Map 端的突發周期的最大值。有效值為 2、4、8、16、32、64、128 和 256
- Allow Unaligned Transfers:啟用或禁用 MM 2 S 數據重新排列引擎(Data Realignment Engine,DRE)。選中時,DRE 被使能並允許在 MM 2 S 儲存映射數據路徑上數據重新對齊到 8 位的字節水平。對於 MM 2 S 通道,則從內存中讀取數據。如果 DRE 被使能,則數據讀取可以從任何緩衝區地址字節偏移開始,並且讀取數據被對齊,使得第一個字節讀取是 AXI 4-Stream 上的第一個有效字節輸出
Enable Write Channel
開啟 AXI DMA 的寫通道 S 2 MM,相關配置同上
Vitis 工程解析#
頭文件引用和宏定義#
/***************************** Include Files *********************************/
#include "xaxidma.h"
#include "xparameters.h"
#include "xil_exception.h"
#include "xdebug.h"
#include "xil_util.h"
#ifdef XPAR_UARTNS550_0_BASEADDR
#include "xuartns550_l.h" /* to use uartns550 */
#endif
#ifdef XPAR_INTC_0_DEVICE_ID
#include "xintc.h"
#else
#include "xscugic.h"
#endif
/************************** Constant Definitions *****************************/
/*
* Device hardware build related constants.
*/
#define DMA_DEV_ID XPAR_AXIDMA_0_DEVICE_ID
#ifdef XPAR_AXI_7SDDR_0_S_AXI_BASEADDR
#define DDR_BASE_ADDR XPAR_AXI_7SDDR_0_S_AXI_BASEADDR
#elif defined(XPAR_MIG7SERIES_0_BASEADDR)
#define DDR_BASE_ADDR XPAR_MIG7SERIES_0_BASEADDR
#elif defined(XPAR_MIG_0_C0_DDR4_MEMORY_MAP_BASEADDR)
#define DDR_BASE_ADDR XPAR_MIG_0_C0_DDR4_MEMORY_MAP_BASEADDR
#elif defined(XPAR_PSU_DDR_0_S_AXI_BASEADDR)
#define DDR_BASE_ADDR XPAR_PSU_DDR_0_S_AXI_BASEADDR
#endif
#define DDR_BASE_ADDR XPAR_PS7_DDR_0_S_AXI_BASEADDR // 0x00100000
#ifndef DDR_BASE_ADDR
#warning CHECK FOR THE VALID DDR ADDRESS IN XPARAMETERS.H, \
DEFAULT SET TO 0x01000000
#define MEM_BASE_ADDR 0x01000000
#else
#define MEM_BASE_ADDR (DDR_BASE_ADDR + 0x01000000) // 0x01100000
#endif
#ifdef XPAR_INTC_0_DEVICE_ID
#define RX_INTR_ID XPAR_INTC_0_AXIDMA_0_S2MM_INTROUT_VEC_ID
#define TX_INTR_ID XPAR_INTC_0_AXIDMA_0_MM2S_INTROUT_VEC_ID
#else
#define RX_INTR_ID XPAR_FABRIC_AXIDMA_0_S2MM_INTROUT_VEC_ID
#define TX_INTR_ID XPAR_FABRIC_AXIDMA_0_MM2S_INTROUT_VEC_ID
#endif
#define TX_BUFFER_BASE (MEM_BASE_ADDR + 0x00100000) // 0x01200000
#define RX_BUFFER_BASE (MEM_BASE_ADDR + 0x00300000) // 0x01400000
#define RX_BUFFER_HIGH (MEM_BASE_ADDR + 0x004FFFFF) // 0x015FFFFF
#ifdef XPAR_INTC_0_DEVICE_ID
#define INTC_DEVICE_ID XPAR_INTC_0_DEVICE_ID
#else
#define INTC_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID
#endif
#ifdef XPAR_INTC_0_DEVICE_ID
#define INTC XIntc
#define INTC_HANDLER XIntc_InterruptHandler
#else
#define INTC XScuGic
#define INTC_HANDLER XScuGic_InterruptHandler
#endif
/* Timeout loop counter for reset
*/
#define RESET_TIMEOUT_COUNTER 10000
#define TEST_START_VALUE 0x1
/*
* Buffer and Buffer Descriptor related constant definition
*/
#define MAX_PKT_LEN 0x200
#define NUMBER_OF_TRANSFERS 10
#define POLL_TIMEOUT_COUNTER 1000000U
#define NUMBER_OF_EVENTS 1
#define DDR_BASE_ADDR XPAR_AXI_7SDDR_0_S_AXI_BASEADDR
重新定義了 DDR 3 的基址。數據讀寫的基址為 #define MEM_BASE_ADDR (DDR_BASE_ADDR + 0x01000000) // 0x01100000
AXI DMA 讀取數據的起始地址為 #define TX_BUFFER_BASE (MEM_BASE_ADDR + 0x00100000) // 0x01200000
,寫入地址為 0x01400000
定義函數和聲明相關的 instance 和 flag 變量#
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
#ifndef DEBUG
extern void xil_printf(const char *format, ...);
#endif
#ifdef XPAR_UARTNS550_0_BASEADDR
static void Uart550_Setup(void);
#endif
static int CheckData(int Length, u8 StartValue);
static void TxIntrHandler(void *Callback);
static void RxIntrHandler(void *Callback);
static int SetupIntrSystem(INTC *IntcInstancePtr,
XAxiDma *AxiDmaPtr, u16 TxIntrId, u16 RxIntrId);
static void DisableIntrSystem(INTC *IntcInstancePtr,
u16 TxIntrId, u16 RxIntrId);
/************************** Variable Definitions *****************************/
/*
* Device instance definitions
*/
static XAxiDma AxiDma; /* Instance of the XAxiDma */
static INTC Intc; /* Instance of the Interrupt Controller */
/*
* Flags interrupt handlers use to notify the application context the events.
*/
volatile u32 TxDone;
volatile u32 RxDone;
volatile u32 Error;
Main 函數#
/*****************************************************************************/
/**
*
* Main function
*
* This function is the main entry of the interrupt test. It does the following:
* Set up the output terminal if UART16550 is in the hardware build
* Initialize the DMA engine
* Set up Tx and Rx channels
* Set up the interrupt system for the Tx and Rx interrupts
* Submit a transfer
* Wait for the transfer to finish
* Check transfer status
* Disable Tx and Rx interrupts
* Print test status and exit
*
* @param None
*
* @return
* - XST_SUCCESS if example finishes successfully
* - XST_FAILURE if example fails.
*
* @note None.
*
******************************************************************************/
int main(void)
{
int Status;
XAxiDma_Config *Config;
int Tries = NUMBER_OF_TRANSFERS;
int Index;
u8 *TxBufferPtr;
u8 *RxBufferPtr;
u8 Value;
TxBufferPtr = (u8 *)TX_BUFFER_BASE;
RxBufferPtr = (u8 *)RX_BUFFER_BASE;
/* Initial setup for Uart16550 */
#ifdef XPAR_UARTNS550_0_BASEADDR
Uart550_Setup();
#endif
xil_printf("\r\n--- Entering main() --- \r\n");
Config = XAxiDma_LookupConfig(DMA_DEV_ID);
if (!Config)
{
xil_printf("No config found for %d\r\n", DMA_DEV_ID);
return XST_FAILURE;
}
else
{
xil_printf("Config found for %d\r\n", DMA_DEV_ID);
}
/* Initialize DMA engine */
Status = XAxiDma_CfgInitialize(&AxiDma, Config);
if (Status != XST_SUCCESS)
{
xil_printf("Initialization failed %d\r\n", Status);
return XST_FAILURE;
}
else
{
xil_printf("DMA Initialization success %d\r\n", Status);
}
if (XAxiDma_HasSg(&AxiDma))
{
xil_printf("Device configured as SG mode \r\n");
return XST_FAILURE;
}
else
{
xil_printf("Device configured as simple mode \r\n");
}
/* Set up Interrupt system */
Status = SetupIntrSystem(&Intc, &AxiDma, TX_INTR_ID, RX_INTR_ID);
if (Status != XST_SUCCESS)
{
xil_printf("Failed intr setup\r\n");
return XST_FAILURE;
}
/* Disable all interrupts before setup */
XAxiDma_IntrDisable(&AxiDma, XAXIDMA_IRQ_ALL_MASK,
XAXIDMA_DMA_TO_DEVICE);
XAxiDma_IntrDisable(&AxiDma, XAXIDMA_IRQ_ALL_MASK,
XAXIDMA_DEVICE_TO_DMA);
/* Enable all interrupts */
XAxiDma_IntrEnable(&AxiDma, XAXIDMA_IRQ_ALL_MASK,
XAXIDMA_DMA_TO_DEVICE);
XAxiDma_IntrEnable(&AxiDma, XAXIDMA_IRQ_ALL_MASK,
XAXIDMA_DEVICE_TO_DMA);
/* Initialize flags before start transfer test */
TxDone = 0;
RxDone = 0;
Error = 0;
Value = TEST_START_VALUE;
for (Index = 0; Index < MAX_PKT_LEN; Index++)
{
TxBufferPtr[Index] = Value;
Value = (Value + 1) & 0xFF;
}
/* Flush the buffers before the DMA transfer, in case the Data Cache
* is enabled
*/
Xil_DCacheFlushRange((UINTPTR)TxBufferPtr, MAX_PKT_LEN);
Xil_DCacheFlushRange((UINTPTR)RxBufferPtr, MAX_PKT_LEN);
/* Send a packet */
for (int i = 0; i < Tries; i++)
{
Status = XAxiDma_SimpleTransfer(&AxiDma, (UINTPTR)RxBufferPtr,
MAX_PKT_LEN, XAXIDMA_DEVICE_TO_DMA);
if (Status != XST_SUCCESS)
{
return XST_FAILURE;
}
Status = XAxiDma_SimpleTransfer(&AxiDma, (UINTPTR)TxBufferPtr,
MAX_PKT_LEN, XAXIDMA_DMA_TO_DEVICE);
if (Status != XST_SUCCESS)
{
return XST_FAILURE;
}
Status = Xil_WaitForEventSet(POLL_TIMEOUT_COUNTER, NUMBER_OF_EVENTS, &Error);
if (Status == XST_SUCCESS)
{
if (!TxDone)
{
xil_printf("Transmit error %d\r\n", Status);
goto Done;
}
else if (Status == XST_SUCCESS && !RxDone)
{
xil_printf("Receive error %d\r\n", Status);
goto Done;
}
}
/*
* Wait for TX done or timeout
*/
Status = Xil_WaitForEventSet(POLL_TIMEOUT_COUNTER, NUMBER_OF_EVENTS, &TxDone);
if (Status != XST_SUCCESS)
{
xil_printf("Transmit failed %d\r\n", Status);
goto Done;
}
/*
* Wait for RX done or timeout
*/
Status = Xil_WaitForEventSet(POLL_TIMEOUT_COUNTER, NUMBER_OF_EVENTS, &RxDone);
if (Status != XST_SUCCESS)
{
xil_printf("Receive failed %d\r\n", Status);
goto Done;
}
/*
* Test finished, check data
*/
Status = CheckData(MAX_PKT_LEN, 0x1);
if (Status != XST_SUCCESS)
{
xil_printf("Data check failed\r\n");
goto Done;
}
xil_printf("Transfer %d done\r\n", i + 1);
}
xil_printf("Successfully ran AXI DMA interrupt Example\r\n");
/* Disable TX and RX Ring interrupts and return success */
DisableIntrSystem(&Intc, TX_INTR_ID, RX_INTR_ID);
Done:
xil_printf("--- Exiting main() --- \r\n");
if (Status != XST_SUCCESS)
{
return XST_FAILURE;
}
return XST_SUCCESS;
}
Tries
為測試回環的次數
函數的實現#
/*****************************************************************************/
/*
*
* This function checks data buffer after the DMA transfer is finished.
*
* We use the static tx/rx buffers.
*
* @param Length is the length to check
* @param StartValue is the starting value of the first byte
*
* @return
* - XST_SUCCESS if validation is successful
* - XST_FAILURE if validation is failure.
*
* @note None.
*
******************************************************************************/
static int CheckData(int Length, u8 StartValue)
{
u8 *RxPacket;
int Index = 0;
u8 Value;
RxPacket = (u8 *)RX_BUFFER_BASE;
Value = StartValue;
/* Invalidate the DestBuffer before receiving the data, in case the
* Data Cache is enabled
*/
Xil_DCacheInvalidateRange((UINTPTR)RxPacket, Length);
for (Index = 0; Index < Length; Index++)
{
if (RxPacket[Index] != Value)
{
xil_printf("Data error %d: %x/%x\r\n",
Index, RxPacket[Index], Value);
return XST_FAILURE;
}
Value = (Value + 1) & 0xFF;
}
return XST_SUCCESS;
}
/*****************************************************************************/
/*
*
* This is the DMA TX Interrupt handler function.
*
* It gets the interrupt status from the hardware, acknowledges it, and if any
* error happens, it resets the hardware. Otherwise, if a completion interrupt
* is present, then sets the TxDone.flag
*
* @param Callback is a pointer to TX channel of the DMA engine.
*
* @return None.
*
* @note None.
*
******************************************************************************/
static void TxIntrHandler(void *Callback)
{
u32 IrqStatus;
int TimeOut;
XAxiDma *AxiDmaInst = (XAxiDma *)Callback;
/* Read pending interrupts */
IrqStatus = XAxiDma_IntrGetIrq(AxiDmaInst, XAXIDMA_DMA_TO_DEVICE);
/* Acknowledge pending interrupts */
XAxiDma_IntrAckIrq(AxiDmaInst, IrqStatus, XAXIDMA_DMA_TO_DEVICE);
/*
* If no interrupt is asserted, we do not do anything
*/
if (!(IrqStatus & XAXIDMA_IRQ_ALL_MASK))
{
return;
}
/*
* If error interrupt is asserted, raise error flag, reset the
* hardware to recover from the error, and return with no further
* processing.
*/
if ((IrqStatus & XAXIDMA_IRQ_ERROR_MASK))
{
Error = 1;
/*
* Reset should never fail for transmit channel
*/
XAxiDma_Reset(AxiDmaInst);
TimeOut = RESET_TIMEOUT_COUNTER;
while (TimeOut)
{
if (XAxiDma_ResetIsDone(AxiDmaInst))
{
break;
}
TimeOut -= 1;
}
return;
}
/*
* If Completion interrupt is asserted, then set the TxDone flag
*/
if ((IrqStatus & XAXIDMA_IRQ_IOC_MASK))
{
TxDone = 1;
}
}
/*****************************************************************************/
/*
*
* This is the DMA RX interrupt handler function
*
* It gets the interrupt status from the hardware, acknowledges it, and if any
* error happens, it resets the hardware. Otherwise, if a completion interrupt
* is present, then it sets the RxDone flag.
*
* @param Callback is a pointer to RX channel of the DMA engine.
*
* @return None.
*
* @note None.
*
******************************************************************************/
static void RxIntrHandler(void *Callback)
{
u32 IrqStatus;
int TimeOut;
XAxiDma *AxiDmaInst = (XAxiDma *)Callback;
/* Read pending interrupts */
IrqStatus = XAxiDma_IntrGetIrq(AxiDmaInst, XAXIDMA_DEVICE_TO_DMA);
/* Acknowledge pending interrupts */
XAxiDma_IntrAckIrq(AxiDmaInst, IrqStatus, XAXIDMA_DEVICE_TO_DMA);
/*
* If no interrupt is asserted, we do not do anything
*/
if (!(IrqStatus & XAXIDMA_IRQ_ALL_MASK))
{
return;
}
/*
* If error interrupt is asserted, raise error flag, reset the
* hardware to recover from the error, and return with no further
* processing.
*/
if ((IrqStatus & XAXIDMA_IRQ_ERROR_MASK))
{
Error = 1;
/* Reset could fail and hang
* NEED a way to handle this or do not call it??
*/
XAxiDma_Reset(AxiDmaInst);
TimeOut = RESET_TIMEOUT_COUNTER;
while (TimeOut)
{
if (XAxiDma_ResetIsDone(AxiDmaInst))
{
break;
}
TimeOut -= 1;
}
return;
}
/*
* If completion interrupt is asserted, then set RxDone flag
*/
if ((IrqStatus & XAXIDMA_IRQ_IOC_MASK))
{
RxDone = 1;
}
}
/*****************************************************************************/
/*
*
* This function setups the interrupt system so interrupts can occur for the
* DMA, it assumes INTC component exists in the hardware system.
*
* @param IntcInstancePtr is a pointer to the instance of the INTC.
* @param AxiDmaPtr is a pointer to the instance of the DMA engine
* @param TxIntrId is the TX channel Interrupt ID.
* @param RxIntrId is the RX channel Interrupt ID.
*
* @return
* - XST_SUCCESS if successful,
* - XST_FAILURE.if not successful
*
* @note None.
*
******************************************************************************/
static int SetupIntrSystem(INTC *IntcInstancePtr,
XAxiDma *AxiDmaPtr, u16 TxIntrId, u16 RxIntrId)
{
int Status;
#ifdef XPAR_INTC_0_DEVICE_ID
/* Initialize the interrupt controller and connect the ISRs */
Status = XIntc_Initialize(IntcInstancePtr, INTC_DEVICE_ID);
if (Status != XST_SUCCESS)
{
xil_printf("Failed init intc\r\n");
return XST_FAILURE;
}
Status = XIntc_Connect(IntcInstancePtr, TxIntrId,
(XInterruptHandler)TxIntrHandler, AxiDmaPtr);
if (Status != XST_SUCCESS)
{
xil_printf("Failed tx connect intc\r\n");
return XST_FAILURE;
}
Status = XIntc_Connect(IntcInstancePtr, RxIntrId,
(XInterruptHandler)RxIntrHandler, AxiDmaPtr);
if (Status != XST_SUCCESS)
{
xil_printf("Failed rx connect intc\r\n");
return XST_FAILURE;
}
/* Start the interrupt controller */
Status = XIntc_Start(IntcInstancePtr, XIN_REAL_MODE);
if (Status != XST_SUCCESS)
{
xil_printf("Failed to start intc\r\n");
return XST_FAILURE;
}
XIntc_Enable(IntcInstancePtr, TxIntrId);
XIntc_Enable(IntcInstancePtr, RxIntrId);
#else
XScuGic_Config *IntcConfig;
/*
* Initialize the interrupt controller driver so that it is ready to
* use.
*/
IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID);
if (NULL == IntcConfig)
{
return XST_FAILURE;
}
Status = XScuGic_CfgInitialize(IntcInstancePtr, IntcConfig,
IntcConfig->CpuBaseAddress);
if (Status != XST_SUCCESS)
{
return XST_FAILURE;
}
//設置中斷優先級和觸發類型
XScuGic_SetPriorityTriggerType(IntcInstancePtr, TxIntrId, 0xA0, 0x3);
XScuGic_SetPriorityTriggerType(IntcInstancePtr, RxIntrId, 0xA0, 0x3);
/*
* Connect the device driver handler that will be called when an
* interrupt for the device occurs, the handler defined above performs
* the specific interrupt processing for the device.
*/
//設置中斷處理函數
Status = XScuGic_Connect(IntcInstancePtr, TxIntrId,
(Xil_InterruptHandler)TxIntrHandler,
AxiDmaPtr);
if (Status != XST_SUCCESS)
{
return Status;
}
Status = XScuGic_Connect(IntcInstancePtr, RxIntrId,
(Xil_InterruptHandler)RxIntrHandler,
AxiDmaPtr);
if (Status != XST_SUCCESS)
{
return Status;
}
XScuGic_Enable(IntcInstancePtr, TxIntrId);
XScuGic_Enable(IntcInstancePtr, RxIntrId);
#endif
/* Enable interrupts from the hardware */
Xil_ExceptionInit();
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
(Xil_ExceptionHandler)INTC_HANDLER,
(void *)IntcInstancePtr);
Xil_ExceptionEnable();
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function disables the interrupts for DMA engine.
*
* @param IntcInstancePtr is the pointer to the INTC component instance
* @param TxIntrId is interrupt ID associated w/ DMA TX channel
* @param RxIntrId is interrupt ID associated w/ DMA RX channel
*
* @return None.
*
* @note None.
*
******************************************************************************/
static void DisableIntrSystem(INTC *IntcInstancePtr,
u16 TxIntrId, u16 RxIntrId)
{
#ifdef XPAR_INTC_0_DEVICE_ID
/* Disconnect the interrupts for the DMA TX and RX channels */
XIntc_Disconnect(IntcInstancePtr, TxIntrId);
XIntc_Disconnect(IntcInstancePtr, RxIntrId);
#else
XScuGic_Disconnect(IntcInstancePtr, TxIntrId);
XScuGic_Disconnect(IntcInstancePtr, RxIntrId);
#endif
}