[米聯客-安路飛龍DR1-FPSOC] SDK入門篇連載-03 GPIO PS/PL實驗

米联客(milianke)發表於2024-08-05

軟體版本:Anlogic -TD5.9.1-DR1_ES1.1

作業系統:WIN10 64bit

硬體平臺:適用安路(Anlogic)FPGA

實驗平臺:米聯客-MLK-L1-CZ06-DR1M90G開發板

板卡獲取平臺:https://milianke.tmall.com/

登入"米聯客"FPGA社群 http://www.uisrc.com 影片課程、答疑解惑!

1 概述

本課對FPSoC晶片GPIO進行介紹,透過點亮PS LEDPL LED以及讀取PL按鍵輸入值,來控制LED燈閃爍,演示GPIO PSGPIO PL的使用方法。

本文實驗目的:

1:熟悉FPSoC PS部分PSIO的內部結構、相關暫存器

2:掌握FPSoC IP核中如何分配GPIO

3:掌握FD中如何使用PSIO

2系統框圖

PSIO一般會分配到固定的外設,包括FLASHEMMCTFCARDUARTUSB2.0ETH乙太網。GPIO也可以單獨配置成普通的PSIO,如果IO不夠用也可以透過PLIO擴充套件更多IO

3 GPIO介紹

3.1功能描述

GPIO(General Purpose I/O Ports),通用輸入/輸出埠。

DR1 器件含有通用I/O(GPI0)外設透過PS IO 模組為軟體提供多達54個裝置引腳的觀察和控制。它還透過PL IO 介面提供對來自可程式設計邏輯(PL)64 個輸入和PL 128 個輸出的訪問。GPI0 被組織成四組暫存器,對相關介面訊號進行分組。每個GPI0 作為輸入、輸出或中斷感測是獨立和動態程式設計。軟體可以使用單個載入指令讀取bank 內的所有GPI0 值,或者使用單個儲存指令將資料寫入一個或多個GPIO(GPIO 的範圍內)

軟體將 GPIO配置為輸出或輸入。無論 GPIO設定為輸入(OE 訊號 false)還是輸出(OE 訊號true),資料暫存器始終返回GPIO引腳的狀態。為了生成輸出波形,軟體會重複寫入一個或多個 GPIO

3.2 GPIO特性

1、裝置引腳的 54 GPI0 訊號(透過PS 10 多路複用器佈線)

  • 輸出具有三態能力

2PS PL 之間透過PL 10 介面的192 GPIO 訊號(64 輸入+64輸出+64輸出使能)

  • 64 個輸入,128 個輸出(64 個真實輸出和64 個輸出使能)

3、每個GPIO的功能可單獨或成組動態程式設計

4、支援位或列資料方式對 GP10 進行寫入、輸出使能和方向控制

5、基於單個 GPIO 的可程式設計中斷

  • 支援初始和遮蔽中斷的狀態讀取
  • 支援中斷可選靈敏度:電平敏感(高或低)或邊緣敏感(正或負)

6、配置為 GPIO 的時候,預設狀態是輸入上拉

3.3 關鍵暫存器

名稱

暫存器名

功能描述

配置控制暫存器

GPIO SWPORTA DR BLK0-3

GPIO SWPORTA DDR BLK0-3

GPIO SWPORTA DR CLR BLK0-3

GPIO SWPORTA DDR CLR BLK0-3

控制 GPIO 的輸入/輸出,清除輸入/輸出的資料。

中斷暫存器

GPIO INTEN CLR BLK0-3

GPIO INTMASK CLR BLK0-3

GPIO INTTYPE LEVEL CLR BLK0-3

GPIO INT POLARITY_CLR_BLK0-3

GPIO INT BOTHEDGE CLR BLKO-3

中斷使能、中斷 mask、中斷清除,中斷響應極性設定。

Debounce暫存器

GPIO DEBOUNCE CLR BLK0-3

GPIO DEBOUNCE BLK0-3

GPIO 濾毛刺暫存器

4硬體電路分析

硬體介面和子卡模組請閱讀"附錄1"

配套工程的FPGA PIN腳定義路徑為soc_prj/uisrc/04_pin/ fpga_pin.adc

5搭建SOC系統工程

詳細的搭建過程這裡不再重複,對於初學讀者如果還不清楚如何建立SOC工程的,請學習"01Vitis Soc開發入門"這篇文章。

本文中的PS設定內容是新增加的GPIO PS以及GPIO PL部分,關於DDRPSIOCPU時鐘等設定請參考"01Vitis Soc開發入門"這篇文章。

5.1GPIO配置

01Vitis Soc開發入門"這篇文章中已經對特定功能的PSIO做了設定,只有剩餘的PSIO可以用於其他的自定義功能。以下設定未分配功能的PSIO,以及需要擴充套件的GPIO PL IO的數量。

5.2GPIO PL定義

設定好後,右擊選擇Create Design Port

設定IO名稱、IO型別、IO位寬

