ZYNQ MIO EMIO IO的區別和靈活使用

2021-10-12 01:16:44 字數 3303 閱讀 8207

zynq:mio、emio、io的區別和靈活使用

在使用zynq上arm cortex-a9平台時首先面臨的就是對io進行操作,總的來說對io操作無怪乎兩種方式,一種是直接對gpio暫存器進行操作,這樣程式效率高,但編寫**困難;另一種是呼叫sdk工具提供的api介面函式。

在實際使用時zynq又把gpio分成mio、emio和pl端的io這三種型別,在剛剛接觸時會因為這三種io的不同配置和使用方式而影響後續的學習,這裡針對三種io進行詳細的說明使用方法。

首先要明白這三種io的物理屬性,簡單的說1、mio只屬於ps端,pl端無法進行操作。

2、emio從物理屬性來說屬於pl端io,但ps端可以通過軟體對映連線來對emio進行操作,且使用效果與mio一致。3、pl端所有io都屬於常規的fpga的io口,可進行輸入輸出操作,但是如果ps端不對emio控制時,lp端可以隨意的使用emio。

1、ps配置mio進行輸出

zynq7000系列晶元由54個mio,隸屬於ps部分,使用時不需要新增引腳約束,對pl部分是不可見的。在使用ps端mio時需要對gpio進行配置,這個配置過程與普通的arm晶元過程一致。首先需要對mio的基本特性進行配置,在對gpio配置時需要呼叫api函式,這裡需要了解下面幾個函式

1、xgpiops_config *xgpiops_lookupconfig(u16 deviceid);

這個函式是根據唯一的裝置id號來查詢裝置配置。這個函式返回乙個配置表入口。實際上就是根據裝置id返回結構體xgpiops_config的配置。

2、s32 xgpiops_cfginitialize(xgpiops *instanceptr, xgpiops_config *configptr, u32 effectiveaddr);
這個函式用於初始化gpio,主要完成對xgpiops結構體的配置。函式總是返回配置成功。

3、 void xgpiops_setdirectionpin(xgpiops *instanceptr, u32 pin, u32 direction);
這個函式為指定的引腳配置輸入輸出方向。實際上是對方向暫存器(dirmodereg暫存器)進行使能。設定為0時禁止輸出驅動使能,也就是輸入有效,設定為1時使能輸出驅動。

4、void xgpiops_setoutputenablepin(xgpiops *instanceptr, u32 pin, u32 openable);
這個函式設定指定引腳輸出使能。這個是對openablereg暫存器進行配置。openablereg與dirmodereg屬於邏輯與的關係,只有兩個都配置成功才能實現mio的輸入或者輸出的配置。

5、u32 xgpiops_readpin(xgpiops *instanceptr, u32 pin);
這個函式是從指定引腳讀出資料。返回值是從data_ro寄存去內取出讀到的資料。

6、void xgpiops_writepin(xgpiops *instanceptr, u32 pin, u32 data);
這個函式是對指定引腳寫入資料。這個函式是對data暫存器、data_msw暫存器、data_lsw暫存器進行配置,共同完成輸出資料的寫入。

在了解了上述函式後,對ps端的gpio操作就相對簡單了。配置流程就是

1、根據裝置id找到基位址和裝置編號,也就是完成xgpiops_config的配置。

2、對找到的裝置進行配置,這個可直接呼叫函式進行完成。

3、設定io的輸入輸出方向。

4、使能對應io的輸入輸出。

5、對io進行讀或者寫操作。

根據上面是配置流程**如下:

#include 「xgpiops.h」

#include 「sleep.h」

int main()

return 0;2、 ps配置emio進行輸出

在使用emio時需要在z7的ip核配置時選擇emio。如下圖,這裡選擇了2個emio埠。

其次又要emio硬體上屬於pl端,需要在pl端對gpio進行約束,通俗的講就是把這個gpio硬體埠鏈結到ps上。管腳約束檔案如下圖

在完成了上述配置後,在sdk上對這些emio進行配置時就和mio一樣。

3、ps配置pl端普通io進行輸出

這個方式對pl端普通io進行操作是比較麻煩的,並且也消耗axi匯流排資源。

axi介面如下表描述:

在使用ps對pl端io操作時,axi_gpio相當於gpio的ip核,是通過axi匯流排掛在ps上的gpio上。因此系統整體連線圖如下圖所示:(這個圖包含了mio、emio和axi_gpio)

這部分由於使用了axi匯流排,裝置的id和位址都是確定的,因此不需要對gpio的裝置id和基位址進行配置,只需要對pl端gpio進行初始化即可。

xstatus = xgpio_initialize(&pl_gpio_instance_ptr, xpar_axi_gpio_0_device_id);

if (null!=xstatus)

print (「pl_axi_gpio config ok \n\r」) ;

xgpio_setdatadirection(&pl_gpio_instance_ptr,1,1);

xgpio_setdatadirection(&pl_gpio_instance_ptr,2,0);

然後對這個io進行讀寫操作,這裡需要主要的是輸入資料為32位,需要把輸入的資料和gpio數量要進行對應。

xgpio_discretewrite(&pl_gpio_instance_ptr,2,0xffffffff);

xgpio_discretewrite(&pl_gpio_instance_ptr,2,0x00000000);

總結這三種gpio的配置有相同的地方和不同的地方,不同的地方主要是由gpio所歸屬的物理位置不同導致,由於物理位置不同進行額外配置在pl端。而在ps端其實需要修改的很少。因此在sdk上進行io操作是相對靈活且簡單的。

記憶體的使用 棧區 堆區 靜態區 唯讀區

記憶體的使用感覺好亂啊,需要整理一下!於是參考c primer與網上資源,整理如下 一 綜述 記憶體中的棧區分配的是區域性變數和函式的引數值的空間,棧的生長方向是從高往低的 堆區是向上增長的用於分配程式設計師申請的記憶體空間 比如new 申請的動態記憶體 注意它與資料結構中的堆是兩回事,分配方式倒是...

C 中的棧區,堆區,常量區

include void main 對應的彙編 10 a c 1 00401067 8a 4d f1 mov cl,byte ptr ebp 0fh 0040106a 88 4d fc mov byte ptr ebp 4 cl 11 a p 1 0040106d 8b 55 ec mov edx,...

堆區 棧區 靜態區 常量區還有???

常見的儲存區域可分為 由編譯器在需要的時候分配,在不需要的時候自動清楚的變數的儲存區。裡面的變數通常是區域性變數 函式引數等。由new分配的記憶體塊,他們的釋放編譯器不去管,由我們的應用程式去控制,一般乙個new就要對應乙個delete。如果程式設計師沒有釋放掉,程式會一直占用記憶體,導致記憶體洩漏...