GPIO Interrupt checking
글쓴이: andykim17 / 작성시간: 화, 2017/01/03 - 5:10오후
안녕하세요?
GPIO Interrupt 확인하고 해당 서비스 진행하기 위해
/sys/class/gpio/gpioN/value 값을 사용하는 코드를 작성하고 있는데
문제가 발생하여 도움을 받고자 합니다.
우선 GPIO Port를 falling edge interrupt 로 사용하기 위해서 init.rc에 다음을 추가하였습니다.
write /sys/class/gpio/export "N"
write /sys/class/gpio/gpioN/active_low "1"
write /sys/class/gpio/gpioN/direction "in"
write /sys/class/gpio/gpioN/edge "falling"
그리고 interrupt 발생여부는 다음과 같은 코드에서 수행됩니다.
jint Java_kr_iges_wallpad_gpiotest_MainActivity_GPIORead(JNIEnv *env, jobject obj, jchar port) { int fd, ret; struct pollfd fdset[1]; char buf[32]; if ((fd = gpio_fd_open(port)) == -1 ){ LOGE("Read Port open error"); return -1; } gpio_poll_fd.fd = fd; gpio_poll_fd.events = POLLPRI; gpio_poll_fd.revents = 0; while (1) { ret = poll(&gpio_poll_fd, 1, 3000); if (ret > 0) { if ((gpio_poll_fd.revents & POLLPRI) == POLLPRI){ LOGD("GPIO interrupt!"); ret = 0; break; } else { LOGW("No GPIO interrupt detected, weird."); } } else if (ret == 0) { LOGE("poll call timed out, should not be possible!"); } else { LOGE("poll call failed - %s.", strerror(errno)); break; } } close(fd); return ret; } int gpio_fd_open(unsigned int gpio) { int fd, len; char buf[MAX_BUF]; len = snprintf(buf, sizeof(buf), GPIO_PATH "/gpio%d/value", gpio); fd = open(buf, O_RDONLY | O_NONBLOCK ); if (fd < 0) { perror("gpio/fd_open"); } return fd; }
여기서 문제는 poll()의 return parameter이고 interrupt 발생 여부를 확인하기 위해 사용되는
gpio_poll_fd.revents값이 항상 POLLPRI라는 것입니다.
/sys/class/gpio/gpioN/value를 확인하면 해당 GPIO Port의 input값에 맞게 변하고 있는데
그리고 direction(in)/edge(falling)도 맞게 설정되어 있는데 이런 문제가 발생하는 군요...
왜 이런 문제가 발생하는지...
어떻게 해결할 수 있을까요?
감사합니다.
Forums:
gpio_poll_fd.revents = 0 를
gpio_poll_fd.revents = 0 를 loop 안으로 넣으시고,
POLLPRI 뿐만 아니라 POLLERR 도 감시하시고,
open() 의 O_NONBLOCK 은 빼시는 게 어떨까요 ?
그런데... 커널 버전이... ?
kernel version
kernel version은 Linux version 3.4.39+입니다.
알려주신 방법은 확인해 보겠습니다.
감사합니다.
말씀하신 대로
말씀하신 대로 다음과 같이 수정했는데 현상은 동일하내요.
int gpio_fd_open(unsigned int gpio)
{
int fd, len;
char buf[MAX_BUF];
len = snprintf(buf, sizeof(buf), GPIO_PATH "/gpio%d/value", gpio);
fd = open(buf, O_RDONLY);
if (fd < 0) {
perror("gpio/fd_open");
}
return fd;
}
jint Java_kr_iges_wallpad_gpiotest_MainActivity_GPIORead(JNIEnv *env, jobject obj, jchar port)
{
int fd, ret;
struct pollfd fdset[1];
char buf[32];
if ((fd = gpio_fd_open(port)) == -1 ){
LOGE("Read Port open error");
return -1;
}
gpio_poll_fd.fd = fd;
gpio_poll_fd.events = POLLPRI;
while (1) {
gpio_poll_fd.revents = 0;
ret = poll(&gpio_poll_fd, 1, 3000);
if (ret > 0) {
if ((gpio_poll_fd.revents & POLLPRI) == POLLPRI){
LOGD("GPIO interrupt!");
ret = 0;
break;
}
if((gpio_poll_fd.revents & POLLERR) == POLLERR){
//seems always to be true ..
LOGD("POLLERR");
}
} else if (ret == 0) {
LOGE("poll call timed out, should not be possible!");
} else {
LOGE("poll call failed - %s.", strerror(errno));
break;
}
}
close(fd);
return ret;
}
fs/sysfs/file.c 의 sysfs_poll(
fs/sysfs/file.c 의 sysfs_poll() 을 보면 아시겠지만,
read 를 해서 value 를 읽어내야만 초기화됩니다.
답변 감사합니다.
답변 감사합니다.
그런데 제가 이 쪽에 대해 문외한이라...
말씀하신 "read 를 해서 value 를 읽어내야만 초기화됩니다."가
무엇을 의미하는지.. 어떻게 해야하는지.. 알려주시면 도움이 많이 될 것 같습니다.
번거러우시겠지만 부탁드려도 될지요..
poll() 하듯 read() 하시라는 뜻입니다.
poll() 하듯 read() 하시라는 뜻입니다.
댓글 달기