【【SOC设计之 数据回路从 DMA到 FIFO再到BRAM 再到FIFO 再写回DMA】】

news2024/11/17 6:28:38

SOC设计之 数据回路从 DMA到 FIFO再到BRAM 再到FIFO 再写回DMA

基本没问题的回路设计
从 DMA出发将数据传递到 FIFO 再 写到 自定义的 RTL文件中 再写到 BRAM 再到 自定义的RTL文件 再到 FIFO 再写回DMA

block design 的 设计连接 可以参考我上一个文件的设计
在这里插入图片描述
下面介绍两个control1.v

control1.v

//11_11 this is new building for real control11
module control11 #(
    parameter      FIFO_CONTROL1_DATA      =       32 ,
    parameter      FIFO_CONTROL1_KEEP      =       4  ,
    parameter      ADDRESSA_WIDTH          =       17 ,
    parameter      ONECONTROL              =       8  ,
    parameter      DINA_WIDTH              =       32
  )(
    // connect fifo
    input                                            sys_clk              ,
    input                                            sys_rst_n            ,
    input    [FIFO_CONTROL1_KEEP - 1 : 0]            control1_tkeep       , // 4
    input    [FIFO_CONTROL1_DATA - 1 : 0]            control1_tdata       ,
    input                                            control1_tlast       ,
    output  reg                                      control1_tready      ,
    input                                            control1_tvaild      ,

    // next is connect BRAM
    output  reg  [ADDRESSA_WIDTH - 1 : 0]                addressa        ,
    output  reg  [DINA_WIDTH - 1 : 0]                    dina            ,
    output  reg                                          ena             ,
    output  reg                                          wea             ,
    output  reg  [ADDRESSA_WIDTH : 0]                    finish
  );

  //===================================================================\\
  //                               internal signal                      \\
  //====================================================================\\
  //wire [FIFO_CONTROL1_KEEP - 1 : 0] tkeep ;
  //assign tkeep = control1_tkeep ;

  //  we can use tlast tell me when the send is finish and the last addressa is what



  reg [2 : 0]  mode   ;

  //reg [DINA_WIDTH - 1 : 0] data_keep  ;
  //reg [ADDRESSA_WIDTH - 1 : 0] addressa_keep ;

 //  how to put control1_tdata and keep  together   control1_tkeep

wire [ONECONTROL - 1 : 0] control1_tdata_0 ;    // 7- 0
wire [ONECONTROL - 1 : 0] control1_tdata_1 ;    // 15 - 8
wire [ONECONTROL - 1 : 0] control1_tdata_2 ;    // 23 - 16
wire [ONECONTROL - 1 : 0] control1_tdata_3 ;    // 31 - 24 
wire [FIFO_CONTROL1_DATA - 1 : 0] control1_tdata_total ;

assign control1_tdata_0 = (control1_tkeep[0] == 1) ? control1_tdata[7 : 0] : 8'b0 ;
assign control1_tdata_1 = (control1_tkeep[1] == 1) ? control1_tdata[15 : 8] : 8'b0 ;
assign control1_tdata_2 = (control1_tkeep[2] == 1) ? control1_tdata[23 : 16] : 8'b0 ;
assign control1_tdata_3 = (control1_tkeep[3] == 1) ? control1_tdata[31 : 24] : 8'b0 ; 
assign control1_tdata_total = {control1_tdata_3,control1_tdata_2,control1_tdata_1,control1_tdata_0} ;


// we need get the number delay 




