scan with timeout

Fernando RUIZ CASAS correo at fernando-ruiz.com
Wed Mar 27 15:54:36 UTC 2002


> -----Mensaje original-----
> De: Stan [mailto:zylog at club-internet.fr]
> Enviado el: miércoles, 27 de marzo de 2002 10:37
> Para: rtems-users at oarcorp.com
> Asunto: scan with timeout
>
>
>
> Hi,
>
> I should like all input operation (read...scan...) return on timeout.
> What are best way for that ?
>
> This code you seem good ?
> In fact, the first call to the function scan return on timeout,
> but not the
> following.
> An idea?
>

Another way. (For all devices TERMIOS or not TERMIOS)

You need implement an events machine.

you can register an event mask for your current task.
Comunicate it at the producer task.
when the producer task get a new data set the event.
the consumer task waits the event for a timeout.

How to implement it?

easy.

--------------------------------------------------
A bref explanation.
For every task you dispose of 32 events. (THE RTEMS EVENTS)
You don't need to choose a fixed value.
You let at the evt machine that it chooses by you the events mask value.
You call set_event() and it returns two variables:
 The handle and the mask for the event.
You can call this evt machine twice or more in order to get several events
for the same task.

Don't worry for the values. The evt machine resolves it.

Now you need a silly character producer task that share the handle.
(And the chars received queue of course)

GLOBAL variable

int hnd_EVENTCHAR;  /* <0 is not asigned */

void task_charproducer(void) {
 char buf;
 for (;;) {
  if (read(CHAR_DEVICE,&buf,sizeof(buf)) {  /* this loop doesn't waste
resources */
   /* now you need save the value in a queue or similar memory buffer */
   ...
   /* I comunicate it at the consumer */
   if (!(hnd_CHARDEVICE<0)) {
    free_event(hnd_CHARDEVICE);  /* set the event and free the handle */
    hnd_EVENTCHAR=-1; /* Nobody wait */
   };

  };
 };
}


Your read procedure then calls this.

 (Only if the queue is empty)

 rtems_status_code wait_char(int timeout) {
  rtems_status_code sc;
  rtems_event_set  event;
  /* HERE I GET A NEW EVENT MASK VALUE */
  if ((sc=set_event(&hnd_EVENTCHAR,&event))!=RTEMS_SUCCESSFUL) return sc;
  /* HERE I WAIT FOR A TIMEOUT THE CHAR ARRIVAL */
  sc=wait_event(event,timeout);
  /* IF THE CHAR IS NOT ARRIVAL CLEAR THE EVENT */
  if (sc!=RTEMS_SUCCESSFUL) clear_events(event);
  /* maybe a semaphore to lock the shared variable?*/
  hnd_EVENTCHAR=-1; /* Nobody wait */
  /*semaphore unlock */
  return sc;
 };


If you can put all of this at the application level
you code will be more readable.
Avoid the rtems minor details implemetation.

Think easy. The easy solution is the best solution if it works.

You can see that evt machine keeps the rtems_task details
doing more easy and readable the use of this.

you have two modes of use this machine.

the producer calls free_event() or the producer calls send_event().

In the first case the handle is loosed. A new set_event() is necesary.

In the second case the handle remains live while the consumer task needs it.

Only a first set_event() is necesary.

The second case is for a main task loop with a select() emulation.
you can wait several ticks and to do another poll tasks.

Of course you need call

void evt_register(void)

before use it.

This software has been used inside the interrupts.


But you only need to build a producer char task and a new console driver
consumer.

The new console driver read function calls wait_char returning 0 bytes moved
and setting a global variable to indicate it.

The task producer call the old console device read.
A shared queue lets store and retrieve the chars.


Fernando RUIZ CASAS
home: correo at fernando-ruiz.com
work: fernando.ruiz at ctv.es



Another example to explain the evt machine.

Scenario.
two computers.
the first send a command in order to get an answer from the remote computer.

the first calls set_event obtaining a handle.
This handle is transmitted at the second machine like a JOBID inside the
command.
When the answer returns the callback function calls free_event(JOBID) with
the handle.
The first only waits the event mask.

/*--------------------------------------------*/
rtems_status_code  get_mataud(void) {  /* get the audio matrix crosspoints
status */
 net_pkg_t pkg;
 rtems_status_code sc;
 int hnd;
 rtems_event_set event;
 if ((sc=set_event(&hnd,&event))!=RTEMS_SUCCESSFUL) return sc;
 pkg.dst=ID_BUS;
 pkg.org=net_bus->idnet;
 pkg.cmd='M'; /* MATRIX */
 pkg.opt='G'; /* GET STATUS */
 pkg.seq=hnd; /* HERE THE JOBID */
 pkg.len=0;
 net_put(net_bus,&pkg);  /* transmit the command */
 sc=wait_event(event,timeout_aud); /* wait the answer */
 if (sc!=RTEMS_SUCCESSFUL) clear_events(event);	 /* nobody waits it */
 return sc;
}
...
/*----------------------------------------------------------*/
/* THE CALLBACK FUNCTION in the main loop*/
/*----------------------------------------------------------*/
int proc_pkg_aud(net_t * net,net_pkg_t * pkg) {
 ...
 switch (pkg->cmd) {
  case 'M':
   switch (pkg->opt) {
    case 'g': /* answer of get_mataud */
          memcpy(mataudbuf,pkg->x.buf,sizeof(mataudbuf)); /* save the
contens */
          free_event(pkg->seq);  /* NOTIFIES THE ANSWER */
          return TRUE;
   };
   break;
  ...
}

Fernando RUIZ CASAS
home: correo at fernando-ruiz.com
work: fernando.ruiz at ctv.es

>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: evt.h
Type: application/octet-stream
Size: 1415 bytes
Desc: not available
URL: <http://lists.rtems.org/pipermail/users/attachments/20020327/4ce2828f/attachment-0002.obj>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: evt.c
Type: application/octet-stream
Size: 5761 bytes
Desc: not available
URL: <http://lists.rtems.org/pipermail/users/attachments/20020327/4ce2828f/attachment-0003.obj>


More information about the users mailing list