最新电影在线观看,jrs低调看直播,avav天堂,囯产精品宾馆在线精品酒店,亚洲精品成人区在线观看

ZYNQ-AXI GPIO使用

學習內容

前面簡單學習了關于GPIO的操作,本次將使用PL 端調用 AXI GPIO IP 核, 并通過 AXI4-Lite 接口實現 PS 與 PL 中 AXI GPIO 模塊的通信。

開發環境

vivado 18.3 SDK PYNQ-Z2

AXI_GPIO簡介

AXI GPIO IP 核為 AXI 接口提供了一個通用的輸入/輸出接口。與 PS 端的 GPIO 不同, AXI GPIO 是一個軟核( Soft IP),即 ZYNQ 芯片在出廠時并不存在這樣的一個硬件電路, 而是由用戶通過配置 PL 端的邏輯資源來實現的一個功能模塊。而 PS 端的 GPIO 是一個硬核( Hard IP) ,它是一個生產時在硅片中實現的功能電路。我們之前驅動的MIO接口,他屬于PS端口的一個搭載好的硬件資源,而對于AXI_GPIO這樣一個IP核來說他就相當于與在PL的邏輯端口實現了一個軟核IP的GPIO接口。AXI 接口作為 ZYNQ PS 和 PL 之間的橋梁, 能夠使兩者協同工作,進而形成一個完整的、 高度集成的系統。AXI GPIO 可以配置成單通道或者雙通道, 每個通道的位寬可以單獨設置。另外通過打開或者關閉三態緩沖器, AXI GPIO 的端口還可以被動態地配置成輸入或者輸出接口。其頂層模塊的框圖如下所示:

模塊的左側實現了一個 32 位的 AXI4-Lite 從接口, 用于主機訪問 AXI GPIO 內 部各通道的寄存器。當右側接口輸入的信號發生變化時,模塊還能向主機產生中斷信號。不過只有在配置 IP核時選擇“ 使能中斷” , 才會啟用模塊的中斷控制功能。

我們可以在xilinx的一個說明書(UG144)中詳細的看到關于AXI_GPIO IP的具體的寄存器,對于不同功能的配置我們只需要像在ARM開發中進行寄存器的配置即可,但寄存器的操作過于繁瑣,在一般的開發過程中我們通常進行的都是庫函數的使用調用。

在文檔中我們可以看到IP的以下特點,基本包含了硬件GPIO的所有功能。設置輸入輸出模式,設置中斷等。

引腳說明表如下,在這個表中,大致分為了兩類,第一類s_axi接口的相關引腳,用于配置掛載到AXI總線,s_axi_*這是一組信號接口,用于進行數據的交互和配置;第二類是和GPIO有關的信號接口,這里的IP中有兩組gpio,每組輸出三個信號經過一個三態緩存器實現三態輸出。為了實現中斷功能,這里的ip2intc_irpt是中斷的敏感信號。

編程指南

同樣在UG144中我們可以找到對于AXI_GPIO IP在應用開發的時候的一個編程指南

設置帶中斷的INPUT

  1. 將端口配置為輸入,將相應的位寫入GPIOx_TRI寄存器,值為1。
  2. 通過設置IP中斷使能中相應的位使能通道中斷注冊;也可以通過設置全局中斷的第31位來啟用全局中斷注冊為1。
  3. 當接收到中斷時,讀取GPIOx_DATA寄存器中相應的位。通過寫入值為1的對應位來清除IP中斷狀態寄存器中的狀態。

這里的編程指南描述的是寄存器的配置流程,在我們的實際應用中簡單來說就是調用庫函數配置端口為輸入,然后進行中斷功能的注冊(類似前文的GPIO的按鍵中斷)。

配置為普通的INPUT

  1. 將端口配置為輸入,將相應的位寫入GPIOx_TRI寄存器,值為1。
  2. 讀取GPIOx_DATA寄存器中相應的位。

配置為普通的OUTPUT

  1. 通過在GPIOx_TRI寄存器中寫入值為0的對應位,將端口配置為輸出。
  2. 將相應的位寫入GPIOx_DATA寄存器。

工程系統框圖

實現功能為使用EMIO的引腳驅動LED,使用AXI_GPIO的IP進行按鍵控制,當我們按鍵按下時,我們的LED進行一次反轉。

硬件平臺搭建

同樣重復前面的步驟,打開vivado工具的block design 添加ZYNQ的IP核,完成基礎配置。

然后打開MIO configuration,對EMIO引腳的LED進行配置

