2017-11-30 3 views
1

Buildroot (커널 4.1)로 빌드 된 Linux를 실행하는 임베디드 시스템 (ARM 코어)에서 Python의 GPIO 액세스를 실험하고 있습니다. 15).Python에서 GPIO 읽기 차단 : epoll() 및 select.EPOLLET을 사용하여 차단하는 방법

코드를 GPIO2에서 핀 변경을 기다리는 BLOCK으로 설정하고 싶습니다. (예 : "read"를 반복적으로 호출하여 핀을 폴링하고 싶지 않습니다.) edge-triggered 모드에서 "epoll"을 사용하여이 작업을 수행하려고합니다.

Python docs for epoll을 참조하십시오. select.EPOLLET 플래그는 epoll에 대한 에지 트리거링을 가져 오는 데 사용됩니다. Linux docs for epoll도 참조하십시오.

# cat /sys/class/gpio/gpio2/direction 
in 
# cat /sys/class/gpio/gpio2/edge 
rising 

여기 내 파이썬 코드입니다 : 편의상

, 나는 이미 콘솔에서 사용 sysfs를 내 GPIO 핀을 설정 한 테스트를 위해

#!/usr/bin/env python 
# coding=utf8 

from time import sleep 
import select 
import sys 

if __name__ == '__main__': 

    try: 
     pinIn = open("/sys/class/gpio/gpio2/value", "r") 
    except IOError: 
     print("Error setting up GPIO pin") 
     sys.exit() 

    myPoll = select.epoll() 
    myPoll.register(pinIn.fileno(), select.EPOLLPRI | select.EPOLLET) 

    while(1): 

     events = myPoll.poll(4) 
     print("EPoll result: %s" % (str(events),)) 

     for fd, event_type in events: 
      print("FD: %d; Events: %d" % (fd, event_type)) 
      if event_type & select.EPOLLIN: 
       print("-EPOLLIN!") 
      if event_type & select.EPOLLPRI: 
       print("-EPOLLPRI!") 
      if event_type & select.EPOLLERR: 
       print("-EPOLLERR!") 

     value = pinIn.read(1) 
     pinIn.seek(0) 
     print("--> %s" % (str(value),)) 
     sleep(1) 

를, I는 입력을 공급하고 1 초당 약 2 초에 신호 발생기의 구형파가있는 핀을 사용하면 핀이 언제 바뀌는 지 알 수 있습니다.

코드는 1 초 수면에 잔
# python3 /usr/sbin/test-gpio-python.py 
EPoll result: [(3, 10)] 
FD: 3; Events: 10 
-EPOLLPRI! 
-EPOLLERR! 
--> 0 

가, 그 다음 반복에, 설문 조사는() 즉시 반환하고 블록을하지 않습니다 : 내 임베디드 시스템에서이 프로그램을 실행할 때

,이 얻을 . 입력이 2 초당 하나의 상승 에지에서만 작동하기 때문에 차단되어야합니다.

"poll()"이 (가) 차단되지 않는 이유는 무엇입니까?

가 ==== 편집 : ====이

원래 코드가 내가 "select.EPOLLET"를 사용하려고 이상한 오류 발생 : 그러나

OverflowError: can't convert negative value to unsigned int 

을 나는 것을 발견 나는 epoll() 대신에 실수로 myPoll = select.poll()을 사용했습니다. 코드가 수정되었습니다.

+1

* libgpiod * (새 커널을 사용할 수있는 경우)를 사용하는 것이 좋습니다 : https://git.kernel.org/pub/scm/libs/libgpiod/libgpiod.git/. – 0andriy

+0

@ 0andriy 좋은 정보, 고마워 ... 나는 sysfs 인터페이스가 사용되지 않을 것임을 몰랐다! 커널 4.1.15를 사용하고 있습니다. – Jeremy

답변

0

/proc/interrupts에서 인터럽트 정보를 확인하기로했습니다. 여기

그것은,는 GPIO 핀은 "상승"할 가장자리를 설정 한 후 초 불과 몇된다

# cat /proc/interrupts 
... 
33:  421 gpio-mxc 2 Edge  gpiolib 
... 

흠, 421 개 인터럽트가 이미 발생! 나중에

두 초 :

# cat /proc/interrupts 
... 
33:  852 gpio-mxc 2 Edge  gpiolib 
... 

을 설명 할 수있다. 인터럽트는 초당 ~ 400에서 쌓이고 있습니다. 파이썬에서 처리하는 것보다 빠릅니다.

추가 조사를 통해 신호 발생기는 약 1.6V 밖에 나오지 않았으며 노이즈가 장치의 입력 회로를 트리거하고있는 것처럼 보였습니다.

올바른 신호 발생기 출력으로 전환하고 GPIO 핀에서 깨끗한 신호를 받았을 때 예상되는 인터럽트 수를 얻기 시작했고 파이썬 코드가 올바르게 작동했습니다 (예 : poll()). 입력).

+0

poll()이 반환 될 때 "EPOLLPRI"와 함께 설정된 "EPOLLERR"플래그가 계속 표시됩니다. 그러나 정상적인 동작 일 수 있습니다 ... https://groups.google.com/forum/#!topic/quick2wire-users/ka-V_85ePtE를 참조하십시오. – Jeremy

관련 문제