ZYNQ筆記(十四):基于 BRAM 的 PS、PL 數據交互

版本: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);
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/78579.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/78579.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/78579.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Python-Django系列—部件

部件是 Django 對 HTML 輸入元素的表示。部件處理 HTML 的渲染&#xff0c;以及從對應于部件的 GET&#xff0f;POST 字典中提取數據。 內置部件生成的 HTML 使用 HTML5 語法&#xff0c;目標是 <!DOCTYPE html>。例如&#xff0c;它使用布爾屬性&#xff0c;如 checked…

【Leetcode 每日一題】2799. 統計完全子數組的數目

問題背景 給你一個由 正 整數組成的數組 n u m s nums nums。 如果數組中的某個子數組滿足下述條件&#xff0c;則稱之為 完全子數組 &#xff1a; 子數組中 不同 元素的數目等于整個數組不同元素的數目。 返回數組中 完全子數組 的數目。 子數組 是數組中的一個連續非空序…

卷積神經網絡(二)

1 卷積運算的兩個問題&#xff1a; 1.1 圖像邊緣信息使用少 邊緣的像素點可能只會被用一次或者2次&#xff0c;中間的會用的更多。 1.2 圖像被壓縮 5*5的圖像&#xff0c;如果經過3*3的卷積核后&#xff0c;大小變成3*3的。 N*N的圖像&#xff0c;果經過F*F的卷積核后&#x…

組網技術-DHCP服務器,RIP協議,OSPF協議

1.DHCP Server提供三種IP地址分配策略&#xff1a; 手工分配地址 自動分配地址 n 動態分配地址 2.DHCP報文類型 DHCP DISCOVER(廣播)&#xff1a;用于尋址DHCP Server DHCP OFFER&#xff08;單播&#xff09;&#xff1a;攜帶分配給客戶端的IP地址 DHCP REQUEST&#xff08;…

反爬策略應對指南:淘寶 API 商品數據采集的 IP 代理與請求偽裝技術

一、引言? 在電商數據驅動決策的時代&#xff0c;淘寶平臺海量的商品數據極具價值。然而&#xff0c;淘寶為保障平臺安全和用戶體驗&#xff0c;構建了嚴密的反爬體系。當采集淘寶 API 商品數據時&#xff0c;若不采取有效措施&#xff0c;頻繁的請求極易觸發反爬機制&#x…

學習筆記(算法學習+Maven)

單調隊列優化多重背包 #include <bits/stdc.h> using namespace std; const int M 2010; const int N 20010; int q[N]; int hh 0, tt -1; int f[N]; int g[N]; int v[M], w[M], s[M]; int n, m; int main() { cin >> n >> m; for (int i 1; …

WPF之項目創建

文章目錄 引言先決條件創建 WPF 項目步驟理解項目結構XAML 與 C# 代碼隱藏第一個 "Hello, WPF!" 示例構建和運行應用程序總結相關學習資源 引言 Windows Presentation Foundation (WPF) 是 Microsoft 用于構建具有豐富用戶界面的 Windows 桌面應用程序的現代框架。它…

JAVAEE初階01

個人主頁 JavaSE專欄 JAVAEE初階01 操作系統 1.對下&#xff08;硬件&#xff09;管理各種計算機設備 2.對上&#xff08;軟件&#xff09;為各種軟件提供一個穩定的運行環境 線程 運行的程序在操作系統中以進程的形式存在 進程是系統分配資源的最小單位 進程與線程的關…

HTML快速入門-4:HTML <meta> 標簽屬性詳解

<meta> 標簽是 HTML 文檔頭部&#xff08;<head> 部分&#xff09;的重要元素&#xff0c;用于提供關于文檔的元數據&#xff08;metadata&#xff09;。這些數據不會直接顯示在頁面上&#xff0c;但對瀏覽器、搜索引擎和其他服務非常重要。 常用屬性 1. name 和 …

前端基礎之《Vue(12)—插件封裝》

一、插件封裝 1、在Vue生態中&#xff0c;除了Vue本身&#xff0c;其它所有的與Vue相關的第三方包&#xff0c;都是插件 例子&#xff1a; import VueRouter form vue-router Vue.use(VueRouter) // 注冊插件 2、如何封裝Vue插件 &#xff08;1&#xff09;第一種寫法 const…

