Linux下如何通過UIO監控PL給到PS的中斷

2023-08-24 16:11:08 來源:大川搬磚

1. 概述

xilinx mpsoc 平臺中,PS 和 PL 進行交互時,PS 需要獲取 PL 發出的中斷信號。從 mpsoc 技術參考手冊 ug1085 TRM 中可知,PL 給到 PS 的中斷有兩組——PL_PS_Group0 和 PL_PS_Group1,中斷號范圍分別為 121~128 和 136 ~143( Linux設備樹中進行配置時,中斷號要減去 32)。


(資料圖片僅供參考)

下面通過一個例程說明 如何通過 UIO 監控 PL 給到 PS 的中斷

2. demo

Linux 環境下,獲取 PL 中斷信號最簡單的方式是通過 UIO。這里,定義一個簡單的測試 demo:

Linux 下控制 AXI-GPIO 產生高低電平;PL 將 AXI-GPIO 的高低電平轉變為中斷信號給到 Linux。

2.1 vivado 配置

2.1.1 vivado

在 PL 端添加 AXI-GPIO IP 核,并使能兩個通道,兩個通道分別連接 PL_PS_Group0 和 PL_PS_Group1。

2.1.2 PL to PS Interrupts

使能 PL 給到 PS 的兩組中斷。

2.1.3 AXI GPIO 配置

使能 AXI GPIO 的兩個通道,每個通道使用 1 位即可。

2.2 PS Linux

PS 端 Linux 系統下,通過 控制 AXI-GPIO 輸出高低電平即可使 PL 生成中斷信號到 PL_PS_Group0 和 PL_PS_Group1

2.2.1 AXI-GPIO 控制

Linux 下,AXI-GPIO 的控制方式和普通 GPIO 沒有區別,最簡單的方式是通過 /sys 文件系統。

cd /sys/class/gpio#使能引腳號為506的引腳——將引腳導出到用戶空間echo 506 > export#設置引腳為輸出模式echo out > gpio506/direction#控制引腳輸出高電平echo 1 > gpio506/value#控制引腳輸出低電平echo 0 > gpio506/value#關閉引腳echo 506 > unexport

2.2.2 設備樹

在設備樹中添加 UIO 中斷節點,注意中斷號的數值。

system-user.dtsi:

pl-ps-group0-1 {    compatible = "generic-uio";    interrupt-controller;    interrupt-parent = < &gic >;    interrupts = < 0 89 1 >;};pl-ps-group0-2 {    compatible = "generic-uio";    interrupt-controller;    interrupt-parent = < &gic >;    interrupts = < 0 90 1 >;};......pl-ps-group0-8 {    compatible = "generic-uio";    interrupt-controller;    interrupt-parent = < &gic >;    interrupts = < 0 96 1 >;};pl-ps-group1-1 {    compatible = "generic-uio";    interrupt-controller;    interrupt-parent = < &gic >;    interrupts = < 0 104 1 >;};pl-ps-group1-2 {    compatible = "generic-uio";    interrupt-controller;    interrupt-parent = < &gic >;    interrupts = < 0 105 1 >;}; ......pl-ps-group1-8 {    compatible = "generic-uio";    interrupt-controller;    interrupt-parent = < &gic >;    interrupts = < 0 111 1 >;};

2.2.3 中斷監控程序

uio-int-monitor.c:

#include < stdio.h >#include < stdlib.h >#include < stdint.h >#include < sys/types.h >#include < sys/stat.h >#include < fcntl.h >#include < pthread.h >#include < unistd.h >#define PL_PS_GROUP0_0_UIO_NAME ("/dev/uio2")#define PL_PS_GROUP1_0_UIO_NAME ("/dev/uio10")struct uio_int_info {    int8_t *uio_name;    int32_t uio_fd;};staticvoid *interrupt_uio_monitor(void *para){    struct uio_int_info *uio_info = (struct uio_int_info *)para;    const uint32_t uio_int_regen_flag = 1;    uint32_t uio_int_happen_cnt = 0;    write(uio_info- >uio_fd, &uio_int_regen_flag, sizeof(uio_int_regen_flag));    while(1)    {        read(uio_info- >uio_fd, &uio_int_happen_cnt, sizeof(uio_int_happen_cnt));        write(uio_info- >uio_fd, &uio_int_regen_flag, sizeof(uio_int_regen_flag));        printf("%s interrupt happen, count:%un", uio_info- >uio_name, uio_int_happen_cnt);    }}int main(int argc, char *argv[]){    pthread_t tid;    struct uio_int_info g0_0 =    {        .uio_name = "gruop0-0",    };    struct uio_int_info g1_0 =    {        .uio_name = "gruop1-0",    };    g0_0.uio_fd = open(PL_PS_GROUP0_0_UIO_NAME, O_RDWR);    g1_0.uio_fd = open(PL_PS_GROUP1_0_UIO_NAME, O_RDWR);    if((-1 == g0_0.uio_fd) || (-1 == g1_0.uio_fd))    {        printf("open uio device failedn");        return -1;    }    pthread_create(&tid, NULL, interrupt_uio_monitor, (void *)&g0_0);    pthread_create(&tid, NULL, interrupt_uio_monitor, (void *)&g1_0);    getchar();    close(g0_0.uio_fd);    close(g1_0.uio_fd);    return 0;}

重點說明:

read(uio_fd)用于監測中斷信號;write(uio_fd, 1)用于使能中斷,使下一次可以收到中斷信號;每次 read()后都需要進行 write(1)

3. 測試(關鍵)

3.1 如何計算 AXI GPIO 引腳號

在我創建的系統中,AXI-GPIO 的起始引腳號為 506(gpiochip506)。由于我使能了 AXI-GPIO 的兩個通道,所以,我可以控制兩個引腳,引腳號分別為 506 和 507,分別連接的是 PL_PS_Group0[0] 和 PL_PS_Group1[0]。

為什么起始引腳號是 506 呢?

mpsoc 中的 MIO 在系統中的起始引腳號是 332,而且,SOC 包含 78 個 MIO 引腳,96 個 EMIO 引腳。所以,AXI GPIO 的起始引腳為 332 + 78 + 96 = 506.

3.2 如何獲取中斷對應 UIO 設備節點

設備樹中包含了所有PL 到 PS 的中斷信息( 注意中斷號要減去 32):

PL_PS_Group0[0:7] 對應 pl-ps-group0-1 ~ pl-ps-group0-8;

PL_PS_Group1[0:7] 對應 pl-ps-group1-1 ~ pl-ps-group1-8。

Linux 下可以通過 cat /sys/class/uio/uio0/name獲取 UIO 設備節點的名稱,從而找到 /dev/ 下對應的 uio 文件。

也可以使用 lsuio命令查看系統中的 UIO 設備節點信息:

3.3 如何產生中斷信號

通過 PS 控制 AXI GPIO 輸出高低電平使 PL 產生中斷信號。

4. 總結

ug1085 TRM 文檔中的中斷號減去 32 后再寫入設備樹中;使用 fd = open()打開 uio 設備節點后,read(fd)用于等待中斷,write(fd, 1)用于使能中斷。

標簽:

上一篇:plc與多種傳感器連接方式的區別
下一篇:最后一頁