使用sysfs操作GPIO

在Linux中,可以在用戶空間使用sysfs和mmap(/dev/mem)方式操作GPIO,本次實(shí)驗(yàn)的平臺(tái)為IMX8MM(飛凌OKMX8MM-C開發(fā)板),主要介紹sysfs操作GPIO步驟,并附完整代碼。

使用sysfs操作GPIO

sysfs是一個(gè)基于內(nèi)存的文件系統(tǒng),可以向用戶模式應(yīng)用程序提供詳細(xì)的內(nèi)核數(shù)據(jù)結(jié)構(gòu)信息。使用sysfs操作GPIO時(shí),需要先導(dǎo)出IO口,然后設(shè)置IO方向及中斷模式。具體介紹見https://www.kernel.org/doc/Documentation/gpio/sysfs.txt。

1、確定GPIO編號(hào)

使用cat /sys/kernel/debug/gpio查看GPIO信息:

root@okmx8mm:~# cat /sys/kernel/debug/gpio
gpiochip0: GPIOs 0-31, parent: platform/30200000.gpio, 30200000.gpio:

gpiochip1: GPIOs 32-63, parent: platform/30210000.gpio, 30210000.gpio:
 gpio-38  (                    |?                   ) out hi    
 gpio-44  (                    |cd                  ) in  hi IRQ
 gpio-51  (                    |VSD_3V3             ) out lo    

gpiochip2: GPIOs 64-95, parent: platform/30220000.gpio, 30220000.gpio:
 gpio-80  (                    |status              ) out hi    
 gpio-83  (                    |usb_otg1_vbus       ) out lo    
 gpio-89  (                    |WLAN_EN             ) out lo    

gpiochip3: GPIOs 96-127, parent: platform/30230000.gpio, 30230000.gpio:
 gpio-118 (                    |headphone detect    ) in  lo IRQ
 gpio-124 (                    |GPIO Key HOME       ) in  hi IRQ
 gpio-127 (                    |GPIO Key UP         ) in  hi IRQ

gpiochip4: GPIOs 128-159, parent: platform/30240000.gpio, 30240000.gpio:
 gpio-130 (                    |GPIO Key DOWN       ) in  hi IRQ
 gpio-137 (                    |spi_imx             ) out hi    
 gpio-141 (                    |spi_imx             ) out hi 

在這兒我要使用GPIO5_IO00,由上面gpiochip4: GPIOs 128-159, parent: platform/30240000.gpio, 30240000.gpio可以看到,GPIO5對應(yīng)的編號(hào)范圍為128~159,所以GPIO5_IO00對應(yīng)的編號(hào)為128(128 + 0),依次類推,GPIO5_IO01的編號(hào)為129。

2、GPIO配置

進(jìn)入/sys/class/gpio,可以看到以下內(nèi)容:

root@okmx8mm:~# cd /sys/class/gpio
root@okmx8mm:/sys/class/gpio# ls
export   gpiochip0    gpiochip32  gpiochip96
gpio118  gpiochip128  gpiochip64  unexport
  • 其中export用于導(dǎo)出GPIO到用戶空間,例如導(dǎo)出編號(hào)為128(GPIO5_IO00):
echo 128 > export

當(dāng)前目錄下會(huì)生成gpio128目錄,當(dāng)系統(tǒng)重啟時(shí),導(dǎo)出的IO口會(huì)消失,所以每次使用時(shí),最好先導(dǎo)出IO口。

  • unexport用于取消導(dǎo)出的GPIO,例如:
echo 128 > unexport

這兒我需要使用GPIO5_IO00GPIO5_IO01,所以需要運(yùn)行以下指令:

echo 128 > export
echo 129 > export

進(jìn)入其中一個(gè)目錄可以看到:

root@okmx8mm:/sys/class/gpio/gpio128# ls
active_low  device  direction  edge  power  subsystem  uevent  value

其中direction用于設(shè)置IO方向(in、out),edge用于設(shè)置中斷模式(none、rising、falling、both),value用于讀取IO電平,具體內(nèi)容見https://www.kernel.org/doc/Documentation/gpio/sysfs.txt。

這兒我把GPIO5_IO00設(shè)置為中斷輸入模式,GPIO5_IO01設(shè)置為輸出模式:

