我正在嵌入式系统(ARM 内核)上尝试从 Python 进行 GPIO 访问,该系统正在运行使用 Buildroot(内核 4.1.15)构建的 linux。
我希望我的代码阻塞等待 GPIO2 上的引脚更改(即我不想通过重复调用“读取”来轮询引脚)。我正在尝试在边缘触发模式下使用“epoll”来做到这一点:
请参阅Python 文档以了解 epoll。select.EPOLLET标志用于获取 epoll 的边沿触发。另请参阅epoll 的 Linux 文档。
为简单起见,我已经使用 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()。代码现已修复。