//reg write ;








  //===================================================================\\
  //               next is main code                                   \\
  //====================================================================\\

  always@(posedge sys_clk or negedge sys_rst_n)
  begin
    if(sys_rst_n == 0)
    begin
      control1_tready     <=  1          ;
      addressa            <=  0          ;
      dina                <=  0          ;
      ena                 <=  0          ;
      wea                 <=  0          ;
      mode                <=  0          ;
     // write               <=  0          ;
    end
    else
    begin
      case(mode)
        3'b000 :
        begin
          if((control1_tvaild && control1_tready && control1_tdata_total) == 0  )
          begin
            addressa   <=   addressa    ;
            dina       <=   dina        ;
            ena        <=   0           ;
            wea        <=   0           ;
            mode       <=   0           ;
         //   write      <=  0            ;
          end
          else
          begin
           // addressa   <=   addressa    ;
            //dina       <=   control1_tdata_total  ;
            //ena        <=   1           ;
           // wea        <=   1           ;
          //  write             <=  0       ;
            mode       <=   3'b001;
          end
        end

        3'b001 : // send addressa and dina
          begin
            control1_tready   <=  0               ;
            addressa          <=  addressa + 4    ;
            dina              <=  control1_tdata_total  ;
            ena               <=  1               ;
            wea               <=  1               ;
          //  write             <=  0               ;
            mode              <=  3'b010          ;
          end
        

        3'b010 :
        begin
          if(control1_tlast == 1)
          begin
            addressa   <=   addressa    ;
            dina       <=   dina        ;
            ena        <=   0           ;
            wea        <=   0           ;
            mode       <=   0           ;
         //   write      <=   0               ;
          end
          else
          begin
            control1_tready   <=  1               ;
            addressa          <=  addressa        ;
            dina              <=  dina            ;
            ena               <=  0               ;
            wea               <=  0               ;
          //  write             <=  1               ;
            mode              <=  3'b001          ;
          end
        end



        default :
        begin
          control1_tready   <=  1               ;
          addressa          <=  addressa     ;
          dina              <=  dina            ;
          ena               <=  0               ;
          wea               <=  0               ;
          mode              <=  0               ;
        end
      endcase       
    end
  end
  // we can use finish send the adress and tlast
  always@(posedge sys_clk or negedge sys_rst_n)
  begin
    if(sys_rst_n == 0)
    begin
      finish <= 0 ;
    end
    else if(control1_tlast == 1)
    begin
      finish <= {addressa,control1_tlast} ;
    end
    else
      finish <= 0 ;
  end
endmodule

control2.v

