Squarewave-example

From RTwiki
Jump to: navigation, search

Contents


Abstract

This is a little example, how to use the realtime preemption patch. First ensure you installed the preemption patch like described on this page: RT_PREEMPT_HOWTO

The example writes a squarewave to the parallelport, so if you want to see something you should connect a oscilloscope to pin 2 of your parallelport.

Code

swave.c :

/* compile using  "gcc -o swave swave.c -lrt -Wall"  */

#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <sched.h>
#include <sys/io.h>

#define PORT 0x378
#define NSEC_PER_SEC    1000000000

/* using clock_nanosleep of librt */
extern int clock_nanosleep(clockid_t __clock_id, int __flags,
      __const struct timespec *__req,
      struct timespec *__rem);

/* the struct timespec consists of nanoseconds
 * and seconds. if the nanoseconds are getting
 * bigger than 1000000000 (= 1 second) the
 * variable containing seconds has to be
 * incremented and the nanoseconds decremented
 * by 1000000000.
 */
static inline void tsnorm(struct timespec *ts)
{
   while (ts->tv_nsec >= NSEC_PER_SEC) {
      ts->tv_nsec -= NSEC_PER_SEC;
      ts->tv_sec++;
   }
}

/* increment counter and write to parallelport */
void out()
{
   static unsigned char state=0;
   outb(state++,PORT);
}

int main(int argc,char** argv)
{
   struct timespec t;
   struct sched_param param;
   /* default interval = 50000ns = 50us
    * cycle duration = 100us
    */
   int interval=50000;

   /* set permissions of parallelport */
   ioperm(PORT,1,1);

   if(argc>=2 && atoi(argv[1])>0)
   {
      printf("using realtime, priority: %d\n",atoi(argv[1]));
      param.sched_priority = atoi(argv[1]);
      /* enable realtime fifo scheduling */
      if(sched_setscheduler(0, SCHED_FIFO, &param)==-1){
         perror("sched_setscheduler failed");
         exit(-1);
      }
   }
   if(argc>=3)
      interval=atoi(argv[2]);

   /* get current time */
   clock_gettime(0,&t);
   /* start after one second */
   t.tv_sec++;
   while(1){
      /* wait untill next shot */
      clock_nanosleep(0, TIMER_ABSTIME, &t, NULL);
      /* do the stuff */
      out();
      /* calculate next shot */
      t.tv_nsec+=interval;
      tsnorm(&t);
   }
   return 0;
}

Compilation

Copy & paste the source and save it to "swave.c", then compile it using this commandline:

gcc -o swave swave.c -lrt -Wall

Execution

./swave arg1 arg2
  • arg1 = realtime priority (0 = no realtime scheduling)
  • arg2 = time between the shots in nanoseconds (default = 50000)

The cycle duration of the wave consists of two shots (pin2 of parallelport), so following cycle durations are achieved with the default time between shots (50000ns):

  • pin2: 100microseconds
  • pin3: 200microseconds
  • pin4: 400microseconds
  • pin5: 800microseconds
  • ...

Execution without realtime scheduling

To run the example, just start it by typing:

./swave

This will start the example _NOT_ using the realtime scheduling. So when you create some system load, like with:

cat /dev/zero > delete_this_file

you will see on the scope, that the squarewave gets really screwed up.

Execution with realtime scheduling

To run it using realtime fifo scheduling execute it this way:

./swave 90

Now it is ran with fifo scheduling with priority 90. And you will see a perfect squarewave on the scope, even when creating heavy system load with

cat /dev/zero > delete_this_file
Personal tools