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

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





--
_______________________________________________
yocto mailing list
yocto@yoctoproject.org
https://lists.yoctoproject.org/listinfo/yocto

Reply via email to