root@okmx8mm:/sys/class/gpio/gpio128# echo "in" > direction
root@okmx8mm:/sys/class/gpio/gpio128# echo "rising" > edge
root@okmx8mm:/sys/class/gpio/gpio128# cd ../gpio129
root@okmx8mm:/sys/class/gpio/gpio129# echo "out" > direction

測試時(shí)可以使用echo 1 > value設(shè)置GPIO5_IO01輸出高電平;echo 0 > value設(shè)置GPIO5_IO01輸出低電平。
最后配置結(jié)果如下:

root@okmx8mm:/sys/class/gpio/gpio129# cat /sys/kernel/debug/gpio
gpiochip0: GPIOs 0-31, parent: platform/30200000.gpio, 30200000.gpio:

gpiochip1: GPIOs 32-63, parent: platform/30210000.gpio, 30210000.gpio:
 gpio-38  (                    |?                   ) out hi    
 gpio-44  (                    |cd                  ) in  hi IRQ
 gpio-51  (                    |VSD_3V3             ) out lo    

gpiochip2: GPIOs 64-95, parent: platform/30220000.gpio, 30220000.gpio:
 gpio-80  (                    |status              ) out hi    
 gpio-83  (                    |usb_otg1_vbus       ) out lo    
 gpio-89  (                    |WLAN_EN             ) out lo    

gpiochip3: GPIOs 96-127, parent: platform/30230000.gpio, 30230000.gpio:
 gpio-118 (                    |headphone detect    ) in  lo IRQ
 gpio-124 (                    |GPIO Key HOME       ) in  hi IRQ
 gpio-127 (                    |GPIO Key UP         ) in  hi IRQ

gpiochip4: GPIOs 128-159, parent: platform/30240000.gpio, 30240000.gpio:
 gpio-128 (                    |sysfs               ) in  lo IRQ
 gpio-129 (                    |sysfs               ) out lo    
 gpio-130 (                    |GPIO Key DOWN       ) in  hi IRQ
 gpio-137 (                    |spi_imx             ) out hi    
 gpio-141 (                    |spi_imx             ) out hi

3、測試

使用epoll讀取GPIO5_IO00中斷,并翻轉(zhuǎn)GPIO5_IO01,完整代碼如下:

//
// Created by txfly on 2020/8/25.
//

#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <sys/epoll.h>

int main(int argc, char *argv[]) {
//    int fd = open("/sys/class/gpio/export", O_WRONLY);
//    if (fd == -1){
//        write(fd, "128", 3);
//        write(fd, "129", 3);
//    }
//    close(fd);
//  前面手動(dòng)導(dǎo)出過,這兒就不做處理了

    // 中斷輸入
    int trigger = open("/sys/class/gpio/gpio128/value", O_RDWR | O_NONBLOCK);
    if (trigger == -1) {
        printf("Fail to open GPIO5_IO00\n");
        exit(1);
    }
    // LED
    int led = open("/sys/class/gpio/gpio129/value", O_WRONLY);
    if (led == -1) {
        printf("Fail to open GPIO5_IO01\n");
        exit(1);
    }
    // epoll
    int epfd = epoll_create(1);
    struct epoll_event ev, events;
    ev.events = EPOLLPRI;
    ev.data.fd = trigger;
    int n = epoll_ctl(epfd, EPOLL_CTL_ADD, trigger, &ev);
    if (n == -1) {
        printf("Fail to add a file descriptor to the interface. \n");
        exit(1);
    }

    char buf = 0;
    while (1) {
        n = epoll_wait(epfd, &events, 1, -1);
        if (n > 0) {
            lseek(trigger, 0, SEEK_SET);
            n = read(trigger, &buf, 1);
            printf("read, buf=%c\tlen=%d\n", buf, n);
            if (buf == '0') {
                write(led, "0", 1);
            } else {
                write(led, "1", 1);
            }
        } else {
            break;
        }
    }
    close(led);
    close(trigger);
    close(epfd);
}

版權(quán)聲明:本文為「txfly」的原創(chuàng)文章,遵循 CC 4.0 BY-SA 版權(quán)協(xié)議,轉(zhuǎn)載請附上原文出處鏈接及本聲明。
原文鏈接:http://www.itdecent.cn/p/0f702330bdc8

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容