OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 150|回复: 2

[XILINX] ZYNQ7020AXI DMA传输S2MM,XAxiDma_IntrGetIrq返回值为0x05000,怎么回事呀??

[复制链接]

2

主题

4

帖子

0

精华

新手上路

积分
29
金钱
29
注册时间
2018-6-21
在线时间
8 小时
发表于 2025-4-9 10:35:22 | 显示全部楼层 |阅读模式
1金钱
领航者底板,核心板7020;
在AXI DMA环路测试的实例上做了修改,不用PS往外的DMA,在PL端做了一个数据生成的module,往FIFO写数,到1024后给PS中断,PS收到中断后XAxiDma_SimpleTransfer(&axidma,(UINTPTR)rx_buffer_ptr, MAX_PKT_LEN, XAXIDMA_DEVICE_TO_DMA);收数,但是在rx_intr_handler中,XAxiDma_IntrGetIrq(axidma_inst, XAXIDMA_DEVICE_TO_DMA);的返回值为0x05000,没有收到数,怎么回事呢?



无标题1.jpg
无标题2.jpg
无标题3.jpg
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

2

主题

4

帖子

0

精华

新手上路

积分
29
金钱
29
注册时间
2018-6-21
在线时间
8 小时
 楼主| 发表于 2025-4-9 11:04:21 | 显示全部楼层
module data_g
(
    input               axi_clk,
    input               sys_rst,
     
    input               sw_ctrl,
    input  [31:0]       freq,
   
    output [31:0]       axi_tdata,
   output [3:0]        axi_tkeep,
   output              axi_tlast,
    input               axi_tready,
    output              tvalid,
   
    output reg          intr1
);

reg [31:0]      freq1;
reg [15:0]      cnt1;
reg [15:0]      cnt2;
reg [2:0]       cnt3;
reg[31:0]       data_tmp;
reg             valid_tmp;
reg             tlast_tmp;

reg [2:0]       status1;
reg             sw_ctrl1;
wire            sw_ctrl_en;


assign axi_tkeep = 4'b1111;
assign axi_tdata = data_tmp;
assign tvalid = valid_tmp;
assign axi_tlast = tlast_tmp;
// sw_ctrl上升沿检测 两个寄存器  组合逻辑
always @(posedge axi_clk)
begin
    if(!sys_rst)
        begin
            sw_ctrl1 <= 1'b0;
        end
    else
        begin
            sw_ctrl1 <= sw_ctrl;
        end
end
assign sw_ctrl_en = (sw_ctrl & ~sw_ctrl1);

