Subversion Repositories shark

Rev

Rev 1086 | Rev 1377 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

/*
 * Project: S.Ha.R.K.
 *
 * Coordinators:
 *   Giorgio Buttazzo    <giorgio@sssup.it>
 *   Paolo Gai           <pj@gandalf.sssup.it>
 *
 * Authors     :
 *   Paolo Gai           <pj@gandalf.sssup.it>
 *   (see the web pages for full authors list)
 *
 * ReTiS Lab (Scuola Superiore S.Anna - Pisa - Italy)
 *
 * http://www.sssup.it
 * http://retis.sssup.it
 * http://shark.sssup.it
 */


/*
 * Copyright (C) 2000 Giorgio Buttazzo, Paolo Gai
 *
 * 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
 *
 *
 * CVS :        $Id: cabs.c,v 1.2 2002-10-28 08:11:29 pj Exp $
 */


/*--------------------------------------------------------------*/
/*                    TEST ON CABS                              */
/*--------------------------------------------------------------*/

#include <kernel/kern.h>
#include <modules/cabs.h>
#include <drivers/glib.h>
#include <drivers/keyb.h>
#include <string.h>

#define NCAB    4               /* max number of CABs   */
#define NCAR    26              /* generated characters */

#define YP      32              /* level of arrows      */
#define R       20              /* task radius          */
#define YY      (YP+R+32)       /* level of writing     */
#define DELTA   (2*R+72)        /* total channel hight  */
#define X1      120             /* start column for P1  */
#define X2      360             /* start column for P2  */

#define XP1     (X1+64)         /* X position of task 1 */
#define XP2     (X2+64)         /* X position of task 2 */
#define XC      (XP1+96)        /* X position of CAB    */
#define L       52              /* CAB rectangle length */

void    my_exit(KEY_EVT *k);
void    draw_channel(int i);
void    create_channel(int i);
void    get_data();

TASK    producer(void *arg);
TASK    consumer(void *arg);

char    *cname[NCAB] = {"cab1", "cab2", "cab3", "cab4"};
char    *pname1[NCAB] = {"wr1", "wr2", "wr3", "wr4"};
char    *pname2[NCAB] = {"rd1", "rd2", "rd3", "rd4"};

CAB     cid[NCAB];              /* CAB identifiers      */
PID     p1[NCAB], p2[NCAB];     /* task identifiers     */

/* Task Periods */
TIME    t1[NCAB] = {200000, 100000, 300000, 800000};
TIME    t2[NCAB] = {400000, 400000, 150000, 200000};

/* Task WCETS */
TIME    w1[NCAB] = {10000, 10000, 10000, 10000};
TIME    w2[NCAB] = {10000, 10000, 10000, 10000};


/****************************************************************/

/* This is the exception handler. It is called when an exception
   is raised.
   It exits from the graphical mode, then it prints a message and
   shutdown the kernel using sys_abort()
*/


void demo_exc_handler(int signo, siginfo_t *info, void *extra)
{
  struct timespec t;

  grx_close();

  /* Default action for an kern exception is  */
  kern_cli();
  ll_gettime(TIME_EXACT, &t),
  cprintf("\nS.Ha.R.K. Exception raised!!!"
          "\nTime (s:ns)     :%ld:%ld"
          "\nException number:%d (numbers in include/bits/errno.h)"
          "\nPID             :%d\n",
          t.tv_sec, t.tv_nsec, info->si_value.sival_int,
          info->si_task);
  sys_abort(1);
}

/******************************************************************/

/* This function is called when Alt-X is pressed.
   It simply shutdown the system using sys_end.
   Note that the byebye() function is called only if we exit from
   the system using sys_end()!!!!
*/

void my_end(KEY_EVT* e)
{
        sys_end();
}

/******************************************************************/

/* This function is called when the system exit correctly after Alt-X.
   It exits from the graphic mode and then it prints a small greeting.
   Note that:
   - The function calls grx_exit, so it must be registered using
     RUNLEVEL_BEFORE_EXIT (RUNLEVEL_AFTER_EXIT does not work because
     at that point the kernel is already returned in real mode!!!)
   - When an exception is raised, the exception handler is called.
     Since the exception handler already exits from the graphic mode,
     this funcion has not to be called. For this reason:
     . we registered byebye using the flag NO_AT_ABORT
     . the exception handler exits using sys_abort; in that way byebye is
       NOT called
*/



/*--------------------------------------------------------------*/
/* User exit function                                           */
/*--------------------------------------------------------------*/

void byebye(void *arg)
{
  grx_close();
  cprintf("Bye Bye!\n");
}

/*--------------------------------------------------------------*/
/* Main task                                                    */
/*--------------------------------------------------------------*/


/****************************** MAIN ******************************/

