Does a poll() function call require a read() in order to work properly?

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Does a poll() function call require a read() in order to work properly?

722 Views
stevenpugmire
Contributor I

I am using an i.MX6 board running Linux 3.0.35 to get input from a motor encoder via GPIO. The software should trigger and count a "tick" on a rising or falling edge from the encoder. Up to this point I have been using the following code on its own thread with few problems except that the thread loops at only 100 - 200 Hz. I need the thread to loop at closer to 5000 Hz in order to catch the edges at the motor's top speed.

I found that if I remove the read() function in the loop that I am able to run this loop at close to 10,000 Hz. However, without that read() function the poll() returns an event every time. Is the read function necessary for the poll() to be called properly, or is there another way I can make this work without that function call?

The code in question:


/****************************************************************

* Encoder thread

****************************************************************/


void *ticksx(void*)

{

  struct pollfd fdset[1];

  int nfds = 1;

  int gpio_fd, timeout, rc;

  char *buf[MAX_BUF];

  unsigned int gpio2;

  int len;

  unsigned int txn = 0;


  gpio2 = 101;

  gpio_export_local(gpio2);

  gpio_set_dir_local(gpio2, 0);

  gpio_set_edge_local(gpio2, (char*)"both");

  gpio_fd = gpio_fd_open_local(gpio2);

  timeout = POLL_TIMEOUT;

  while (1)

  {

  // -------------------------------------

  // Get time for debug

  gettimeofday(&t5, NULL);

  float xt = (float)t5.tv_sec;

  xt += (float)t5.tv_usec / 1000000.0;

  if(ticksxNum < debugMax)

  xtickstime[ticksxNum] = xt;

  // -------------------------------------

  memset((void*)fdset, 0, sizeof(fdset));

  fdset[0].fd = gpio_fd;

  fdset[0].events = POLLPRI;

  rc = poll(fdset, nfds, timeout);          

  if (fdset[0].revents & POLLPRI)

  {

//(void)read(fdset[0].fd, buf, MAX_BUF);

  if(backLashTicksX > 0)

  {

  backLashTicksX--;

  }

  else

  {

  pthread_mutex_lock( &xtickslock );

  tickstogox -= swivelDirection; // Decrement tickstogox using the proper direction

  realTicksX += swivelDirection;

  pthread_mutex_unlock( &xtickslock );

  }

  }

  usleep(200);

  pixelsX = realTicksX / TICKS_PER_PIXEL_X;

  if(ticksxNum < debugMax)

  {

  //xtickstime[ticksxNum] = xt;

  xticksticks[ticksxNum] = realTicksX;

  pVx_vector[ticksxNum] = pVx;

  yVx_vector[ticksxNum] = yVx;

  }

  if(exitSignal)

  {

  gpio_fd_close_local(gpio_fd);

  pthread_exit(0);

  }

  ticksxNum++;

  xVp++;

  xVy++;

  pVx = 0;

  yVx = 0;

  }

}

For reference, these are some functions called from this thread:

/****************************************************************

* gpio_export_local

****************************************************************/

int gpio_export_local(unsigned int gpio)

{

  int fd, len;

  char buf[MAX_BUF];

  fd = open(SYSFS_GPIO_DIR "/export", O_WRONLY);

  if (fd < 0) {

  perror("gpio/export");

  return fd;

  }

  len = snprintf(buf, sizeof(buf), "%d", gpio);

  pthread_mutex_lock( &writelock );

  write(fd, buf, len);

  pthread_mutex_unlock( &writelock );

  close(fd);

  return 0;

}

/****************************************************************

* gpio_unexport_local

****************************************************************/

int gpio_unexport_local(unsigned int gpio)

{

  int fd, len;

  char buf[MAX_BUF];

  fd = open(SYSFS_GPIO_DIR "/unexport", O_WRONLY);

  if (fd < 0) {

  perror("gpio/export");

  return fd;

  }

  len = snprintf(buf, sizeof(buf), "%d", gpio);

  pthread_mutex_lock( &writelock );

  write(fd, buf, len);

  pthread_mutex_unlock( &writelock );

  close(fd);

  return 0;

}

/****************************************************************

* gpio_set_dir_local

****************************************************************/

