阻止从Python读取GPIO:如何阻止使用epoll()和select.EPOLLET

时间:2017-11-30 02:01:52

标签: python select embedded-linux epoll epollet

我在嵌入式系统(ARM核心)上试验Python的GPIO访问,该系统运行的是用Buildroot(内核4.1.15)构建的linux。

我希望我的代码BLOCK等待GPIO2上的引脚更改(即我不想通过反复调用“read”来轮询引脚)。我试图在边缘触发模式下使用“epoll”来做到这一点:

Python docs for epoll select.EPOLLET 标志用于获取epoll的边缘触发。另请参阅Linux docs for epoll

为简单起见,我已经使用sysfs:

从控制台设置了我的GPIO引脚
# cat /sys/class/gpio/gpio2/direction 
in
# cat /sys/class/gpio/gpio2/edge
rising

这是我的Python代码:

#!/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)

为了进行测试,我使用来自信号发生器的方波输入引脚,每个周期大约2秒,所以我可以看到引脚何时发生变化。

当我在嵌入式系统上运行时,我得到了这个:

# python3 /usr/sbin/test-gpio-python.py 
EPoll result: [(3, 10)]
FD: 3; Events: 10
-EPOLLPRI!
-EPOLLERR!
--> 0

代码在1秒睡眠时休眠,然后在下一次迭代中,poll()立即返回并且不会阻塞。它应该阻止,因为我的输入仅在每2秒一个上升沿运行。

为什么“poll()”阻止?

====编辑:====

最初,当我尝试使用“select.EPOLLET”时,代码导致了一个奇怪的错误:

OverflowError: can't convert negative value to unsigned int

但是,我发现我不小心使用了 myPoll = select.poll()而不是 epoll()。代码现已修复。

1 个答案:

答案 0 :(得分: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左右的速度堆积,绝对比我在Python中处理它们更快。

对示波器的进一步研究表明,信号发生器仅输出约1.6 V,看起来噪声正在触发器件上的输入电路。

当我切换到正确的信号发生器输出并在GPIO引脚上得到一个干净的信号时,我开始得到预期的中断次数,并且python代码正常工作(即poll()在输入的上升沿之间正确阻塞)。