Robert Butera wrote:
> 
> After almost a 2 year hiatus, I've released BUZZ v1.0.
> 
> BUZZ is a silly program that provides a working example of some common
> functions implemented when programming in a realtime Linux environment.
> It uses the normally mundane PC speaker to output a frequency modulated
> tone, sounding a lot like an old Atari 2600.
> 
> The current version uses RTAI version 1.1.
> 
> New in this version:
> - ported to RTAI
> - no longer programming the timer and using an interrupt routine -- now uses
>   a RTAI periodic task for the speaker update
> - uses RTAI implementation of shared memory
> - other miscellaneous things
> 
> Next step is a version independent of using RTAI or RTL.  If someone
> wants to do this, be my guest.
> 
> You can get BUZZ-1.0 at
> http://users.ece.gatech.edu/rbutera/software/buzz.html.
> 
> Happy hacking.
> 
> Robert Butera, Assistant Professor
> School of Electrical and Computer Engineering
> Institute for Bioengineering and Biosciences
> Georgia Institute of Technology, Atlanta, GA, 30332-0363 USA
> --> http://www.ece.gatech.edu/users/rbutera/

Hi Robert,

This is a good idea.  I have been working on a common API for RTL/RTAI
which is similar to the RTAI/RTLinux V1 API.  The purpose is to let
people code the same way and run under either RTL or RTAI.  The project
is still fairly new, but all are welcome to contribute.  I have attached
the first version of the header file, and a simple example that uses
it.  

Regards, Stuart
KFLAGS = -D__KERNEL__ -DMODULE $(RTFLAGS)
CFLAGS = -O2 -g  -fno-schedule-insns2

all: para_rt.o 
para_rt.o : para.c
        $(CC) $(CFLAGS) $(KFLAGS) -c -o $@ $^
clean:
        rm -f *.o

///////////////////////////////////////////////////////////////////////////////
//
// Copyright � 1999 Zentropic Computing LLC.
//
// Authors:             Stuart Hughes
// Original date:       Thu June 24 1999
// Id:                  @(#)$Id: para.c,v 1.4 1999/10/08 14:03:53 seh Exp $
// 
// Description:         This is a basic example that shows how to create a
//                      real-time task and toggle pin2 output of the 
//                      parallel port.
//
//  This program is free software; you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation; either version 2 of the License, or
//  (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
//
//  You should have received a copy of the GNU General Public License
//  along with this program; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
///////////////////////////////////////////////////////////////////////////////

// this is ugly but the header file uses BASE_FREQ
#define FREQ            1000 
#define BASE_PER        (NSECS_PER_SEC/FREQ)
#include "rt_compat.h"

void *para_task(int);
void parallel(int value, int channel);

#define NTASKS                  1
#define ZDB                     0

struct task_data td[NTASKS] = { 
        {
                {0},                    // task structure
                para_task,              // function
                0,                      // function arg
                3000,                   // stack size
                4,                      // priority 0 = highest
                1,                      // task period = n * BASE_PER
                1,                      // uses_fpu
                0                       // signal handler 
        } 
};

// test data
typedef struct db_dat_ {

        int     icounter;
        float   fcounter;
        double  dcounter;
        int     flash_interval;

} DB_DAT;

DB_DAT d = { 0, 0.0f, 0.0, 1000 };


void *para_task(int arg)
{
    //char buf[12] = "test";            // would fail, calls implicit memset
    char *buf = "wink";         
    static int led = 1;
    while(1) {
        rt_task_wait_period();
        d.icounter++;
        d.fcounter += 1.0f;
        d.dcounter += 1.0;
        if(d.icounter % d.flash_interval == 0) {
            led    = !led;
            parallel(led ,arg);
        }
    }
}

int init_module(void)
{
    int i, err;

    // create task(s)
    for(i = 0; i < NTASKS; i++) {
        if( (err = rt_task_create(&td[i])) ) {
            return err;
        }
    }
    return 0;
}

void cleanup_module(void)
{
    int i;

    rt_timer_stop();

    // kill tasks
    for(i = 0; i < NTASKS; i++) {
        rt_task_del(&td[i].task);
    }
}

#define LPT_PORT 0x378
void parallel(int value, int channel)
{
    static int output = 0x0000;
    if(value) {
        output |=  (1 << channel);
    } else {
        output &= ~(1 << channel);
    }
    outb(output, LPT_PORT);
}