int gpio_set_dir_local(unsigned int gpio, unsigned int out_flag)

{

  int fd, len;

  char buf[MAX_BUF];

  len = snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR  "/gpio%d/direction", gpio);

  fd = open(buf, O_WRONLY);

  if (fd < 0) {

  perror("gpio/direction");

  return fd;

  }

  if (out_flag)

  {

  pthread_mutex_lock( &writelock );

  write(fd, "out", 4);

  pthread_mutex_unlock( &writelock );

  }

  else

  {

  pthread_mutex_lock( &writelock );

  write(fd, "in", 3);

  pthread_mutex_unlock( &writelock );

  }

  close(fd);

  return 0;

}

/****************************************************************

* gpio_set_value_local

****************************************************************/

int gpio_set_value_local(unsigned int gpio, unsigned int value)

{

  int fd, len;

  char buf[MAX_BUF];

  len = snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR "/gpio%d/value", gpio);

  fd = open(buf, O_WRONLY);

  if (fd < 0) {

  perror("gpio/set-value");

  return fd;

  }

  if (value)

  {

  pthread_mutex_lock( &writelock );

  write(fd, "1", 2);

  pthread_mutex_unlock( &writelock );

  }

  else

  {

  pthread_mutex_lock( &writelock );

  write(fd, "0", 2);

  pthread_mutex_unlock( &writelock );

  }

  close(fd);

  return 0;

}

/****************************************************************

* gpio_get_value_local

****************************************************************/

int gpio_get_value_local(unsigned int gpio, unsigned int *value)

{

  int fd, len;

  char buf[MAX_BUF];

  char ch;

  len = snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR "/gpio%d/value", gpio);

  fd = open(buf, O_RDONLY);

  if (fd < 0) {

  perror("gpio/get-value");

  return fd;

  }

  read(fd, &ch, 1);

  if (ch != '0') {

  *value = 1;

  } else {

  *value = 0;

  }

  close(fd);

  return 0;

}

/****************************************************************

* gpio_set_edge_local

****************************************************************/

int gpio_set_edge_local(unsigned int gpio, char *edge)

{

  int fd, len;

  char buf[MAX_BUF];

  len = snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR "/gpio%d/edge", gpio);

  fd = open(buf, O_WRONLY);

  if (fd < 0) {

  perror("gpio/set-edge");

  return fd;

  }

  pthread_mutex_lock( &writelock );

  write(fd, edge, strlen(edge) + 1);

  pthread_mutex_unlock( &writelock );

  close(fd);

  return 0;

}

/****************************************************************

* gpio_fd_open_local

****************************************************************/

int gpio_fd_open_local(unsigned int gpio)

{

  int fd, len;

  char buf[MAX_BUF];

  len = snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR "/gpio%d/value", gpio);

  fd = open(buf, O_RDONLY | O_NONBLOCK );

  if (fd < 0) {

  perror("gpio/fd_open");

  }

  return fd;

}

/****************************************************************

* gpio_fd_close_local

****************************************************************/

int gpio_fd_close_local(int fd)

{

  return close(fd);

}

Labels (2)
0 Kudos
2 Replies

503 Views
igorpadykov
NXP Employee
NXP Employee

Hi Steven

one needs to use read() function, without it gpio will not be read,

for gpio sysfs usage example one can look below

Handle many Gpio Interruptions C++ Linux - Stack Overflow

Best regards

igor

-----------------------------------------------------------------------------------------------------------------------

Note: If this post answers your question, please click the Correct Answer button. Thank you!

-----------------------------------------------------------------------------------------------------------------------

503 Views
stevenpugmire
Contributor I

Igor, thanks for the reply. Just to make sure we're understanding one another here --- I'm not interested in the value on the GPIO line here (the "edge" line in this case), I just want to know whether an event happened. I was under the impression that the poll(), as set up here, would return on an edge-triggered event. My "if" statement is conditional only upon that poll() returning a true revents value through the POLLPRI bitmask. The read() call seems to happen after determining that an edge actually occurred; I don't even use the value placed on the buffer by read().

So, my question is, even though I don't use read() to get any values, does read() do something under the hood here (such as advancing the file position) that makes the next poll() work properly? If so, is there a faster way I can do that?

0 Kudos