source: rtems/cpukit/rtems/src/timercreate.c @ 66cb142

Last change on this file since 66cb142 was 9480815a, checked in by Sebastian Huber <sebastian.huber@…>, on Dec 21, 2017 at 1:36:52 PM

score: Introduce new monotonic clock

Rename PER_CPU_WATCHDOG_MONOTONIC to PER_CPU_WATCHDOG_TICKS. Add new
PER_CPU_WATCHDOG_MONOTONIC which is based on the system uptime (measured
by timecounter).

Close #3264.

  • Property mode set to 100644
File size: 5.2 KB
Line 
1/**
2 *  @file
3 *
4 *  @brief RTEMS Create Timer
5 *  @ingroup ClassicTimer
6 */
7
8/*
9 *  COPYRIGHT (c) 1989-2002.
10 *  On-Line Applications Research Corporation (OAR).
11 *
12 *  The license and distribution terms for this file may be
13 *  found in the file LICENSE in this distribution or at
14 *  http://www.rtems.org/license/LICENSE.
15 */
16
17#if HAVE_CONFIG_H
18#include "config.h"
19#endif
20
21#include <rtems/rtems/timerimpl.h>
22#include <rtems/rtems/clock.h>
23#include <rtems/rtems/status.h>
24#include <rtems/rtems/support.h>
25#include <rtems/score/assert.h>
26#include <rtems/score/chainimpl.h>
27#include <rtems/score/thread.h>
28#include <rtems/score/todimpl.h>
29#include <rtems/score/watchdogimpl.h>
30
31RTEMS_STATIC_ASSERT(
32  PER_CPU_WATCHDOG_REALTIME == TIMER_CLASS_BIT_TIME_OF_DAY,
33  TIMER_CLASS_BIT_TIME_OF_DAY
34);
35
36void _Timer_Routine_adaptor( Watchdog_Control *the_watchdog )
37{
38  Timer_Control   *the_timer;
39  Per_CPU_Control *cpu;
40
41  the_timer = RTEMS_CONTAINER_OF( the_watchdog, Timer_Control, Ticker );
42  cpu = _Watchdog_Get_CPU( &the_timer->Ticker );
43  the_timer->stop_time = _Timer_Get_CPU_ticks( cpu );
44
45  ( *the_timer->routine )( the_timer->Object.id, the_timer->user_data );
46}
47
48rtems_status_code _Timer_Fire(
49  rtems_id                           id,
50  rtems_interval                     interval,
51  rtems_timer_service_routine_entry  routine,
52  void                              *user_data,
53  Timer_Classes                      the_class,
54  Watchdog_Service_routine_entry     adaptor
55)
56{
57  Timer_Control    *the_timer;
58  ISR_lock_Context  lock_context;
59
60  the_timer = _Timer_Get( id, &lock_context );
61  if ( the_timer != NULL ) {
62    Per_CPU_Control *cpu;
63
64    cpu = _Timer_Acquire_critical( the_timer, &lock_context );
65    _Timer_Cancel( cpu, the_timer );
66    _Watchdog_Initialize( &the_timer->Ticker, adaptor );
67    the_timer->the_class = the_class;
68    the_timer->routine = routine;
69    the_timer->user_data = user_data;
70    the_timer->initial = interval;
71    the_timer->start_time = _Timer_Get_CPU_ticks( cpu );
72
73    if ( _Timer_Is_interval_class( the_class ) ) {
74      _Watchdog_Insert(
75        &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_TICKS ],
76        &the_timer->Ticker,
77        cpu->Watchdog.ticks + interval
78      );
79    } else {
80      _Watchdog_Insert(
81        &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_REALTIME ],
82        &the_timer->Ticker,
83        _Watchdog_Ticks_from_seconds( interval )
84      );
85    }
86
87    _Timer_Release( cpu, &lock_context );
88    return RTEMS_SUCCESSFUL;
89  }
90
91  return RTEMS_INVALID_ID;
92}
93
94rtems_status_code _Timer_Fire_after(
95  rtems_id                           id,
96  rtems_interval                     ticks,
97  rtems_timer_service_routine_entry  routine,
98  void                              *user_data,
99  Timer_Classes                      the_class,
100  Watchdog_Service_routine_entry     adaptor
101)
102{
103  if ( ticks == 0 )
104    return RTEMS_INVALID_NUMBER;
105
106  if ( !routine )
107    return RTEMS_INVALID_ADDRESS;
108
109  return _Timer_Fire(
110    id,
111    ticks,
112    routine,
113    user_data,
114    the_class,
115    adaptor
116  );
117}
118
119rtems_status_code _Timer_Fire_when(
120  rtems_id                           id,
121  const rtems_time_of_day           *wall_time,
122  rtems_timer_service_routine_entry  routine,
123  void                              *user_data,
124  Timer_Classes                      the_class,
125  Watchdog_Service_routine_entry     adaptor
126)
127{
128  rtems_interval seconds;
129
130  if ( !_TOD_Is_set() )
131    return RTEMS_NOT_DEFINED;
132
133  if ( !routine )
134    return RTEMS_INVALID_ADDRESS;
135
136  if ( !_TOD_Validate( wall_time ) )
137    return RTEMS_INVALID_CLOCK;
138
139  seconds = _TOD_To_seconds( wall_time );
140  if ( seconds <= _TOD_Seconds_since_epoch() )
141    return RTEMS_INVALID_CLOCK;
142
143  return _Timer_Fire(
144    id,
145    seconds,
146    routine,
147    user_data,
148    the_class,
149    adaptor
150  );
151}
152
153void _Timer_Cancel( Per_CPU_Control *cpu, Timer_Control *the_timer )
154{
155  Timer_Classes the_class;
156
157  the_class = the_timer->the_class;
158
159  if ( _Watchdog_Is_scheduled( &the_timer->Ticker ) ) {
160    the_timer->stop_time = _Timer_Get_CPU_ticks( cpu );
161    _Watchdog_Remove(
162      &cpu->Watchdog.Header[ _Timer_Watchdog_header_index( the_class ) ],
163      &the_timer->Ticker
164    );
165  } else if ( _Timer_Is_on_task_class( the_class ) ) {
166    Timer_server_Control *timer_server;
167    ISR_lock_Context      lock_context;
168
169    timer_server = _Timer_server;
170    _Assert( timer_server != NULL );
171    _Timer_server_Acquire_critical( timer_server, &lock_context );
172
173    if ( _Watchdog_Get_state( &the_timer->Ticker ) == WATCHDOG_PENDING ) {
174      _Watchdog_Set_state( &the_timer->Ticker, WATCHDOG_INACTIVE );
175      _Chain_Extract_unprotected( &the_timer->Ticker.Node.Chain );
176    }
177
178    _Timer_server_Release_critical( timer_server, &lock_context );
179  }
180}
181
182rtems_status_code rtems_timer_create(
183  rtems_name  name,
184  rtems_id   *id
185)
186{
187  Timer_Control *the_timer;
188
189  if ( !rtems_is_name_valid( name ) )
190    return RTEMS_INVALID_NAME;
191
192  if ( !id )
193    return RTEMS_INVALID_ADDRESS;
194
195  the_timer = _Timer_Allocate();
196
197  if ( !the_timer ) {
198    _Objects_Allocator_unlock();
199    return RTEMS_TOO_MANY;
200  }
201
202  the_timer->the_class = TIMER_DORMANT;
203  _Watchdog_Preinitialize( &the_timer->Ticker, _Per_CPU_Get_snapshot() );
204
205  _Objects_Open(
206    &_Timer_Information,
207    &the_timer->Object,
208    (Objects_Name) name
209  );
210
211  *id = the_timer->Object.id;
212  _Objects_Allocator_unlock();
213  return RTEMS_SUCCESSFUL;
214}
Note: See TracBrowser for help on using the repository browser.