TCP基礎題:音樂播放列表管理系統

需求描述 服務器端 創建一個 TCP 服務器&#xff0c;監聽本地的 9999 端口&#xff0c;支持多個客戶端連接。維護一個音樂播放列表&#xff0c;每個音樂條目包含歌曲名稱、歌手、時長等信息。能夠處理客戶端的以下請求&#xff1a; 添加音樂到播放列表&#xff1a;接收客戶端發…

Verilog 語法 (二)

在掌握了 Verilog 的基礎語法和常用程序框架之后&#xff0c;本節將帶大家深入學習一些 高級設計知識點。這些內容包括&#xff1a; 阻塞賦值&#xff08;&#xff09;與非阻塞賦值&#xff08;<&#xff09;的區別及使用場景&#xff1b; assign 和 always 語句的差異&am…

OpenCV 圖形API(61)圖像特征檢測------檢測圖像邊緣的函數Canny()

操作系統&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 編程語言&#xff1a;C11 算法描述 使用Canny算法在圖像中查找邊緣。 該函數在輸入圖像中查找邊緣&#xff0c;并使用Canny算法在輸出映射&#xff08;edges&#xff09;中標記它們…

ubantu中下載編譯安裝qt5.15.3

操作步驟如下&#xff1a; 克隆 Qt 倉庫&#xff1a; git clone https://code.qt.io/qt/qt5.git cd qt5 切換到 Qt 5.15.3 標簽&#xff1a; git checkout v5.15.3-lts-lgpl 初始化子模塊&#xff1a; perl init-repository 配置和編譯 Qt&#xff1a; ./configure -prefix $H…

畢業論文設計基本內容和要求:

畢業設計基本內容和要求&#xff1a; 研究內容 調查了解LAMP架構和PHP開發&#xff1b; 學習百度旅游調用的其他產品線服務并熟悉請求接口&#xff1b; 學習社區業務層規范&#xff1b; 設計并實現旅游主要模塊&#xff1b; 技術指標 熟悉企業中流程運轉的方式&#xff0c;…

【大語言模型】大語言模型(LLMs)在工業缺陷檢測領域的應用

大語言模型&#xff08;LLMs&#xff09;在工業缺陷檢測領域的應用場景正在快速擴展&#xff0c;結合其多模態理解、文本生成和邏輯推理能力&#xff0c;為傳統檢測方法提供了新的技術路徑。以下是該領域的主要應用場景及相關技術進展&#xff1a; 1. 多模態缺陷檢測與解釋 視…

【AI插件開發】Notepad++ AI插件開發1.0發布和使用說明

一、產品簡介 AiCoder是一款為Notepad設計的輕量級AI輔助插件&#xff0c;提供以下核心功能&#xff1a; 嵌入式提問&#xff1a;對選中的文本內容進行AI分析&#xff0c;通過側邊欄聊天界面與AI交互&#xff0c;實現多輪對話、問題解答或代碼生成。對話式提問&#xff1a;獨…

第2講:R語言中的色彩美學——科研圖表配色指南

目錄 一、背景導引:科研圖表為何需要“配色講究”? 二、色彩基礎認知:別讓“紅綠盲”錯過你的科研成果 三、R語言中的配色庫全景圖 四、案例演示與代碼實戰 ??案例1:ggplot2 + viridis 配色的熱圖 ??案例2:MetBrewer 中的印象派色彩 五、技巧點撥:如何為SCI圖…

基于Django的個性化股票交易管理系統

本項目基于Python3.6、Django2.1、MySql8.0&#xff08;最好不要使用5.6&#xff0c;字符集等方面均不兼容&#xff0c;否則導入數據庫會出錯&#xff09;與股票信息工具包TuShare實現。 創建或激活對應Python開發環境 這里使用了conda來管理環境&#xff0c;強烈推薦&#xf…

超越GPT-4?下一代大模型的技術突破與挑戰

超越GPT-4&#xff1f;下一代大模型的技術突破與挑戰 引言&#xff1a;大模型的演進歷程 人工智能領域近年來最引人注目的發展莫過于大型語言模型(Large Language Models, LLMs)的快速進步。從GPT-3到GPT-4&#xff0c;再到如今各種宣稱"超越GPT-4"的模型不斷涌現&…