source: rtems/cpukit/include/rtems/timecounter.h @ 3db9c820

Last change on this file since 3db9c820 was 3db9c820, checked in by Sebastian Huber <sebastian.huber@…>, on 11/28/20 at 10:16:28

sapi: Canonicalize @defgroup and @file comments

Adjust group identifier and names to be in line with a common pattern.
Use common phrases for the group and file brief descriptions.

Update #3706.

  • Property mode set to 100644
File size: 8.6 KB
Line 
1/**
2 * @file
3 *
4 * @ingroup RTEMSAPIClassicTimecounter
5 *
6 * @brief This header file provides the Timecounter Support API.
7 */
8
9/*
10 * Copyright (c) 2015 embedded brains GmbH.  All rights reserved.
11 *
12 *  embedded brains GmbH
13 *  Dornierstr. 4
14 *  82178 Puchheim
15 *  Germany
16 *  <rtems@embedded-brains.de>
17 *
18 * The license and distribution terms for this file may be
19 * found in the file LICENSE in this distribution or at
20 * http://www.rtems.org/license/LICENSE.
21 */
22
23#ifndef _RTEMS_TIMECOUNTER_H
24#define _RTEMS_TIMECOUNTER_H
25
26#include <rtems/score/timecounter.h>
27#include <rtems/score/basedefs.h>
28
29#ifdef __cplusplus
30extern "C" {
31#endif /* __cplusplus */
32
33/**
34 * @defgroup RTEMSAPIClassicTimecounter Timecounter Support
35 *
36 * @ingroup RTEMSAPIClassic
37 *
38 * @brief The timecounter support provides directives to implement clock device
39 *   drivers.
40 *
41 * @{
42 */
43
44/**
45 * @brief Timecounter quality for the clock drivers.
46 *
47 * Timecounter with higher quality value are used in favour of those with lower
48 * quality value.
49 */
50#define RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER 100
51
52/**
53 * @copydoc _Timecounter_Install()
54 *
55 * Below is an exemplary code snippet that shows the adjustable parameters and
56 * the following call of the install routine.
57 *
58 * @code
59 * struct timecounter tc;
60 *
61 * uint32_t get_timecount( struct timecounter *tc )
62 * {
63 *   return some_free_running_counter;
64 * }
65 *
66 * void install( void )
67 * {
68 *   tc.tc_get_timecount = get_timecount;
69 *   tc.tc_counter_mask = 0xffffffff;
70 *   tc.tc_frequency = 123456;
71 *   tc.tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER;
72 *   rtems_timecounter_install( &tc );
73 * }
74 * @endcode
75 */
76RTEMS_INLINE_ROUTINE void rtems_timecounter_install(
77  struct timecounter *tc
78)
79{
80  _Timecounter_Install( tc );
81}
82
83/**
84 * @copydoc _Timecounter_Tick()
85 */
86RTEMS_INLINE_ROUTINE void rtems_timecounter_tick(void)
87{
88  _Timecounter_Tick();
89}
90
91/**
92 * @brief Simple timecounter to support legacy clock drivers.
93 */
94typedef struct {
95  struct timecounter tc;
96  uint64_t scaler;
97  uint32_t real_interval;
98  uint32_t binary_interval;
99} rtems_timecounter_simple;
100
101/**
102 * @brief At tick handling done under protection of the timecounter lock.
103 */
104typedef void rtems_timecounter_simple_at_tick(
105  rtems_timecounter_simple *tc
106);
107
108/**
109 * @brief Returns the current value of a simple timecounter.
110 */
111typedef uint32_t rtems_timecounter_simple_get(
112  rtems_timecounter_simple *tc
113);
114
115/**
116 * @brief Returns true if the interrupt of a simple timecounter is pending, and
117 * false otherwise.
118 */
119typedef bool rtems_timecounter_simple_is_pending(
120  rtems_timecounter_simple *tc
121);
122
123/**
124 * @brief Initializes and installs a simple timecounter.
125 *
126 * A simple timecounter can be used if the hardware provides no free running
127 * counter.  A periodic hardware counter must be provided.  The counter period
128 * must be synchronous to the clock tick.  The counter ticks per clock tick is
129 * scaled up to the next power of two.
130 *
131 * @param[in] tc Zero initialized simple timecounter.
132 * @param[in] counter_frequency_in_hz The hardware counter frequency in Hz.
133 * @param[in] counter_ticks_per_clock_tick The hardware counter ticks per clock
134 *   tick.
135 * @param[in] get_timecount The method to get the current time count.
136 *
137 * @code
138 * #include <rtems/timecounter.h>
139 *
140 * static rtems_timecounter_simple some_tc;
141 *
142 * static uint32_t some_tc_get( rtems_timecounter_simple *tc )
143 * {
144 *   return some.value;
145 * }
146 *
147 * static bool some_tc_is_pending( rtems_timecounter_simple *tc )
148 * {
149 *   return some.is_pending;
150 * }
151 *
152 * static uint32_t some_tc_get_timecount( struct timecounter *tc )
153 * {
154 *   return rtems_timecounter_simple_downcounter_get(
155 *     tc,
156 *     some_tc_get,
157 *     some_tc_is_pending
158 *   );
159 * }
160 *
161 * static void some_tc_tick( void )
162 * {
163 *   rtems_timecounter_simple_downcounter_tick( &some_tc, some_tc_get );
164 * }
165 *
166 * void some_tc_init( void )
167 * {
168 *   uint64_t us_per_tick;
169 *   uint32_t counter_frequency_in_hz;
170 *   uint32_t counter_ticks_per_clock_tick;
171 *
172 *   us_per_tick = rtems_configuration_get_microseconds_per_tick();
173 *   counter_frequency_in_hz = some_tc_get_frequency();
174 *   counter_ticks_per_clock_tick =
175 *     (uint32_t) ( counter_frequency_in_hz * us_per_tick ) / 1000000;
176 *
177 *   some_tc_init_hardware( counter_ticks_per_clock_tick );
178 *   some_tc_init_clock_tick_interrupt( some_tc_tick );
179 *
180 *   rtems_timecounter_simple_install(
181 *     &some_tc,
182 *     counter_frequency_in_hz,
183 *     counter_ticks_per_clock_tick,
184 *     some_tc_get_timecount
185 *   );
186 * }
187 * @endcode
188 *
189 * @see rtems_timecounter_simple_downcounter_get(),
190 * rtems_timecounter_simple_downcounter_tick(),
191 * rtems_timecounter_simple_upcounter_get() and
192 * rtems_timecounter_simple_upcounter_tick().
193 */
194void rtems_timecounter_simple_install(
195  rtems_timecounter_simple *tc,
196  uint32_t                  counter_frequency_in_hz,
197  uint32_t                  counter_ticks_per_clock_tick,
198  timecounter_get_t        *get_timecount
199);
200
201/**
202 * @brief Maps a simple timecounter value into its binary frequency domain.
203 *
204 * @param[in] tc The simple timecounter.
205 * @param[in] value The value of the simple timecounter.
206 *
207 * @return The scaled value.
208 */
209RTEMS_INLINE_ROUTINE uint32_t rtems_timecounter_simple_scale(
210  const rtems_timecounter_simple *tc,
211  uint32_t value
212)
213{
214  return (uint32_t) ( ( value * tc->scaler ) >> 32 );
215}
216
217/**
218 * @brief Performs a simple timecounter tick for downcounters.
219 *
220 * @param[in] tc The simple timecounter.
221 * @param[in] get The method to get the value of the simple timecounter.
222 * @param[in] at_tick The method to perform work under timecounter lock
223 * protection at this tick, e.g. clear a pending flag.
224 */
225RTEMS_INLINE_ROUTINE void rtems_timecounter_simple_downcounter_tick(
226  rtems_timecounter_simple         *tc,
227  rtems_timecounter_simple_get      get,
228  rtems_timecounter_simple_at_tick  at_tick
229)
230{
231  ISR_lock_Context lock_context;
232  uint32_t current;
233
234  _Timecounter_Acquire( &lock_context );
235
236  ( *at_tick )( tc );
237
238  current = rtems_timecounter_simple_scale(
239    tc,
240    tc->real_interval - ( *get )( tc )
241  );
242
243  _Timecounter_Tick_simple( tc->binary_interval, current, &lock_context );
244}
245
246/**
247 * @brief Performs a simple timecounter tick for upcounters.
248 *
249 * @param[in] tc The simple timecounter.
250 * @param[in] get The method to get the value of the simple timecounter.
251 * @param[in] at_tick The method to perform work under timecounter lock
252 * protection at this tick, e.g. clear a pending flag.
253 */
254RTEMS_INLINE_ROUTINE void rtems_timecounter_simple_upcounter_tick(
255  rtems_timecounter_simple         *tc,
256  rtems_timecounter_simple_get      get,
257  rtems_timecounter_simple_at_tick  at_tick
258)
259{
260  ISR_lock_Context lock_context;
261  uint32_t current;
262
263  _Timecounter_Acquire( &lock_context );
264
265  ( *at_tick )( tc );
266
267  current = rtems_timecounter_simple_scale( tc, ( *get )( tc ) );
268
269  _Timecounter_Tick_simple( tc->binary_interval, current, &lock_context );
270}
271
272/**
273 * @brief Gets the simple timecounter value mapped to its binary frequency
274 * domain for downcounters.
275 *
276 * @param[in] tc The simple timecounter.
277 * @param[in] get The method to get the value of the simple timecounter.
278 * @param[in] is_pending The method which indicates if the interrupt of the
279 * simple timecounter is pending.
280 */
281RTEMS_INLINE_ROUTINE uint32_t rtems_timecounter_simple_downcounter_get(
282  struct timecounter                  *tc_base,
283  rtems_timecounter_simple_get         get,
284  rtems_timecounter_simple_is_pending  is_pending
285)
286{
287  rtems_timecounter_simple *tc;
288  uint32_t counter;
289  uint32_t interval;
290
291  tc = (rtems_timecounter_simple *) tc_base;
292  counter = ( *get )( tc );
293  interval = tc->real_interval;
294
295  if ( ( *is_pending )( tc ) ) {
296    counter = ( *get )( tc );
297    interval *= 2;
298  }
299
300  return rtems_timecounter_simple_scale( tc, interval - counter );
301}
302
303/**
304 * @brief Gets the simple timecounter value mapped to its binary frequency
305 * domain for upcounters.
306 *
307 * @param[in] tc The simple timecounter.
308 * @param[in] get The method to get the value of the simple timecounter.
309 * @param[in] is_pending The method which indicates if the interrupt of the
310 * simple timecounter is pending.
311 */
312RTEMS_INLINE_ROUTINE uint32_t rtems_timecounter_simple_upcounter_get(
313  struct timecounter                  *tc_base,
314  rtems_timecounter_simple_get         get,
315  rtems_timecounter_simple_is_pending  is_pending
316)
317{
318  rtems_timecounter_simple *tc;
319  uint32_t counter;
320  uint32_t interval;
321
322  tc = (rtems_timecounter_simple *) tc_base;
323  counter = ( *get )( tc );
324  interval = 0;
325
326  if ( ( *is_pending )( tc ) ) {
327    counter = ( *get )( tc );
328    interval = tc->real_interval;
329  }
330
331  return rtems_timecounter_simple_scale( tc, interval + counter );
332}
333
334/** @} */
335
336#ifdef __cplusplus
337}
338#endif /* __cplusplus */
339
340#endif /* _RTEMS_TIMECOUNTER_H */
Note: See TracBrowser for help on using the repository browser.