[yocto] Yocto Realtime tests on beaglebone black

Bruce Ashfield bruce.ashfield at windriver.com
Tue Feb 10 06:16:39 PST 2015


On 15-02-10 08:06 AM, Stephen Flowers wrote:
> Hi All,
>
> I have built the realtime kernel using Yocto and deployed on the
> beaglebone black (specifically core-image-rt-sdk).  I have written a
> program to test the timer latency and interrupt latency of userspace
> applications.  For this I'm using a simple timerfd to generate a
> periodic 10ms gpio toggle which itself acts as a gpio interrupt on
> another gpio pin.
> I find the latency is much worse on the preempt_rt kernel than the
> standard one.  RT kernel gives around 220us average with the standard
> kernel about 80us.  Testing with Xenomai gives about 60us. The response
> times are measured with an external logic analyser, and taken with no
> other load on the system.  Kernel version is 3.14.
>
> The difference between standard and RT kernel configs:
> Preemption model: desktop vs. realtime kernel
> Timer: 100Hz vs 1000Hz
> High resolution timers disabled

Can you share the full .config for both configurations ? That should
shed a bit more light on what might be misconfigured.

I haven't run tests on the beaglebone black myself, but on similar
ARM boards, performance has been as expected.

You are talking about average latency above, what about the max
latency ? We expect that the preempt-rt kernel will have a higher
minimum, and often average latency .. but will be significantly
better in maximum latency.

It would also be useful to grab cyclictest results for the standard
and preempt-rt kernel as a baseline performance measure.

Bruce

>
> I'm having a hard time figuring out why the RT kernel gives worse
> latency.  Anyone have any insight into this?
> Included the source code below.
>
> Thanks & Regards,
> Steve
>
> #include<sys/time.h>
> #include<time.h>
> #include<sys/types.h>
> #include <signal.h>
> #include <stdlib.h>
> #include <stdio.h>
> #include <sched.h>
> #include <sys/mman.h>
> #include "poll.h"
> #include "fcntl.h"
> #include "string.h"
> #include "errno.h"
> #include <sys/timerfd.h>
>
> #define TIMER_OUT_PATH     "/sys/class/gpio/gpio47"
> #define LED_OUT_PATH     "/sys/class/gpio/gpio26"
> #define IRQ_IN_PATH     "/sys/class/gpio/gpio46"
>
> static int timer_toggle = 0;
> static int output_toggle = 0;
>
> void stack_prefault(void)
> {
>      unsigned char dummy[8192];
>      memset(dummy, 0, 8192);
> }
>
>
> int main(int argc, char* argv[])
> {
>     struct itimerspec itv;
>     unsigned long long timer_increment = 0;
>
>     clock_t prevClock;
>     int sigCnt = 0;
>     struct sigaction sa;
>     struct sched_param sp;
>
>     struct pollfd fdset[2];
>     int fd_in;
>     int action;
>     int fd_led;
>     int fd_timer_out;
>     int fd_timer_in;
>
>     char buf[2];
>     int len;
>
>     // setup gpio
>     if(system("echo 46 > /sys/class/gpio/export") == -1)
>          perror("unable to export gpio 46");
>
>     if(system("echo 47 > /sys/class/gpio/export") == -1)
>          perror("unable to export gpio 47");
>
>     if(system("echo 26 > /sys/class/gpio/export") == -1)
>          perror("unable to export gpio 26");
>
>     // timer out
>     if(system("echo out > /sys/class/gpio/gpio47/direction") == -1)
>          perror("unable to set 47 to output");
>
>      // led out
>      if(system("echo out > /sys/class/gpio/gpio26/direction") == -1)
>          perror("unable to set 26 to output");
>
>      // irq in
>      if(system("echo in > /sys/class/gpio/gpio46/direction") == -1)
>          perror("unable to set 46 to input");
>
>      if(system("echo both > /sys/class/gpio/gpio46/edge") == -1)
>          perror("unable to set 46 edge");
>
>      // set scheduling parameters
>      sp.sched_priority = sched_get_priority_max(SCHED_FIFO);
>      if(sched_setscheduler(0, SCHED_FIFO, &sp) == -1)
>      {
>          perror("setscheduler");
>          exit(-1);
>      }
>
>      // lock memory
>      if(mlockall(MCL_CURRENT|MCL_FUTURE) == -1)
>          perror("mlockall");
>
>      stack_prefault();
>
>     // Set up timer
>      fd_timer_in = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK);
>      printf("fd_timer:%d\n",fd_timer_in);
>
>      if(fd_timer_in < 0)
>      {
>          perror("timerfd_create()");
>      }
>
>     itv.it_value.tv_sec = 0;
>     itv.it_value.tv_nsec = 10000000;
>     itv.it_interval.tv_sec = 0;
>     itv.it_interval.tv_nsec = 10000000;
>     if(-1 == timerfd_settime(fd_timer_in, 0, &itv, NULL))
>     {
>         perror("settime()");
>     }
>
>     // setup file descriptor for poll()
>     fd_in = open(IRQ_IN_PATH "/value", O_RDONLY | O_NONBLOCK);
>     printf("fd irq input:%d\n",fd_in);
>
>     if(fd_in < 0)
>     {
>         perror("file open problem");
>         exit(0);
>     }
>
>     while(1)
>     {
>          memset((void*)fdset, 0, sizeof(fdset));
>          fdset[0].fd = fd_in;
>          fdset[0].events = POLLPRI | POLLERR;
>          fdset[0].revents = 0;
>
>          fdset[1].fd = fd_timer_in;
>          fdset[1].events = POLLIN | POLLERR;
>          fdset[1].revents = 0;
>          action = poll(fdset, 2, -1);
>
>          if(action < 0)
>          {
>              if(errno == EINTR)
>              {
>                  // when signal interrupts poll, we poll again
>                  continue;
>              }
>              else
>              {
>                  perror("poll failed");
>                  exit(0);
>              }
>          }
>
>          if(fdset[1].revents & POLLIN)
>          {
>              //len = read(fdset[1].fd, 0, SEEK_SET);
>              len = read(fdset[1].fd, &timer_increment,
> sizeof(timer_increment));
>
>              fd_timer_out = open( TIMER_OUT_PATH "/value", O_WRONLY);
>
>             if(timer_toggle ^= 1)
>             {
>                 write(fd_timer_out, "1", 2);
>             }
>             else
>             {
>                 write(fd_timer_out, "0", 2);
>             }
>
>             close(fd_timer_out);
>          }
>
>          if(fdset[0].revents & POLLPRI)
>          {
>              lseek(fdset[0].fd, 0, SEEK_SET);    // read from start of file
>              len = read(fdset[0].fd, buf, sizeof(buf));
>
>              fd_led = open( LED_OUT_PATH "/value", O_WRONLY | O_NONBLOCK);
>
>              if(buf[0] == '1')
>              {
>                  write(fd_led, "1", 2);
>              }
>              else
>              {
>                  write(fd_led, "0", 2);
>              }
>
>              close(fd_led);
>          }
>      }
>
>     close(fd_in);
>     close(fd_timer_in);
>     close(fd_led);
>     printf("finished\n");
>     return 0;
> }
>
>
>
>
>




More information about the yocto mailing list