MiniRTL: A Minimal Real-Time Linux 
by Peter Wurmsdobler and Nicholas McGuire


Listing One
extern unsigned short int rt_daq_aget( void );
extern void rt_daq_aset(unsigned short int channel, unsigned short int value);

Listing Two
typedef struct
    {
    int w; /* setpoint */
    int k; /* gain */
    }
shm_t *shm; /* shm to user space */
pthread_t control_thread; /* control thread */
void *rt_control_function( void *t ) /* control thread's function */
    {
    int Y, U, E;
    shm->k = 0;
    shm->w = 0;
    pthread_make_periodic_np( control_thread, gethrtime(), SAMPLE_TIME
);
    while(1) /* this is the periodic part */
        {
        pthread_wait_np(); /* wait for next sample hit */
        Y = rt_daq_aget(); /* get DAQ input */
        E = (int) ( shm->w - Y ); /* control deviation */
        U = (unsigned short int)( shm->k * E ); /* P controller */
        rt_daq_aset( OUTPUT_CHANNEL, U ); /* output control variable */
        rtf_put( Y_FIFO, &Y, sizeof(Y) ); /* stuff Y into fifo */
        rtf_put( U_FIFO, &U, sizeof(U) ); /* stuff U into fifo */
        }
    }
/* interrupt service routine for "emergency shutdown" */
unsigned int rt_spp_isr( unsigned int irq_number, struct pt_regs *p )
    {
    rt_daq_aset( OUTPUT_CHANNEL, 0 ); /* output 0 */
    pthread_make_periodic_np( control_thread, HRTIME_INFINITY, 0 );
    return 0;
    }


Listing Three
int init_module(void)
    {
    pthread_attr_t attr;      /* attributes */
    struct sched_param param; /* parameter */
    /* Get a hard IRQ for SPP */
    rtl_request_global_irq( SPP_IRQ, rt_spp_isr );
    /* Initialize shared memory */
    shm_allocate( SHM_NAME, SHM_SIZE, (void **) &shm );
    /* Initialize rt-fifos */
    rtf_create( Y_FIFO, FIFO_SIZE );
    rtf_create( U_FIFO, FIFO_SIZE );
    /* and now we initialize the kernel thread. */
    pthread_attr_init( &attr );
    pthread_attr_setcpu_np( &attr, 0 );
    sched_param.sched_priority = 1;
    pthread_attr_setschedparam( &attr, &param );
    pthread_create( &control_thread, &attr, rt_control_function, (void *)1 );
    return 0;
    }
void cleanup_module(void)
    {
    /* Release the SPP */
    rtl_free_global_irq( SPP_IRQ );
    /* Delete control thread */
    pthread_delete_np( control );
    /* Release rt-fifos */
    rtf_destroy( Y_FIFO );
    rtf_destroy( U_FIFO );
    /* Release shared memory */
    shm_deallocate( shm );
    }

Listing Four
#include <rtl.h>
#include <time.h>
#include <pthread.h>
#include <asm/io.h>

/* set the paralell port address */
int lpt_port=0x378;

/* compiled in addresses are unpractical so lsets define a module parameter
 * that permits setting the parport address at module insertion time
 * insmod sched_toggle.o lpt_port=0x3bc would override 0x378 . */
MODULE_PARM(lpt_port,"i");
pthread_t thread;
/* the runtime thread toggling D0-D3 of the paralell port  */
void * toggle(void *arg)
    {
    int nibl;
    hrtime_t now;
    struct sched_param p;
    p. sched_priority = 1;
    /* set the attributes for the thread, this
     * defines the scheduling policy and priority */
    pthread_setschedparam (pthread_self(), SCHED_FIFO, &p);
    now = gethrtime(); /* get the current time in nano-seconds */
    /* make the thread periodic
     * starting now, with a period of 500000000 nano-seconds */
    pthread_make_periodic_np (pthread_self(), now, 500000000);
    nibl = 0x0f;
    while (1)
        {
        outb(nibl,lpt_port); /* write it out to the parport*/
        nibl = ~nibl; /* two's complement of nibl*/
        pthread_wait_np (); /* put the thread on the wait queue */
        }
    return 0;
    }
/* init_module is called when the module is inserted it will do
 * the basic setup and register the module with the kernel */
int init_module(void)
    {
    rtl_printf("sched_toggle.c: RTL thread starts on CPU%d:
    using LPT at 0x%x\n", rtl_getcpuid(),lpt_port);
    /* create the thread. attributes are "initialized" to NULL and 
     * set in toggle thread, attributes, function, ARG */
    return pthread_create (&thread, NULL , toggle , 0 );
    }
/* when the module is removed with rmmod sched_toggle this is called
 * to cleanup any kernels trace of this module */
void cleanup_module(void)
    {
    /* send a request to thread asking for cancelation */
    pthread_cancel (thread);
    /* wait until thread gave up and exited properly */
    pthread_join (thread, NULL);
    }





7


