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


    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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174

    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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141

    下面是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);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251
    • 252
    • 253
    • 254
    • 255
    • 256
    • 257
    • 258
    • 259
    • 260
    • 261
    • 262
    • 263
    • 264
    • 265
    • 266
    • 267
    • 268
    • 269
    • 270
    • 271
    • 272
    • 273
    • 274
    • 275
    • 276
    • 277
    • 278
    • 279
    • 280
    • 281
    • 282
    • 283
    • 284
    • 285
    • 286
    • 287
    • 288
    • 289
    • 290
    • 291
    • 292
    • 293
    • 294
    • 295
    • 296
    • 297
    • 298
    • 299
    • 300
    • 301
    • 302
    • 303
    • 304
    • 305
    • 306
    • 307
    • 308
    • 309
    • 310
    • 311
    • 312
    • 313
    • 314
    • 315
    • 316
    • 317
    • 318
    • 319
    • 320
    • 321
    • 322
    • 323
    • 324
    • 325
    • 326
    • 327
    • 328
    • 329
    • 330
    • 331
    • 332
    • 333
    • 334
    • 335
    • 336
    • 337
    • 338
    • 339
    • 340
    • 341
    • 342
    • 343
    • 344
    • 345
    • 346
    • 347
    • 348
    • 349
    • 350
    • 351
    • 352
    • 353
    • 354
    • 355
    • 356
    • 357
    • 358
    • 359
    • 360
    • 361
    • 362
    • 363
    • 364
    • 365
    • 366
    • 367
    • 368
    • 369
    • 370
    • 371
    • 372
    • 373
    • 374
    • 375
    • 376
    • 377
    • 378
    • 379
    • 380
    • 381
    • 382
    • 383
    • 384
    • 385
    • 386
    • 387
    • 388
    • 389
    • 390
    • 391
    • 392
    • 393
    • 394
    • 395
    • 396
    • 397
    • 398
    • 399
    • 400
    • 401
    • 402
    • 403
    • 404
    • 405
    • 406
    • 407
    • 408
    • 409
    • 410
    • 411
    • 412
    • 413
    • 414
    • 415
    • 416
    • 417
    • 418
    • 419
    • 420
    • 421
    • 422
    • 423
    • 424
    • 425
    • 426
    • 427
    • 428
    • 429
    • 430
    • 431
    • 432
    • 433
    • 434
    • 435
    • 436
    • 437
    • 438
    • 439
    • 440
    • 441
    • 442
    • 443
    • 444
    • 445
    • 446
    • 447
    • 448
    • 449
    • 450
    • 451
    • 452
    • 453
    • 454
    • 455
    • 456
    • 457
    • 458
    • 459
    • 460
    • 461
    • 462
    • 463
    • 464
    • 465
  • 相关阅读:
    Ubuntu安装docker,并换镜像源详细教程,建议收藏
    在线教育项目【前端路由和Ajax实现分析&与后端连接分析】
    5G创新突破 | 紫光展锐5G芯片全球首发R17 NR广播端到端业务演示
    k8s docker cgroup驱动问题 —— 筑梦之路
    播放量暴涨2000w+,单日狂揽24w粉,内卷的搞笑赛道还有机会
    2023最新Nmap安装和使用详解,超详细教程
    什么是无损检测设备?
    JSON一些注意语法点
    Centos7 安装MySQL详细步骤
    中国储运杂志中国储运杂志社中国储运编辑部2022年第7期目录
  • 原文地址:https://blog.csdn.net/weixin_50965981/article/details/134491479