因為這里我們要使用AXI_GPIO的中斷功能,所以我們打開中斷界面進行配置,開啟中斷后,勾選PL到PS的中斷功能。這里的中斷標號有16個,對應原則是[15:0]對應的是[91:84]:[68:61],這里我們只使用了一個中斷,所以我們的中斷標號是61。

配置完成后添加AXI_GPIO的IP核。配置使能中斷,GPIO的位寬選擇為1即可。

完成配置后得到下圖點擊運行自動連接,可以進行幫助我們進行對應端口的自動連接:

自動連接完成后如圖所示:

這里工具幫助我們完成了大部分的連接,但是沒有幫助我們進行中斷功能的連線,我們需要手動進行連接。

手動連接完成:

完成設計后,我們進行generate output product 然后生成HDL封裝。接著就對應引腳進行引腳約束即可(PYNQ的粉色開發板可以直接引用這個約束):

set_property -dict { PACKAGE_PIN R14   IOSTANDARD LVCMOS33 } [get_ports { GPIO_0_tri_io[0] }]; #IO_L6N_T0_VREF_34 Sch=led[0]
set_property -dict { PACKAGE_PIN D19   IOSTANDARD LVCMOS33 } [get_ports { axi_gpio0_tri_io[0] }]; #IO_L4P_T0_35 Sch=btn[0]

完成約束后進行綜合布局布線,等待生成bit流文件。bit文件生成后在FILE處,點擊導出硬件資源(包含bit流文件),接著launch SDK。

軟件部分編寫

這里引用的AXI GPIO的資源對應的是gpio的部分,配置相應的功能函數可以參考相應的文件和對應的例程。

首先給出我本次的工程代碼,在后面進行簡要的說明:

#include 
#include "platform.h"
#include "xil_printf.h"
#include "xgpiops.h"
#include "xgpio.h"
#include "xparameters.h"
#include "xparameters_ps.h"
#include "xscugic.h"
#include "sleep.h"
//設置設備id和io編號
#define GPIO_ID XPAR_XGPIOPS_0_DEVICE_ID //PS GPIO的器件ID
#define AXI_GPIO_ID XPAR_GPIO_0_DEVICE_ID//AXIGPIO的器件ID
#define SCUGIC_ID XPAR_PS7_SCUGIC_0_DEVICE_ID//中斷的ID
//axi gpio的中斷號
#define AXI_GPIO_INTR_ID XPAR_FABRIC_GPIO_0_VEC_ID
#define LED0 54
//axi gpio通道1
#define AXI_GPIO_CHANNEL 1
//定義調用GpioPs的結構體
XGpioPs gpiops;
XGpioPs_Config *gpio_cfg;
//定義調用中斷的結構體
XScuGic gpio_gic;
XScuGic_Config *gpio_gic_cfg;
//定義調用Gpio的結構體
XGpio axi_Gpio;
//變量聲明
u32 key_value=0;
//函數聲明
void Init_gpio();
void IntrHandler();
int main()
{
	u32 led_status=0;
    init_platform();
    Init_gpio();
    Init_interrupt();
    print("axi_gpio TEST\n\r");
    while(1)
    {
    	if(key_value==1){
    		//清除中斷狀態
    		if(XGpio_DiscreteRead(&axi_Gpio, AXI_GPIO_CHANNEL)==1){
    			led_status=~led_status;
    		}
    		XGpio_InterruptClear(&axi_Gpio, 0x0000001);
    		key_value=0;

    		XGpioPs_WritePin(&gpiops,LED0,led_status);
    		usleep(200000);
    		//打開中斷使能
    		XGpio_InterruptEnable(&axi_Gpio, 0x0000001);//使能中斷
    	}
    }
    cleanup_platform();
    return0;
}
//初始化gpio
void Init_gpio(){
	//查找設備ID	,gpio初始化操作
	gpio_cfg=XGpioPs_LookupConfig(GPIO_ID);
	XGpioPs_CfgInitialize(&gpiops,gpio_cfg,gpio_cfg->BaseAddr);
	//設置gpio為輸出,開啟使能
	XGpioPs_SetDirectionPin(&gpiops,LED0,1);
	XGpioPs_SetOutputEnablePin(&gpiops,LED0,1);
	//對PL端的gpio進行初始化
	XGpio_Initialize(&axi_Gpio,AXI_GPIO_ID);
	//對AXI設置方向
	XGpio_SetDataDirection(&axi_Gpio,AXI_GPIO_CHANNEL,0x0000001);//設置為輸入

}
void Init_interrupt(){
	//初始化gic
	gpio_gic_cfg = XScuGic_LookupConfig(SCUGIC_ID);
	XScuGic_CfgInitialize(&gpio_gic,gpio_gic_cfg,gpio_gic_cfg->CpuBaseAddress);

	//初始化異常處理
	Xil_ExceptionInit();
	//CPU中斷異常注冊
	Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,(Xil_ExceptionHandler)XScuGic_InterruptHandler,&gpio_gic);
	//使能處理器中斷
	Xil_ExceptionEnableMask(XIL_EXCEPTION_IRQ);

	//鏈接中斷信號
	XScuGic_Connect(&gpio_gic,AXI_GPIO_INTR_ID,(Xil_InterruptHandler)IntrHandler,&axi_Gpio);
	//使能中斷
	XScuGic_Enable(&gpio_gic,AXI_GPIO_INTR_ID);
	//0xa0中斷優先級
	XScuGic_SetPriorityTriggerType(&gpio_gic,AXI_GPIO_INTR_ID,0xA0, 0x3);
	//axi gpio使能中斷
	XGpio_InterruptGlobalEnable(&axi_Gpio);//打開全局中斷
	XGpio_InterruptEnable(&axi_Gpio, 0x0000001);//使能中斷
}
void IntrHandler(){
	printf("interrupt~~\n\r");
	key_value=1;
	//關閉中斷使能
	XGpio_InterruptDisable(&axi_Gpio, 0x0000000);

}

