版本:Vivado2020.2(Vitis)
實驗任務:
????????PS 將字符串數據寫入BRAM,再將數據讀取出來;PL 從 BRAM 中讀取數據,bing。通過 ILA 來觀察讀出的數據,與前面串口打印的數據進行對照(檢查是否正確讀出)。
目錄
一、介紹
1. BRAM(Block RAM)
2. AXI BRAM Controller?????????
二、硬件設計
1. 整體系統框圖
2. 配置 BRAM
3. 配置 AXI BRAM Controller
4. 自定義IP核(pl_bram_rd)
5. 最終?bd 設計
三、軟件設計
四、效果
一、介紹
1. BRAM(Block RAM)
????????BRAM(Block RAM)?是 Xilinx Zynq SoC 內部的嵌入式高速靜態存儲器(SRAM),分布在 FPGA 可編程邏輯(PL)部分,但也可被處理器系統(PS)直接訪問。主要特點:
特性 | 說明 |
---|---|
高速訪問 | 1~2 個時鐘周期完成讀寫,遠快于外部 DDR(通常需數十周期) |
低功耗 | 低功耗,片上存儲無需外部總線交互 |
雙端口架構 | 支持雙端口(可獨立讀寫),可配置為單端口或真雙端口模式 |
存儲容量 | 每塊 36Kb(可拆分為 2×18Kb),器件集成數量:幾十至數百塊 |
初始化方式 | 支持 COE 文件預加載或運行時寫入 |
典型用途 | 高速緩存、查找表、PS-PL 數據共享、跨時鐘域同步 |
ECC 支持 | 可選校驗功能 |
2. AXI BRAM Controller?????????
????????AXI BRAM Controller 是 Xilinx FPGA 和 Zynq SoC 中常用的 IP 核,用于通過?AXI 總線協議?訪問?BRAM?(Block RAM)。它允許 PS 端或 DMA 控制器通過標準 AXI 接口高效讀寫 BRAM,同時支持 PL(FPGA 邏輯)和 PS(處理器系統)之間的數據共享。
特性 | 說明 |
---|---|
支持的 AXI 協議 | AXI4(高性能)、AXI4-Lite(簡化版) |
數據位寬 | 32/64/128/256/512 位(需匹配 BRAM 配置) |
突發傳輸 | AXI4 支持突發(Burst)讀寫,提升吞吐量 |
ECC 支持 | 可選,增加數據校驗功能 |
低延遲配置 | 可配置訪問延遲 |
多主設備支持 | 多個 Master(如 CPU + DMA)可共享同一 BRAM |
二、硬件設計
1. 整體系統框圖
????????PS端:除了 基本的 DDR 和 UART 還使用到了?AXI 接口,因此如時鐘、復位、AXI接口 都需要保留和配置。?
????????PL 端:存儲數據的 BRAM 的 IP 核、實現對 BRAM 寫入數據的 AXI BRAM 控制器 IP?核、讀取 BRAM IP 核數據的自定義的 IP 核(pl_bram_rd)。
2. 配置 BRAM
????????即添加 Block Memory Generator IP 核,配置如下:
????????BRAM IP 核支持兩種模式,一種是獨立模式(Stand Alone),在此模式下,可以自由配置 RAM 的數 據深度和寬度;另一種是 BRAM 控制器模式(BRAM Controller),在此模式下,地址和數據默認為 32 位, 由于本次實驗添加了 BRAM 控制器 IP 核,因此 BRAM 模式選擇 BRAM 控制器模式。
????????存儲類型(Memory Type)設置為“True Dual Port RAM” 真雙端口 RAM。一端連接 PL 讀 BRAM IP 核,另一端連接 BRAM 控制器。
? ? ? ? 來到其他選項:取消使能安全電路(如果勾選使能安全電路,BRAM 端口會增加 rst_busy?端口,用于表示何時可以訪問 BRAM。)
????????在?AXI BRAM Controller?模式下,BRAM 的?we
寫使能信號為?4 位,這是為了支持?按字節寫入(Byte-Write)功能,允許對 32 位數據(4 字節)中的特定字節進行單獨寫入,而無需覆蓋整個字。以下是詳細說明:
-
AXI 總線特性:AXI 協議支持字節級寫入(通過?
WSTRB
?信號),因此 BRAM Controller 需將 AXI 的字節使能信號轉換為 BRAM 的?we[3:0]
。 -
數據對齊:32 位 BRAM 數據(4 字節)中,每個?
we
?位對應一個字節的寫使能:-
we[0]
:控制?字節 0(數據位?[7:0]
) -
we[1]
:控制?字節 1(數據位?[15:8]
) -
we[2]
:控制?字節 2(數據位?[23:16]
) -
we[3]
:控制?字節 3(數據位?[31:24]
)
-
3. 配置 AXI BRAM Controller
????????AXI Protocol(AXI 協議)選擇的是 AXI4_Lite,本實驗只需發送一段開源電子網網址的字符串,因此選擇適用于低吞吐率存儲映射的 AXI4_Lite 接口即可滿足傳輸需求。
????????Data Width(數據位寬)固定為默認的?32 位,由于 AXI4 總線為字節尋址,因此在映射到 BRAM 地址時,需要按 4 字節尋址。
????????BRAM 接口數?1,本次?BRAM 控制器只需要讀寫 BRAM 的一個端口,
? ? ? ? 此外 Memory Depth(存儲深度)不可以設置,尋址 BRAM 的存儲深度是在 Address Editor 里設置。讀取延時默認1個時鐘周期。ECC 用于數據錯誤糾正與檢查,不使能。所有配置如下:
4. 自定義IP核(pl_bram_rd)
? ? ? ? 自定義 IP 核的設計和封裝可參考:ZYNQ筆記(六):自定義IP核-LED呼吸燈?。可以直接點擊菜單欄的 “Tools”,選擇 “Creat and Package New IP…” 在當前工程目錄快速進行自定義 IP 核的創建,如下圖所示:
????????需要注意創建的是 帶 AXI 接口的 IP?
? ? ? ? IP 默認在工程目錄的上一級目錄創建目錄ip_repo (/../ip_repo) ,這里去掉一個點讓他創建在當前工程目錄下(/./ip_repo) :
? ? ? ? AXI 接口類型設置為 Lite 和前面保持一致,接口模式為從。Next、Finish。
? ? ? ? 在IP Catolog 內找到 整個自定義 IP pl_bram_rd,右鍵進行編輯。pl_bram_rd 里面所添加的自定義verilog模塊是直接使用的正點原子的?bram_rd 模塊,模塊引出了 bram 接口并實現了對 bram 的讀操作,控制信號在例化時相依分配寄存器即可,這樣 PS 端通過讀相應寄存器實現對 PL 端 自定義IP核 pl_bram_rd 的控制。
bram_rd 模塊
/*BRAM讀數據 模塊例化bram_rd bram_rd(.clk (S_AXI_ACLK ), //時鐘信號.rst_n (S_AXI_ARESETN), //復位信號//PS端輸入的控制信號(分配三個寄存器進行控制).start_rd (slv_reg0[0]), //讀開始信號(上升沿有效).start_addr (slv_reg1 ), //讀開始地址 .rd_len (slv_reg2 ), //讀數據的長度//BRAM端口 .ram_clk (ram_clk ), //RAM時鐘.ram_rst (ram_rst ), //RAM復位信號,高有效.ram_en (ram_en ), //RAM工作使能信號.ram_we (ram_we ), //RAM寫使能信號.ram_addr (ram_addr ), //RAM地址.ram_wr_data (ram_wr_data), //RAM要寫入的數據.ram_rd_data (ram_rd_data) //RAM中讀出的數據);
*///模塊實現對BRAM的讀取操作(BRAM為控制模式為 BRAM Contrulor 控制)
module bram_rd(input clk , //時鐘信號input rst_n , //復位信號//控制信號input start_rd , //讀開始信號(上升沿有效)input [31:0] start_addr , //讀開始地址 input [31:0] rd_len , //讀數據的長度//BRAM端口output ram_clk , //RAM時鐘output ram_rst , //RAM復位信號,高有效output reg ram_en , //RAM工作使能信號output reg [3:0] ram_we , //RAM寫使能信號output reg [31:0] ram_addr , //RAM地址output reg [31:0] ram_wr_data, //RAM要寫入的數據input [31:0] ram_rd_data //RAM中讀出的數據
);
reg [1:0] flow_cnt;//流程計數
reg start_rd_d0;
reg start_rd_d1;assign ram_rst = 1'b0;
assign ram_clk = clk ;//讀開始信號上升沿標志信號
wire pos_start_rd;
assign pos_start_rd = ~start_rd_d1 & start_rd_d0;//延時兩拍,采start_rd信號的上升沿
always @(posedge clk or negedge rst_n) beginif(!rst_n) beginstart_rd_d0 <= 1'b0; start_rd_d1 <= 1'b0; endelse beginstart_rd_d0 <= start_rd; start_rd_d1 <= start_rd_d0; end
end//判斷讀開始信號,從RAM中讀出數據
always @(posedge clk or negedge rst_n) beginif(!rst_n) beginflow_cnt <= 2'd0;ram_en <= 1'b0;ram_we <= 4'd0;ram_addr <= 32'd0;end//通過計數實現的簡單狀態機else begincase(flow_cnt)2'd0 : beginif(pos_start_rd) beginram_en <= 1'b1;ram_addr <= start_addr;flow_cnt <= flow_cnt + 2'd1;endend2'd1 : beginif(ram_addr - start_addr == rd_len - 4) begin //數據讀完(讀完差值為rd_len-4)ram_en <= 1'b0;flow_cnt <= flow_cnt + 2'd1;endelseram_addr <= ram_addr + 32'd4; //地址累加4(,一次讀32位4個字節,一個字節對應一個地址)end2'd2 : beginram_addr <= 32'd0; flow_cnt <= 2'd0;endendcaseend
endendmodule
? ? ? ? 接著就是把 bram_rd 模塊例化到 官方AXI 接口模塊中并添加端口定義:
AXI接口模塊例化、添加端口定義:
AXI 接口頂層模塊添加端口定義:
????????接著保存后綜合,并打包IP核(參考:ZYNQ筆記(六):自定義IP核-LED呼吸燈?)。注意再PORT 欄部分,為了使 IP 核最后在 bd 視圖簡潔規范,這里需要對自定義的端口封裝成一個BRAM的總線接口并匹配端口類型(也可以不設置,不過結果就是db視圖中IP核自定義端口全部羅列在視圖上不能縮略為接口,同時運行自動連線時不能自動連接BRAM,需要手動連線):
? ? ? ? 找到端口,可能有端口被納入到其他組里面,選中右鍵 Remove Interface 把它移出來即可:
? ? ? ? 選中所有自定義端口右鍵添加總線接口,接口定義設置為官方的bram接口,自己進行命名,模式選“Master”主模式(因為是要讀寫BRAM模塊)
? ? ? ? 為自定義的端口添加接口映射(左右對應選中點擊Map Ports):
? ? ? ? 最后添加自動計算參數,這里直接全部添加過去(Vivado 根據連接的總線或關聯 IP 自動推導,這里沒有進行特定的設置,直接選“自動”即可)
? ? ? ?完成后PORT欄可以查看接口情況,GUI視圖欄也可以看到這些端口被封裝為一個接口了:
? ? ? ? 最后打包IP即可。注意 : 在Vitis 開發環境下,需要修改自定義IP核的 Makefile 文件,如果不修改,當包含該 IP 的硬件(xsa)文件導出 到 vitis 后,對 vitis 工程進行編譯就會報錯,報錯信息為“xxx.h: No such file or directory”。因此需要在使用該 IP 前完成修改: Makefile 修改方法
5. 最終?bd 設計
? ? ? ? 添加完自定義IP核后可以運行自動連接,為了保險起見手動設置要自定義IP核要連接的 BRAM 避免出錯。
? ? ? ? 接著需要設置地址映射,設置地址范圍也會間接定義 BRAM 的大小。這里讀/寫同一?bram 就都設置為 4K(單位字節),也定義 BRAM 深度大小為 1K (BRAM 數據位寬32位 4字節)。BRAM 控制器 和 自定義 IP(BRAM讀控制器) 的地址范圍不能重合。
? ? ? ? 除了定義 BRAM 大小,兩個 bram 控制器需要設置映射地址和范圍是為了定義可訪問的 BRAM 地址,確保模塊能夠準確讀寫數據。盡管已經通過連接明確了物理關系(接口連接),地址映射仍然是必要的,實際設置的是?BRAM 的映射地址,而非 BRAM 控制器本身,以確保控制器能正確進行數據訪問。? ? ??
????????最后整體 bd 設計部分如圖所示:設計檢查、Generate Output Products、 Create HDL Wrapper、管腳約束(沒有PL管腳,忽略這一步)、Gnerate Bitstream、Export Hardware(包含比特流文件)、啟動Vitis
三、軟件設計
#include "xil_printf.h"
#include "xparameters.h"
#include "pl_bram_rd.h" //自定義IP頭文件(包含對IP寄存器進行讀寫的函數)
#include "xbram.h" //AXI BRAM Controller IP頭文件(包含使用該IP進行BRAM讀寫的函數)
#include "stdio.h"
#include "sleep.h"//===================用戶自定義宏===================//
#define BRAM_BASEADDR XPAR_BRAM_0_BASEADDR //BRAM器件(BRAM IP核) 基地址#define BRAM_RD_IP XPAR_PL_BRAM_RD_0_S00_AXI_BASEADDR //自定義IP核(pl_bram_rd)寄存器基地址
#define BRAM_RD_START_RD PL_BRAM_RD_S00_AXI_SLV_REG0_OFFSET //start_rd 對應寄存器(slv_reg0)地址偏移量(pl_bram_rd.h中查看)
#define BRAM_RD_STRAT_ADDR PL_BRAM_RD_S00_AXI_SLV_REG1_OFFSET //start_addr對應寄存器(slv_reg1)地址偏移量
#define BRAM_RD_RD_LEN PL_BRAM_RD_S00_AXI_SLV_REG2_OFFSET //rd_len 對應寄存器(slv_reg2)地址偏移量#define STRAT_ADDR 0 //讀起始地址(從0開始)
#define BRAM_DATA_BYTE 4 //BRAM 數據字節數(32位寬 4字節)//===================函數變量聲明===================//
void BRAM_Ctrl_Wr(); //BRAM控制器寫數據
void BRAM_Ctrl_Rd(); //BRAM控制器讀數據
void PL_BRAM_RD_Rd(); //自定義IP核(pl_bram_rd)讀數據int wr_len; //寫入數據長度
char wr_buff[50] = "Hello"; //寫入數據(字符數組)
char rd_buff[50] = ""; //讀出數據//======================主函數======================//
int main()
{while(1){xil_printf("Write Char Data : %s\r\n", wr_buff); // 打印待寫入數據數據wr_len = strlen(wr_buff); //獲取字符串長度BRAM_Ctrl_Wr(); //BRAM控制器寫數據BRAM_Ctrl_Rd(); //BRAM控制器讀數據PL_BRAM_RD_Rd(); //自定義IP核(pl_bram_rd)讀數據sleep(3); //每隔3秒執行一次}return 0;
}//================BRAM控制器寫數據================//
void BRAM_Ctrl_Wr()
{//用XBram_WriteReg一次寫入一個字符,用for循環遍歷寫入所有字符for(int i=0; i<wr_len; i++){//XBram_WriteReg(BRAM基地址,偏移量,寫入數據),這里一次偏移4字節是因為BRAM數據位寬32位4字節,不過每次只寫1個字符XBram_WriteReg(BRAM_BASEADDR, i*BRAM_DATA_BYTE, wr_buff[i]);}xil_printf("BRAM Write done! \r\n");
}//================BRAM控制器讀數據================//
void BRAM_Ctrl_Rd()
{xil_printf("Read Char Data : ");//用XBram_WriteReg一次讀取一個字符,用for循環遍歷讀取所有字符for(int i=0; i<wr_len; i++){//XBram_ReadReg(BRAM基地址,偏移量)rd_buff[i] = XBram_ReadReg(BRAM_BASEADDR, i*BRAM_DATA_BYTE);xil_printf("%c",rd_buff[i]);}xil_printf("\r\n");
}//===========自定義IP核(pl_bram_rd)讀數據===========//
void PL_BRAM_RD_Rd()
{PL_BRAM_RD_mWriteReg(BRAM_RD_IP, BRAM_RD_RD_LEN, wr_len*BRAM_DATA_BYTE); //設置讀數據長度PL_BRAM_RD_mWriteReg(BRAM_RD_IP, BRAM_RD_STRAT_ADDR, STRAT_ADDR*BRAM_DATA_BYTE); //設置讀起始地址//產生讀開始信號有效上升沿PL_BRAM_RD_mWriteReg(BRAM_RD_IP, BRAM_RD_START_RD, 1); //拉高讀開始信號PL_BRAM_RD_mWriteReg(BRAM_RD_IP, BRAM_RD_START_RD, 0); //拉低讀開始信號
}
四、效果
????????PS 端:先打印待寫入數據,寫入后將數據讀取并打印。可看到前后一致說明寫入數據無誤
????????PL?端:要用到 ILA 查看 自定義IP 核讀取的數據是否正確,手動添加一個 ILA IP 核并在system_warper 中進行例化(修改保存后需要重新走一遍導出xac文件之前的流程)。
? ? ? ? 不過這樣到最后并沒有實現PL到PS的數據傳輸,可以考慮自定義IP核加一個中斷輸出,并重新修改功能,實現讀取數據后再接著最后一個地址開始,再把數據寫到BRAM上,然后產生一個高脈沖信號(中斷信號)時PS端得到中斷開讀數據檢查兩端數據是否一致:參考文章
ZYNQ—BRAM全雙工PS_PL數據交互(開源)?
? ? ? ? 關于自定義IP核的中斷(BD設計里面需要給ZYNQ添加中斷端口),我這里也有一個可參考的模板,中斷類型位上升沿中斷:
#include "xil_printf.h"
#include "xparameters.h"
#include "pl_bram_rd.h" //自定義IP頭文件(包含對IP寄存器進行讀寫的函數)
#include "xbram.h" //AXI BRAM Controller IP頭文件(包含使用該IP進行BRAM讀寫的函數)
#include "xscugic.h"
#include "stdio.h"//===================用戶自定義宏===================//
#define BRAM_BASEADDR XPAR_BRAM_0_BASEADDR //BRAM器件(BRAM IP核) 基地址#define BRAM_RD_IP XPAR_PL_BRAM_RD_0_S00_AXI_BASEADDR //自定義IP核(pl_bram_rd)寄存器基地址
#define BRAM_RD_START_RD PL_BRAM_RD_S00_AXI_SLV_REG0_OFFSET //start_rd 對應寄存器(slv_reg0)地址偏移量(pl_bram_rd.h中查看)
#define BRAM_RD_STRAT_ADDR PL_BRAM_RD_S00_AXI_SLV_REG1_OFFSET //start_addr對應寄存器(slv_reg1)地址偏移量
#define BRAM_RD_RD_LEN PL_BRAM_RD_S00_AXI_SLV_REG2_OFFSET //rd_len 對應寄存器(slv_reg2)地址偏移量#define STRAT_ADDR 0 //讀起始地址(從0開始)
#define BRAM_DATA_BYTE 4 //BRAM 數據字節數(32位寬 4字節)#define INTC_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID //宏定義中斷控制器(GIC)ID
#define BRAM_RD_IP_ID XPAR_PL_BRAM_RD_0_DEVICE_ID //自定義IP核(pl_bram_rd)器件ID
#define BRAM_RD_IP_INTR_ID XPAR_FABRIC_PL_BRAM_RD_0_INTR_INTR //宏定義GPIO中斷號(每個器件都有中斷號,xparameters.h查詢)//===================函數變量聲明===================//
XScuGic Intc; //中斷控制器驅動實例void BRAM_Ctrl_Wr (); //BRAM控制器寫數據
void BRAM_Ctrl_Rd (); //BRAM控制器讀數據
void PL_BRAM_RD_Rd(); //自定義IP核(pl_bram_rd)讀數據
void Set_Intr_Sys(XScuGic *GicInstancePtr, u16 DeviceIntrID); //建立中斷系統
void IntrHandler(); //中斷處理函數int wr_len; //寫入數據長度
char wr_buff[] = "ABC"; //寫入數據(字符數組)//======================主函數======================//
int main()
{//建立中斷系統Set_Intr_Sys(&Intc, BRAM_RD_IP_INTR_ID);wr_len = strlen(wr_buff); //獲取字符串長度BRAM_Ctrl_Wr (); //BRAM控制器寫數據BRAM_Ctrl_Rd (); //BRAM控制器讀數據PL_BRAM_RD_Rd(); //自定義IP核(pl_bram_rd)讀寫數據while(1)return 0;
}//================BRAM控制器寫數據================//
void BRAM_Ctrl_Wr()
{//用XBram_WriteReg一次寫入一個字符,用for循環遍歷寫入所有字符for(int i=0; i<wr_len; i++){//XBram_WriteReg(BRAM基地址,偏移量,寫入數據),這里一次偏移4字節是因為BRAM數據位寬32位4字節,不過每次只寫1個字符//讀寫地址=基地址+偏移量XBram_WriteReg(BRAM_BASEADDR, i*BRAM_DATA_BYTE, wr_buff[i]);}xil_printf("BRAM Write Finish! \r\n");
}//================BRAM控制器讀數據================//
void BRAM_Ctrl_Rd()
{int r_data;xil_printf("Read the Written Data : ");//用XBram_WriteReg一次讀取一個字符,用for循環遍歷讀取所有字符for(int i=0; i<wr_len; i++){//XBram_ReadReg(BRAM基地址,偏移量)//讀寫地址=基地址+偏移量r_data = XBram_ReadReg(BRAM_BASEADDR, i*BRAM_DATA_BYTE);xil_printf("%c",r_data);}xil_printf("\r\n");
}//===========自定義IP核(pl_bram_rd)讀數據===========//
void PL_BRAM_RD_Rd(u32 addr)
{xil_printf("START the custom IP: \r\n");PL_BRAM_RD_mWriteReg(BRAM_RD_IP, BRAM_RD_RD_LEN, wr_len*BRAM_DATA_BYTE); //設置讀數據長度PL_BRAM_RD_mWriteReg(BRAM_RD_IP, BRAM_RD_STRAT_ADDR, STRAT_ADDR*BRAM_DATA_BYTE); //設置讀起始地址//產生讀開始信號有效上升沿PL_BRAM_RD_mWriteReg(BRAM_RD_IP, BRAM_RD_START_RD, 1); //拉高讀開始信號PL_BRAM_RD_mWriteReg(BRAM_RD_IP, BRAM_RD_START_RD, 0); //拉低讀開始信號
}//===========================中斷處理函數===========================//
void IntrHandler(void *CallbackRef)
{int r_data;xil_printf("Interrupt Detected , Start Read BRAM :\r\n");//clear interrupt status//PL_BRAM_RD_mWriteReg(PL_RAM_BASE, PL_RAM_CTRL , INTRCLR_MASK) ;//BRAM控制器讀數據for(int i=0; i<wr_len*2; i++){//XBram_ReadReg(BRAM基地址,偏移量)//讀寫地址=基地址+偏移量r_data = XBram_ReadReg(BRAM_BASEADDR, i*BRAM_DATA_BYTE);xil_printf("Address:%d Data:%c \r\n", i*BRAM_DATA_BYTE, r_data);}xil_printf("\r\n");
}//===========================建立中斷系統===========================//
/* 建立中斷系統,使能自定義IP核終端輸出信號的上升沿產生中斷* @param GicInstancePtr 是指向 XScuGic 驅動實例的指針* @param DeviceIntrID 是器件中斷 ID*/
void Set_Intr_Sys(XScuGic *GicInstancePtr, u16 DeviceIntrID)
{//定義中斷控制器配置信息(指針類型)XScuGic_Config * IntcConfig;//根據中斷控制器ID,查找GIC配置信息(Generic Interrupt Controller(通用)中斷控制器)IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID);//初始化中斷控制器驅動XScuGic_CfgInitialize(GicInstancePtr, IntcConfig, IntcConfig->CpuBaseAddress);//設置并打開中斷異常處理功能Xil_ExceptionInit();Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,(Xil_ExceptionHandler)XScuGic_InterruptHandler,GicInstancePtr);//為GPIO中斷設置中斷處理函數(IntrHandler為自己編寫的中斷函數)XScuGic_Connect(GicInstancePtr, DeviceIntrID,(Xil_ExceptionHandler)IntrHandler, (void *) NULL); //自定義IP核無實例NULL//使能處理器中斷Xil_ExceptionEnable();//設置中斷優先級、觸發類型(優先級從最高0開始步長8最大為248,0xA0=160優先級中等;觸發類型:上升沿)XScuGic_SetPriorityTriggerType(GicInstancePtr, DeviceIntrID, 0xA0 , 0x3);//使能來自于器件的中斷XScuGic_Enable(GicInstancePtr, DeviceIntrID);
}