////////////////////////////////////////////////////////////////////////////////
//
//  Copyright � 1998 Zentropic Computing
//
//  Authors:            Stuart Hughes
//  Contact:            [EMAIL PROTECTED]
//  Original date:      April 13th 2000
//  Ident:              @(#)$Id$
//  Description:        RTL/RTAI common api header
//
//  This program is free software; you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation; either version 2 of the License, or
//  (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
//
//  You should have received a copy of the GNU General Public License
//  along with this program; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
////////////////////////////////////////////////////////////////////////////////

#ifndef RTL_RTAI_H

#define NSECS_PER_SEC   1000000000

typedef void *(* VP_FP)();
typedef void  (* V_FP_V  )(void);
typedef void  (* V_FP_I  )(int);

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/config.h>
#include <asm/io.h>

#if CONFIG_RTL
#    include <rt/rtl.h>
#    include <rt/rtl_fifo.h>
#    include <rt/rtl_sched.h>
#    include <rt/posix/pthread.h>
#    define TASK_STR              pthread_t
#    define get_time_ns           gethrtime
#    define rt_task_wait_period   pthread_wait_np
#    define rt_task_suspend(x)    pthread_suspend_np(*x)
#    define rt_task_resume(x)     pthread_wakeup_np(*x)
#    define rt_get_time_ns        get_time_ns
#    define rtl_task_make_periodic(task_ptr, when_ns, period_ns)        \
        pthread_make_periodic_np(*task_ptr, when_ns, period_ns)
#    define rt_task_del(task_ptr)                                       \
        pthread_delete_np(*task_ptr)
#    define rt_timer_stop()
#else
#    include <rt/rtai.h>
#    include <rt/rtai_sched.h>
#    include <rt/rtai_fifos.h>
#    define TASK_STR              RT_TASK
#    define rtf_create(num, size) rtf_create_using_bh(num, size, 0)
#    define get_time_ns           rt_get_cpu_time_ns
#    define rtl_schedule()
#    define rtl_task_make_periodic(task_ptr, when_ns, period_ns)        \
        rt_task_make_periodic(task_ptr,                                 \
                                nano2count(when_ns),                    \
                                nano2count(period_ns))
#    define     rt_task_del(task_ptr)                                   \
        do {    rt_task_suspend(task_ptr);                              \
                rt_task_delete(task_ptr);       } while(0)
#    define     rt_timer_stop()                                         \
        do {    stop_rt_timer();                                        \
                rt_busy_sleep(1e7);             } while(0)
#endif

struct task_data {
    TASK_STR task;
    VP_FP func;
    int arg;
    int stack_size;
    int priority;
    int period;
    int    uses_fpu;
    V_FP_V sig_han;
    long long period_ns;
    long long when_ns;
};

////////////////////////////////////////////////////////////////
// task creation wrapper
///////////////////////////////////////////////////////////////
static inline int rt_task_create( struct task_data *t)
{
#if CONFIG_RTL

    struct sched_param p;
    pthread_create(     &t->task,
                        NULL,
                        t->func,
                        (void *)t->arg
                );
    if(t->uses_fpu) {
        pthread_setfp_np(t->task, 1);
    }
    p.sched_priority = 100 - t->priority;
    pthread_setschedparam(t->task, SCHED_FIFO, &p);

    if(t->period == 0) {
        return 0;
    }

#else                                   // RTAI

    static int timer_started = 0;

    if( timer_started == 0) {
        // start timer, this defaults to periodic mode
        start_rt_timer(nano2count(BASE_PER));
        timer_started   = 1;
    }

    rt_task_init(       &t->task,
                        (V_FP_I)t->func,
                        t->arg,
                        t->stack_size,
                        t->priority,
                        t->uses_fpu,
                        t->sig_han
                );

    if(t->period == 0) {
        return 0;
    }
    if(t->uses_fpu) {
        rt_linux_use_fpu(1);
    }

#endif

    t->when_ns          = rt_get_time_ns() + 1 * NSECS_PER_SEC;
    t->period_ns        = (long long)t->period * BASE_PER;
    rtl_task_make_periodic( &t->task, t->when_ns, t->period_ns);

    return 0;
}



#endif

Reply via email to