source: rtems/bsps/shared/dev/clock/clockimpl.h @ 718a84af

5
Last change on this file since 718a84af was 7632906, checked in by Sebastian Huber <sebastian.huber@…>, on 04/19/18 at 04:35:52

bsps: Move clock drivers to bsps

This patch is a part of the BSP source reorganization.

Update #3285.

  • Property mode set to 100644
File size: 5.7 KB
Line 
1/**
2 * @file
3 *
4 * @ingroup bsp_clock
5 *
6 * @brief Clock Tick Device Driver Shell
7 */
8
9/*
10 *  COPYRIGHT (c) 1989-2014.
11 *  On-Line Applications Research Corporation (OAR).
12 *
13 *  The license and distribution terms for this file may be
14 *  found in the file LICENSE in this distribution or at
15 *  http://www.rtems.org/license/LICENSE.
16 */
17
18#include <stdlib.h>
19
20#include <bsp.h>
21#include <rtems/clockdrv.h>
22#include <rtems/score/percpu.h>
23#include <rtems/score/smpimpl.h>
24#include <rtems/score/watchdogimpl.h>
25
26#ifdef Clock_driver_nanoseconds_since_last_tick
27#error "Update driver to use the timecounter instead of nanoseconds extension"
28#endif
29
30/**
31 * @defgroup bsp_clock Clock Support
32 *
33 * @ingroup bsp_shared
34 *
35 * @brief Clock support
36 *
37 */
38#if CLOCK_DRIVER_USE_FAST_IDLE && CLOCK_DRIVER_ISRS_PER_TICK
39#error "Fast Idle PLUS n ISRs per tick is not supported"
40#endif
41
42/**
43 * @brief Do nothing by default.
44 */
45#ifndef Clock_driver_support_install_isr
46  #define Clock_driver_support_install_isr(isr)
47#endif
48
49/**
50 * @brief This method is rarely used so default it.
51 */
52#ifndef Clock_driver_support_find_timer
53  #define Clock_driver_support_find_timer()
54#endif
55
56/**
57 * @brief Do nothing by default.
58 */
59#ifndef Clock_driver_support_at_tick
60  #define Clock_driver_support_at_tick()
61#endif
62
63/**
64 * @brief Do nothing by default.
65 */
66#ifndef Clock_driver_support_set_interrupt_affinity
67  #define Clock_driver_support_set_interrupt_affinity(online_processors)
68#endif
69
70/*
71 * A specialized clock driver may use for example rtems_timecounter_tick_simple()
72 * instead of the default.
73 */
74#ifndef Clock_driver_timecounter_tick
75static void Clock_driver_timecounter_tick( void )
76{
77#if defined(CLOCK_DRIVER_USE_DUMMY_TIMECOUNTER)
78  rtems_clock_tick();
79#elif defined(RTEMS_SMP) && defined(CLOCK_DRIVER_USE_ONLY_BOOT_PROCESSOR)
80  uint32_t cpu_count = _SMP_Get_processor_count();
81  uint32_t cpu_index;
82
83  for ( cpu_index = 0 ; cpu_index < cpu_count ; ++cpu_index ) {
84    Per_CPU_Control *cpu;
85
86    cpu = _Per_CPU_Get_by_index( cpu_index );
87
88    if ( _Per_CPU_Is_boot_processor( cpu ) ) {
89      rtems_timecounter_tick();
90    } else if ( _Processor_mask_Is_set( _SMP_Get_online_processors(), cpu_index ) ) {
91      _Watchdog_Tick( cpu );
92    }
93  }
94#else
95  rtems_timecounter_tick();
96#endif
97}
98#endif
99
100/**
101 * @brief ISRs until next clock tick
102 */
103#if CLOCK_DRIVER_ISRS_PER_TICK
104  volatile uint32_t  Clock_driver_isrs;
105#endif
106
107/**
108 * @brief Clock ticks since initialization
109 */
110volatile uint32_t    Clock_driver_ticks;
111
112#ifdef Clock_driver_support_shutdown_hardware
113void Clock_exit( void );
114#endif
115
116/**
117 *  @brief Clock_isr
118 *
119 *  This is the clock tick interrupt handler.
120 *
121 *  @param vector Vector number.
122 */
123#if defined(BSP_FEATURE_IRQ_EXTENSION) || \
124    (CPU_SIMPLE_VECTORED_INTERRUPTS != TRUE)
125void Clock_isr(void *arg);
126void Clock_isr(void *arg)
127{
128#else
129rtems_isr Clock_isr(rtems_vector_number vector);
130rtems_isr Clock_isr(
131  rtems_vector_number vector
132)
133{
134#endif
135  /*
136   *  Accurate count of ISRs
137   */
138  Clock_driver_ticks += 1;
139
140  #if CLOCK_DRIVER_USE_FAST_IDLE
141    {
142      struct timecounter *tc = _Timecounter;
143      uint64_t us_per_tick = rtems_configuration_get_microseconds_per_tick();
144      uint32_t interval = (uint32_t)
145        ((tc->tc_frequency * us_per_tick) / 1000000);
146
147      Clock_driver_timecounter_tick();
148
149      if (!rtems_configuration_is_smp_enabled()) {
150        while (
151          _Thread_Heir == _Thread_Executing && _Thread_Executing->is_idle
152        ) {
153          ISR_lock_Context lock_context;
154
155          _Timecounter_Acquire(&lock_context);
156          _Timecounter_Tick_simple(
157            interval,
158            (*tc->tc_get_timecount)(tc),
159            &lock_context
160          );
161        }
162      }
163
164      Clock_driver_support_at_tick();
165    }
166  #else
167    /*
168     *  Do the hardware specific per-tick action.
169     *
170     *  The counter/timer may or may not be set to automatically reload.
171     */
172    Clock_driver_support_at_tick();
173
174    #if CLOCK_DRIVER_ISRS_PER_TICK
175      /*
176       *  The driver is multiple ISRs per clock tick.
177       */
178      if ( !Clock_driver_isrs ) {
179        Clock_driver_timecounter_tick();
180
181        Clock_driver_isrs = CLOCK_DRIVER_ISRS_PER_TICK;
182      }
183      Clock_driver_isrs--;
184    #else
185      /*
186       *  The driver is one ISR per clock tick.
187       */
188      Clock_driver_timecounter_tick();
189    #endif
190  #endif
191}
192
193#ifdef Clock_driver_support_shutdown_hardware
194/**
195 *  @brief Clock_exit
196 *
197 *  This routine allows the clock driver to exit by masking the interrupt and
198 *  disabling the clock's counter.
199 */
200void Clock_exit( void )
201{
202  Clock_driver_support_shutdown_hardware();
203
204  /* do not restore old vector */
205}
206#endif
207
208/**
209 * @brief Clock_initialize
210 *
211 * This routine initializes the clock driver.
212 *
213 * @param[in] major Clock device major number.
214 * @param[in] minor Clock device minor number.
215 * @param[in] parg  Pointer to optional device driver arguments
216 *
217 * @retval rtems_device_driver status code
218 */
219rtems_device_driver Clock_initialize(
220  rtems_device_major_number major,
221  rtems_device_minor_number minor,
222  void *pargp
223)
224{
225  Clock_driver_ticks = 0;
226
227  /*
228   *  Find timer -- some BSPs search buses for hardware timer
229   */
230  Clock_driver_support_find_timer();
231
232  /*
233   *  Install vector
234   */
235  Clock_driver_support_install_isr( Clock_isr );
236
237  #ifdef RTEMS_SMP
238    Clock_driver_support_set_interrupt_affinity(
239      _SMP_Get_online_processors()
240    );
241  #endif
242
243  /*
244   *  Now initialize the hardware that is the source of the tick ISR.
245   */
246  Clock_driver_support_initialize_hardware();
247
248#ifdef Clock_driver_support_shutdown_hardware
249  atexit( Clock_exit );
250#endif
251
252  /*
253   *  If we are counting ISRs per tick, then initialize the counter.
254   */
255  #if CLOCK_DRIVER_ISRS_PER_TICK
256    Clock_driver_isrs = CLOCK_DRIVER_ISRS_PER_TICK_VALUE;
257  #endif
258
259  return RTEMS_SUCCESSFUL;
260}
Note: See TracBrowser for help on using the repository browser.