最終GPIO PL需要定義到FPGAIO中,所以我們需要引出GPIO PL訊號到system_top頂層檔案

 1 module system_top (
 2     output PL_LED,
 3     input  PL_KEY
 4 );
 5   wire [1:0] pl_gpio_in;
 6   wire [1:0] pl_gpio_out;
 7   assign PL_LED = pl_gpio_out[0];
 8   assign pl_gpio_in[1] = PL_KEY;
 9   system I_system (
10       .pl_gpio_in (pl_gpio_in),
11       .pl_gpio_out(pl_gpio_out)
12   );
13 
14 endmodule

5.3編譯並匯出平臺檔案

以下步驟簡寫,有不清楚的看第1篇《01 Soc開發入門》文章。

匯出完成後,對應工程路徑的soc_hw路徑下有硬體平臺檔案:fpga_prj.hpf的檔案。根據硬體平臺檔案fpga_prj.hpf來建立需要Platform平臺。

6 搭建SDK工程

建立soc_base sdk platformAPP工程的過程不再重複,如果不清楚請參考本章節第一個demo

6.1建立Platform工程

建立soc_base sdk platformAPP工程的過程不再重複,如果不清楚請參考本章節第一個demo01 Soc開發入門》文章。

6.2建立gpio_ctl_led APP工程

7程式分析

Gpio_ctl_led.c

 1 #include "al_gpio_hal.h"
 2 
 3 #define PS_LED 51 //PS GPIO 51
 4 #define PL_LED 54 //PL GPIO 01
 5 #define PS_KEY 50 //PS GPIO 50
 6 #define PL_KEY 55 //PL GPIO 02
 7 #define LED_IN_BANK0          0x80000
 8 #define LED_IN_BANK2          0x1
 9 #define AL_GPIO_DEVICE_ID     0
10 #define AL_GPIO_DELAY_20MS    20
11 #define AL_GPIO_DELAY_2000MS  2000
12 
13 AL_S32 AlGpio_Hal_Ctl_LED_Example()
14 {
15     AL_GPIO_HalStruct *GPIO;
16     AL_S32 PS_LedValue = 0;
17     AL_S32 PL_LedValue = 0;
18     AL_S32 PS_KeyValue = 0;
19     AL_S32 PL_KeyValue = 0;
20 
21     /* 1、Test AlGpio_Hal_Init */
22     AL_S32 ret = AlGpio_Hal_Init(&GPIO, AL_GPIO_DEVICE_ID, AL_NULL);
23 
24     if (ret == AL_OK) {
25         AL_LOG(AL_LOG_LEVEL_INFO, "[TEST] APU AlGpio_Hal_Init success");
26     }
27     else {
28         AL_LOG(AL_LOG_LEVEL_INFO, "[TEST] APU AlGpio_Hal_Init failed");
29     }
30 
31     /* 2、Test Gpio function through Bank. */
32     AlGpio_Hal_WriteBank(GPIO, AL_GPIO_BANK1, LED_IN_BANK0);
33     AlGpio_Hal_WriteBank(GPIO, AL_GPIO_BANK2, LED_IN_BANK2);
34     AlSys_MDelay(AL_GPIO_DELAY_2000MS);
35     AlGpio_Hal_WriteBank(GPIO, AL_GPIO_BANK1, 0x0);
36     AlGpio_Hal_WriteBank(GPIO, AL_GPIO_BANK2, 0x0);
37     AlSys_MDelay(AL_GPIO_DELAY_2000MS);
38 
39 
40     /* 3、Test Gpio polling */
41     PS_LedValue = AlGpio_Hal_ReadPinOutput(GPIO, PS_LED);
42     AL_LOG(AL_LOG_LEVEL_INFO, "GPIO PS led value is 0x%x", PS_LedValue);
43     PL_LedValue = AlGpio_Hal_ReadPinOutput(GPIO, PL_LED);
44     AL_LOG(AL_LOG_LEVEL_INFO, "GPIO PL led value is 0x%x", PL_LedValue);
45 
46     while(1)
47     {
48         PS_KeyValue = AlGpio_Hal_ReadPinInput(GPIO, PS_KEY);
49         PL_KeyValue = AlGpio_Hal_ReadPinInput(GPIO, PL_KEY);
50         if(PS_KeyValue == 0|PL_KeyValue == 0){
51             AlSys_MDelay(AL_GPIO_DELAY_20MS);
52             if (PS_KeyValue == 0|PL_KeyValue == 0) {
53                 AlGpio_Hal_WritePin(GPIO, PS_LED, ~PS_LedValue);
54                 AlGpio_Hal_WritePin(GPIO, PL_LED, ~PL_LedValue);
55                 AlSys_MDelay(AL_GPIO_DELAY_20MS);
56                 AlGpio_Hal_WritePin(GPIO, PS_LED, PS_LedValue);
57                 AlGpio_Hal_WritePin(GPIO, PL_LED, PL_LedValue);
58                 AlSys_MDelay(AL_GPIO_DELAY_20MS);
59             }
60         }
61     }
62 
63     return AL_OK;
64 }
65 
66 
67 AL_S32 main(void) {
68     AL_LOG(AL_LOG_LEVEL_INFO, "[TEST]AlGpio_Hal_CTL_LED_Test start");
69     AlGpio_Hal_Ctl_LED_Example();
70 
71     return AL_OK;
72 }