部分代碼講解

代碼很類似上次的GPIO的中斷功能的代碼,這里只是更改了部分函數對axi gpio的ip進行ip的配置,實現帶中斷的輸入功能的KEY。axi的初始化只需要一行代碼即可完成,然后根據編程指南設置下方向即可完成輸入的配置XGpio_Initialize(&axi_Gpio,AXI_GPIO_ID);//對PL端的gpio進行初始化XGpio_SetDataDirection(&axi_Gpio,AXI_GPIO_CHANNEL,0x0000001);//對AXI設置方向設置為輸入對于這里的AXI_GPIO中斷的標號就是我們前面提到的61,在這里我們可以進行define一下,方便我們進行引用。#define AXI_GPIO_INTR_ID XPAR_FABRIC_GPIO_0_VEC_ID//axi gpio的中斷號在SDK中尋一下這個參數的數據也可以驗證我們的標號數值:

對于axi _gpio,我們配置的時候可以看到,每個IP核有兩路GPIO,這里我們只用了通道1,所以我們的通道編號定義為1                    #define AXI_GPIO_CHANNEL 1//axi gpio通道1在配置axi gpio的中斷功能時,用的了 XScuGic_SetPriorityTriggerType(&gpio_gic,AXI_GPIO_INTR_ID,0xA0, 0x3);在尋到該函數定義時候,可以簡要了解下參數的配置功能。

0xa0配置了中斷優先級,這里我們不進行中斷優先級的配置,所以引用的是示例里面的默認值,中斷編號就是我們AXI GPIO的編號,0x03這個值用于配置中斷的方式。這里我們的中斷有高電平觸發和邊沿觸發模式。我們設置邊沿觸發后,在我們按下按鍵會滿足兩次邊沿觸發的條件(這里我感覺注釋和實際操作不相符),然后回看我們的編程指南,在中斷配置時候是也是要求我們:當接收到中斷時,讀取GPIOx_DATA寄存器中相應的位。通過寫入值為1的對應位來清除IP中斷狀態寄存器中的狀態。所以我們就引用了XGpio_DiscreteRead(&axi_Gpio, AXI_GPIO_CHANNEL) 對中斷的狀態進行讀取。對應編程指南代碼編寫如下:

//清除中斷狀態
    if(XGpio_DiscreteRead(&axi_Gpio, AXI_GPIO_CHANNEL)==1){
   		led_status=~led_status;
    }
    XGpio_InterruptClear(&axi_Gpio, 0x0000001);

完成代碼編寫后下載到我們的PYNQ的開發板即可完成本次實驗。

聲明:本內容為作者獨立觀點,不代表電子星球立場。未經允許不得轉載。授權事宜與稿件投訴,請聯系:editor@netbroad.com
覺得內容不錯的朋友,別忘了一鍵三連哦!
贊 2
收藏 3
關注 20
成為作者 賺取收益
全部留言
0/200
成為第一個和作者交流的人吧