[X]关闭

AXI DMA_PL2PS接收中断异常

文档创建者:裴宇758
浏览次数:5888
最后更新:2019-03-25
       看了米联客有关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();

}



发表评论已发布 2

裴宇758

发表于 2019-3-21 10:17:43 | 显示全部楼层

问题解决了,是FPGA这边的时钟大于总线的时钟,AXI-DMA这端太快了。怪自己想当然的认为异步的AXI-STR DATAFIFO会处理这个跨时钟域的问题,奈若何是同样的位宽呀

uisrc

发表于 2019-3-25 09:38:41 | 显示全部楼层

回帖奖励 +1 积分

越努力越幸运!加油!
回复

使用道具 举报

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

本版积分规则