[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Events.



Hi Joel and rtems-users.

I have a question about events.

I have implemented an event dispatcher and
I want to known if I am in the right way.

1. Environment.

   Two cpu's need to comunicate and the first send a command towards the
second.

   The second take a while and sends the reply.

   The caller task need to wait the reply until it arrives.

   The reply is catched by another task (dispatcher & supervisor).

2. Event handler.

   Every task can manage a maximum of 32 events. (RTEMS LIMITS)
   The availiable events are known by every task.
   To avoid the duplicates in lieu of a constant event
   the task call to lock for a new free event availiable
   and it is stored in a var.
   A events mask for every task is placed in a handlers table.

   /*--------------------------------------------*/
   typedef struct {
    rtems_id        id;    /* TASK ID */
    rtems_event_set event;
   } THndEvent;
   /*--------------------------------------------*/
   static THndEvent tbl_events[MAX_EVENTS];  /* The handlers */
   static THndEvent msk_events[TSK_EVENTS];  /* The task mask */

   static int last_event;                    /* this works like a PID inc
every time */
   static int max_msk_event;

  /*--------------------------------------------*/
  rtems_status_code lock_event(rtems_event_set * event) {
   rtems_status_code sc;
   rtems_event_set * mask,
                     ignored;
   sc=get_msk_events((rtems_id)0,&mask);
   if (sc!=RTEMS_SUCCESSFUL) return sc;
   *event=RTEMS_EVENT_0;
   while (*event&*mask) {
    *event<<=1;
    if (!*event) return RTEMS_TOO_MANY;
   };
   rtems_event_receive(*event,RTEMS_NO_WAIT,0,&ignored); /* clear it */
   *mask|=*event;
   return RTEMS_SUCCESSFUL;
  }

   With this a new procedure

   rtems_status_code set_event(int *handle,rtems_event_set * event) ;

   gives a handler and the new event locked.

   The first task places this handler in the comand sended towards the
second cpu.
   When the reply arrives the dispatcher task calls to

 /*--------------------------------------------*/
 void free_event(int handle) {
  rtems_status_code sc;
  if (handle<0) return;
  if (handle>=MAX_EVENTS)  return;
  if (tbl_events[handle].event) {
   sc=rtems_event_send(tbl_events[handle].id,tbl_events[handle].event);
   if (sc!=RTEMS_SUCCESSFUL) rtems_error(sc,"send event to
%08X",tbl_events[handle].id);
   unlock_event(tbl_events[handle].id,tbl_events[handle].event);
   tbl_events[handle].id   =0;
   tbl_events[handle].event=0;
  };
 }
 /*--------------------------------------------*/

   freeing the handle and sending the event at the first task.

   How the first task waits for this event the process is completed.

   ====================================================================
   Question:

	Is this way the right way to resolve this kind of problems?

	Where is the place in RTEMS to put the task mask used events?

	With this place I can eliminate this

   rtems_status_code get_msk_events(rtems_id task_id,rtems_event_set **
msk);

   ====================================================================
  The module includes also:

   void send_event(int handle) ; to wake_up asyncronously.
   void clear_events(rtems_event_set event); unlock the event and
                                             the handler for current task

   rtems_interval msecs2ticks(int msecs) ;
   rtems_status_code wait_event(rtems_event_set ev,rtems_interval msecs);

   With this last procedure I can use it like rtems_monotonic waiting a
   locked event known only by the current task.

/*----------------------------------------------------*/
/*-  My shell command to spy the module              -*/
/*----------------------------------------------------*/
#include <stdio.h>
#include <shell.h>
int main_events(int argc,char * argv[]) {
 int n,i,num;
 rtems_event_set ev;
 printf("MSK EVTS           1         2         3 \n");
 printf("TASK ID  01234567890123456789012345678901\n");
 printf("-------- --------------------------------\n");
 for (n=0;n<max_msk_event;n++) {
  printf("%08X ",msk_events[n].id);
  ev=RTEMS_EVENT_0;
  for (i=0;i<32;i++) {
   putchar(msk_events[n].event&ev?'X':' ');
   ev<<=1;
  };
  putchar('\n');
 };
 printf("-------- --------------------------------\n");
 printf("%d tasks\n",max_msk_event);
 printf("-------- --------------------------------\n");
 printf("TBL EVTS           1         2         3 \n");
 printf("TASK ID  01234567890123456789012345678901 HND\n");
 printf("-------- -------------------------------- ---\n");
 num=0;
 for (n=0;n<MAX_EVENTS;n++) {
  if (tbl_events[n].id) {
   num++;
   printf("%08X ",tbl_events[n].id);
   ev=RTEMS_EVENT_0;
   for (i=0;i<32;i++) {
    putchar(tbl_events[n].event&ev?'X':' ');
    ev<<=1;
   };
   printf(" %3d\n",n);
  };
 };
 printf("-------- --------------------------------\n");
 printf("%d events activated\n",num);
 printf("-------- --------------------------------\n");
 return 0;
}


Thanks for your comments.

Fernando RUIZ CASAS

correo at fernando-ruiz.com
fernando.ruiz at ctv.es