int main(int argc, char **argv)
{
    struct sigaction action;

    char c = 0;         /* character from keyboard      */

    /* Init the standard S.Ha.R.K. exception handler */
    action.sa_flags = SA_SIGINFO;            /* Set the signal action */
    action.sa_sigaction = demo_exc_handler;
    action.sa_handler = 0;
    sigfillset(&action.sa_mask); /* we block all the other signals... */

    if (sigaction(SIGHEXC, &action, NULL) == -1) {  /* set the signal */
      perror("Error initializing signals...");
      sys_end();
    }

    /* Set the closing function */
    sys_atrunlevel(byebye, NULL, RUNLEVEL_BEFORE_EXIT|NO_AT_ABORT);

    /* graphic card Initialization */
    if (grx_init() < 1) {
       sys_abort(1);
    }
   
    if (grx_open(640, 480, 8) < 0) {
        cprintf("GRX Err\n");
        sys_abort(1);
    }

    grx_clear(BLACK);

    grx_text("Press a key [1-4]", 10, 16, 7, 0);
    grx_text("to create a pair",  10, 24, 7, 0);
    grx_text("ESC to exit demo",  10, 48, 7, 0);

    while (c != 27) {
      c = keyb_getch(BLOCK);
      if ((c >= '1') && (c <= '1'+NCAB-1))
        create_channel(c-'1');
    }
 
    sys_end();

    return 0;
}


/*--------------------------------------------------------------*/
/* write data in a cab                                          */
/*--------------------------------------------------------------*/

TASK    producer(void *arg)
{
int     i = (int)arg;
char    c;                      /* message character            */
char    *p;                     /* pointer to a cab buffer      */
char    s[2];                   /* string to display            */
int     k = 0;
int     x, y;
int     col = 13;
int     ybase = YY + i*DELTA;

        x = X1;
        y = ybase;
        s[1] = 0;

        k = 0;
        while (1) {
                c = 'A' + k;
                p = cab_reserve(cid[i]);
                *p = c;
                cab_putmes(cid[i], p);

                s[0] = c;
                k = (k + 1) % NCAR;
                grx_text(s,x,y,col,0);

                x += 8;
                if (x >= (X1 + NCAR*8)) {
                        x = X1;
                        y = y + 8;
                        if (y >= ybase+16) {
                                y = ybase;
                                col = col % 15 + 1;
                        }
                }

                task_endcycle();
        }
}

/*--------------------------------------------------------------*/
/* read data from a cab                                         */
/*--------------------------------------------------------------*/

TASK    consumer(void *arg)
{
int     i = (int)arg;
char    *p;
char    s[2];
int     x, y;
int     col = 13;
int     ybase = YY + i*DELTA;

        x = X2;
        y = ybase;
        s[1] = 0;

        while (1) {
                p = cab_getmes(cid[i]);
                s[0] = *p - 'A' + 'a';
                cab_unget(cid[i], p);

                grx_text(s,x,y,col,0);
                x += 8;

                if (x >= (X2 + NCAR*8)) {
                        x = X2;
                        y = y + 8;
                        if (y >= ybase+16) {
                                y = ybase;
                                col = col % 15 + 1;
                        }
                }
                task_endcycle();
        }
}

/*--------------------------------------------------------------*/
/* create the two tasks and a channel                           */
/*--------------------------------------------------------------*/

void    create_channel(int i)
{
        HARD_TASK_MODEL m;

        draw_channel(i);
        cid[i] = cab_create(cname[i], 1, 2);

        hard_task_default_model(m);
        hard_task_def_ctrl_jet (m);
        hard_task_def_arg      (m, (void *)i);
        hard_task_def_wcet     (m, w1[i]);
        hard_task_def_mit      (m, t1[i]);
        hard_task_def_usemath  (m);
        p1[i] = task_create(pname1[i], producer, &m, NULL);
        if (p1[i] == NIL) {
          grx_close();
          perror("Could not create task <producer>");
          sys_abort(1);
        }
        task_activate(p1[i]);

        hard_task_default_model(m);
        hard_task_def_ctrl_jet (m);
        hard_task_def_arg      (m, (void *)i);
        hard_task_def_wcet     (m, w2[i]);
        hard_task_def_mit      (m, t2[i]);
        hard_task_def_usemath  (m);
        p2[i] = task_create(pname2[i], consumer, &m, NULL);
        if (p2[i] == NIL) {
          grx_close();
          perror("Could not create task <consumer>");
          sys_abort(1);
        }
        task_activate(p2[i]);
}

/*--------------------------------------------------------------*/
/* Disegna i processi e il canale di comunicazione              */
/*--------------------------------------------------------------*/

void    draw_channel(int i)
{
char    buffer[32];                     /* buffer per sprintf   */
int     yc = YP + i*DELTA;              /* altezza del canale   */

        grx_circle(XP1,yc,R,2);
        grx_text("P1",XP1-8,yc-4,12,0);

        grx_circle(XP2,yc,R,2);
        grx_text("P2",XP2-8,yc-4,12,0);

        grx_rect(XC,yc-R,XC+L,yc+R,3);
        grx_text("CAB",XC+16,yc-4,12,0);

        grx_line(XP1+R,yc,XC,yc,4);
        grx_line(XC+L,yc,XP2-R,yc,4);

        grx_text("T1 =          ms",X1+40,yc+R+16,14,0);
        sprintf(buffer,"%ld", t1[i]);
        grx_text(buffer,X1+88,yc+R+16,14,0);

        grx_text("T2 =          ms",X2+40,yc+R+16,14,0);
        sprintf(buffer,"%ld", t2[i]);
        grx_text(buffer,X2+88,yc+R+16,14,0);
}

/*--------------------------------------------------------------*/