Blame |
Last modification |
View Log
| RSS feed
/*--------------------------------------------------------------*/
/* 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
),
kern_printf
("\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
();
kern_printf
("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) {
kern_printf
("GRX Err\n");
sys_abort
(1);
}
kern_printf
("Video card ok!\n");
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);
}
/*--------------------------------------------------------------*/