接下來對程式進行分析。

7.1GPIO位號定義

1 #define PS_LED 51 //PS GPIO 51
2 #define PL_LED 54 //PL GPIO 01
3 #define PS_KEY 50 //PS GPIO 50
4 #define PL_KEY 55 //PL GPIO 02

PS GPIO比較好確認,主要是根據原理圖確認好PSIO編號即可。GPIO PL擴充套件的GPIO需要根據繫結的FPGA PIN來劃分,GPIO PL [0]位對應的位號為54,是Bank 2中的第1位。其他的以此類推。

7.2GPIO操控方法

程式中使用了2種方式演示操控GPIO,依次分析:

方法1:直接操控對應Bank暫存器,下列程式分別對Bank1以及Bank2直接進行寫資料。由原理圖可知PS LEDPSIO51Bank0的最大位號為31,所以Bank1的第1個位號為32。以此類推,PSIO51對應的是在對應的地址為0x80000,正好對應第20位。PL IO由此推斷為Bank2的第1位,對應的地址為0x1。該程式完成了點亮PS_LEDPL_LED持續2000MS之後再熄滅功能。

反應到開發板上狀態為,PL_LED以及PS_LED先點亮200MS後熄滅。

1  /* 2、Test Gpio function through Bank. */
2     AlGpio_Hal_WriteBank(GPIO, AL_GPIO_BANK1, LED_IN_BANK0);
3     AlGpio_Hal_WriteBank(GPIO, AL_GPIO_BANK2, LED_IN_BANK2);
4     AlSys_MDelay(AL_GPIO_DELAY_2000MS);
5     AlGpio_Hal_WriteBank(GPIO, AL_GPIO_BANK1, 0x0);
6     AlGpio_Hal_WriteBank(GPIO, AL_GPIO_BANK2, 0x0);
7     AlSys_MDelay(AL_GPIO_DELAY_2000MS);

方法2:透過位號控制,先透過AlGpio_Hal_ReadPinOutput函式透過位號讀取了PL_LED以及PS_LED的狀態。然後持續讀取PS_KEYPL_KEY的狀態,當發現PS_KeyValue == 0|PL_KeyValue == 0時,也就是PL KEY或者PS KEY任意哪個按鍵按下時,將PL_LED以及PS_LED20MS為週期持續取反。

反應到開發板上狀態為,當任意對應按鍵KEY按下時,PL_LED以及PS_LED持續閃爍。

 1     /* 3、Test Gpio polling */
 2     PS_LedValue = AlGpio_Hal_ReadPinOutput(GPIO, PS_LED);
 3     AL_LOG(AL_LOG_LEVEL_INFO, "GPIO PS led value is 0x%x", PS_LedValue);
 4     PL_LedValue = AlGpio_Hal_ReadPinOutput(GPIO, PL_LED);
 5     AL_LOG(AL_LOG_LEVEL_INFO, "GPIO PL led value is 0x%x", PL_LedValue);
 6 
 7     while(1)
 8     {
 9         PS_KeyValue = AlGpio_Hal_ReadPinInput(GPIO, PS_KEY);
10         PL_KeyValue = AlGpio_Hal_ReadPinInput(GPIO, PL_KEY);
11         if(PS_KeyValue == 0|PL_KeyValue == 0){
12             AlSys_MDelay(AL_GPIO_DELAY_20MS);
13             if (PS_KeyValue == 0|PL_KeyValue == 0) {
14                 AlGpio_Hal_WritePin(GPIO, PS_LED, ~PS_LedValue);
15                 AlGpio_Hal_WritePin(GPIO, PL_LED, ~PL_LedValue);
16                 AlSys_MDelay(AL_GPIO_DELAY_20MS);
17                 AlGpio_Hal_WritePin(GPIO, PS_LED, PS_LedValue);
18                 AlGpio_Hal_WritePin(GPIO, PL_LED, PL_LedValue);
19                 AlSys_MDelay(AL_GPIO_DELAY_20MS);
20             }
21         }
22     }

8方案演示

8.1硬體準備

本實驗需要用到JTAG下載器、USB轉串列埠外設,另外需要把SW1模式開關設定到JTAG模式

5.8.2實驗結果

由於新增了PL端按鍵資源,所以Debug時需要將TD生成的soc_prj/soc_prj_Runs/best_result/soc_prj.bit檔案同時新增進來,在debug前會先下載PL端資源後啟動SOC部分。

IO輸出功能,可看到底板上的PS LED以及PL LED先亮起,後熄滅。

IO輸入功能,可以透過按動KEY2KEY4,觀察到PS LED以及PL LED20MS週期閃爍。

串列埠觀察到讀取的PS LED以及PL LED的狀態。

相關文章