一、定义部分
#include "xaxidma.h"
#include "xparameters.h"
#include "xil_printf.h"
#include "xscugic.h"
#define DMA_DEV_ID XPAR_AXIDMA_0_DEVICE_ID
#define INT_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID
#define INTR_ID XPAR_FABRIC_AXI_DMA_0_S2MM_INTROUT_INTR //中断定义
#define FIFO_DATABYTE 4 //字节数
#define TEST_COUNT 80
#define MAX_PKT_LEN TEST_COUNT*FIFO_DATABYTE//发送包长度
#define TEST_START_VALUE 0xC //开始值
#define NUMBER_OF_TRANSFERS 2 //传输次数
/*
* Function declaration //数据检测函数
*/
int XAxiDma_Setup(u16 DeviceId); //
static int CheckData(void);
int SetInterruptInit(XScuGic *InstancePtr, u16 IntrID, XAxiDma *XAxiDmaPtr) ;
XScuGic INST ;
XAxiDma AxiDma;
u8 TxBufferPtr[MAX_PKT_LEN] ;//发送
u8 RxBufferPtr[MAX_PKT_LEN] ;//接收
二、建立中断代码部分
思路:初始化,配置ID和地址--中断处理函数:将ID和中断处理函数连接--启动中断
中断异常:初始化异常--处理异常函数--返回成功。
代码解释:
int SetInterruptInit(XScuGic *InstancePtr, u16 IntrID, XAxiDma *XAxiDmaPtr)
{
XScuGic_Config * Config ; //XAxiDma_Config是一个AXI_DMA配置的信息结构体,它里面包含 需要配置的各种信息,传递给API函数
int Status ;
Config = XScuGic_LookupConfig(INT_DEVICE_ID) ;//初始化,XScuGic_Config其中的中断函数,
Status = XScuGic_CfgInitialize(&INST, Config, Config->CpuBaseAddress) ;//初始化,配置(cfg)地址 ,scugic:系统级中断控制器
if (Status != XST_SUCCESS)
return XST_FAILURE ;
Status = XScuGic_Connect(InstancePtr, IntrID,
(Xil_ExceptionHandler)CheckData,
XAxiDmaPtr) ; //中断设置中断处理函数:将中断ID和中断处理函数连接起来,当中断被识 别后执行相应的处理函数
if (Status != XST_SUCCESS) {
return Status;
}
XScuGic_Enable(InstancePtr, IntrID) ;//启动中断
Xil_ExceptionInit();//通用API,用于ARM处理器中初始化异常处理程序。
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
(Xil_ExceptionHandler) XScuGic_InterruptHandler,
InstancePtr); //为异常情况注册一个处理器,当处理器遇到指定异常时,调用此处理程序。 XIL_EXCEPTION_ID_INT是xilinx处理器定义的。
Xil_ExceptionEnable(); //使能中断(用于控制处理器是否响应中断)异常
return XST_SUCCESS ;
}
三、DMA部分(重要)
思路:初始化DMA-确认sg/simple模式--建立中断系统--启动S2MM中断--赋值--Cache刷新--开始传输接收。
代码:
int XAxiDma_Setup(u16 DeviceId)
{
XAxiDma_Config *CfgPtr;
int Status;
int Tries = NUMBER_OF_TRANSFERS;
int Index;
u8 Value;
/* Initialize the XAxiDma device.
*/
//初始化DMA设备 cfg配置文件 ptr指针记录
CfgPtr = XAxiDma_LookupConfig(DeviceId);//将DMA设备ID赋值给XAxiDma_Config结构体;
if (!CfgPtr) {
xil_printf("No config found for %d\r\n", DeviceId);
return XST_FAILURE;
}
/*初始化DMA引擎,将DMA设备ID赋值给XAxiDma_Config结构体;
* 根据PL端对DMA core的配置参数,PS对DMA进行真正的配置初始化过程,
axidma还存储在PS端的AXI——DMA配置表,根据对PL参数的读取,
PS运行对PL侧的DMA配置,这个配置过程是通过GP0接口对AXI_Lite4总线的控制完成的*/
Status = XAxiDma_CfgInitialize(&AxiDma, CfgPtr);
if (Status != XST_SUCCESS) {
xil_printf("Initialization failed %d\r\n", Status);
return XST_FAILURE;
}
/*sg/simple mode?,如果是SG,则配置失败。
* 配置的是使用PL侧DMA的直接寄存器访问模式,所以数据传递也是通过该方式运行的,
为了以防万一,在这里运行一下SG查询函数看看是不是配置成了SG模式*/
if(XAxiDma_HasSg(&AxiDma)){
xil_printf("Device configured as SG mode \r\n");
return XST_FAILURE;
}
// 建立中断系统
Status = SetInterruptInit(&INST,INTR_ID, &AxiDma) ;
if (Status != XST_SUCCESS)
return XST_FAILURE ;
/* 使能DMA中断, 启动S2MM中断*/
XAxiDma_IntrEnable(&AxiDma, XAXIDMA_IRQ_IOC_MASK,
XAXIDMA_DEVICE_TO_DMA);
XAxiDma_IntrDisable(&AxiDma, XAXIDMA_IRQ_ALL_MASK,
XAXIDMA_DMA_TO_DEVICE);
//对写入数据进行赋值
Value = TEST_START_VALUE;
for(Index = 0; Index < MAX_PKT_LEN; Index ++) {
TxBufferPtr[Index] = Value;
Value = (Value + 1) & 0xFF;
}
/*在DMA传输前刷新SrcBuffer,以防数据缓存。
将要写入fifo的数据刷入Cache */
Xil_DCacheFlushRange((UINTPTR)TxBufferPtr, MAX_PKT_LEN); //刷新Data Cache
Xil_DCacheFlushRange((UINTPTR)RxBufferPtr, MAX_PKT_LEN); //刷新到ddr,Cache关联地址的数据写入到DDR中,并把Cache里的数据清空,将CACHE数据更新到MEMORY
for(Index = 0; Index < Tries; Index ++) {
//开始传输
Status = XAxiDma_SimpleTransfer(&AxiDma,(UINTPTR) TxBufferPtr,
MAX_PKT_LEN, XAXIDMA_DMA_TO_DEVICE);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
//开始接收
Status = XAxiDma_SimpleTransfer(&AxiDma,(UINTPTR) RxBufferPtr,
MAX_PKT_LEN, XAXIDMA_DEVICE_TO_DMA);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
while ((XAxiDma_Busy(&AxiDma,XAXIDMA_DEVICE_TO_DMA)) ||
(XAxiDma_Busy(&AxiDma,XAXIDMA_DMA_TO_DEVICE)))
{
/* Wait */
}
}
/* Test finishes successfully
*/
return XST_SUCCESS;
}
四、数据检测
思路:请求待处理的中断--刷新Cache---检查数据缓冲区--数据验证