![]() |
|
|||
File indexing completed on 2025-05-11 08:24:14
0001 /* SPDX-License-Identifier: BSD-2-Clause */ 0002 0003 /** 0004 * @file 0005 * 0006 * @ingroup RTEMSAPIClassicTimecounter 0007 * 0008 * @brief This header file provides the Timecounter Support API. 0009 */ 0010 0011 /* 0012 * Copyright (c) 2015 embedded brains GmbH & Co. KG 0013 * 0014 * Redistribution and use in source and binary forms, with or without 0015 * modification, are permitted provided that the following conditions 0016 * are met: 0017 * 1. Redistributions of source code must retain the above copyright 0018 * notice, this list of conditions and the following disclaimer. 0019 * 2. Redistributions in binary form must reproduce the above copyright 0020 * notice, this list of conditions and the following disclaimer in the 0021 * documentation and/or other materials provided with the distribution. 0022 * 0023 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 0024 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 0025 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 0026 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 0027 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 0028 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 0029 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 0030 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 0031 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 0032 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 0033 * POSSIBILITY OF SUCH DAMAGE. 0034 */ 0035 0036 #ifndef _RTEMS_TIMECOUNTER_H 0037 #define _RTEMS_TIMECOUNTER_H 0038 0039 #include <rtems/score/timecounter.h> 0040 #include <rtems/score/basedefs.h> 0041 0042 #ifdef __cplusplus 0043 extern "C" { 0044 #endif /* __cplusplus */ 0045 0046 /** 0047 * @defgroup RTEMSAPIClassicTimecounter Timecounter Support 0048 * 0049 * @ingroup RTEMSAPIClassic 0050 * 0051 * @brief The timecounter support provides directives to implement clock device 0052 * drivers. 0053 * 0054 * @{ 0055 */ 0056 0057 /** 0058 * @brief Timecounter quality for the clock drivers. 0059 * 0060 * Timecounter with higher quality value are used in favour of those with lower 0061 * quality value. 0062 */ 0063 #define RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER 100 0064 0065 /** 0066 * @copydoc _Timecounter_Install() 0067 * 0068 * Below is an exemplary code snippet that shows the adjustable parameters and 0069 * the following call of the install routine. 0070 * 0071 * @code 0072 * struct timecounter tc; 0073 * 0074 * uint32_t get_timecount( struct timecounter *tc ) 0075 * { 0076 * return some_free_running_counter; 0077 * } 0078 * 0079 * void install( void ) 0080 * { 0081 * tc.tc_get_timecount = get_timecount; 0082 * tc.tc_counter_mask = 0xffffffff; 0083 * tc.tc_frequency = 123456; 0084 * tc.tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER; 0085 * rtems_timecounter_install( &tc ); 0086 * } 0087 * @endcode 0088 */ 0089 static inline void rtems_timecounter_install( 0090 struct timecounter *tc 0091 ) 0092 { 0093 _Timecounter_Install( tc ); 0094 } 0095 0096 /** 0097 * @copydoc _Timecounter_Tick() 0098 */ 0099 static inline void rtems_timecounter_tick(void) 0100 { 0101 _Timecounter_Tick(); 0102 } 0103 0104 /** 0105 * @brief Simple timecounter to support legacy clock drivers. 0106 */ 0107 typedef struct { 0108 struct timecounter tc; 0109 uint64_t scaler; 0110 uint32_t real_interval; 0111 uint32_t binary_interval; 0112 } rtems_timecounter_simple; 0113 0114 /** 0115 * @brief At tick handling done under protection of the timecounter lock. 0116 */ 0117 typedef void rtems_timecounter_simple_at_tick( 0118 rtems_timecounter_simple *tc 0119 ); 0120 0121 /** 0122 * @brief Returns the current value of a simple timecounter. 0123 */ 0124 typedef uint32_t rtems_timecounter_simple_get( 0125 rtems_timecounter_simple *tc 0126 ); 0127 0128 /** 0129 * @brief Returns true if the interrupt of a simple timecounter is pending, and 0130 * false otherwise. 0131 */ 0132 typedef bool rtems_timecounter_simple_is_pending( 0133 rtems_timecounter_simple *tc 0134 ); 0135 0136 /** 0137 * @brief Initializes and installs a simple timecounter. 0138 * 0139 * A simple timecounter can be used if the hardware provides no free running 0140 * counter. A periodic hardware counter must be provided. The counter period 0141 * must be synchronous to the clock tick. The counter ticks per clock tick is 0142 * scaled up to the next power of two. 0143 * 0144 * @param[in] tc Zero initialized simple timecounter. 0145 * @param[in] counter_frequency_in_hz The hardware counter frequency in Hz. 0146 * @param[in] counter_ticks_per_clock_tick The hardware counter ticks per clock 0147 * tick. 0148 * @param[in] get_timecount The method to get the current time count. 0149 * 0150 * @code 0151 * #include <rtems/timecounter.h> 0152 * 0153 * static rtems_timecounter_simple some_tc; 0154 * 0155 * static uint32_t some_tc_get( rtems_timecounter_simple *tc ) 0156 * { 0157 * return some.value; 0158 * } 0159 * 0160 * static bool some_tc_is_pending( rtems_timecounter_simple *tc ) 0161 * { 0162 * return some.is_pending; 0163 * } 0164 * 0165 * static uint32_t some_tc_get_timecount( struct timecounter *tc ) 0166 * { 0167 * return rtems_timecounter_simple_downcounter_get( 0168 * tc, 0169 * some_tc_get, 0170 * some_tc_is_pending 0171 * ); 0172 * } 0173 * 0174 * static void some_tc_tick( void ) 0175 * { 0176 * rtems_timecounter_simple_downcounter_tick( &some_tc, some_tc_get ); 0177 * } 0178 * 0179 * void some_tc_init( void ) 0180 * { 0181 * uint64_t us_per_tick; 0182 * uint32_t counter_frequency_in_hz; 0183 * uint32_t counter_ticks_per_clock_tick; 0184 * 0185 * us_per_tick = rtems_configuration_get_microseconds_per_tick(); 0186 * counter_frequency_in_hz = some_tc_get_frequency(); 0187 * counter_ticks_per_clock_tick = 0188 * (uint32_t) ( counter_frequency_in_hz * us_per_tick ) / 1000000; 0189 * 0190 * some_tc_init_hardware( counter_ticks_per_clock_tick ); 0191 * some_tc_init_clock_tick_interrupt( some_tc_tick ); 0192 * 0193 * rtems_timecounter_simple_install( 0194 * &some_tc, 0195 * counter_frequency_in_hz, 0196 * counter_ticks_per_clock_tick, 0197 * some_tc_get_timecount 0198 * ); 0199 * } 0200 * @endcode 0201 * 0202 * @see rtems_timecounter_simple_downcounter_get(), 0203 * rtems_timecounter_simple_downcounter_tick(), 0204 * rtems_timecounter_simple_upcounter_get() and 0205 * rtems_timecounter_simple_upcounter_tick(). 0206 */ 0207 void rtems_timecounter_simple_install( 0208 rtems_timecounter_simple *tc, 0209 uint32_t counter_frequency_in_hz, 0210 uint32_t counter_ticks_per_clock_tick, 0211 timecounter_get_t *get_timecount 0212 ); 0213 0214 /** 0215 * @brief Maps a simple timecounter value into its binary frequency domain. 0216 * 0217 * @param[in] tc The simple timecounter. 0218 * @param[in] value The value of the simple timecounter. 0219 * 0220 * @return The scaled value. 0221 */ 0222 static inline uint32_t rtems_timecounter_simple_scale( 0223 const rtems_timecounter_simple *tc, 0224 uint32_t value 0225 ) 0226 { 0227 return (uint32_t) ( ( value * tc->scaler ) >> 32 ); 0228 } 0229 0230 /** 0231 * @brief Performs a simple timecounter tick for downcounters. 0232 * 0233 * @param[in] tc The simple timecounter. 0234 * @param[in] get The method to get the value of the simple timecounter. 0235 * @param[in] at_tick The method to perform work under timecounter lock 0236 * protection at this tick, e.g. clear a pending flag. 0237 */ 0238 static inline void rtems_timecounter_simple_downcounter_tick( 0239 rtems_timecounter_simple *tc, 0240 rtems_timecounter_simple_get get, 0241 rtems_timecounter_simple_at_tick at_tick 0242 ) 0243 { 0244 ISR_lock_Context lock_context; 0245 uint32_t current; 0246 0247 _Timecounter_Acquire( &lock_context ); 0248 0249 ( *at_tick )( tc ); 0250 0251 current = rtems_timecounter_simple_scale( 0252 tc, 0253 tc->real_interval - ( *get )( tc ) 0254 ); 0255 0256 _Timecounter_Tick_simple( tc->binary_interval, current, &lock_context ); 0257 } 0258 0259 /** 0260 * @brief Performs a simple timecounter tick for upcounters. 0261 * 0262 * @param[in] tc The simple timecounter. 0263 * @param[in] get The method to get the value of the simple timecounter. 0264 * @param[in] at_tick The method to perform work under timecounter lock 0265 * protection at this tick, e.g. clear a pending flag. 0266 */ 0267 static inline void rtems_timecounter_simple_upcounter_tick( 0268 rtems_timecounter_simple *tc, 0269 rtems_timecounter_simple_get get, 0270 rtems_timecounter_simple_at_tick at_tick 0271 ) 0272 { 0273 ISR_lock_Context lock_context; 0274 uint32_t current; 0275 0276 _Timecounter_Acquire( &lock_context ); 0277 0278 ( *at_tick )( tc ); 0279 0280 current = rtems_timecounter_simple_scale( tc, ( *get )( tc ) ); 0281 0282 _Timecounter_Tick_simple( tc->binary_interval, current, &lock_context ); 0283 } 0284 0285 /** 0286 * @brief Gets the simple timecounter value mapped to its binary frequency 0287 * domain for downcounters. 0288 * 0289 * @param[in] tc The simple timecounter. 0290 * @param[in] get The method to get the value of the simple timecounter. 0291 * @param[in] is_pending The method which indicates if the interrupt of the 0292 * simple timecounter is pending. 0293 */ 0294 static inline uint32_t rtems_timecounter_simple_downcounter_get( 0295 struct timecounter *tc_base, 0296 rtems_timecounter_simple_get get, 0297 rtems_timecounter_simple_is_pending is_pending 0298 ) 0299 { 0300 rtems_timecounter_simple *tc; 0301 uint32_t counter; 0302 uint32_t interval; 0303 0304 tc = (rtems_timecounter_simple *) tc_base; 0305 counter = ( *get )( tc ); 0306 interval = tc->real_interval; 0307 0308 if ( ( *is_pending )( tc ) ) { 0309 counter = ( *get )( tc ); 0310 interval *= 2; 0311 } 0312 0313 return rtems_timecounter_simple_scale( tc, interval - counter ); 0314 } 0315 0316 /** 0317 * @brief Gets the simple timecounter value mapped to its binary frequency 0318 * domain for upcounters. 0319 * 0320 * @param[in] tc The simple timecounter. 0321 * @param[in] get The method to get the value of the simple timecounter. 0322 * @param[in] is_pending The method which indicates if the interrupt of the 0323 * simple timecounter is pending. 0324 */ 0325 static inline uint32_t rtems_timecounter_simple_upcounter_get( 0326 struct timecounter *tc_base, 0327 rtems_timecounter_simple_get get, 0328 rtems_timecounter_simple_is_pending is_pending 0329 ) 0330 { 0331 rtems_timecounter_simple *tc; 0332 uint32_t counter; 0333 uint32_t interval; 0334 0335 tc = (rtems_timecounter_simple *) tc_base; 0336 counter = ( *get )( tc ); 0337 interval = 0; 0338 0339 if ( ( *is_pending )( tc ) ) { 0340 counter = ( *get )( tc ); 0341 interval = tc->real_interval; 0342 } 0343 0344 return rtems_timecounter_simple_scale( tc, interval + counter ); 0345 } 0346 0347 /** @} */ 0348 0349 #ifdef __cplusplus 0350 } 0351 #endif /* __cplusplus */ 0352 0353 #endif /* _RTEMS_TIMECOUNTER_H */
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
![]() ![]() |