看了米联客有关DMA的视频和博客,启发很大,于是乎搭建了自己的AXI DMA系统。本人是学校学生,用的开发板是实验室的zedboard。在进行DMA LOOP测试时未发现任何问题,收发正常,可是在进行AXI DMA PL2PS的测试时确出现了发送正常,接受错误的情况,具体是接收中断异常产生。恳请大家帮帮忙,我现在这里谢过了。
本次移植工程中,与米联客教程有所不同是采用32位数据位宽,其他的硬件设置未有不同。相应的MAX_PKT_LEN也从2048改为4096。
RTL代码如下:
module axi_dma_pl2ps
(DDR_addr,
DDR_ba,
DDR_cas_n,
DDR_ck_n,
DDR_ck_p,
DDR_cke,
DDR_cs_n,
DDR_dm,
DDR_dq,
DDR_dqs_n,
DDR_dqs_p,
DDR_odt,
DDR_ras_n,
DDR_reset_n,
DDR_we_n,
FIXED_IO_ddr_vrn,
FIXED_IO_ddr_vrp,
FIXED_IO_mio,
FIXED_IO_ps_clk,
FIXED_IO_ps_porb,
FIXED_IO_ps_srstb,
UART1_RX_0,
UART1_TX_0
);
inout [14:0]DDR_addr;
inout [2:0]DDR_ba;
inout DDR_cas_n;
inout DDR_ck_n;
inout DDR_ck_p;
inout DDR_cke;
inout DDR_cs_n;
inout [3:0]DDR_dm;
inout [31:0]DDR_dq;
inout [3:0]DDR_dqs_n;
inout [3:0]DDR_dqs_p;
inout DDR_odt;
inout DDR_ras_n;
inout DDR_reset_n;
inout DDR_we_n;
inout FIXED_IO_ddr_vrn;
inout FIXED_IO_ddr_vrp;
inout [53:0]FIXED_IO_mio;
inout FIXED_IO_ps_clk;
inout FIXED_IO_ps_porb;
inout FIXED_IO_ps_srstb;
input UART1_RX_0;
output UART1_TX_0;
wire [14:0]DDR_addr;
wire [2:0]DDR_ba;
wire DDR_cas_n;
wire DDR_ck_n;
wire DDR_ck_p;
wire DDR_cke;
wire DDR_cs_n;
wire [3:0]DDR_dm;
wire [31:0]DDR_dq;
wire [3:0]DDR_dqs_n;
wire [3:0]DDR_dqs_p;
wire DDR_odt;
wire DDR_ras_n;
wire DDR_reset_n;
wire DDR_we_n;
wire FCLK_CLK1_0;
wire FIXED_IO_ddr_vrn;
wire FIXED_IO_ddr_vrp;
wire [53:0]FIXED_IO_mio;
wire FIXED_IO_ps_clk;
wire FIXED_IO_ps_porb;
wire FIXED_IO_ps_srstb;
wire UART1_RX_0;
wire UART1_TX_0;
wire peripheral_aresetn;
wire [0:0]gpio_rtl_0_tri_i_0;
wire [0:0]gpio_rtl_0_tri_io_0;
wire [0:0]gpio_rtl_0_tri_o_0;
wire [0:0]gpio_rtl_0_tri_t_0;
//user logic
//时钟
wire m_axis_aclk_0;
wire m_axis_aresetn_0;
wire s_axis_aclk_0;
wire s_axis_aresetn_0;
//M_AXIS
wire [31:0] M_AXIS_0_tdata; //ad数据
wire [3:0] M_AXIS_0_tkeep;
wire M_AXIS_0_tlast;
wire M_AXIS_0_tready;
wire M_AXIS_0_tvalid;
assign M_AXIS_0_tready=1'b1;
//S_AXIS
reg [31:0] ad_data; //ad数据
wire [3:0] S_AXIS_tkeep;
reg S_AXIS_tlast;
wire S_AXIS_tready;
reg S_AXIS_tvalid;
reg [1:0] state;
assign s_axis_aclk_0 = FCLK_CLK1_0;
assign m_axis_aclk_0 = FCLK_CLK1_0;
assign m_axis_aresetn_0 = peripheral_aresetn;
assign s_axis_aresetn_0 = peripheral_aresetn;
assign S_AXIS_tkeep = 4'b1111;
always@(posedge FCLK_CLK1_0)
begin
if(!peripheral_aresetn) begin
S_AXIS_tvalid <= 1'b0;
ad_data <= 32'd0;
S_AXIS_tlast <= 1'b0;
state <=0;
end
else begin
case(state)
0: begin
if(gpio_rtl_0_tri_o_0&& S_AXIS_tready) begin //启动接收
S_AXIS_tvalid <= 1'b1;
state <= 1;
end
else begin
S_AXIS_tvalid <= 1'b0;
state <= 0;
end
end
1:begin //发0-1023
if(S_AXIS_tready) begin
ad_data <= ad_data + 1'b1;
if(ad_data == 32'd1022) begin
S_AXIS_tlast <= 1'b1;
state <= 2;
end
else begin
S_AXIS_tlast <= 1'b0;
state <= 1;
end
end
else begin
ad_data <= ad_data;
state <= 1;
end
end
2:begin
if(!S_AXIS_tready) begin
S_AXIS_tvalid <= 1'b1;
S_AXIS_tlast <= 1'b1;
ad_data <= ad_data;
state <= 2;
end
else begin
S_AXIS_tvalid <= 1'b0;
S_AXIS_tlast <= 1'b0;
ad_data <= 32'd0;
state <= 0;
end
end
default: state <=0;
endcase
end
end
design_1 design_1_i
(.DDR_addr(DDR_addr),
.DDR_ba(DDR_ba),
.DDR_cas_n(DDR_cas_n),
.DDR_ck_n(DDR_ck_n),
.DDR_ck_p(DDR_ck_p),
.DDR_cke(DDR_cke),
.DDR_cs_n(DDR_cs_n),
.DDR_dm(DDR_dm),
.DDR_dq(DDR_dq),
.DDR_dqs_n(DDR_dqs_n),
.DDR_dqs_p(DDR_dqs_p),
.DDR_odt(DDR_odt),
.DDR_ras_n(DDR_ras_n),
.DDR_reset_n(DDR_reset_n),
.DDR_we_n(DDR_we_n),
.FCLK_CLK1_0(FCLK_CLK1_0),
.FIXED_IO_ddr_vrn(FIXED_IO_ddr_vrn),
.FIXED_IO_ddr_vrp(FIXED_IO_ddr_vrp),
.FIXED_IO_mio(FIXED_IO_mio),
.FIXED_IO_ps_clk(FIXED_IO_ps_clk),
.FIXED_IO_ps_porb(FIXED_IO_ps_porb),
.FIXED_IO_ps_srstb(FIXED_IO_ps_srstb),
.M_AXIS_0_tdata(M_AXIS_0_tdata),
.M_AXIS_0_tkeep(M_AXIS_0_tkeep),
.M_AXIS_0_tlast(M_AXIS_0_tlast),
.M_AXIS_0_tready(M_AXIS_0_tready),
.M_AXIS_0_tvalid(M_AXIS_0_tvalid),
.S_AXIS_0_tdata(ad_data),
.S_AXIS_0_tkeep(S_AXIS_tkeep),
.S_AXIS_0_tlast(S_AXIS_tlast),
.S_AXIS_0_tready(S_AXIS_tready),
.S_AXIS_0_tvalid(S_AXIS_tvalid),
.UART1_RX_0(UART1_RX_0),
.UART1_TX_0(UART1_TX_0),
.gpio_rtl_0_tri_i(gpio_rtl_0_tri_i_0),
.gpio_rtl_0_tri_o(gpio_rtl_0_tri_o_0),
.gpio_rtl_0_tri_t(gpio_rtl_0_tri_t_0),
.peripheral_aresetn(peripheral_aresetn),
.m_axis_aclk_0(m_axis_aclk_0),
.m_axis_aresetn_0(m_axis_aresetn_0),
.s_axis_aclk_0(s_axis_aclk_0),
.s_axis_aresetn_0(s_axis_aresetn_0));
endmodule
SDK中主程序c代码如下:
/*
*
* www.osrc.cn
* www.milinker.com
* copyright by nan jin mi lian dian zi www.osrc.cn
* axi dma test
*
*/
#include "dma_intr.h"
#include "timer_intr.h"
#include "sys_intr.h"
#include "xgpio.h"
#include <string.h>
#include <stdlib.h>
static XScuGic Intc; //GIC
static XAxiDma AxiDma;
static XScuTimer Timer;//timer
volatile u32 RX_success;
volatile u32 TX_success;
volatile u32 RX_ready=1;
volatile u32 TX_ready=1;
#define TIMER_LOAD_VALUE 166666665 //0.5S
char oled_str[17]="";
int Tries = NUMBER_OF_TRANSFERS;
int i;
int Index;
u32 *TxBufferPtr= (u32 *)TX_BUFFER_BASE;
u32 *RxBufferPtr=(u32 *)RX_BUFFER_BASE;
u32 Value=0;
float speed_tx;
float speed_rx;
static XGpio Gpio;
#define AXI_GPIO_DEV_ID XPAR_AXI_GPIO_0_DEVICE_ID
int axi_dma_test()
{
int Status;
TxDone = 0;
RxDone = 0;
Error = 0;
int u =0;
xil_printf("PKT_LEN=%d\r\n",MAX_PKT_LEN);
sprintf(oled_str,"PKT_LEN=%d",MAX_PKT_LEN);
for(Index = 0; Index < MAX_PKT_LEN; Index ++) {
TxBufferPtr[Index] = Value;
Value = (Value + 1) & 0xFF;
}
/* Flush the SrcBuffer before the DMA transfer, in case the Data Cache
* is enabled
*/
//Xil_DCacheFlushRange((u32)RxBufferPtr, MAX_PKT_LEN);
Timer_start(&Timer);
while(1)
//for(i = 0; i < 50; i ++)
{
//RX DMA Transfer
if(RX_ready)
{
RX_ready=0;
Status = XAxiDma_SimpleTransfer(&AxiDma,(u32)RxBufferPtr,
(u32)(MAX_PKT_LEN), XAXIDMA_DEVICE_TO_DMA);
xil_printf("ilyzsn");
if (Status != XST_SUCCESS) {
xil_printf("rx_errr");
return XST_FAILURE;
}
}
if(RxDone)
{
RxDone=0;
RX_ready=1;
RX_success++;
xil_printf("rx_xnt=%d\r\n",RX_success);
}
for(int j=0; j<10000; j++)
u =0;
Xil_DCacheFlushRange((u32)TxBufferPtr, MAX_PKT_LEN);
//TX DMA Transfer
if(TX_ready)
{
TX_ready=0;
Status = XAxiDma_SimpleTransfer(&AxiDma,(u32) TxBufferPtr,
(u32)(MAX_PKT_LEN), XAXIDMA_DMA_TO_DEVICE);
if (Status != XST_SUCCESS) {return XST_FAILURE;}
}
if(TxDone)
{
TxDone=0;
TX_ready=1;
TX_success++;
xil_printf("tx_cnt=%d\r\n",TX_success);
}
if (Error) {
xil_printf("Failed test transmit%s done, "
"receive%s done\r\n", TxDone? "":" not",
RxDone? "":" not");
goto Done;
}
}
/* Disable TX and RX Ring interrupts and return success */
DMA_DisableIntrSystem(&Intc, TX_INTR_ID, RX_INTR_ID);
Done:
xil_printf("--- Exiting Test --- \r\n");
return XST_SUCCESS;
}
int init_intr_sys(void)
{
DMA_Intr_Init(&AxiDma,0);//initial interrupt system
Timer_init(&Timer,TIMER_LOAD_VALUE,0);
Init_Intr_System(&Intc); // initial DMA interrupt system
Setup_Intr_Exception(&Intc);
DMA_Setup_Intr_System(&Intc,&AxiDma,TX_INTR_ID,RX_INTR_ID);//setup dma interrpt system
Timer_Setup_Intr_System(&Intc,&Timer,TIMER_IRPT_INTR);
DMA_Intr_Enable(&Intc,&AxiDma);
}
int main(void)
{
XGpio_Initialize(&Gpio, AXI_GPIO_DEV_ID);
XGpio_SetDataDirection(&Gpio, 1, 0);
init_intr_sys();
XGpio_DiscreteWrite(&Gpio, 1, 1); //GPIO拉高开启PL端数据传输
axi_dma_test();
}
|
|