source: rtems/cpukit/include/rtems/timecounter.h @ 255fe43

Last change on this file since 255fe43 was 255fe43, checked in by Joel Sherrill <joel@…>, on 03/01/22 at 20:40:44

cpukit/: Scripted embedded brains header file clean up

Updates #4625.

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