我正试图通过sysfs
使用poll()
在GPIO上捕获中断。我在第三个位置有-1,所以它可以阻止,但它似乎总是返回。我在SO上查了一些类似的帖子。值得注意的是this (1),this (2)和this (3)。
在(1)中,通过在调用read()
之前放置一个虚拟poll()
来解决它。如果我这样做(请参阅代码中注释的read()
)。我的代码在循环中运行一次,第二次在poll()
上永久阻塞。
在(2)中,这可能是一个解释,但并没有真正解决我的问题。
在(3)中,我的lseek()
read()
当gpio的poll()
发生变化时,如何阻止此value
阻止并仅在中断时返回?
以下是代码段:
int read_gpio(char *path, void (*callback)(int)){
int fd;
char buf[11];
int res = 0;
char c;
int off;
struct pollfd gpio_poll_fd = {
.fd = fd,
.events = POLLPRI,
.revents = 0
};
for(;;){
gpio_poll_fd.fd = open(path, O_RDONLY);
if(fd == -1){
perror("error opening file");
return -1;
}
// char c;
// read(fd,&c,1);
LOGD("for begins");
res = poll(&gpio_poll_fd,1,-1);
LOGD("polling ended");
if(res == -1){
perror("error polling");
break;
}
if((gpio_poll_fd.revents & POLLPRI) == POLLPRI){
LOGD("POLLPRI");
off = lseek(fd, 0, SEEK_SET);
if(off == -1) break;
memset(&buf[0], 0, 11);
size_t num = read(fd, &buf[0], 10*sizeof(char));
LOGD("Before callback");
callback(atoi(buf));
LOGD("After Callback");
}
if((gpio_poll_fd.revents & POLLERR) == POLLERR) {
//seems always to be true ..
//LOGD("POLLERR");
}
close(fd);
LOGD("for ends");
}
LOGD("for exits");
return 0;
}
注意:我在Android JNI上这样做,我从LOGD()
更新的
根据jxh评论中的建议,我已经安排了这样的结构,尽管现在它无限期地阻塞poll()
。当值的内容从外部施加的电压改变时,POLLPRI不会变高,并且poll()不会返回:
int read_gpio(char *path, void (*callback)(int)){
int fd = open(path, O_RDONLY);
if(fd == -1){
perror("error opening file");
return -1;
}
char buf[11];
int res, off;
char c;
struct pollfd pfd = {
.fd = fd,
.events = POLLPRI,
.revents = 0
};
for(;;){
LOGD("for begins");
// dummy read causes poll never to run
// lseek() alone here cause poll never to run
// read(fd, &buf[],1);
// lseek(fd, 0, SEEK_SET);
res = poll(&pfd,1,-1);
LOGD("polling ended");
if(res == -1){
perror("error polling");
break;
}
if((pfd.revents & POLLPRI) == POLLPRI){
LOGD("POLLPRI");
off = lseek(fd, 0, SEEK_SET);
if(off == -1) break;
memset(&buf[0], 0, 11);
read(fd, &buf[0], 10*sizeof(char));
// These two lines will cause it to poll constantly
// close(fd);
// fd = open(path, O_RDONLY);
LOGD("Before callback");
callback(atoi(buf));
LOGD("After Callback");
}
LOGD("for ends");
}
close(fd);
LOGD("for exits");
return 0;
}
答案 0 :(得分:4)
在您的代码中,fd
未初始化。
当您打开文件时,您直接分配到gpio_poll_fd.fd
,而不使用fd
,因此fd
仍然未初始化。
尝试:
gpio_poll_fd.fd = fd = open(path, O_RDONLY);
正如评论中所指出的,根据GPIO manual(我在仔细阅读这些评论之后才读到),GPIO sysfs
界面有点特别:
如果引脚可以配置为产生中断的中断 如果它已配置为生成中断(请参阅 “edge”的描述,你可以{i}在那个文件上 只要中断被触发,
poll(2)
就会返回。如果 您使用poll(2)
,设置事件poll(2)
和POLLPRI
。如果你 使用POLLERR
,在select(2)
中设置文件描述符。后exceptfds
poll(2)
返回lseek(2)
的开头sysfs
文件并读取新值或关闭文件并重新打开它 阅读价值。
所以,虽然它不是典型的poll()
习语,但你的结束和重新开放的结构是正确的。但是,我会选择保持文件描述符处于打开状态。所以,我将如何构建您的代码:
int read_gpio(char *path, void (*callback)(int)){
char buf[11];
int fd, res, off;
struct pollfd pfd;
if((pfd.fd = fd = open(path, O_RDONLY)) == -1){
perror("path");
return -1;
}
LOGD("First read");
res = read(fd, buf, 10);
assert(res == 10);
LOGD("Before callback");
callback(atoi(buf));
LOGD("After Callback");
pfd.events = POLLPRI|POLLERR; // poll(2) says setting POLLERR is
// unnecessary, but GPIO may be
// special.
for(;;){
LOGD("for begins");
if((res = poll(&pfd,1,-1)) == -1){
perror("poll");
break;
}
LOGD("polling ended");
if((pfd.revents & POLLPRI) == POLLPRI){
LOGD("POLLPRI");
off = lseek(fd, 0, SEEK_SET);
if(off == -1) break;
memset(buf, 0, 11);
res = read(fd, buf, 10);
assert(res == 10);
LOGD("Before callback");
callback(atoi(buf));
LOGD("After Callback");
} else {
// POLLERR, POLLHUP, or POLLNVAL
break;
}
LOGD("for ends");
}
close(fd);
LOGD("for exits");
return 0;
}