AnsweredAssumed Answered

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

Question asked by Steven Pugmire on Feb 24, 2015
Latest reply on Feb 26, 2015 by Steven Pugmire

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);

}

Outcomes