source: rtems/cpukit/sapi/include/rtems/timecounter.h @ 31be416

4.115
Last change on this file since 31be416 was 31be416, checked in by Alexander Krutwig <alexander.krutwig@…>, on 04/20/15 at 09:08:22

timecounter: Port to RTEMS

New test sptests/timecounter01.

Update #2271.

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