always @(posedge axi_clk)
begin
    if(!sys_rst)
        begin
            freq1 <= 'd200;
        end
    else
        begin
            if(sw_ctrl_en == 1'b1)
            begin
                freq1 <= freq;
            end
        end
end

always @(posedge axi_clk)
begin
    if(!sys_rst)
        begin
            cnt1 <= 16'b0;
        end
    else
        begin
            if(sw_ctrl == 1'b1)
            begin
                if(cnt1 < freq1)
                begin
                    cnt1 <= cnt1 + 16'b1;
                end
                else
                begin
                    cnt1 <= 16'b0;
                end
            end
            else
            begin
                cnt1 <= 16'b0;
            end
        end
end

always @(posedge axi_clk)
begin
    if(!sys_rst)
    begin
        data_tmp <= 32'b0;
        status1 <= 3'b0;
        valid_tmp <= 1'b0;
        cnt2 <= 16'b0;
        intr1 <= 1'b0;
        tlast_tmp <= 1'b0;
    end
    else
    begin
       case(status1)   
            0:begin
                intr1 <= 1'b0;
                tlast_tmp <= 1'b0;
                if(cnt1 == freq1)
                begin
                    status1 <= 3'b001;
                    //valid_tmp <= 1'b1;
                   // data_tmp <= data_tmp + 32'b1;
                end
                else
                begin
                    status1 <= 3'b000;  
                end
            end  
             1:begin
                valid_tmp <= 1'b1;
                if(axi_tready == 1'b1)
                begin
                    status1 <= 3'b010;
                end
            end     
             2:begin
                valid_tmp <= 1'b0;
                data_tmp <= data_tmp + 32'b1;
                status1 <= 3'b011;
            end
            3:begin
                valid_tmp <= 1'b1;
                if(axi_tready == 1'b1)
                begin
                    status1 <= 3'b100;
                end
            end
            4:begin
                if(cnt2 < 'd1024)
                begin
                    valid_tmp <= 1'b0;
                    data_tmp <= data_tmp + 32'b1;
                    status1 <= 3'b000;               
                    cnt2 <= cnt2 + 16'b0000000000000010;                    
                end
                if(cnt2 > 'd1020)
                begin
                    intr1 <= 1'b1;
                    tlast_tmp <= 1'b1;
                    status1 <= 3'b100;
                   // cnt2 <= 16'b000000000000000;
                end
            end
       endcase
    end
end

endmodule
回复

使用道具 举报

2

主题

4

帖子

0

精华

新手上路

积分
29
金钱
29
注册时间
2018-6-21
在线时间
8 小时
 楼主| 发表于 2025-4-9 11:05:21 | 显示全部楼层
#include "stdio.h"
#include "xaxidma.h"
#include "xparameters.h"
#include "xil_exception.h"
#include "xscugic.h"
#include "AXI4_Lite.h"
#include "sleep.h"


/************************** Constant Definitions *****************************/

#define DMA_DEV_ID XPAR_AXIDMA_0_DEVICE_ID
#define RX_INTR_ID XPAR_FABRIC_AXIDMA_0_VEC_ID
//#define TX_INTR_ID XPAR_FABRIC_AXIDMA_0_MM2S_INTROUT_VEC_ID
#define INTC_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID
#define DDR_BASE_ADDR XPAR_PS7_DDR_0_S_AXI_BASEADDR //0x00100000
#define MEM_BASE_ADDR (DDR_BASE_ADDR + 0x1000000) //0x01100000
//#define TX_BUFFER_BASE (MEM_BASE_ADDR + 0x00100000) //0x01200000
#define RX_BUFFER_BASE (MEM_BASE_ADDR + 0x00100000) //0x01400000

#define AXI4_lite_IP_BASEADDR XPAR_AXI4_LITE_0_S0_AXI_BASEADDR //AXI4_lite IP 基地址
#define AXI4_lite_IP_REG0 AXI4_LITE_S0_AXI_SLV_REG0_OFFSET //AXI4_lite IP 寄存器地址 0
#define AXI4_lite_IP_REG1 AXI4_LITE_S0_AXI_SLV_REG1_OFFSET //AXI4_lite IP 寄存器地址 1

#define RESET_TIMEOUT_COUNTER 10000 //复位时间
#define TEST_START_VALUE 0x0 //测试起始值
#define MAX_PKT_LEN 4096 //发送包长度

/************************** Function Prototypes ******************************/

//static void tx_intr_handler(void *callback);
static void rx_intr_handler(void *callback);

static void Devicd_intr_handler();
static int setup_intr_system(XScuGic * int_ins_ptr, XAxiDma * axidma_ptr, u16 rx_intr_id, u16 intr_id1);
static void disable_intr_system(XScuGic * int_ins_ptr, u16 rx_intr_id, u16 intr_id1);

/************************** Variable Definitions *****************************/

static XAxiDma axidma; //XAxiDma 实例
static XScuGic intc; //中断控制器的实例
volatile int rx_done; //接收完成标志
volatile int error; //传输出错标志
volatile int Index;
/************************** Function Definitions *****************************/

int main(void)
{
        int status;
        u8 *rx_buffer_ptr;
        XAxiDma_Config *config;

        //rx_buffer_ptr = (u8 *)RX_BUFFER_BASE;
        Index = 0;
        rx_done = 0;
        xil_printf("\r\n---Entering main()---\r\r");

        config = XAxiDma_LookupConfig(DMA_DEV_ID);//查找DMA控制器的配置信息
        if(!config)
        {
                xil_printf("No config found for %d\r\n",DMA_DEV_ID);
                return XST_FAILURE;
        }

        //初始化DMA引擎
        status = XAxiDma_CfgInitialize(&axidma,config);
        if(status != XST_SUCCESS)
        {
                xil_printf("Initialization failed %d\r\n", status);
                return XST_FAILURE;
        }

        if(XAxiDma_HasSg(&axidma))
        {
                xil_printf("Device configured as SG mode \r\n");
                return XST_FAILURE;
        }

        //建立中断系统
        status = setup_intr_system(&intc, &axidma,  RX_INTR_ID, XPS_FPGA0_INT_ID);
        if(status != XST_SUCCESS)
        {
                xil_printf("Failed intr setup\r\n");
                return XST_FAILURE;
        }

        AXI4_LITE_mWriteReg(AXI4_lite_IP_BASEADDR,AXI4_lite_IP_REG1,100);
        AXI4_LITE_mWriteReg(AXI4_lite_IP_BASEADDR,AXI4_lite_IP_REG0,100);
        //usleep(50);
//        while(1)
//                ;
//        AXI4_LITE_mWriteReg(AXI4_lite_IP_BASEADDR,AXI4_lite_IP_REG0,100);
        while(Index == 0)
                ;
        rx_buffer_ptr = (u8 *)RX_BUFFER_BASE;
        status = XAxiDma_SimpleTransfer(&axidma,(UINTPTR)rx_buffer_ptr, MAX_PKT_LEN, XAXIDMA_DEVICE_TO_DMA);
        if(status != XST_SUCCESS)
        {
                return XST_FAILURE;
        }
        while(rx_done == 0)
                        ;
        xil_printf("Successfully ran AXI DMA Loop\r\n");
        disable_intr_system(&intc, RX_INTR_ID, XPS_FPGA0_INT_ID);

        xil_printf("---Exiting main()---\r\n");
        return XST_SUCCESS;
}

//DMA RX 中断处理函数
static void rx_intr_handler(void *callback)
{
        u32 irq_status;
        int timeout;
        XAxiDma *axidma_inst = (XAxiDma *) callback;

        irq_status = XAxiDma_IntrGetIrq(axidma_inst, XAXIDMA_DEVICE_TO_DMA);
        XAxiDma_IntrAckIrq(axidma_inst, irq_status, XAXIDMA_DEVICE_TO_DMA);

        //Rx出错
        if((irq_status &XAXIDMA_IRQ_ERROR_MASK))
        {
                error = 1;
                XAxiDma_Reset(axidma_inst);
                timeout = RESET_TIMEOUT_COUNTER;
                while(timeout)
                {
                        if(XAxiDma_ResetIsDone(axidma_inst))
                                break;
                        timeout -= 1;
                }
                return;
        }

        //Rx完成
        if((irq_status &XAXIDMA_IRQ_IOC_MASK))
                rx_done = 1;
}


static void Devicd_intr_handler()
{

        AXI4_LITE_mWriteReg(AXI4_lite_IP_BASEADDR,AXI4_lite_IP_REG0,100);
        Index = 1;

}


//建立 DMA 中断系统
// @param int_ins_ptr 是指向 XScuGic 实例的指针
// @param AxiDmaPtr 是指向 DMA 引擎实例的指针
// @param tx_intr_id 是 TX 通道中断 ID
// @param rx_intr_id 是 RX 通道中断 ID
// @return:成功返回 XST_SUCCESS,否则返回 XST_FAILURE
static int setup_intr_system(XScuGic * int_ins_ptr,XAxiDma * axidma_ptr, u16 rx_intr_id, u16 intr_id1)
{
        int status;
        XScuGic_Config *intc_config;

        //初始化中断控制器驱动
        intc_config = XScuGic_LookupConfig(INTC_DEVICE_ID);
        if(NULL == intc_config)
        {
                return XST_FAILURE;
        }
        status = XScuGic_CfgInitialize(int_ins_ptr, intc_config, intc_config->CpuBaseAddress);
        if (status != XST_SUCCESS)
        {
                return XST_FAILURE;
        }

        //设置优先级和触发类型
        XScuGic_SetPriorityTriggerType(int_ins_ptr, rx_intr_id, 0xA0, 0x3);
        XScuGic_SetPriorityTriggerType(int_ins_ptr, intr_id1, 0xA0, 0x3);

        //为中断设置中断处理函数
        status = XScuGic_Connect(int_ins_ptr, rx_intr_id, (Xil_InterruptHandler)rx_intr_handler,axidma_ptr);
        if(status != XST_SUCCESS)
        {
                return status;
        }
        status = XScuGic_Connect(int_ins_ptr, intr_id1, (Xil_InterruptHandler)Devicd_intr_handler,(void *)1);
        if(status != XST_SUCCESS)
        {
                return status;
        }

        XScuGic_Enable(int_ins_ptr, rx_intr_id);
        XScuGic_Enable(int_ins_ptr, intr_id1);

        //启用来自硬件的中断
        Xil_ExceptionInit();
        Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, (Xil_ExceptionHandler)XScuGic_InterruptHandler, (void *)int_ins_ptr);
        Xil_ExceptionEnable();

        //使能DMA中断
        XAxiDma_IntrEnable(&axidma, XAXIDMA_IRQ_ALL_MASK, XAXIDMA_DEVICE_TO_DMA);

        return XST_SUCCESS;
}

//此函数禁用 DMA 引擎的中断
static void disable_intr_system(XScuGic * int_ins_ptr, u16 rx_intr_id, u16 intr_id1)
{
        XScuGic_Disconnect(int_ins_ptr, rx_intr_id);
        XScuGic_Disconnect(int_ins_ptr, intr_id1);
}
回复

使用道具 举报

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

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-4-21 10:41

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表