user RTEMS TIMER EXPLANATION

Correo Fernando-ruiz (E-mail) correo at fernando-ruiz.com
Thu Mar 1 22:09:35 UTC 2001


-----Mensaje original-----
De: azzedine [mailto:azzedine at iuplo.univ-ubs.fr]
Enviado el: jueves, 01 de marzo de 2001 17:19
Para: rtems-snapshots at OARcorp.com
Asunto: user RTEMS


hello,

In RTEMS to start a timer it is necessary to call the directive :

rtems_status_code rtems_timer_fire_when(
  rtems_id                           id,
  rtems_time_of_day                 *wall_time,
  rtems_timer_service_routine_entry  routine,
  void                              *user_data
);
Do you have explanation for an example has the concept of
rtems_timer_service_routine_entry  routine,
  void                              *user_data

azzedine.

[FRC]
Hi Azzedine.
The first concept in a timer is:
  What is that I need run when the timer start?
The user_timer_service can be a generic routine.
To adapt in every case I need parameters before run the routine.
How I can pass the parameter with a generic declaration?
With a pointer to a structure or variable.
That is the user data. The place to put a pointer to parameters.

Ça alors...
Ici mon example un peu bizarre mais suffisant pour le comprendre.
Il faut ajouter le traitement des erreurs(rtems_status_code).
Domage.

//----------------------------------
#include <rtems.h>
...
rtems_interval ticks_per_second; /*Global variable*/
rtems_id       timer_door_opened,
               timer_window_close;

typedef  struct {
  int timer_value;
  int alarm_value;
  int alarm_flag;
  int alarm_signal;
} timer_parameters_t;

rtems_timer_service_routine
user_timer_routine_generic (rtems_id timer_id,void *user_data)
{
 timer_parameter_t * arg=(timer_parameter_t *) user_data; /* typecast*/
 arg->timer_value++; /* times */
 arg->alarm_signal=TRUE; /* passed */
 if (arg->timer_value>arg->alarm_value) arg->alarm_flag=TRUE; /* expired */
 if (!arg->alarm_flag) rtems_timer_reset(timer_id); /* no more if expired */
}
/*--------------------------------------------*/
rtems_interval msecs2ticks(int msecs) {
 return (msecs*ticks_per_second)/1000;
}
/*--------------------------------------------*/
void tim_register(void) {
 rtems_clock_get(RTEMS_CLOCK_GET_TICKS_PER_SECOND,&ticks_per_second);
 rtems_timer_create(rtems_build_name('T','M','D','O'),&timer_door_opened);
 rtems_timer_create(rtems_build_name('T','M','W','C'),&timer_window_closed);
}
/*---------------------------------------------*/
rtems_task
Init (rtems_task_argument ignored)
{
  timer_parameter_t tp_door  ,
                    tp_window;

  tp_door.timer_value =0;
  tp_door.alarm_value =60; /* seconds, maximum time to maintain opened the
door*/
  tp_door.alarm_flag  =FALSE; /* the timer routine has not been called  */
  tp_door.alarm_signal=FALSE; /* the total time (60 seconds) has been
expired */

  tp_window.timer_value =0;
  tp_window.alarm_value =30;    /* minutes,maximum time to maintain closed
the window*/
  tp_window.alarm_flag  =FALSE; /* the timer routine has not been called  */
  tp_window.alarm_signal=FALSE; /* the total time (30 minutes) has been
expired */

  tim_register();
  for (;;) {

   /* CHECK THAT THE DOOR IS NOT OPENED.
      WHEN OPENED SOUND THE BUZZER EVERY SECOND UNTIL 60 SECONDS.
      THE DOOR IS CLOSED AUTOMATICALY WHEN TIMEOUT*/

   if (door_opened()) { /* check the door */
    if (!tp_door.timer_value) { /* not started */
     tp_door.timer_value=1; /* to mark . Runs every second to sound the
buzzer*/

rtems_timer_fire_after(timer_door_opened,msecs2ticks(1000),user_timer_routin
e_generic,(void*)&tp_door);
    } else {
     if (tp_door.alarm_signal) {
      tp_door.alarm_signal=FALSE;
      sound_buzzer();
      disp_message("CLOSE THE DOOR
",tp_door.alarm_value-tp_door.timer_value); /* Show the seconds*/
      if (tp_door.alarm_signal) {
       tp_door.alarm_signal=FALSE;
       disp_message("CLOSING THE DOOR");
       close_door();
      };
     };
    };
   } else {
     tp_door.timer_value=0;
     rtems_timer_cancel(timer_door_opened);
   };

   /* CHECK THAT THE WINDOW IS OPENED.
      WHEN CLOSED SOUND THE BUZZER EVERY MINUTE UNTIL 30 MINUTES.
      THE WINDOW IS OPENED AUTOMATICALY WHEN TIMEOUT*/

   if (window_closed()) { /* check the window */
    if (!tp_window.timer_value) { /* not started */
     tp_window.timer_value=1; /* to mark . Runs every minute to sound the
buzzer*/

rtems_timer_fire_after(timer_window_closed,msecs2ticks(60*1000),user_timer_r
outine_generic,(void*)&tp_window);
    } else {
     if (tp_window.alarm_signal) {
      tp_window.alarm_signal=FALSE;
      sound_buzzer();
      disp_message("OPEN THE
WINDOW",tp_window.alarm_value-tp_window.timer_value); /* Show the minutes*/
      if (tp_window.alarm_signal) {
       tp_window.alarm_signal=FALSE;
       disp_message("OPENING THE WINDOW");
       open_window();
      };
     };
    };
   } else {
     tp_window.timer_value=0;
     rtems_timer_cancel(timer_window_closed);
   };
  };
}

//----------------------
You can also call to rtems_timer_fire_when() instead
rtems_timer_fire_after()
but you need a RTC or similar (a user prompt)
to set the rtems_clock_timer in order to call with a logical wall_time.
In embedded system the user prompt is not the best solution. The ticks are
very stable.
Le decalage est toujours le meme.

With the multitask and waiting events the timers can be avoided in a lot of
cases.
You can wait an event for ticks interval. In this case the task is dormant
and the system
runs very happy. In a for(;;) the system is always ready and the scheduler
is very poor.

Do you need run a routine vevery second?
Start a new task and call to rtems_task_wake_after(ticks) in a for(;;).

rtems_task
periodic_task(rtems_arguments ignored) {
 for (;;) {
   routine_every_second();
   rtems_task_wake_after(msecs2ticks(1000));
 };
}

My watchdog is implemented in this way.
The task doesn't disturb the scheduler and the CPU
runs without problem of resources.


C'est tout.

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






More information about the users mailing list