// this is 11_11 new building for control22
module control22 #(
    parameter        FINISH_WIDTH     =       17   ,
    parameter        DATA_WIDTH       =       32   ,
    parameter        TKEEP_WIDTH      =       4
  )(
    input     sys_clk ,
    input     sys_rst_n ,
    // from control11
    input      [FINISH_WIDTH : 0]       finish_control22   ,

    // connect BRAM
    output reg                             enb                ,
    output reg    [FINISH_WIDTH - 1 : 0]   addressb           ,
    input         [DATA_WIDTH - 1 : 0]     doutb              ,

    // connect  FIFO
    output reg    [DATA_WIDTH - 1 : 0]     tdata              ,
    output reg       [TKEEP_WIDTH - 1 : 0]    tkeep              ,
    output                              tlast              ,
    output reg                             tvaild             ,
    input                               tready
  );

  //===========================================================\\
  //                     internal signal                       \\
  //===========================================================\\

  //assign tkeep = {TKEEP_WIDTH{1'b1}} ;
  reg [2 : 0] mode ;

  //reg  [FINISH_WIDTH - 1 : 0] addressb_keep ;


  //===========================================================\\
  //             next is main code                             \\
  //============================================================\\
  // finish_control22
  // doutb
  // tready

  //tlast


  assign tlast = (addressb >= finish_control22[FINISH_WIDTH : 1] && addressb != 0)  ? 1 : 0  ;


  //assign tvaild = (finish_control22[0] == 1 && (addressb != finish_control22[FINISH_WIDTH : 1])) ? 1 : 0 ;



  always@(posedge sys_clk or negedge sys_rst_n)
  begin
    if(sys_rst_n == 0)
    begin
      enb       <= 0          ;
      addressb  <= 0          ;
      tdata     <= 0          ;
      tvaild    <= 0           ;
      mode      <= 0          ;
      tkeep    <={TKEEP_WIDTH{1'b0}} ;
    end
    else
    begin
      case(mode)
        3'b000 :
        begin
          if( (tready && finish_control22[0]) == 0)
          begin
            enb <= 0 ;
            tdata    <= 0          ;
            addressb  <= addressb      ;
            mode     <= 0               ;
            tvaild   <=  0              ;
            tkeep    <={TKEEP_WIDTH{1'b0}} ;
          end
          else
          begin
            tvaild <= 1    ;
            mode <= 3'b001 ;
            // tlast    <=(addressb == finish_control22[FINISH_WIDTH : 1] && addressb != 0)  ? 1 : 0 ;
            //tkeep    <={TKEEP_WIDTH{1'b1}} ;
          end
        end
        3'b001 :
        begin
          if((tready && tvaild) == 1)
          begin
            tvaild    <=  0                   ;
            enb       <=  1                   ;
            addressb  <=  addressb + 4        ;
            tdata     <=  doutb               ;
            tkeep    <={TKEEP_WIDTH{1'b1}} ;

            mode      <=  3'b010              ;
          end
          else
          begin
            mode <= 3'b000 ;
          end
        end


        3'b010 :
          // begin
          //  if(tlast == 1)begin
          //   enb           <= 0                    ;
          //  addressb      <= addressb               ;
          //   tdata         <= tdata                ;
          //  tvaild        <= 0                    ;
          //   mode          <= 3'b010            ;
          //   tkeep    <={TKEEP_WIDTH{1'b1}} ;

          //  end
          // else
        begin
          enb           <= 0                    ;
          addressb      <= addressb               ;
          tdata         <= tdata                ;
          tvaild        <= 1                    ;
          mode          <= 3'b001            ;
          tkeep    <={TKEEP_WIDTH{1'b1}} ;
        end
        // end



        default :
        begin
          tvaild        <= 0                    ;
          enb           <= 0                    ;
          addressb      <= addressb             ;
          tdata         <= tdata                ;
          mode          <= 0                    ;
          tkeep    <={TKEEP_WIDTH{1'b0}} ;
        end
      endcase
    end
  end

endmodule

下面是SDK的 C语言代码

#include "xparameters.h"  //包含vivado所导出的信息包含vivado的基地址
#include "xil_printf.h"   //调用打印函数的时候,需要引用这个头文件
#include "ff.h"           //使用FATFS库函数时需要
#include "xstatus.h"      //需要的一些关键信息
#include"stdio.h"         // 专业写法
#include "xdevcfg.h"
#include "xil_io.h"
/下面讲述关于 DMA
#include "xaxidma.h"
#include "xparameters.h"
#include "xil_exception.h"
#include "xscugic.h"
#include "sleep.h"

/************************** Variable Definitions *****************************/
static FATFS fatfs;                         //文件系统


//#define FILE_NAME "parameter_512_512.txt"                //定义文件名
#define FILE_NAME "zxs1.txt"
#define FILE_READ_NAME "zzxxss.txt"





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


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

#define DMA_DEV_ID          XPAR_AXIDMA_0_DEVICE_ID
#define RX_INTR_ID          XPAR_FABRIC_AXIDMA_0_S2MM_INTROUT_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 + 0x00700000)    //0x01800000
#define RESET_TIMEOUT_COUNTER   100000000    //复位时间
//复位时间设置的如此之长 是为了保证在下面的刷新DMA的用时 虽然我之前小数据只写了1000


//#define TEST_START_VALUE        0x0      //测试起始值
//#define MAX_PKT_LEN             0x100    //发送包长度 对应十进制是256  DMA传递的单次包长最大是256
//指的是stream流的包长度 不是突发长度

#define MAX_PKT_LEN            5000    //发送包长度  163840
//指的是单次 DMA 传输的包长度 因为数据一共有 16384 × 8  再加上 转

#define    len                    5000        //传输数据的大小



//函数声明
int platform_init_fs();
int sd_mount() ;     //  挂载SD卡
int sd_write_data(char *file_name,u32 src_addr,u32 byte_len); //SD卡写数据
int sd_read_data(char *file_name,u32 src_addr,u32 byte_len) ; //SD卡读数据
static void tx_intr_handler(void *callback);
static void rx_intr_handler(void *callback);
static int setup_intr_system(XScuGic * int_ins_ptr, XAxiDma * axidma_ptr,
        u16 tx_intr_id, u16 rx_intr_id);
static void disable_intr_system(XScuGic * int_ins_ptr, u16 tx_intr_id,
        u16 rx_intr_id);






// main函数
int main()
{
	 int status;   // 当前状态

     int i = 0 ;                    // 传递函数使用的顺序i t
     int t = 0 ;
     u32 value = 0 ;

	 u32  *tx_buffer_ptr;
	 u32  *rx_buffer_ptr;
	 XAxiDma_Config *config;
	 tx_buffer_ptr = (u32 *) TX_BUFFER_BASE;
	 rx_buffer_ptr = (u32 *) RX_BUFFER_BASE;

// 如果分配成功:则返回指向被分配内存空间的指针,不然返回指针NULL 。同时,当内存不再使用的时候,应使用free()函数将内存块释放掉。

//	 关于:void*,表示未确定类型的指针,c,
	 //c++规定void*可以强转为任何其他类型的指针,关于void还有一种说法就是其他任何类型都可以直接赋值给它,无需进行强转,但是反过来不可以 。
	 //它被用来在运行时而不是编译时分配内存。因此,如果您的数据数组基于来自用户,数据库,文件等的某种输入,那么一旦知道所需大小,就必须使用malloc。

	 //malloc 在堆上开辟空间
	    char *ch_data = NULL;           //SD卡读到的数据
	 	char *ddr_rd_data = NULL;       //重新写回SD卡的数据

	 	ch_data = malloc(len);
	 	if(ch_data == NULL) printf("ERRIOR \r\n");

	 	ddr_rd_data = malloc(len);
	 	if(ddr_rd_data == NULL) printf("ERRIOR \r\n");
// 两个东西 一个 放 开始内容 另一个 写结束



//常规
	    status = sd_mount();           //挂载SD卡----调用函数
	    ///
	    if(status != XST_SUCCESS){
			xil_printf("Failed to open SD card!\n");
			return 0;
	    }
	    else
	        xil_printf("Success to open SD card!\n");
	    //为了展示效果 我决定写一下sd卡
	    //len = strlen(src_str);         //计算字符串长度

	    //SD卡写数据
	    //sd_write_data(FILE_NAME,(u32)src_str,len);


	    sd_read_data(FILE_NAME,(u32)ch_data,len);

	//
	     printf("Successful write SD  in Pc ! \r\n");
	     usleep(1);
	  // sd_read_data(FILE_NAME,(u32)dest_str,len);   //读数据进入dest_str
	   //printf("Successful Read SD ! \r\n");
	   //到目前我们已经把数据放到了dest_str

	   // 写数据
	   for(i=0; i<len; i++)
	   	 	   	     	{
	   	 	   	     		Xil_Out32(TX_BUFFER_BASE+i*4,ch_data[i]);
	   	 	   	     	}
             i=0;
		usleep(1);

	   	 	   	 	   //读数据
	   	 	   	     printf("Successful Write SD in DDR! \r\n");
	   	 	   	xil_printf("--- Entering main() --- \r\n");
	   	 	printf("DMA initialization succeeded ! \r\n");




		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, TX_INTR_ID, RX_INTR_ID);
		           	    if (status != XST_SUCCESS) {
		           	        xil_printf("Failed intr setup\r\n");
		           	       return XST_FAILURE;
		           	    }

                //初始化标志信号
		 tx_done = 0;
		 rx_done = 0;
	     error   = 0;
	     usleep(10);


		       //数据地址都确定了


		Xil_DCacheFlushRange((UINTPTR)(tx_buffer_ptr), len);   //刷新Data Cache
// may be this is wrong


       printf("DDR send Read data5 \n");

		 status = XAxiDma_SimpleTransfer(&axidma, (u32) (tx_buffer_ptr),
		   len, XAXIDMA_DMA_TO_DEVICE);
		    if (status != XST_SUCCESS) {
		        return XST_FAILURE;
		    }

		    Xil_DCacheFlushRange((UINTPTR) (tx_buffer_ptr), len);   //刷新Data Cache
		    printf("DDR send Read data6 \n");
       usleep(10) ;
       //DMA写通道开启
		 status = XAxiDma_SimpleTransfer(&axidma, (u32) (rx_buffer_ptr),
		    len, XAXIDMA_DEVICE_TO_DMA);
		    首先是器件例化的指针 ,起始或目的地址 ,传输长度  , DMA传输方向
		    if (status != XST_SUCCESS) {
		        return XST_FAILURE;
		    }
		    printf("DDR send Read data7 \n");
		    Xil_DCacheFlushRange((UINTPTR) (rx_buffer_ptr), len);   //刷新Data Cache

            while (!tx_done && !rx_done && !error);

           printf("DDR get Read data \n");
		    //传输出错
           if (error) {
              	        xil_printf("Failed test transmit%s done, "
              	                "receive %s done\r\n", tx_done ? "" : "tx_done not",
              	                rx_done ? "" : "rx_done not");
              	        goto Done;
              	    }
              	    usleep(10000);
		     //传输完成,检查数据是否正确

		     xil_printf("Successfully ran AXI DMA Loop\r\n");

		     disable_intr_system(&intc, TX_INTR_ID, RX_INTR_ID);

		     Done: xil_printf("--- Exiting main() --- \r\n");

		     for(i=0; i<len; i++)
		     	{
		     	    value = Xil_In32(RX_BUFFER_BASE+i*4);
		     	   ddr_rd_data[t] = value;
		     	    t++;
		     	}
usleep(1);
		     	sd_write_data(FILE_READ_NAME,(u32)ddr_rd_data,len);

		     	printf("SD Write Successfully ! \r\n");
		     	free(ch_data);
		     		free(ddr_rd_data);
		     return XST_SUCCESS;
}












//初始化文件系统
int platform_init_fs()
{
	FRESULT status;
	TCHAR *Path = "0:/";
	BYTE work[FF_MAX_SS];

    //注册一个工作区(挂载分区文件系统)
    //在使用任何其它文件函数之前,必须使用f_mount函数为每个使用卷注册一个工作区
	status = f_mount(&fatfs, Path, 1);  //挂载SD卡
	if (status != FR_OK) {
		xil_printf("Volume is not FAT formated; formating FAT\r\n");
		//格式化SD卡
		status = f_mkfs(Path, FM_FAT32, 0, work, sizeof work);
		if (status != FR_OK) {
			xil_printf("Unable to format FATfs\r\n");
			return -1;
		}
		//格式化之后,重新挂载SD卡
		status = f_mount(&fatfs, Path, 1);
		if (status != FR_OK) {
			xil_printf("Unable to mount FATfs\r\n");
			return -1;
		}
	}
	return 0;
}








//挂载SD(TF)卡
int sd_mount()
{
    FRESULT status;
    //初始化文件系统(挂载SD卡,如果挂载不成功,则格式化SD卡)
    status = platform_init_fs();
    if(status){
        xil_printf("ERROR: f_mount returned %d!\n",status);
        return XST_FAILURE;
    }
    return XST_SUCCESS;
}


//SD卡写数据
int sd_write_data(char *file_name,u32 src_addr,u32 byte_len)
{
    FIL fil;         //文件对象
    UINT bw;         //f_write函数返回已写入的字节数

    //打开一个文件,如果不存在,则创建一个文件
    f_open(&fil,file_name,FA_CREATE_ALWAYS | FA_WRITE);
    //移动打开的文件对象的文件读/写指针     0:指向文件开头
    f_lseek(&fil, 0);
    //向文件中写入数据
    f_write(&fil,(void*) src_addr,byte_len,&bw);
    //关闭文件
    f_close(&fil);
    return 0;
}


//SD卡读数据
int sd_read_data(char *file_name,u32 src_addr,u32 byte_len)
{
	FIL fil;         //文件对象
    UINT br;         //f_read函数返回已读出的字节数

    //打开一个只读的文件
    f_open(&fil,file_name,FA_READ);
    //移动打开的文件对象的文件读/写指针     0:指向文件开头
    f_lseek(&fil,0);
    //从SD卡中读出数据
    f_read(&fil,(void*)src_addr,byte_len,&br);
    //关闭文件
    f_close(&fil);
    return 0;
}

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

    //读取待处理的中断
    irq_status = XAxiDma_IntrGetIrq(axidma_inst, XAXIDMA_DMA_TO_DEVICE);
    //确认待处理的中断
    XAxiDma_IntrAckIrq(axidma_inst, irq_status, XAXIDMA_DMA_TO_DEVICE);

    //Tx出错
    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;
    }

    //Tx完成
    if ((irq_status & XAXIDMA_IRQ_IOC_MASK))
        tx_done = 1;
}

//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;
}

//建立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 tx_intr_id, u16 rx_intr_id)
{
    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, tx_intr_id, 0xA0, 0x3);
    XScuGic_SetPriorityTriggerType(int_ins_ptr, rx_intr_id, 0xA0, 0x3);

    //为中断设置中断处理函数
    status = XScuGic_Connect(int_ins_ptr, tx_intr_id,
            (Xil_InterruptHandler) tx_intr_handler, axidma_ptr);
    if (status != XST_SUCCESS) {
        return status;
    }

    status = XScuGic_Connect(int_ins_ptr, rx_intr_id,
            (Xil_InterruptHandler) rx_intr_handler, axidma_ptr);
    if (status != XST_SUCCESS) {
        return status;
    }

    XScuGic_Enable(int_ins_ptr, tx_intr_id);
    XScuGic_Enable(int_ins_ptr, rx_intr_id);

    //启用来自硬件的中断
    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_DMA_TO_DEVICE);
    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 tx_intr_id,
        u16 rx_intr_id)
{
    XScuGic_Disconnect(int_ins_ptr, tx_intr_id);
    XScuGic_Disconnect(int_ins_ptr, rx_intr_id);
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1226842.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

线性变换概论

线性变换 定义 设 V V V 和 W W W 都是在域 K K K上定义的向量空间&#xff0c; T : V → W T :V \rightarrow W T:V→W 对任二向量 x , y ∈ V x,y \in V x,y∈V,与任何标量 a ∈ K a \in K a∈K&#xff0c;满足&#xff1a; T ( x y ) T ( x ) T ( y ) T(xy)T(x)T(…

Zookeeper实战案例(1)

前置知识&#xff1a; Zookeeper学习笔记&#xff08;1&#xff09;—— 基础知识-CSDN博客 Zookeeper学习笔记&#xff08;2&#xff09;—— Zookeeper API简单操作-CSDN博客 Zookeeper 服务器动态上下线监听案例 需求分析 某分布式系统中&#xff0c;主节点可以有多台&am…

2023最新最全【内网渗透工具】零基础安装教程

1.1 简介 nps是一款轻量级、高性能、功能强大的内网穿透代理服务器。目前支持tcp、udp流量转发&#xff0c;可支持任何tcp、udp上层协议&#xff08;访问内网网站、本地支付接口调试、ssh访问、远程桌面&#xff0c;内网dns解析等等……&#xff09;&#xff0c;此外还支持内网…

《洛谷深入浅出基础篇》 P5250 木材仓库————集合应用实例

上链接&#xff1a; P5250 【深基17.例5】木材仓库 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)https://www.luogu.com.cn/problem/P5250上题干&#xff1a; 题目描述 博艾市有一个木材仓库&#xff0c;里面可以存储各种长度的木材&#xff0c;但是保证没有两个木材的长度是…

Spring Boot中使用Redis进行大数据缓存

Spring Boot中使用Redis进行大数据缓存 在Spring Boot中使用Redis进行大数据缓存是一种常见的做法&#xff0c;因为Redis是一种高性能的内存数据库&#xff0c;适用于缓存大量数据。以下是说明和示例代码&#xff0c;演示如何在Spring Boot项目中使用Redis进行大数据缓存。 步…

【C++初阶】STL详解(四)vector的模拟实现

本专栏内容为&#xff1a;C学习专栏&#xff0c;分为初阶和进阶两部分。 通过本专栏的深入学习&#xff0c;你可以了解并掌握C。 &#x1f493;博主csdn个人主页&#xff1a;小小unicorn ⏩专栏分类&#xff1a;C &#x1f69a;代码仓库&#xff1a;小小unicorn的代码仓库&…

【Kingbase FlySync】命令模式:部署双轨并行,并实现切换同步

【Kingbase FlySync】命令模式:安装部署同步软件&#xff0c;实现Oracle到KES实现同步 双轨并行方案说明一.准备工作二.环境说明三.目标实操(1).准备安装环境Orcle服务器(Oracle40)1.上传所有工具包2.操作系统配置a.增加flysync 用户、设置密码b.配置环境变量c.调整limits.conf…

【Leetcode合集】2342. 数位和相等数对的最大和

文章目录 2342. 数位和相等数对的最大和方案1方案2方案3方案4 2342. 数位和相等数对的最大和 2342. 数位和相等数对的最大和 代码仓库地址&#xff1a; https://github.com/slience-me/Leetcode 个人博客 &#xff1a;https://slienceme.xyz 给你一个下标从 0 开始的数组 nu…

单链表在线OJ题(详解+图解)

1.删除链表中等于给定值 val 的所有节点 本题的要求是输入一个val的整形值&#xff0c;若链表中节点存储的值与val相等&#xff0c;则删除这个节点&#xff0c;并最后返回这个删除节点后的链表&#xff0c;思路如下&#xff1a; 我们可以直接使用while循环&#xff0c;并且使用…

Python 如何实现职责链设计模式?什么是职责链设计模式?Python 职责链设计模式示例代码

什么是职责链&#xff08;Chain of Responsibility&#xff09;设计模式&#xff1f; 职责链&#xff08;Chain of Responsibility&#xff09;设计模式是一种行为型设计模式&#xff0c;旨在构建一个对象链&#xff0c;每个对象都有机会处理请求&#xff0c;并且可以将请求传…

基于stm32移植使用u8g2 库

前言 前面我已经写了如何使用stm32 使用软件IIC的方法驱动OLED&#xff0c;但是其实我们可以有更简单的使用方法&#xff0c;对于SSD1306 这款OLED 显示屏来说&#xff0c;其实已经有开源库可以直接使用了&#xff0c;我们只需要将对应的库移植过来&#xff0c;做一些简单的修改…

单片机课程设计——基于C51电子密码锁(源代码)

本设计是基于AT89C51单片机的电子密码锁设计&#xff0c;实现电子密码锁的基本功能。我们这里实现的是硬件仿真&#xff0c;关于软件仿真可以参考其他人的文章。 单片机课程设计--基于C51电子密码锁 效果展示 我们先来看效果展示&#xff0c;公主王子请看视频&#xff1a; 课…

【Spring总结】注解开发

本篇讲的内容主要是基于Spring v2.5的注解来完成bean的定义 之前都是使用纯配置的方式来定义的bean 文章目录 前言1. Spring v2.5 注解开发定义bean第一步&#xff1a;在需要定义的类上写上注解Component第二步&#xff1a;在Spring Config中定义扫描包第三步&#xff1a;主方法…

java springboot 在测试类中声明临时Bean对象

上文 java springboot在当前测试类中添加临时属性 不影响application和其他范围 中 我们讲了怎么在测试类中设置临时属性 但是 如果我们想设置临时的Bean呢&#xff1f; 其实做过几个项目的人都会理解 我们很多功能 需要一些第三方bean才能完成 那么 我们可能存在需要用第三方b…

图书管理系统(图文详解,附源码)

前言&#xff1a;本文旨在用面向对象的思想编程实现图书管理系统&#xff0c;功能包括增删查找&#xff0c;完整源码放在文末&#xff0c;大家有需自取 目录 一.整体框架 二.书籍和书架 书籍(Book) 书架(BookRack) 三.对书籍的相关操作 操作接口(IOperation) 新增图书(A…

项目点使用Redis作为缓存技术-自用

在spring boot项目中&#xff0c;使用缓存技术只需在项目中导入相关缓存技术的依赖包&#xff0c;并在启动类上使用EnableCaching开启缓存支持即可。 例如&#xff0c;使用Redis作为缓存技术&#xff0c;只需要导入Spring data Redis的maven坐标即可。 描述 使用Redis缓存高频数…

WSA子系统(一)

WSA子系统安装教程 Windows Subsystem for Android (WSA) 是微软推出的一项功能&#xff0c;它允许用户在 Windows 11 上运行 Android 应用程序。通过在 Windows 11 上引入 WSA&#xff0c;用户可以在其 PC 上轻松运行 Android 应用程序&#xff0c;从而扩展了用户的应用程序选…

RobotFramework之用例执行时添加命令行参数(十三)

学习目录 引言 标签tag 设置变量 随机执行顺序 设置监听器 输出日志目录和文件 引言 Robot Framework 提供了许多命令行选项&#xff0c;可用于控制测试用例的执行方式以及生成的输出。本节介绍一些常用的选项语法。 标签tag 之前文章我们介绍过&#xff0c;在测试套件…

Leetcode经典题目之“双指针交换元素“类题目

1 LC 27. 移除元素 class Solution {public int removeElement(int[] nums, int val) {int nnums.length;int s0;for(int i0;i<n;i){// 只有不等于目标值的时候才会进行交换&#xff0c;然后移动s指针if(nums[i]!val){swap(nums,i,s);}}return s;}void swap(int[]nums, int…